View | Details | Raw Unified | Return to bug 13614
Collapse All | Expand All

(-)a/koha-tmpl/intranet-tmpl/lib/yui/animation/animation-debug.js (-1396 lines)
Lines 1-1396 Link Here
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.8.0r4
6
*/
7
(function() {
8
9
var Y = YAHOO.util;
10
11
/*
12
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
13
Code licensed under the BSD License:
14
http://developer.yahoo.net/yui/license.txt
15
*/
16
17
/**
18
 * The animation module provides allows effects to be added to HTMLElements.
19
 * @module animation
20
 * @requires yahoo, event, dom
21
 */
22
23
/**
24
 *
25
 * Base animation class that provides the interface for building animated effects.
26
 * <p>Usage: var myAnim = new YAHOO.util.Anim(el, { width: { from: 10, to: 100 } }, 1, YAHOO.util.Easing.easeOut);</p>
27
 * @class Anim
28
 * @namespace YAHOO.util
29
 * @requires YAHOO.util.AnimMgr
30
 * @requires YAHOO.util.Easing
31
 * @requires YAHOO.util.Dom
32
 * @requires YAHOO.util.Event
33
 * @requires YAHOO.util.CustomEvent
34
 * @constructor
35
 * @param {String | HTMLElement} el Reference to the element that will be animated
36
 * @param {Object} attributes The attribute(s) to be animated.  
37
 * Each attribute is an object with at minimum a "to" or "by" member defined.  
38
 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").  
39
 * All attribute names use camelCase.
40
 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
41
 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
42
 */
43
44
var Anim = function(el, attributes, duration, method) {
45
    if (!el) {
46
        YAHOO.log('element required to create Anim instance', 'error', 'Anim');
47
    }
48
    this.init(el, attributes, duration, method); 
49
};
50
51
Anim.NAME = 'Anim';
52
53
Anim.prototype = {
54
    /**
55
     * Provides a readable name for the Anim instance.
56
     * @method toString
57
     * @return {String}
58
     */
59
    toString: function() {
60
        var el = this.getEl() || {};
61
        var id = el.id || el.tagName;
62
        return (this.constructor.NAME + ': ' + id);
63
    },
64
    
65
    patterns: { // cached for performance
66
        noNegatives:        /width|height|opacity|padding/i, // keep at zero or above
67
        offsetAttribute:  /^((width|height)|(top|left))$/, // use offsetValue as default
68
        defaultUnit:        /width|height|top$|bottom$|left$|right$/i, // use 'px' by default
69
        offsetUnit:         /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i // IE may return these, so convert these to offset
70
    },
71
    
72
    /**
73
     * Returns the value computed by the animation's "method".
74
     * @method doMethod
75
     * @param {String} attr The name of the attribute.
76
     * @param {Number} start The value this attribute should start from for this animation.
77
     * @param {Number} end  The value this attribute should end at for this animation.
78
     * @return {Number} The Value to be applied to the attribute.
79
     */
80
    doMethod: function(attr, start, end) {
81
        return this.method(this.currentFrame, start, end - start, this.totalFrames);
82
    },
83
    
84
    /**
85
     * Applies a value to an attribute.
86
     * @method setAttribute
87
     * @param {String} attr The name of the attribute.
88
     * @param {Number} val The value to be applied to the attribute.
89
     * @param {String} unit The unit ('px', '%', etc.) of the value.
90
     */
91
    setAttribute: function(attr, val, unit) {
92
        var el = this.getEl();
93
        if ( this.patterns.noNegatives.test(attr) ) {
94
            val = (val > 0) ? val : 0;
95
        }
96
97
        if (attr in el && !('style' in el && attr in el.style)) {
98
            el[attr] = val;
99
        } else {
100
            Y.Dom.setStyle(el, attr, val + unit);
101
        }
102
    },                        
103
    
104
    /**
105
     * Returns current value of the attribute.
106
     * @method getAttribute
107
     * @param {String} attr The name of the attribute.
108
     * @return {Number} val The current value of the attribute.
109
     */
110
    getAttribute: function(attr) {
111
        var el = this.getEl();
112
        var val = Y.Dom.getStyle(el, attr);
113
114
        if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
115
            return parseFloat(val);
116
        }
117
        
118
        var a = this.patterns.offsetAttribute.exec(attr) || [];
119
        var pos = !!( a[3] ); // top or left
120
        var box = !!( a[2] ); // width or height
121
        
122
        if ('style' in el) {
123
            // use offsets for width/height and abs pos top/left
124
            if ( box || (Y.Dom.getStyle(el, 'position') == 'absolute' && pos) ) {
125
                val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
126
            } else { // default to zero for other 'auto'
127
                val = 0;
128
            }
129
        } else if (attr in el) {
130
            val = el[attr];
131
        }
132
133
        return val;
134
    },
135
    
136
    /**
137
     * Returns the unit to use when none is supplied.
138
     * @method getDefaultUnit
139
     * @param {attr} attr The name of the attribute.
140
     * @return {String} The default unit to be used.
141
     */
142
    getDefaultUnit: function(attr) {
143
         if ( this.patterns.defaultUnit.test(attr) ) {
144
            return 'px';
145
         }
146
         
147
         return '';
148
    },
149
        
150
    /**
151
     * Sets the actual values to be used during the animation.  Should only be needed for subclass use.
152
     * @method setRuntimeAttribute
153
     * @param {Object} attr The attribute object
154
     * @private 
155
     */
156
    setRuntimeAttribute: function(attr) {
157
        var start;
158
        var end;
159
        var attributes = this.attributes;
160
161
        this.runtimeAttributes[attr] = {};
162
        
163
        var isset = function(prop) {
164
            return (typeof prop !== 'undefined');
165
        };
166
        
167
        if ( !isset(attributes[attr]['to']) && !isset(attributes[attr]['by']) ) {
168
            return false; // note return; nothing to animate to
169
        }
170
        
171
        start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
172
173
        // To beats by, per SMIL 2.1 spec
174
        if ( isset(attributes[attr]['to']) ) {
175
            end = attributes[attr]['to'];
176
        } else if ( isset(attributes[attr]['by']) ) {
177
            if (start.constructor == Array) {
178
                end = [];
179
                for (var i = 0, len = start.length; i < len; ++i) {
180
                    end[i] = start[i] + attributes[attr]['by'][i] * 1; // times 1 to cast "by" 
181
                }
182
            } else {
183
                end = start + attributes[attr]['by'] * 1;
184
            }
185
        }
186
        
187
        this.runtimeAttributes[attr].start = start;
188
        this.runtimeAttributes[attr].end = end;
189
190
        // set units if needed
191
        this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ?
192
                attributes[attr]['unit'] : this.getDefaultUnit(attr);
193
        return true;
194
    },
195
196
    /**
197
     * Constructor for Anim instance.
198
     * @method init
199
     * @param {String | HTMLElement} el Reference to the element that will be animated
200
     * @param {Object} attributes The attribute(s) to be animated.  
201
     * Each attribute is an object with at minimum a "to" or "by" member defined.  
202
     * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").  
203
     * All attribute names use camelCase.
204
     * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
205
     * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
206
     */ 
207
    init: function(el, attributes, duration, method) {
208
        /**
209
         * Whether or not the animation is running.
210
         * @property isAnimated
211
         * @private
212
         * @type Boolean
213
         */
214
        var isAnimated = false;
215
        
216
        /**
217
         * A Date object that is created when the animation begins.
218
         * @property startTime
219
         * @private
220
         * @type Date
221
         */
222
        var startTime = null;
223
        
224
        /**
225
         * The number of frames this animation was able to execute.
226
         * @property actualFrames
227
         * @private
228
         * @type Int
229
         */
230
        var actualFrames = 0; 
231
232
        /**
233
         * The element to be animated.
234
         * @property el
235
         * @private
236
         * @type HTMLElement
237
         */
238
        el = Y.Dom.get(el);
239
        
240
        /**
241
         * The collection of attributes to be animated.  
242
         * Each attribute must have at least a "to" or "by" defined in order to animate.  
243
         * If "to" is supplied, the animation will end with the attribute at that value.  
244
         * If "by" is supplied, the animation will end at that value plus its starting value. 
245
         * If both are supplied, "to" is used, and "by" is ignored. 
246
         * Optional additional member include "from" (the value the attribute should start animating from, defaults to current value), and "unit" (the units to apply to the values).
247
         * @property attributes
248
         * @type Object
249
         */
250
        this.attributes = attributes || {};
251
        
252
        /**
253
         * The length of the animation.  Defaults to "1" (second).
254
         * @property duration
255
         * @type Number
256
         */
257
        this.duration = !YAHOO.lang.isUndefined(duration) ? duration : 1;
258
        
259
        /**
260
         * The method that will provide values to the attribute(s) during the animation. 
261
         * Defaults to "YAHOO.util.Easing.easeNone".
262
         * @property method
263
         * @type Function
264
         */
265
        this.method = method || Y.Easing.easeNone;
266
267
        /**
268
         * Whether or not the duration should be treated as seconds.
269
         * Defaults to true.
270
         * @property useSeconds
271
         * @type Boolean
272
         */
273
        this.useSeconds = true; // default to seconds
274
        
275
        /**
276
         * The location of the current animation on the timeline.
277
         * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
278
         * @property currentFrame
279
         * @type Int
280
         */
281
        this.currentFrame = 0;
282
        
283
        /**
284
         * The total number of frames to be executed.
285
         * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
286
         * @property totalFrames
287
         * @type Int
288
         */
289
        this.totalFrames = Y.AnimMgr.fps;
290
        
291
        /**
292
         * Changes the animated element
293
         * @method setEl
294
         */
295
        this.setEl = function(element) {
296
            el = Y.Dom.get(element);
297
        };
298
        
299
        /**
300
         * Returns a reference to the animated element.
301
         * @method getEl
302
         * @return {HTMLElement}
303
         */
304
        this.getEl = function() { return el; };
305
        
306
        /**
307
         * Checks whether the element is currently animated.
308
         * @method isAnimated
309
         * @return {Boolean} current value of isAnimated.     
310
         */
311
        this.isAnimated = function() {
312
            return isAnimated;
313
        };
314
        
315
        /**
316
         * Returns the animation start time.
317
         * @method getStartTime
318
         * @return {Date} current value of startTime.      
319
         */
320
        this.getStartTime = function() {
321
            return startTime;
322
        };        
323
        
324
        this.runtimeAttributes = {};
325
        
326
        var logger = {};
327
        logger.log = function() {YAHOO.log.apply(window, arguments)};
328
        
329
        logger.log('creating new instance of ' + this);
330
        
331
        /**
332
         * Starts the animation by registering it with the animation manager. 
333
         * @method animate  
334
         */
335
        this.animate = function() {
336
            if ( this.isAnimated() ) {
337
                return false;
338
            }
339
            
340
            this.currentFrame = 0;
341
            
342
            this.totalFrames = ( this.useSeconds ) ? Math.ceil(Y.AnimMgr.fps * this.duration) : this.duration;
343
    
344
            if (this.duration === 0 && this.useSeconds) { // jump to last frame if zero second duration 
345
                this.totalFrames = 1; 
346
            }
347
            Y.AnimMgr.registerElement(this);
348
            return true;
349
        };
350
          
351
        /**
352
         * Stops the animation.  Normally called by AnimMgr when animation completes.
353
         * @method stop
354
         * @param {Boolean} finish (optional) If true, animation will jump to final frame.
355
         */ 
356
        this.stop = function(finish) {
357
            if (!this.isAnimated()) { // nothing to stop
358
                return false;
359
            }
360
361
            if (finish) {
362
                 this.currentFrame = this.totalFrames;
363
                 this._onTween.fire();
364
            }
365
            Y.AnimMgr.stop(this);
366
        };
367
        
368
        var onStart = function() {            
369
            this.onStart.fire();
370
            
371
            this.runtimeAttributes = {};
372
            for (var attr in this.attributes) {
373
                this.setRuntimeAttribute(attr);
374
            }
375
            
376
            isAnimated = true;
377
            actualFrames = 0;
378
            startTime = new Date(); 
379
        };
380
        
381
        /**
382
         * Feeds the starting and ending values for each animated attribute to doMethod once per frame, then applies the resulting value to the attribute(s).
383
         * @private
384
         */
385
         
386
        var onTween = function() {
387
            var data = {
388
                duration: new Date() - this.getStartTime(),
389
                currentFrame: this.currentFrame
390
            };
391
            
392
            data.toString = function() {
393
                return (
394
                    'duration: ' + data.duration +
395
                    ', currentFrame: ' + data.currentFrame
396
                );
397
            };
398
            
399
            this.onTween.fire(data);
400
            
401
            var runtimeAttributes = this.runtimeAttributes;
402
            
403
            for (var attr in runtimeAttributes) {
404
                this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit); 
405
            }
406
            
407
            actualFrames += 1;
408
        };
409
        
410
        var onComplete = function() {
411
            var actual_duration = (new Date() - startTime) / 1000 ;
412
            
413
            var data = {
414
                duration: actual_duration,
415
                frames: actualFrames,
416
                fps: actualFrames / actual_duration
417
            };
418
            
419
            data.toString = function() {
420
                return (
421
                    'duration: ' + data.duration +
422
                    ', frames: ' + data.frames +
423
                    ', fps: ' + data.fps
424
                );
425
            };
426
            
427
            isAnimated = false;
428
            actualFrames = 0;
429
            this.onComplete.fire(data);
430
        };
431
        
432
        /**
433
         * Custom event that fires after onStart, useful in subclassing
434
         * @private
435
         */    
436
        this._onStart = new Y.CustomEvent('_start', this, true);
437
438
        /**
439
         * Custom event that fires when animation begins
440
         * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction)
441
         * @event onStart
442
         */    
443
        this.onStart = new Y.CustomEvent('start', this);
444
        
445
        /**
446
         * Custom event that fires between each frame
447
         * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction)
448
         * @event onTween
449
         */
450
        this.onTween = new Y.CustomEvent('tween', this);
451
        
452
        /**
453
         * Custom event that fires after onTween
454
         * @private
455
         */
456
        this._onTween = new Y.CustomEvent('_tween', this, true);
457
        
458
        /**
459
         * Custom event that fires when animation ends
460
         * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction)
461
         * @event onComplete
462
         */
463
        this.onComplete = new Y.CustomEvent('complete', this);
464
        /**
465
         * Custom event that fires after onComplete
466
         * @private
467
         */
468
        this._onComplete = new Y.CustomEvent('_complete', this, true);
469
470
        this._onStart.subscribe(onStart);
471
        this._onTween.subscribe(onTween);
472
        this._onComplete.subscribe(onComplete);
473
    }
474
};
475
476
    Y.Anim = Anim;
477
})();
478
/**
479
 * Handles animation queueing and threading.
480
 * Used by Anim and subclasses.
481
 * @class AnimMgr
482
 * @namespace YAHOO.util
483
 */
484
YAHOO.util.AnimMgr = new function() {
485
    /** 
486
     * Reference to the animation Interval.
487
     * @property thread
488
     * @private
489
     * @type Int
490
     */
491
    var thread = null;
492
    
493
    /** 
494
     * The current queue of registered animation objects.
495
     * @property queue
496
     * @private
497
     * @type Array
498
     */    
499
    var queue = [];
500
501
    /** 
502
     * The number of active animations.
503
     * @property tweenCount
504
     * @private
505
     * @type Int
506
     */        
507
    var tweenCount = 0;
508
509
    /** 
510
     * Base frame rate (frames per second). 
511
     * Arbitrarily high for better x-browser calibration (slower browsers drop more frames).
512
     * @property fps
513
     * @type Int
514
     * 
515
     */
516
    this.fps = 1000;
517
518
    /** 
519
     * Interval delay in milliseconds, defaults to fastest possible.
520
     * @property delay
521
     * @type Int
522
     * 
523
     */
524
    this.delay = 1;
525
526
    /**
527
     * Adds an animation instance to the animation queue.
528
     * All animation instances must be registered in order to animate.
529
     * @method registerElement
530
     * @param {object} tween The Anim instance to be be registered
531
     */
532
    this.registerElement = function(tween) {
533
        queue[queue.length] = tween;
534
        tweenCount += 1;
535
        tween._onStart.fire();
536
        this.start();
537
    };
538
    
539
    /**
540
     * removes an animation instance from the animation queue.
541
     * All animation instances must be registered in order to animate.
542
     * @method unRegister
543
     * @param {object} tween The Anim instance to be be registered
544
     * @param {Int} index The index of the Anim instance
545
     * @private
546
     */
547
    this.unRegister = function(tween, index) {
548
        index = index || getIndex(tween);
549
        if (!tween.isAnimated() || index === -1) {
550
            return false;
551
        }
552
        
553
        tween._onComplete.fire();
554
        queue.splice(index, 1);
555
556
        tweenCount -= 1;
557
        if (tweenCount <= 0) {
558
            this.stop();
559
        }
560
561
        return true;
562
    };
563
    
564
    /**
565
     * Starts the animation thread.
566
	* Only one thread can run at a time.
567
     * @method start
568
     */    
569
    this.start = function() {
570
        if (thread === null) {
571
            thread = setInterval(this.run, this.delay);
572
        }
573
    };
574
575
    /**
576
     * Stops the animation thread or a specific animation instance.
577
     * @method stop
578
     * @param {object} tween A specific Anim instance to stop (optional)
579
     * If no instance given, Manager stops thread and all animations.
580
     */    
581
    this.stop = function(tween) {
582
        if (!tween) {
583
            clearInterval(thread);
584
            
585
            for (var i = 0, len = queue.length; i < len; ++i) {
586
                this.unRegister(queue[0], 0);  
587
            }
588
589
            queue = [];
590
            thread = null;
591
            tweenCount = 0;
592
        }
593
        else {
594
            this.unRegister(tween);
595
        }
596
    };
597
    
598
    /**
599
     * Called per Interval to handle each animation frame.
600
     * @method run
601
     */    
602
    this.run = function() {
603
        for (var i = 0, len = queue.length; i < len; ++i) {
604
            var tween = queue[i];
605
            if ( !tween || !tween.isAnimated() ) { continue; }
606
607
            if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
608
            {
609
                tween.currentFrame += 1;
610
                
611
                if (tween.useSeconds) {
612
                    correctFrame(tween);
613
                }
614
                tween._onTween.fire();          
615
            }
616
            else { YAHOO.util.AnimMgr.stop(tween, i); }
617
        }
618
    };
619
    
620
    var getIndex = function(anim) {
621
        for (var i = 0, len = queue.length; i < len; ++i) {
622
            if (queue[i] === anim) {
623
                return i; // note return;
624
            }
625
        }
626
        return -1;
627
    };
628
    
629
    /**
630
     * On the fly frame correction to keep animation on time.
631
     * @method correctFrame
632
     * @private
633
     * @param {Object} tween The Anim instance being corrected.
634
     */
635
    var correctFrame = function(tween) {
636
        var frames = tween.totalFrames;
637
        var frame = tween.currentFrame;
638
        var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
639
        var elapsed = (new Date() - tween.getStartTime());
640
        var tweak = 0;
641
        
642
        if (elapsed < tween.duration * 1000) { // check if falling behind
643
            tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
644
        } else { // went over duration, so jump to end
645
            tweak = frames - (frame + 1); 
646
        }
647
        if (tweak > 0 && isFinite(tweak)) { // adjust if needed
648
            if (tween.currentFrame + tweak >= frames) {// dont go past last frame
649
                tweak = frames - (frame + 1);
650
            }
651
            
652
            tween.currentFrame += tweak;      
653
        }
654
    };
655
    this._queue = queue;
656
    this._getIndex = getIndex;
657
};
658
/**
659
 * Used to calculate Bezier splines for any number of control points.
660
 * @class Bezier
661
 * @namespace YAHOO.util
662
 *
663
 */
664
YAHOO.util.Bezier = new function() {
665
    /**
666
     * Get the current position of the animated element based on t.
667
     * Each point is an array of "x" and "y" values (0 = x, 1 = y)
668
     * At least 2 points are required (start and end).
669
     * First point is start. Last point is end.
670
     * Additional control points are optional.     
671
     * @method getPosition
672
     * @param {Array} points An array containing Bezier points
673
     * @param {Number} t A number between 0 and 1 which is the basis for determining current position
674
     * @return {Array} An array containing int x and y member data
675
     */
676
    this.getPosition = function(points, t) {  
677
        var n = points.length;
678
        var tmp = [];
679
680
        for (var i = 0; i < n; ++i){
681
            tmp[i] = [points[i][0], points[i][1]]; // save input
682
        }
683
        
684
        for (var j = 1; j < n; ++j) {
685
            for (i = 0; i < n - j; ++i) {
686
                tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
687
                tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1]; 
688
            }
689
        }
690
    
691
        return [ tmp[0][0], tmp[0][1] ]; 
692
    
693
    };
694
};
695
(function() {
696
/**
697
 * Anim subclass for color transitions.
698
 * <p>Usage: <code>var myAnim = new Y.ColorAnim(el, { backgroundColor: { from: '#FF0000', to: '#FFFFFF' } }, 1, Y.Easing.easeOut);</code> Color values can be specified with either 112233, #112233, 
699
 * [255,255,255], or rgb(255,255,255)</p>
700
 * @class ColorAnim
701
 * @namespace YAHOO.util
702
 * @requires YAHOO.util.Anim
703
 * @requires YAHOO.util.AnimMgr
704
 * @requires YAHOO.util.Easing
705
 * @requires YAHOO.util.Bezier
706
 * @requires YAHOO.util.Dom
707
 * @requires YAHOO.util.Event
708
 * @constructor
709
 * @extends YAHOO.util.Anim
710
 * @param {HTMLElement | String} el Reference to the element that will be animated
711
 * @param {Object} attributes The attribute(s) to be animated.
712
 * Each attribute is an object with at minimum a "to" or "by" member defined.
713
 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
714
 * All attribute names use camelCase.
715
 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
716
 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
717
 */
718
    var ColorAnim = function(el, attributes, duration,  method) {
719
        ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
720
    };
721
    
722
    ColorAnim.NAME = 'ColorAnim';
723
724
    ColorAnim.DEFAULT_BGCOLOR = '#fff';
725
    // shorthand
726
    var Y = YAHOO.util;
727
    YAHOO.extend(ColorAnim, Y.Anim);
728
729
    var superclass = ColorAnim.superclass;
730
    var proto = ColorAnim.prototype;
731
    
732
    proto.patterns.color = /color$/i;
733
    proto.patterns.rgb            = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
734
    proto.patterns.hex            = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
735
    proto.patterns.hex3          = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
736
    proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/; // need rgba for safari
737
    
738
    /**
739
     * Attempts to parse the given string and return a 3-tuple.
740
     * @method parseColor
741
     * @param {String} s The string to parse.
742
     * @return {Array} The 3-tuple of rgb values.
743
     */
744
    proto.parseColor = function(s) {
745
        if (s.length == 3) { return s; }
746
    
747
        var c = this.patterns.hex.exec(s);
748
        if (c && c.length == 4) {
749
            return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
750
        }
751
    
752
        c = this.patterns.rgb.exec(s);
753
        if (c && c.length == 4) {
754
            return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
755
        }
756
    
757
        c = this.patterns.hex3.exec(s);
758
        if (c && c.length == 4) {
759
            return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
760
        }
761
        
762
        return null;
763
    };
764
765
    proto.getAttribute = function(attr) {
766
        var el = this.getEl();
767
        if (this.patterns.color.test(attr) ) {
768
            var val = YAHOO.util.Dom.getStyle(el, attr);
769
            
770
            var that = this;
771
            if (this.patterns.transparent.test(val)) { // bgcolor default
772
                var parent = YAHOO.util.Dom.getAncestorBy(el, function(node) {
773
                    return !that.patterns.transparent.test(val);
774
                });
775
776
                if (parent) {
777
                    val = Y.Dom.getStyle(parent, attr);
778
                } else {
779
                    val = ColorAnim.DEFAULT_BGCOLOR;
780
                }
781
            }
782
        } else {
783
            val = superclass.getAttribute.call(this, attr);
784
        }
785
786
        return val;
787
    };
788
    
789
    proto.doMethod = function(attr, start, end) {
790
        var val;
791
    
792
        if ( this.patterns.color.test(attr) ) {
793
            val = [];
794
            for (var i = 0, len = start.length; i < len; ++i) {
795
                val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
796
            }
797
            
798
            val = 'rgb('+Math.floor(val[0])+','+Math.floor(val[1])+','+Math.floor(val[2])+')';
799
        }
800
        else {
801
            val = superclass.doMethod.call(this, attr, start, end);
802
        }
803
804
        return val;
805
    };
806
807
    proto.setRuntimeAttribute = function(attr) {
808
        superclass.setRuntimeAttribute.call(this, attr);
809
        
810
        if ( this.patterns.color.test(attr) ) {
811
            var attributes = this.attributes;
812
            var start = this.parseColor(this.runtimeAttributes[attr].start);
813
            var end = this.parseColor(this.runtimeAttributes[attr].end);
814
            // fix colors if going "by"
815
            if ( typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined' ) {
816
                end = this.parseColor(attributes[attr].by);
817
            
818
                for (var i = 0, len = start.length; i < len; ++i) {
819
                    end[i] = start[i] + end[i];
820
                }
821
            }
822
            
823
            this.runtimeAttributes[attr].start = start;
824
            this.runtimeAttributes[attr].end = end;
825
        }
826
    };
827
828
    Y.ColorAnim = ColorAnim;
829
})();
830
/*!
831
TERMS OF USE - EASING EQUATIONS
832
Open source under the BSD License.
833
Copyright 2001 Robert Penner All rights reserved.
834
835
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
836
837
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
838
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
839
 * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
840
841
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
842
*/
843
844
/**
845
 * Singleton that determines how an animation proceeds from start to end.
846
 * @class Easing
847
 * @namespace YAHOO.util
848
*/
849
850
YAHOO.util.Easing = {
851
852
    /**
853
     * Uniform speed between points.
854
     * @method easeNone
855
     * @param {Number} t Time value used to compute current value
856
     * @param {Number} b Starting value
857
     * @param {Number} c Delta between start and end values
858
     * @param {Number} d Total length of animation
859
     * @return {Number} The computed value for the current animation frame
860
     */
861
    easeNone: function (t, b, c, d) {
862
    	return c*t/d + b;
863
    },
864
    
865
    /**
866
     * Begins slowly and accelerates towards end.
867
     * @method easeIn
868
     * @param {Number} t Time value used to compute current value
869
     * @param {Number} b Starting value
870
     * @param {Number} c Delta between start and end values
871
     * @param {Number} d Total length of animation
872
     * @return {Number} The computed value for the current animation frame
873
     */
874
    easeIn: function (t, b, c, d) {
875
    	return c*(t/=d)*t + b;
876
    },
877
878
    /**
879
     * Begins quickly and decelerates towards end.
880
     * @method easeOut
881
     * @param {Number} t Time value used to compute current value
882
     * @param {Number} b Starting value
883
     * @param {Number} c Delta between start and end values
884
     * @param {Number} d Total length of animation
885
     * @return {Number} The computed value for the current animation frame
886
     */
887
    easeOut: function (t, b, c, d) {
888
    	return -c *(t/=d)*(t-2) + b;
889
    },
890
    
891
    /**
892
     * Begins slowly and decelerates towards end.
893
     * @method easeBoth
894
     * @param {Number} t Time value used to compute current value
895
     * @param {Number} b Starting value
896
     * @param {Number} c Delta between start and end values
897
     * @param {Number} d Total length of animation
898
     * @return {Number} The computed value for the current animation frame
899
     */
900
    easeBoth: function (t, b, c, d) {
901
    	if ((t/=d/2) < 1) {
902
            return c/2*t*t + b;
903
        }
904
        
905
    	return -c/2 * ((--t)*(t-2) - 1) + b;
906
    },
907
    
908
    /**
909
     * Begins slowly and accelerates towards end.
910
     * @method easeInStrong
911
     * @param {Number} t Time value used to compute current value
912
     * @param {Number} b Starting value
913
     * @param {Number} c Delta between start and end values
914
     * @param {Number} d Total length of animation
915
     * @return {Number} The computed value for the current animation frame
916
     */
917
    easeInStrong: function (t, b, c, d) {
918
    	return c*(t/=d)*t*t*t + b;
919
    },
920
    
921
    /**
922
     * Begins quickly and decelerates towards end.
923
     * @method easeOutStrong
924
     * @param {Number} t Time value used to compute current value
925
     * @param {Number} b Starting value
926
     * @param {Number} c Delta between start and end values
927
     * @param {Number} d Total length of animation
928
     * @return {Number} The computed value for the current animation frame
929
     */
930
    easeOutStrong: function (t, b, c, d) {
931
    	return -c * ((t=t/d-1)*t*t*t - 1) + b;
932
    },
933
    
934
    /**
935
     * Begins slowly and decelerates towards end.
936
     * @method easeBothStrong
937
     * @param {Number} t Time value used to compute current value
938
     * @param {Number} b Starting value
939
     * @param {Number} c Delta between start and end values
940
     * @param {Number} d Total length of animation
941
     * @return {Number} The computed value for the current animation frame
942
     */
943
    easeBothStrong: function (t, b, c, d) {
944
    	if ((t/=d/2) < 1) {
945
            return c/2*t*t*t*t + b;
946
        }
947
        
948
    	return -c/2 * ((t-=2)*t*t*t - 2) + b;
949
    },
950
951
    /**
952
     * Snap in elastic effect.
953
     * @method elasticIn
954
     * @param {Number} t Time value used to compute current value
955
     * @param {Number} b Starting value
956
     * @param {Number} c Delta between start and end values
957
     * @param {Number} d Total length of animation
958
     * @param {Number} a Amplitude (optional)
959
     * @param {Number} p Period (optional)
960
     * @return {Number} The computed value for the current animation frame
961
     */
962
963
    elasticIn: function (t, b, c, d, a, p) {
964
    	if (t == 0) {
965
            return b;
966
        }
967
        if ( (t /= d) == 1 ) {
968
            return b+c;
969
        }
970
        if (!p) {
971
            p=d*.3;
972
        }
973
        
974
    	if (!a || a < Math.abs(c)) {
975
            a = c; 
976
            var s = p/4;
977
        }
978
    	else {
979
            var s = p/(2*Math.PI) * Math.asin (c/a);
980
        }
981
        
982
    	return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
983
    },
984
985
    /**
986
     * Snap out elastic effect.
987
     * @method elasticOut
988
     * @param {Number} t Time value used to compute current value
989
     * @param {Number} b Starting value
990
     * @param {Number} c Delta between start and end values
991
     * @param {Number} d Total length of animation
992
     * @param {Number} a Amplitude (optional)
993
     * @param {Number} p Period (optional)
994
     * @return {Number} The computed value for the current animation frame
995
     */
996
    elasticOut: function (t, b, c, d, a, p) {
997
    	if (t == 0) {
998
            return b;
999
        }
1000
        if ( (t /= d) == 1 ) {
1001
            return b+c;
1002
        }
1003
        if (!p) {
1004
            p=d*.3;
1005
        }
1006
        
1007
    	if (!a || a < Math.abs(c)) {
1008
            a = c;
1009
            var s = p / 4;
1010
        }
1011
    	else {
1012
            var s = p/(2*Math.PI) * Math.asin (c/a);
1013
        }
1014
        
1015
    	return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
1016
    },
1017
    
1018
    /**
1019
     * Snap both elastic effect.
1020
     * @method elasticBoth
1021
     * @param {Number} t Time value used to compute current value
1022
     * @param {Number} b Starting value
1023
     * @param {Number} c Delta between start and end values
1024
     * @param {Number} d Total length of animation
1025
     * @param {Number} a Amplitude (optional)
1026
     * @param {Number} p Period (optional)
1027
     * @return {Number} The computed value for the current animation frame
1028
     */
1029
    elasticBoth: function (t, b, c, d, a, p) {
1030
    	if (t == 0) {
1031
            return b;
1032
        }
1033
        
1034
        if ( (t /= d/2) == 2 ) {
1035
            return b+c;
1036
        }
1037
        
1038
        if (!p) {
1039
            p = d*(.3*1.5);
1040
        }
1041
        
1042
    	if ( !a || a < Math.abs(c) ) {
1043
            a = c; 
1044
            var s = p/4;
1045
        }
1046
    	else {
1047
            var s = p/(2*Math.PI) * Math.asin (c/a);
1048
        }
1049
        
1050
    	if (t < 1) {
1051
            return -.5*(a*Math.pow(2,10*(t-=1)) * 
1052
                    Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
1053
        }
1054
    	return a*Math.pow(2,-10*(t-=1)) * 
1055
                Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
1056
    },
1057
1058
1059
    /**
1060
     * Backtracks slightly, then reverses direction and moves to end.
1061
     * @method backIn
1062
     * @param {Number} t Time value used to compute current value
1063
     * @param {Number} b Starting value
1064
     * @param {Number} c Delta between start and end values
1065
     * @param {Number} d Total length of animation
1066
     * @param {Number} s Overshoot (optional)
1067
     * @return {Number} The computed value for the current animation frame
1068
     */
1069
    backIn: function (t, b, c, d, s) {
1070
    	if (typeof s == 'undefined') {
1071
            s = 1.70158;
1072
        }
1073
    	return c*(t/=d)*t*((s+1)*t - s) + b;
1074
    },
1075
1076
    /**
1077
     * Overshoots end, then reverses and comes back to end.
1078
     * @method backOut
1079
     * @param {Number} t Time value used to compute current value
1080
     * @param {Number} b Starting value
1081
     * @param {Number} c Delta between start and end values
1082
     * @param {Number} d Total length of animation
1083
     * @param {Number} s Overshoot (optional)
1084
     * @return {Number} The computed value for the current animation frame
1085
     */
1086
    backOut: function (t, b, c, d, s) {
1087
    	if (typeof s == 'undefined') {
1088
            s = 1.70158;
1089
        }
1090
    	return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
1091
    },
1092
    
1093
    /**
1094
     * Backtracks slightly, then reverses direction, overshoots end, 
1095
     * then reverses and comes back to end.
1096
     * @method backBoth
1097
     * @param {Number} t Time value used to compute current value
1098
     * @param {Number} b Starting value
1099
     * @param {Number} c Delta between start and end values
1100
     * @param {Number} d Total length of animation
1101
     * @param {Number} s Overshoot (optional)
1102
     * @return {Number} The computed value for the current animation frame
1103
     */
1104
    backBoth: function (t, b, c, d, s) {
1105
    	if (typeof s == 'undefined') {
1106
            s = 1.70158; 
1107
        }
1108
        
1109
    	if ((t /= d/2 ) < 1) {
1110
            return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
1111
        }
1112
    	return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
1113
    },
1114
1115
    /**
1116
     * Bounce off of start.
1117
     * @method bounceIn
1118
     * @param {Number} t Time value used to compute current value
1119
     * @param {Number} b Starting value
1120
     * @param {Number} c Delta between start and end values
1121
     * @param {Number} d Total length of animation
1122
     * @return {Number} The computed value for the current animation frame
1123
     */
1124
    bounceIn: function (t, b, c, d) {
1125
    	return c - YAHOO.util.Easing.bounceOut(d-t, 0, c, d) + b;
1126
    },
1127
    
1128
    /**
1129
     * Bounces off end.
1130
     * @method bounceOut
1131
     * @param {Number} t Time value used to compute current value
1132
     * @param {Number} b Starting value
1133
     * @param {Number} c Delta between start and end values
1134
     * @param {Number} d Total length of animation
1135
     * @return {Number} The computed value for the current animation frame
1136
     */
1137
    bounceOut: function (t, b, c, d) {
1138
    	if ((t/=d) < (1/2.75)) {
1139
    		return c*(7.5625*t*t) + b;
1140
    	} else if (t < (2/2.75)) {
1141
    		return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
1142
    	} else if (t < (2.5/2.75)) {
1143
    		return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
1144
    	}
1145
        return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
1146
    },
1147
    
1148
    /**
1149
     * Bounces off start and end.
1150
     * @method bounceBoth
1151
     * @param {Number} t Time value used to compute current value
1152
     * @param {Number} b Starting value
1153
     * @param {Number} c Delta between start and end values
1154
     * @param {Number} d Total length of animation
1155
     * @return {Number} The computed value for the current animation frame
1156
     */
1157
    bounceBoth: function (t, b, c, d) {
1158
    	if (t < d/2) {
1159
            return YAHOO.util.Easing.bounceIn(t*2, 0, c, d) * .5 + b;
1160
        }
1161
    	return YAHOO.util.Easing.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
1162
    }
1163
};
1164
1165
(function() {
1166
/**
1167
 * Anim subclass for moving elements along a path defined by the "points" 
1168
 * member of "attributes".  All "points" are arrays with x, y coordinates.
1169
 * <p>Usage: <code>var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1170
 * @class Motion
1171
 * @namespace YAHOO.util
1172
 * @requires YAHOO.util.Anim
1173
 * @requires YAHOO.util.AnimMgr
1174
 * @requires YAHOO.util.Easing
1175
 * @requires YAHOO.util.Bezier
1176
 * @requires YAHOO.util.Dom
1177
 * @requires YAHOO.util.Event
1178
 * @requires YAHOO.util.CustomEvent 
1179
 * @constructor
1180
 * @extends YAHOO.util.ColorAnim
1181
 * @param {String | HTMLElement} el Reference to the element that will be animated
1182
 * @param {Object} attributes The attribute(s) to be animated.  
1183
 * Each attribute is an object with at minimum a "to" or "by" member defined.  
1184
 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").  
1185
 * All attribute names use camelCase.
1186
 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1187
 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
1188
 */
1189
    var Motion = function(el, attributes, duration,  method) {
1190
        if (el) { // dont break existing subclasses not using YAHOO.extend
1191
            Motion.superclass.constructor.call(this, el, attributes, duration, method);
1192
        }
1193
    };
1194
1195
1196
    Motion.NAME = 'Motion';
1197
1198
    // shorthand
1199
    var Y = YAHOO.util;
1200
    YAHOO.extend(Motion, Y.ColorAnim);
1201
    
1202
    var superclass = Motion.superclass;
1203
    var proto = Motion.prototype;
1204
1205
    proto.patterns.points = /^points$/i;
1206
    
1207
    proto.setAttribute = function(attr, val, unit) {
1208
        if (  this.patterns.points.test(attr) ) {
1209
            unit = unit || 'px';
1210
            superclass.setAttribute.call(this, 'left', val[0], unit);
1211
            superclass.setAttribute.call(this, 'top', val[1], unit);
1212
        } else {
1213
            superclass.setAttribute.call(this, attr, val, unit);
1214
        }
1215
    };
1216
1217
    proto.getAttribute = function(attr) {
1218
        if (  this.patterns.points.test(attr) ) {
1219
            var val = [
1220
                superclass.getAttribute.call(this, 'left'),
1221
                superclass.getAttribute.call(this, 'top')
1222
            ];
1223
        } else {
1224
            val = superclass.getAttribute.call(this, attr);
1225
        }
1226
1227
        return val;
1228
    };
1229
1230
    proto.doMethod = function(attr, start, end) {
1231
        var val = null;
1232
1233
        if ( this.patterns.points.test(attr) ) {
1234
            var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;				
1235
            val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
1236
        } else {
1237
            val = superclass.doMethod.call(this, attr, start, end);
1238
        }
1239
        return val;
1240
    };
1241
1242
    proto.setRuntimeAttribute = function(attr) {
1243
        if ( this.patterns.points.test(attr) ) {
1244
            var el = this.getEl();
1245
            var attributes = this.attributes;
1246
            var start;
1247
            var control = attributes['points']['control'] || [];
1248
            var end;
1249
            var i, len;
1250
            
1251
            if (control.length > 0 && !(control[0] instanceof Array) ) { // could be single point or array of points
1252
                control = [control];
1253
            } else { // break reference to attributes.points.control
1254
                var tmp = []; 
1255
                for (i = 0, len = control.length; i< len; ++i) {
1256
                    tmp[i] = control[i];
1257
                }
1258
                control = tmp;
1259
            }
1260
1261
            if (Y.Dom.getStyle(el, 'position') == 'static') { // default to relative
1262
                Y.Dom.setStyle(el, 'position', 'relative');
1263
            }
1264
    
1265
            if ( isset(attributes['points']['from']) ) {
1266
                Y.Dom.setXY(el, attributes['points']['from']); // set position to from point
1267
            } 
1268
            else { Y.Dom.setXY( el, Y.Dom.getXY(el) ); } // set it to current position
1269
            
1270
            start = this.getAttribute('points'); // get actual top & left
1271
            
1272
            // TO beats BY, per SMIL 2.1 spec
1273
            if ( isset(attributes['points']['to']) ) {
1274
                end = translateValues.call(this, attributes['points']['to'], start);
1275
                
1276
                var pageXY = Y.Dom.getXY(this.getEl());
1277
                for (i = 0, len = control.length; i < len; ++i) {
1278
                    control[i] = translateValues.call(this, control[i], start);
1279
                }
1280
1281
                
1282
            } else if ( isset(attributes['points']['by']) ) {
1283
                end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
1284
                
1285
                for (i = 0, len = control.length; i < len; ++i) {
1286
                    control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
1287
                }
1288
            }
1289
1290
            this.runtimeAttributes[attr] = [start];
1291
            
1292
            if (control.length > 0) {
1293
                this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control); 
1294
            }
1295
1296
            this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
1297
        }
1298
        else {
1299
            superclass.setRuntimeAttribute.call(this, attr);
1300
        }
1301
    };
1302
    
1303
    var translateValues = function(val, start) {
1304
        var pageXY = Y.Dom.getXY(this.getEl());
1305
        val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
1306
1307
        return val; 
1308
    };
1309
    
1310
    var isset = function(prop) {
1311
        return (typeof prop !== 'undefined');
1312
    };
1313
1314
    Y.Motion = Motion;
1315
})();
1316
(function() {
1317
/**
1318
 * Anim subclass for scrolling elements to a position defined by the "scroll"
1319
 * member of "attributes".  All "scroll" members are arrays with x, y scroll positions.
1320
 * <p>Usage: <code>var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1321
 * @class Scroll
1322
 * @namespace YAHOO.util
1323
 * @requires YAHOO.util.Anim
1324
 * @requires YAHOO.util.AnimMgr
1325
 * @requires YAHOO.util.Easing
1326
 * @requires YAHOO.util.Bezier
1327
 * @requires YAHOO.util.Dom
1328
 * @requires YAHOO.util.Event
1329
 * @requires YAHOO.util.CustomEvent 
1330
 * @extends YAHOO.util.ColorAnim
1331
 * @constructor
1332
 * @param {String or HTMLElement} el Reference to the element that will be animated
1333
 * @param {Object} attributes The attribute(s) to be animated.  
1334
 * Each attribute is an object with at minimum a "to" or "by" member defined.  
1335
 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").  
1336
 * All attribute names use camelCase.
1337
 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1338
 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
1339
 */
1340
    var Scroll = function(el, attributes, duration,  method) {
1341
        if (el) { // dont break existing subclasses not using YAHOO.extend
1342
            Scroll.superclass.constructor.call(this, el, attributes, duration, method);
1343
        }
1344
    };
1345
1346
    Scroll.NAME = 'Scroll';
1347
1348
    // shorthand
1349
    var Y = YAHOO.util;
1350
    YAHOO.extend(Scroll, Y.ColorAnim);
1351
    
1352
    var superclass = Scroll.superclass;
1353
    var proto = Scroll.prototype;
1354
1355
    proto.doMethod = function(attr, start, end) {
1356
        var val = null;
1357
    
1358
        if (attr == 'scroll') {
1359
            val = [
1360
                this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
1361
                this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
1362
            ];
1363
            
1364
        } else {
1365
            val = superclass.doMethod.call(this, attr, start, end);
1366
        }
1367
        return val;
1368
    };
1369
1370
    proto.getAttribute = function(attr) {
1371
        var val = null;
1372
        var el = this.getEl();
1373
        
1374
        if (attr == 'scroll') {
1375
            val = [ el.scrollLeft, el.scrollTop ];
1376
        } else {
1377
            val = superclass.getAttribute.call(this, attr);
1378
        }
1379
        
1380
        return val;
1381
    };
1382
1383
    proto.setAttribute = function(attr, val, unit) {
1384
        var el = this.getEl();
1385
        
1386
        if (attr == 'scroll') {
1387
            el.scrollLeft = val[0];
1388
            el.scrollTop = val[1];
1389
        } else {
1390
            superclass.setAttribute.call(this, attr, val, unit);
1391
        }
1392
    };
1393
1394
    Y.Scroll = Scroll;
1395
})();
1396
YAHOO.register("animation", YAHOO.util.Anim, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/animation/animation-min.js (-23 lines)
Lines 1-23 Link Here
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.8.0r4
6
*/
7
(function(){var B=YAHOO.util;var A=function(D,C,E,F){if(!D){}this.init(D,C,E,F);};A.NAME="Anim";A.prototype={toString:function(){var C=this.getEl()||{};var D=C.id||C.tagName;return(this.constructor.NAME+": "+D);},patterns:{noNegatives:/width|height|opacity|padding/i,offsetAttribute:/^((width|height)|(top|left))$/,defaultUnit:/width|height|top$|bottom$|left$|right$/i,offsetUnit:/\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i},doMethod:function(C,E,D){return this.method(this.currentFrame,E,D-E,this.totalFrames);},setAttribute:function(C,F,E){var D=this.getEl();if(this.patterns.noNegatives.test(C)){F=(F>0)?F:0;}if(C in D&&!("style" in D&&C in D.style)){D[C]=F;}else{B.Dom.setStyle(D,C,F+E);}},getAttribute:function(C){var E=this.getEl();var G=B.Dom.getStyle(E,C);if(G!=="auto"&&!this.patterns.offsetUnit.test(G)){return parseFloat(G);}var D=this.patterns.offsetAttribute.exec(C)||[];var H=!!(D[3]);var F=!!(D[2]);if("style" in E){if(F||(B.Dom.getStyle(E,"position")=="absolute"&&H)){G=E["offset"+D[0].charAt(0).toUpperCase()+D[0].substr(1)];}else{G=0;}}else{if(C in E){G=E[C];}}return G;},getDefaultUnit:function(C){if(this.patterns.defaultUnit.test(C)){return"px";}return"";},setRuntimeAttribute:function(D){var I;var E;var F=this.attributes;this.runtimeAttributes[D]={};var H=function(J){return(typeof J!=="undefined");};if(!H(F[D]["to"])&&!H(F[D]["by"])){return false;}I=(H(F[D]["from"]))?F[D]["from"]:this.getAttribute(D);if(H(F[D]["to"])){E=F[D]["to"];}else{if(H(F[D]["by"])){if(I.constructor==Array){E=[];for(var G=0,C=I.length;G<C;++G){E[G]=I[G]+F[D]["by"][G]*1;}}else{E=I+F[D]["by"]*1;}}}this.runtimeAttributes[D].start=I;this.runtimeAttributes[D].end=E;this.runtimeAttributes[D].unit=(H(F[D].unit))?F[D]["unit"]:this.getDefaultUnit(D);return true;},init:function(E,J,I,C){var D=false;var F=null;var H=0;E=B.Dom.get(E);this.attributes=J||{};this.duration=!YAHOO.lang.isUndefined(I)?I:1;this.method=C||B.Easing.easeNone;this.useSeconds=true;this.currentFrame=0;this.totalFrames=B.AnimMgr.fps;this.setEl=function(M){E=B.Dom.get(M);};this.getEl=function(){return E;};this.isAnimated=function(){return D;};this.getStartTime=function(){return F;};this.runtimeAttributes={};this.animate=function(){if(this.isAnimated()){return false;}this.currentFrame=0;this.totalFrames=(this.useSeconds)?Math.ceil(B.AnimMgr.fps*this.duration):this.duration;if(this.duration===0&&this.useSeconds){this.totalFrames=1;}B.AnimMgr.registerElement(this);return true;};this.stop=function(M){if(!this.isAnimated()){return false;}if(M){this.currentFrame=this.totalFrames;this._onTween.fire();}B.AnimMgr.stop(this);};var L=function(){this.onStart.fire();this.runtimeAttributes={};for(var M in this.attributes){this.setRuntimeAttribute(M);}D=true;H=0;F=new Date();};var K=function(){var O={duration:new Date()-this.getStartTime(),currentFrame:this.currentFrame};O.toString=function(){return("duration: "+O.duration+", currentFrame: "+O.currentFrame);};this.onTween.fire(O);var N=this.runtimeAttributes;for(var M in N){this.setAttribute(M,this.doMethod(M,N[M].start,N[M].end),N[M].unit);}H+=1;};var G=function(){var M=(new Date()-F)/1000;var N={duration:M,frames:H,fps:H/M};N.toString=function(){return("duration: "+N.duration+", frames: "+N.frames+", fps: "+N.fps);};D=false;H=0;this.onComplete.fire(N);};this._onStart=new B.CustomEvent("_start",this,true);this.onStart=new B.CustomEvent("start",this);this.onTween=new B.CustomEvent("tween",this);this._onTween=new B.CustomEvent("_tween",this,true);this.onComplete=new B.CustomEvent("complete",this);this._onComplete=new B.CustomEvent("_complete",this,true);this._onStart.subscribe(L);this._onTween.subscribe(K);this._onComplete.subscribe(G);}};B.Anim=A;})();YAHOO.util.AnimMgr=new function(){var C=null;var B=[];var A=0;this.fps=1000;this.delay=1;this.registerElement=function(F){B[B.length]=F;A+=1;F._onStart.fire();this.start();};this.unRegister=function(G,F){F=F||E(G);if(!G.isAnimated()||F===-1){return false;}G._onComplete.fire();B.splice(F,1);A-=1;if(A<=0){this.stop();}return true;};this.start=function(){if(C===null){C=setInterval(this.run,this.delay);}};this.stop=function(H){if(!H){clearInterval(C);for(var G=0,F=B.length;G<F;++G){this.unRegister(B[0],0);}B=[];C=null;A=0;}else{this.unRegister(H);}};this.run=function(){for(var H=0,F=B.length;H<F;++H){var G=B[H];if(!G||!G.isAnimated()){continue;}if(G.currentFrame<G.totalFrames||G.totalFrames===null){G.currentFrame+=1;if(G.useSeconds){D(G);}G._onTween.fire();}else{YAHOO.util.AnimMgr.stop(G,H);}}};var E=function(H){for(var G=0,F=B.length;G<F;++G){if(B[G]===H){return G;}}return -1;};var D=function(G){var J=G.totalFrames;var I=G.currentFrame;var H=(G.currentFrame*G.duration*1000/G.totalFrames);var F=(new Date()-G.getStartTime());var K=0;if(F<G.duration*1000){K=Math.round((F/H-1)*G.currentFrame);}else{K=J-(I+1);}if(K>0&&isFinite(K)){if(G.currentFrame+K>=J){K=J-(I+1);}G.currentFrame+=K;}};this._queue=B;this._getIndex=E;};YAHOO.util.Bezier=new function(){this.getPosition=function(E,D){var F=E.length;var C=[];for(var B=0;B<F;++B){C[B]=[E[B][0],E[B][1]];}for(var A=1;A<F;++A){for(B=0;B<F-A;++B){C[B][0]=(1-D)*C[B][0]+D*C[parseInt(B+1,10)][0];C[B][1]=(1-D)*C[B][1]+D*C[parseInt(B+1,10)][1];}}return[C[0][0],C[0][1]];};};(function(){var A=function(F,E,G,H){A.superclass.constructor.call(this,F,E,G,H);};A.NAME="ColorAnim";A.DEFAULT_BGCOLOR="#fff";var C=YAHOO.util;YAHOO.extend(A,C.Anim);var D=A.superclass;var B=A.prototype;B.patterns.color=/color$/i;B.patterns.rgb=/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;B.patterns.hex=/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;B.patterns.hex3=/^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;B.patterns.transparent=/^transparent|rgba\(0, 0, 0, 0\)$/;B.parseColor=function(E){if(E.length==3){return E;}var F=this.patterns.hex.exec(E);if(F&&F.length==4){return[parseInt(F[1],16),parseInt(F[2],16),parseInt(F[3],16)];}F=this.patterns.rgb.exec(E);if(F&&F.length==4){return[parseInt(F[1],10),parseInt(F[2],10),parseInt(F[3],10)];}F=this.patterns.hex3.exec(E);if(F&&F.length==4){return[parseInt(F[1]+F[1],16),parseInt(F[2]+F[2],16),parseInt(F[3]+F[3],16)];
8
}return null;};B.getAttribute=function(E){var G=this.getEl();if(this.patterns.color.test(E)){var I=YAHOO.util.Dom.getStyle(G,E);var H=this;if(this.patterns.transparent.test(I)){var F=YAHOO.util.Dom.getAncestorBy(G,function(J){return !H.patterns.transparent.test(I);});if(F){I=C.Dom.getStyle(F,E);}else{I=A.DEFAULT_BGCOLOR;}}}else{I=D.getAttribute.call(this,E);}return I;};B.doMethod=function(F,J,G){var I;if(this.patterns.color.test(F)){I=[];for(var H=0,E=J.length;H<E;++H){I[H]=D.doMethod.call(this,F,J[H],G[H]);}I="rgb("+Math.floor(I[0])+","+Math.floor(I[1])+","+Math.floor(I[2])+")";}else{I=D.doMethod.call(this,F,J,G);}return I;};B.setRuntimeAttribute=function(F){D.setRuntimeAttribute.call(this,F);if(this.patterns.color.test(F)){var H=this.attributes;var J=this.parseColor(this.runtimeAttributes[F].start);var G=this.parseColor(this.runtimeAttributes[F].end);if(typeof H[F]["to"]==="undefined"&&typeof H[F]["by"]!=="undefined"){G=this.parseColor(H[F].by);for(var I=0,E=J.length;I<E;++I){G[I]=J[I]+G[I];}}this.runtimeAttributes[F].start=J;this.runtimeAttributes[F].end=G;}};C.ColorAnim=A;})();
9
/*
10
TERMS OF USE - EASING EQUATIONS
11
Open source under the BSD License.
12
Copyright 2001 Robert Penner All rights reserved.
13
14
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
15
16
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
17
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
18
 * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
19
20
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21
*/
22
YAHOO.util.Easing={easeNone:function(B,A,D,C){return D*B/C+A;},easeIn:function(B,A,D,C){return D*(B/=C)*B+A;},easeOut:function(B,A,D,C){return -D*(B/=C)*(B-2)+A;},easeBoth:function(B,A,D,C){if((B/=C/2)<1){return D/2*B*B+A;}return -D/2*((--B)*(B-2)-1)+A;},easeInStrong:function(B,A,D,C){return D*(B/=C)*B*B*B+A;},easeOutStrong:function(B,A,D,C){return -D*((B=B/C-1)*B*B*B-1)+A;},easeBothStrong:function(B,A,D,C){if((B/=C/2)<1){return D/2*B*B*B*B+A;}return -D/2*((B-=2)*B*B*B-2)+A;},elasticIn:function(C,A,G,F,B,E){if(C==0){return A;}if((C/=F)==1){return A+G;}if(!E){E=F*0.3;}if(!B||B<Math.abs(G)){B=G;var D=E/4;}else{var D=E/(2*Math.PI)*Math.asin(G/B);}return -(B*Math.pow(2,10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E))+A;},elasticOut:function(C,A,G,F,B,E){if(C==0){return A;}if((C/=F)==1){return A+G;}if(!E){E=F*0.3;}if(!B||B<Math.abs(G)){B=G;var D=E/4;}else{var D=E/(2*Math.PI)*Math.asin(G/B);}return B*Math.pow(2,-10*C)*Math.sin((C*F-D)*(2*Math.PI)/E)+G+A;},elasticBoth:function(C,A,G,F,B,E){if(C==0){return A;}if((C/=F/2)==2){return A+G;}if(!E){E=F*(0.3*1.5);}if(!B||B<Math.abs(G)){B=G;var D=E/4;}else{var D=E/(2*Math.PI)*Math.asin(G/B);}if(C<1){return -0.5*(B*Math.pow(2,10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E))+A;}return B*Math.pow(2,-10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E)*0.5+G+A;},backIn:function(B,A,E,D,C){if(typeof C=="undefined"){C=1.70158;}return E*(B/=D)*B*((C+1)*B-C)+A;},backOut:function(B,A,E,D,C){if(typeof C=="undefined"){C=1.70158;}return E*((B=B/D-1)*B*((C+1)*B+C)+1)+A;},backBoth:function(B,A,E,D,C){if(typeof C=="undefined"){C=1.70158;}if((B/=D/2)<1){return E/2*(B*B*(((C*=(1.525))+1)*B-C))+A;}return E/2*((B-=2)*B*(((C*=(1.525))+1)*B+C)+2)+A;},bounceIn:function(B,A,D,C){return D-YAHOO.util.Easing.bounceOut(C-B,0,D,C)+A;},bounceOut:function(B,A,D,C){if((B/=C)<(1/2.75)){return D*(7.5625*B*B)+A;}else{if(B<(2/2.75)){return D*(7.5625*(B-=(1.5/2.75))*B+0.75)+A;}else{if(B<(2.5/2.75)){return D*(7.5625*(B-=(2.25/2.75))*B+0.9375)+A;}}}return D*(7.5625*(B-=(2.625/2.75))*B+0.984375)+A;},bounceBoth:function(B,A,D,C){if(B<C/2){return YAHOO.util.Easing.bounceIn(B*2,0,D,C)*0.5+A;}return YAHOO.util.Easing.bounceOut(B*2-C,0,D,C)*0.5+D*0.5+A;}};(function(){var A=function(H,G,I,J){if(H){A.superclass.constructor.call(this,H,G,I,J);}};A.NAME="Motion";var E=YAHOO.util;YAHOO.extend(A,E.ColorAnim);var F=A.superclass;var C=A.prototype;C.patterns.points=/^points$/i;C.setAttribute=function(G,I,H){if(this.patterns.points.test(G)){H=H||"px";F.setAttribute.call(this,"left",I[0],H);F.setAttribute.call(this,"top",I[1],H);}else{F.setAttribute.call(this,G,I,H);}};C.getAttribute=function(G){if(this.patterns.points.test(G)){var H=[F.getAttribute.call(this,"left"),F.getAttribute.call(this,"top")];}else{H=F.getAttribute.call(this,G);}return H;};C.doMethod=function(G,K,H){var J=null;if(this.patterns.points.test(G)){var I=this.method(this.currentFrame,0,100,this.totalFrames)/100;J=E.Bezier.getPosition(this.runtimeAttributes[G],I);}else{J=F.doMethod.call(this,G,K,H);}return J;};C.setRuntimeAttribute=function(P){if(this.patterns.points.test(P)){var H=this.getEl();var J=this.attributes;var G;var L=J["points"]["control"]||[];var I;var M,O;if(L.length>0&&!(L[0] instanceof Array)){L=[L];}else{var K=[];for(M=0,O=L.length;M<O;++M){K[M]=L[M];}L=K;}if(E.Dom.getStyle(H,"position")=="static"){E.Dom.setStyle(H,"position","relative");}if(D(J["points"]["from"])){E.Dom.setXY(H,J["points"]["from"]);
23
}else{E.Dom.setXY(H,E.Dom.getXY(H));}G=this.getAttribute("points");if(D(J["points"]["to"])){I=B.call(this,J["points"]["to"],G);var N=E.Dom.getXY(this.getEl());for(M=0,O=L.length;M<O;++M){L[M]=B.call(this,L[M],G);}}else{if(D(J["points"]["by"])){I=[G[0]+J["points"]["by"][0],G[1]+J["points"]["by"][1]];for(M=0,O=L.length;M<O;++M){L[M]=[G[0]+L[M][0],G[1]+L[M][1]];}}}this.runtimeAttributes[P]=[G];if(L.length>0){this.runtimeAttributes[P]=this.runtimeAttributes[P].concat(L);}this.runtimeAttributes[P][this.runtimeAttributes[P].length]=I;}else{F.setRuntimeAttribute.call(this,P);}};var B=function(G,I){var H=E.Dom.getXY(this.getEl());G=[G[0]-H[0]+I[0],G[1]-H[1]+I[1]];return G;};var D=function(G){return(typeof G!=="undefined");};E.Motion=A;})();(function(){var D=function(F,E,G,H){if(F){D.superclass.constructor.call(this,F,E,G,H);}};D.NAME="Scroll";var B=YAHOO.util;YAHOO.extend(D,B.ColorAnim);var C=D.superclass;var A=D.prototype;A.doMethod=function(E,H,F){var G=null;if(E=="scroll"){G=[this.method(this.currentFrame,H[0],F[0]-H[0],this.totalFrames),this.method(this.currentFrame,H[1],F[1]-H[1],this.totalFrames)];}else{G=C.doMethod.call(this,E,H,F);}return G;};A.getAttribute=function(E){var G=null;var F=this.getEl();if(E=="scroll"){G=[F.scrollLeft,F.scrollTop];}else{G=C.getAttribute.call(this,E);}return G;};A.setAttribute=function(E,H,G){var F=this.getEl();if(E=="scroll"){F.scrollLeft=H[0];F.scrollTop=H[1];}else{C.setAttribute.call(this,E,H,G);}};B.Scroll=D;})();YAHOO.register("animation",YAHOO.util.Anim,{version:"2.8.0r4",build:"2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/animation/animation.js (-1392 lines)
Lines 1-1392 Link Here
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.8.0r4
6
*/
7
(function() {
8
9
var Y = YAHOO.util;
10
11
/*
12
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
13
Code licensed under the BSD License:
14
http://developer.yahoo.net/yui/license.txt
15
*/
16
17
/**
18
 * The animation module provides allows effects to be added to HTMLElements.
19
 * @module animation
20
 * @requires yahoo, event, dom
21
 */
22
23
/**
24
 *
25
 * Base animation class that provides the interface for building animated effects.
26
 * <p>Usage: var myAnim = new YAHOO.util.Anim(el, { width: { from: 10, to: 100 } }, 1, YAHOO.util.Easing.easeOut);</p>
27
 * @class Anim
28
 * @namespace YAHOO.util
29
 * @requires YAHOO.util.AnimMgr
30
 * @requires YAHOO.util.Easing
31
 * @requires YAHOO.util.Dom
32
 * @requires YAHOO.util.Event
33
 * @requires YAHOO.util.CustomEvent
34
 * @constructor
35
 * @param {String | HTMLElement} el Reference to the element that will be animated
36
 * @param {Object} attributes The attribute(s) to be animated.  
37
 * Each attribute is an object with at minimum a "to" or "by" member defined.  
38
 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").  
39
 * All attribute names use camelCase.
40
 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
41
 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
42
 */
43
44
var Anim = function(el, attributes, duration, method) {
45
    if (!el) {
46
    }
47
    this.init(el, attributes, duration, method); 
48
};
49
50
Anim.NAME = 'Anim';
51
52
Anim.prototype = {
53
    /**
54
     * Provides a readable name for the Anim instance.
55
     * @method toString
56
     * @return {String}
57
     */
58
    toString: function() {
59
        var el = this.getEl() || {};
60
        var id = el.id || el.tagName;
61
        return (this.constructor.NAME + ': ' + id);
62
    },
63
    
64
    patterns: { // cached for performance
65
        noNegatives:        /width|height|opacity|padding/i, // keep at zero or above
66
        offsetAttribute:  /^((width|height)|(top|left))$/, // use offsetValue as default
67
        defaultUnit:        /width|height|top$|bottom$|left$|right$/i, // use 'px' by default
68
        offsetUnit:         /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i // IE may return these, so convert these to offset
69
    },
70
    
71
    /**
72
     * Returns the value computed by the animation's "method".
73
     * @method doMethod
74
     * @param {String} attr The name of the attribute.
75
     * @param {Number} start The value this attribute should start from for this animation.
76
     * @param {Number} end  The value this attribute should end at for this animation.
77
     * @return {Number} The Value to be applied to the attribute.
78
     */
79
    doMethod: function(attr, start, end) {
80
        return this.method(this.currentFrame, start, end - start, this.totalFrames);
81
    },
82
    
83
    /**
84
     * Applies a value to an attribute.
85
     * @method setAttribute
86
     * @param {String} attr The name of the attribute.
87
     * @param {Number} val The value to be applied to the attribute.
88
     * @param {String} unit The unit ('px', '%', etc.) of the value.
89
     */
90
    setAttribute: function(attr, val, unit) {
91
        var el = this.getEl();
92
        if ( this.patterns.noNegatives.test(attr) ) {
93
            val = (val > 0) ? val : 0;
94
        }
95
96
        if (attr in el && !('style' in el && attr in el.style)) {
97
            el[attr] = val;
98
        } else {
99
            Y.Dom.setStyle(el, attr, val + unit);
100
        }
101
    },                        
102
    
103
    /**
104
     * Returns current value of the attribute.
105
     * @method getAttribute
106
     * @param {String} attr The name of the attribute.
107
     * @return {Number} val The current value of the attribute.
108
     */
109
    getAttribute: function(attr) {
110
        var el = this.getEl();
111
        var val = Y.Dom.getStyle(el, attr);
112
113
        if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
114
            return parseFloat(val);
115
        }
116
        
117
        var a = this.patterns.offsetAttribute.exec(attr) || [];
118
        var pos = !!( a[3] ); // top or left
119
        var box = !!( a[2] ); // width or height
120
        
121
        if ('style' in el) {
122
            // use offsets for width/height and abs pos top/left
123
            if ( box || (Y.Dom.getStyle(el, 'position') == 'absolute' && pos) ) {
124
                val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
125
            } else { // default to zero for other 'auto'
126
                val = 0;
127
            }
128
        } else if (attr in el) {
129
            val = el[attr];
130
        }
131
132
        return val;
133
    },
134
    
135
    /**
136
     * Returns the unit to use when none is supplied.
137
     * @method getDefaultUnit
138
     * @param {attr} attr The name of the attribute.
139
     * @return {String} The default unit to be used.
140
     */
141
    getDefaultUnit: function(attr) {
142
         if ( this.patterns.defaultUnit.test(attr) ) {
143
            return 'px';
144
         }
145
         
146
         return '';
147
    },
148
        
149
    /**
150
     * Sets the actual values to be used during the animation.  Should only be needed for subclass use.
151
     * @method setRuntimeAttribute
152
     * @param {Object} attr The attribute object
153
     * @private 
154
     */
155
    setRuntimeAttribute: function(attr) {
156
        var start;
157
        var end;
158
        var attributes = this.attributes;
159
160
        this.runtimeAttributes[attr] = {};
161
        
162
        var isset = function(prop) {
163
            return (typeof prop !== 'undefined');
164
        };
165
        
166
        if ( !isset(attributes[attr]['to']) && !isset(attributes[attr]['by']) ) {
167
            return false; // note return; nothing to animate to
168
        }
169
        
170
        start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
171
172
        // To beats by, per SMIL 2.1 spec
173
        if ( isset(attributes[attr]['to']) ) {
174
            end = attributes[attr]['to'];
175
        } else if ( isset(attributes[attr]['by']) ) {
176
            if (start.constructor == Array) {
177
                end = [];
178
                for (var i = 0, len = start.length; i < len; ++i) {
179
                    end[i] = start[i] + attributes[attr]['by'][i] * 1; // times 1 to cast "by" 
180
                }
181
            } else {
182
                end = start + attributes[attr]['by'] * 1;
183
            }
184
        }
185
        
186
        this.runtimeAttributes[attr].start = start;
187
        this.runtimeAttributes[attr].end = end;
188
189
        // set units if needed
190
        this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ?
191
                attributes[attr]['unit'] : this.getDefaultUnit(attr);
192
        return true;
193
    },
194
195
    /**
196
     * Constructor for Anim instance.
197
     * @method init
198
     * @param {String | HTMLElement} el Reference to the element that will be animated
199
     * @param {Object} attributes The attribute(s) to be animated.  
200
     * Each attribute is an object with at minimum a "to" or "by" member defined.  
201
     * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").  
202
     * All attribute names use camelCase.
203
     * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
204
     * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
205
     */ 
206
    init: function(el, attributes, duration, method) {
207
        /**
208
         * Whether or not the animation is running.
209
         * @property isAnimated
210
         * @private
211
         * @type Boolean
212
         */
213
        var isAnimated = false;
214
        
215
        /**
216
         * A Date object that is created when the animation begins.
217
         * @property startTime
218
         * @private
219
         * @type Date
220
         */
221
        var startTime = null;
222
        
223
        /**
224
         * The number of frames this animation was able to execute.
225
         * @property actualFrames
226
         * @private
227
         * @type Int
228
         */
229
        var actualFrames = 0; 
230
231
        /**
232
         * The element to be animated.
233
         * @property el
234
         * @private
235
         * @type HTMLElement
236
         */
237
        el = Y.Dom.get(el);
238
        
239
        /**
240
         * The collection of attributes to be animated.  
241
         * Each attribute must have at least a "to" or "by" defined in order to animate.  
242
         * If "to" is supplied, the animation will end with the attribute at that value.  
243
         * If "by" is supplied, the animation will end at that value plus its starting value. 
244
         * If both are supplied, "to" is used, and "by" is ignored. 
245
         * Optional additional member include "from" (the value the attribute should start animating from, defaults to current value), and "unit" (the units to apply to the values).
246
         * @property attributes
247
         * @type Object
248
         */
249
        this.attributes = attributes || {};
250
        
251
        /**
252
         * The length of the animation.  Defaults to "1" (second).
253
         * @property duration
254
         * @type Number
255
         */
256
        this.duration = !YAHOO.lang.isUndefined(duration) ? duration : 1;
257
        
258
        /**
259
         * The method that will provide values to the attribute(s) during the animation. 
260
         * Defaults to "YAHOO.util.Easing.easeNone".
261
         * @property method
262
         * @type Function
263
         */
264
        this.method = method || Y.Easing.easeNone;
265
266
        /**
267
         * Whether or not the duration should be treated as seconds.
268
         * Defaults to true.
269
         * @property useSeconds
270
         * @type Boolean
271
         */
272
        this.useSeconds = true; // default to seconds
273
        
274
        /**
275
         * The location of the current animation on the timeline.
276
         * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
277
         * @property currentFrame
278
         * @type Int
279
         */
280
        this.currentFrame = 0;
281
        
282
        /**
283
         * The total number of frames to be executed.
284
         * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
285
         * @property totalFrames
286
         * @type Int
287
         */
288
        this.totalFrames = Y.AnimMgr.fps;
289
        
290
        /**
291
         * Changes the animated element
292
         * @method setEl
293
         */
294
        this.setEl = function(element) {
295
            el = Y.Dom.get(element);
296
        };
297
        
298
        /**
299
         * Returns a reference to the animated element.
300
         * @method getEl
301
         * @return {HTMLElement}
302
         */
303
        this.getEl = function() { return el; };
304
        
305
        /**
306
         * Checks whether the element is currently animated.
307
         * @method isAnimated
308
         * @return {Boolean} current value of isAnimated.     
309
         */
310
        this.isAnimated = function() {
311
            return isAnimated;
312
        };
313
        
314
        /**
315
         * Returns the animation start time.
316
         * @method getStartTime
317
         * @return {Date} current value of startTime.      
318
         */
319
        this.getStartTime = function() {
320
            return startTime;
321
        };        
322
        
323
        this.runtimeAttributes = {};
324
        
325
        
326
        
327
        /**
328
         * Starts the animation by registering it with the animation manager. 
329
         * @method animate  
330
         */
331
        this.animate = function() {
332
            if ( this.isAnimated() ) {
333
                return false;
334
            }
335
            
336
            this.currentFrame = 0;
337
            
338
            this.totalFrames = ( this.useSeconds ) ? Math.ceil(Y.AnimMgr.fps * this.duration) : this.duration;
339
    
340
            if (this.duration === 0 && this.useSeconds) { // jump to last frame if zero second duration 
341
                this.totalFrames = 1; 
342
            }
343
            Y.AnimMgr.registerElement(this);
344
            return true;
345
        };
346
          
347
        /**
348
         * Stops the animation.  Normally called by AnimMgr when animation completes.
349
         * @method stop
350
         * @param {Boolean} finish (optional) If true, animation will jump to final frame.
351
         */ 
352
        this.stop = function(finish) {
353
            if (!this.isAnimated()) { // nothing to stop
354
                return false;
355
            }
356
357
            if (finish) {
358
                 this.currentFrame = this.totalFrames;
359
                 this._onTween.fire();
360
            }
361
            Y.AnimMgr.stop(this);
362
        };
363
        
364
        var onStart = function() {            
365
            this.onStart.fire();
366
            
367
            this.runtimeAttributes = {};
368
            for (var attr in this.attributes) {
369
                this.setRuntimeAttribute(attr);
370
            }
371
            
372
            isAnimated = true;
373
            actualFrames = 0;
374
            startTime = new Date(); 
375
        };
376
        
377
        /**
378
         * Feeds the starting and ending values for each animated attribute to doMethod once per frame, then applies the resulting value to the attribute(s).
379
         * @private
380
         */
381
         
382
        var onTween = function() {
383
            var data = {
384
                duration: new Date() - this.getStartTime(),
385
                currentFrame: this.currentFrame
386
            };
387
            
388
            data.toString = function() {
389
                return (
390
                    'duration: ' + data.duration +
391
                    ', currentFrame: ' + data.currentFrame
392
                );
393
            };
394
            
395
            this.onTween.fire(data);
396
            
397
            var runtimeAttributes = this.runtimeAttributes;
398
            
399
            for (var attr in runtimeAttributes) {
400
                this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit); 
401
            }
402
            
403
            actualFrames += 1;
404
        };
405
        
406
        var onComplete = function() {
407
            var actual_duration = (new Date() - startTime) / 1000 ;
408
            
409
            var data = {
410
                duration: actual_duration,
411
                frames: actualFrames,
412
                fps: actualFrames / actual_duration
413
            };
414
            
415
            data.toString = function() {
416
                return (
417
                    'duration: ' + data.duration +
418
                    ', frames: ' + data.frames +
419
                    ', fps: ' + data.fps
420
                );
421
            };
422
            
423
            isAnimated = false;
424
            actualFrames = 0;
425
            this.onComplete.fire(data);
426
        };
427
        
428
        /**
429
         * Custom event that fires after onStart, useful in subclassing
430
         * @private
431
         */    
432
        this._onStart = new Y.CustomEvent('_start', this, true);
433
434
        /**
435
         * Custom event that fires when animation begins
436
         * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction)
437
         * @event onStart
438
         */    
439
        this.onStart = new Y.CustomEvent('start', this);
440
        
441
        /**
442
         * Custom event that fires between each frame
443
         * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction)
444
         * @event onTween
445
         */
446
        this.onTween = new Y.CustomEvent('tween', this);
447
        
448
        /**
449
         * Custom event that fires after onTween
450
         * @private
451
         */
452
        this._onTween = new Y.CustomEvent('_tween', this, true);
453
        
454
        /**
455
         * Custom event that fires when animation ends
456
         * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction)
457
         * @event onComplete
458
         */
459
        this.onComplete = new Y.CustomEvent('complete', this);
460
        /**
461
         * Custom event that fires after onComplete
462
         * @private
463
         */
464
        this._onComplete = new Y.CustomEvent('_complete', this, true);
465
466
        this._onStart.subscribe(onStart);
467
        this._onTween.subscribe(onTween);
468
        this._onComplete.subscribe(onComplete);
469
    }
470
};
471
472
    Y.Anim = Anim;
473
})();
474
/**
475
 * Handles animation queueing and threading.
476
 * Used by Anim and subclasses.
477
 * @class AnimMgr
478
 * @namespace YAHOO.util
479
 */
480
YAHOO.util.AnimMgr = new function() {
481
    /** 
482
     * Reference to the animation Interval.
483
     * @property thread
484
     * @private
485
     * @type Int
486
     */
487
    var thread = null;
488
    
489
    /** 
490
     * The current queue of registered animation objects.
491
     * @property queue
492
     * @private
493
     * @type Array
494
     */    
495
    var queue = [];
496
497
    /** 
498
     * The number of active animations.
499
     * @property tweenCount
500
     * @private
501
     * @type Int
502
     */        
503
    var tweenCount = 0;
504
505
    /** 
506
     * Base frame rate (frames per second). 
507
     * Arbitrarily high for better x-browser calibration (slower browsers drop more frames).
508
     * @property fps
509
     * @type Int
510
     * 
511
     */
512
    this.fps = 1000;
513
514
    /** 
515
     * Interval delay in milliseconds, defaults to fastest possible.
516
     * @property delay
517
     * @type Int
518
     * 
519
     */
520
    this.delay = 1;
521
522
    /**
523
     * Adds an animation instance to the animation queue.
524
     * All animation instances must be registered in order to animate.
525
     * @method registerElement
526
     * @param {object} tween The Anim instance to be be registered
527
     */
528
    this.registerElement = function(tween) {
529
        queue[queue.length] = tween;
530
        tweenCount += 1;
531
        tween._onStart.fire();
532
        this.start();
533
    };
534
    
535
    /**
536
     * removes an animation instance from the animation queue.
537
     * All animation instances must be registered in order to animate.
538
     * @method unRegister
539
     * @param {object} tween The Anim instance to be be registered
540
     * @param {Int} index The index of the Anim instance
541
     * @private
542
     */
543
    this.unRegister = function(tween, index) {
544
        index = index || getIndex(tween);
545
        if (!tween.isAnimated() || index === -1) {
546
            return false;
547
        }
548
        
549
        tween._onComplete.fire();
550
        queue.splice(index, 1);
551
552
        tweenCount -= 1;
553
        if (tweenCount <= 0) {
554
            this.stop();
555
        }
556
557
        return true;
558
    };
559
    
560
    /**
561
     * Starts the animation thread.
562
	* Only one thread can run at a time.
563
     * @method start
564
     */    
565
    this.start = function() {
566
        if (thread === null) {
567
            thread = setInterval(this.run, this.delay);
568
        }
569
    };
570
571
    /**
572
     * Stops the animation thread or a specific animation instance.
573
     * @method stop
574
     * @param {object} tween A specific Anim instance to stop (optional)
575
     * If no instance given, Manager stops thread and all animations.
576
     */    
577
    this.stop = function(tween) {
578
        if (!tween) {
579
            clearInterval(thread);
580
            
581
            for (var i = 0, len = queue.length; i < len; ++i) {
582
                this.unRegister(queue[0], 0);  
583
            }
584
585
            queue = [];
586
            thread = null;
587
            tweenCount = 0;
588
        }
589
        else {
590
            this.unRegister(tween);
591
        }
592
    };
593
    
594
    /**
595
     * Called per Interval to handle each animation frame.
596
     * @method run
597
     */    
598
    this.run = function() {
599
        for (var i = 0, len = queue.length; i < len; ++i) {
600
            var tween = queue[i];
601
            if ( !tween || !tween.isAnimated() ) { continue; }
602
603
            if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
604
            {
605
                tween.currentFrame += 1;
606
                
607
                if (tween.useSeconds) {
608
                    correctFrame(tween);
609
                }
610
                tween._onTween.fire();          
611
            }
612
            else { YAHOO.util.AnimMgr.stop(tween, i); }
613
        }
614
    };
615
    
616
    var getIndex = function(anim) {
617
        for (var i = 0, len = queue.length; i < len; ++i) {
618
            if (queue[i] === anim) {
619
                return i; // note return;
620
            }
621
        }
622
        return -1;
623
    };
624
    
625
    /**
626
     * On the fly frame correction to keep animation on time.
627
     * @method correctFrame
628
     * @private
629
     * @param {Object} tween The Anim instance being corrected.
630
     */
631
    var correctFrame = function(tween) {
632
        var frames = tween.totalFrames;
633
        var frame = tween.currentFrame;
634
        var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
635
        var elapsed = (new Date() - tween.getStartTime());
636
        var tweak = 0;
637
        
638
        if (elapsed < tween.duration * 1000) { // check if falling behind
639
            tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
640
        } else { // went over duration, so jump to end
641
            tweak = frames - (frame + 1); 
642
        }
643
        if (tweak > 0 && isFinite(tweak)) { // adjust if needed
644
            if (tween.currentFrame + tweak >= frames) {// dont go past last frame
645
                tweak = frames - (frame + 1);
646
            }
647
            
648
            tween.currentFrame += tweak;      
649
        }
650
    };
651
    this._queue = queue;
652
    this._getIndex = getIndex;
653
};
654
/**
655
 * Used to calculate Bezier splines for any number of control points.
656
 * @class Bezier
657
 * @namespace YAHOO.util
658
 *
659
 */
660
YAHOO.util.Bezier = new function() {
661
    /**
662
     * Get the current position of the animated element based on t.
663
     * Each point is an array of "x" and "y" values (0 = x, 1 = y)
664
     * At least 2 points are required (start and end).
665
     * First point is start. Last point is end.
666
     * Additional control points are optional.     
667
     * @method getPosition
668
     * @param {Array} points An array containing Bezier points
669
     * @param {Number} t A number between 0 and 1 which is the basis for determining current position
670
     * @return {Array} An array containing int x and y member data
671
     */
672
    this.getPosition = function(points, t) {  
673
        var n = points.length;
674
        var tmp = [];
675
676
        for (var i = 0; i < n; ++i){
677
            tmp[i] = [points[i][0], points[i][1]]; // save input
678
        }
679
        
680
        for (var j = 1; j < n; ++j) {
681
            for (i = 0; i < n - j; ++i) {
682
                tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
683
                tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1]; 
684
            }
685
        }
686
    
687
        return [ tmp[0][0], tmp[0][1] ]; 
688
    
689
    };
690
};
691
(function() {
692
/**
693
 * Anim subclass for color transitions.
694
 * <p>Usage: <code>var myAnim = new Y.ColorAnim(el, { backgroundColor: { from: '#FF0000', to: '#FFFFFF' } }, 1, Y.Easing.easeOut);</code> Color values can be specified with either 112233, #112233, 
695
 * [255,255,255], or rgb(255,255,255)</p>
696
 * @class ColorAnim
697
 * @namespace YAHOO.util
698
 * @requires YAHOO.util.Anim
699
 * @requires YAHOO.util.AnimMgr
700
 * @requires YAHOO.util.Easing
701
 * @requires YAHOO.util.Bezier
702
 * @requires YAHOO.util.Dom
703
 * @requires YAHOO.util.Event
704
 * @constructor
705
 * @extends YAHOO.util.Anim
706
 * @param {HTMLElement | String} el Reference to the element that will be animated
707
 * @param {Object} attributes The attribute(s) to be animated.
708
 * Each attribute is an object with at minimum a "to" or "by" member defined.
709
 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
710
 * All attribute names use camelCase.
711
 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
712
 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
713
 */
714
    var ColorAnim = function(el, attributes, duration,  method) {
715
        ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
716
    };
717
    
718
    ColorAnim.NAME = 'ColorAnim';
719
720
    ColorAnim.DEFAULT_BGCOLOR = '#fff';
721
    // shorthand
722
    var Y = YAHOO.util;
723
    YAHOO.extend(ColorAnim, Y.Anim);
724
725
    var superclass = ColorAnim.superclass;
726
    var proto = ColorAnim.prototype;
727
    
728
    proto.patterns.color = /color$/i;
729
    proto.patterns.rgb            = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
730
    proto.patterns.hex            = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
731
    proto.patterns.hex3          = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
732
    proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/; // need rgba for safari
733
    
734
    /**
735
     * Attempts to parse the given string and return a 3-tuple.
736
     * @method parseColor
737
     * @param {String} s The string to parse.
738
     * @return {Array} The 3-tuple of rgb values.
739
     */
740
    proto.parseColor = function(s) {
741
        if (s.length == 3) { return s; }
742
    
743
        var c = this.patterns.hex.exec(s);
744
        if (c && c.length == 4) {
745
            return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
746
        }
747
    
748
        c = this.patterns.rgb.exec(s);
749
        if (c && c.length == 4) {
750
            return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
751
        }
752
    
753
        c = this.patterns.hex3.exec(s);
754
        if (c && c.length == 4) {
755
            return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
756
        }
757
        
758
        return null;
759
    };
760
761
    proto.getAttribute = function(attr) {
762
        var el = this.getEl();
763
        if (this.patterns.color.test(attr) ) {
764
            var val = YAHOO.util.Dom.getStyle(el, attr);
765
            
766
            var that = this;
767
            if (this.patterns.transparent.test(val)) { // bgcolor default
768
                var parent = YAHOO.util.Dom.getAncestorBy(el, function(node) {
769
                    return !that.patterns.transparent.test(val);
770
                });
771
772
                if (parent) {
773
                    val = Y.Dom.getStyle(parent, attr);
774
                } else {
775
                    val = ColorAnim.DEFAULT_BGCOLOR;
776
                }
777
            }
778
        } else {
779
            val = superclass.getAttribute.call(this, attr);
780
        }
781
782
        return val;
783
    };
784
    
785
    proto.doMethod = function(attr, start, end) {
786
        var val;
787
    
788
        if ( this.patterns.color.test(attr) ) {
789
            val = [];
790
            for (var i = 0, len = start.length; i < len; ++i) {
791
                val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
792
            }
793
            
794
            val = 'rgb('+Math.floor(val[0])+','+Math.floor(val[1])+','+Math.floor(val[2])+')';
795
        }
796
        else {
797
            val = superclass.doMethod.call(this, attr, start, end);
798
        }
799
800
        return val;
801
    };
802
803
    proto.setRuntimeAttribute = function(attr) {
804
        superclass.setRuntimeAttribute.call(this, attr);
805
        
806
        if ( this.patterns.color.test(attr) ) {
807
            var attributes = this.attributes;
808
            var start = this.parseColor(this.runtimeAttributes[attr].start);
809
            var end = this.parseColor(this.runtimeAttributes[attr].end);
810
            // fix colors if going "by"
811
            if ( typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined' ) {
812
                end = this.parseColor(attributes[attr].by);
813
            
814
                for (var i = 0, len = start.length; i < len; ++i) {
815
                    end[i] = start[i] + end[i];
816
                }
817
            }
818
            
819
            this.runtimeAttributes[attr].start = start;
820
            this.runtimeAttributes[attr].end = end;
821
        }
822
    };
823
824
    Y.ColorAnim = ColorAnim;
825
})();
826
/*!
827
TERMS OF USE - EASING EQUATIONS
828
Open source under the BSD License.
829
Copyright 2001 Robert Penner All rights reserved.
830
831
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
832
833
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
834
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
835
 * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
836
837
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
838
*/
839
840
/**
841
 * Singleton that determines how an animation proceeds from start to end.
842
 * @class Easing
843
 * @namespace YAHOO.util
844
*/
845
846
YAHOO.util.Easing = {
847
848
    /**
849
     * Uniform speed between points.
850
     * @method easeNone
851
     * @param {Number} t Time value used to compute current value
852
     * @param {Number} b Starting value
853
     * @param {Number} c Delta between start and end values
854
     * @param {Number} d Total length of animation
855
     * @return {Number} The computed value for the current animation frame
856
     */
857
    easeNone: function (t, b, c, d) {
858
    	return c*t/d + b;
859
    },
860
    
861
    /**
862
     * Begins slowly and accelerates towards end.
863
     * @method easeIn
864
     * @param {Number} t Time value used to compute current value
865
     * @param {Number} b Starting value
866
     * @param {Number} c Delta between start and end values
867
     * @param {Number} d Total length of animation
868
     * @return {Number} The computed value for the current animation frame
869
     */
870
    easeIn: function (t, b, c, d) {
871
    	return c*(t/=d)*t + b;
872
    },
873
874
    /**
875
     * Begins quickly and decelerates towards end.
876
     * @method easeOut
877
     * @param {Number} t Time value used to compute current value
878
     * @param {Number} b Starting value
879
     * @param {Number} c Delta between start and end values
880
     * @param {Number} d Total length of animation
881
     * @return {Number} The computed value for the current animation frame
882
     */
883
    easeOut: function (t, b, c, d) {
884
    	return -c *(t/=d)*(t-2) + b;
885
    },
886
    
887
    /**
888
     * Begins slowly and decelerates towards end.
889
     * @method easeBoth
890
     * @param {Number} t Time value used to compute current value
891
     * @param {Number} b Starting value
892
     * @param {Number} c Delta between start and end values
893
     * @param {Number} d Total length of animation
894
     * @return {Number} The computed value for the current animation frame
895
     */
896
    easeBoth: function (t, b, c, d) {
897
    	if ((t/=d/2) < 1) {
898
            return c/2*t*t + b;
899
        }
900
        
901
    	return -c/2 * ((--t)*(t-2) - 1) + b;
902
    },
903
    
904
    /**
905
     * Begins slowly and accelerates towards end.
906
     * @method easeInStrong
907
     * @param {Number} t Time value used to compute current value
908
     * @param {Number} b Starting value
909
     * @param {Number} c Delta between start and end values
910
     * @param {Number} d Total length of animation
911
     * @return {Number} The computed value for the current animation frame
912
     */
913
    easeInStrong: function (t, b, c, d) {
914
    	return c*(t/=d)*t*t*t + b;
915
    },
916
    
917
    /**
918
     * Begins quickly and decelerates towards end.
919
     * @method easeOutStrong
920
     * @param {Number} t Time value used to compute current value
921
     * @param {Number} b Starting value
922
     * @param {Number} c Delta between start and end values
923
     * @param {Number} d Total length of animation
924
     * @return {Number} The computed value for the current animation frame
925
     */
926
    easeOutStrong: function (t, b, c, d) {
927
    	return -c * ((t=t/d-1)*t*t*t - 1) + b;
928
    },
929
    
930
    /**
931
     * Begins slowly and decelerates towards end.
932
     * @method easeBothStrong
933
     * @param {Number} t Time value used to compute current value
934
     * @param {Number} b Starting value
935
     * @param {Number} c Delta between start and end values
936
     * @param {Number} d Total length of animation
937
     * @return {Number} The computed value for the current animation frame
938
     */
939
    easeBothStrong: function (t, b, c, d) {
940
    	if ((t/=d/2) < 1) {
941
            return c/2*t*t*t*t + b;
942
        }
943
        
944
    	return -c/2 * ((t-=2)*t*t*t - 2) + b;
945
    },
946
947
    /**
948
     * Snap in elastic effect.
949
     * @method elasticIn
950
     * @param {Number} t Time value used to compute current value
951
     * @param {Number} b Starting value
952
     * @param {Number} c Delta between start and end values
953
     * @param {Number} d Total length of animation
954
     * @param {Number} a Amplitude (optional)
955
     * @param {Number} p Period (optional)
956
     * @return {Number} The computed value for the current animation frame
957
     */
958
959
    elasticIn: function (t, b, c, d, a, p) {
960
    	if (t == 0) {
961
            return b;
962
        }
963
        if ( (t /= d) == 1 ) {
964
            return b+c;
965
        }
966
        if (!p) {
967
            p=d*.3;
968
        }
969
        
970
    	if (!a || a < Math.abs(c)) {
971
            a = c; 
972
            var s = p/4;
973
        }
974
    	else {
975
            var s = p/(2*Math.PI) * Math.asin (c/a);
976
        }
977
        
978
    	return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
979
    },
980
981
    /**
982
     * Snap out elastic effect.
983
     * @method elasticOut
984
     * @param {Number} t Time value used to compute current value
985
     * @param {Number} b Starting value
986
     * @param {Number} c Delta between start and end values
987
     * @param {Number} d Total length of animation
988
     * @param {Number} a Amplitude (optional)
989
     * @param {Number} p Period (optional)
990
     * @return {Number} The computed value for the current animation frame
991
     */
992
    elasticOut: function (t, b, c, d, a, p) {
993
    	if (t == 0) {
994
            return b;
995
        }
996
        if ( (t /= d) == 1 ) {
997
            return b+c;
998
        }
999
        if (!p) {
1000
            p=d*.3;
1001
        }
1002
        
1003
    	if (!a || a < Math.abs(c)) {
1004
            a = c;
1005
            var s = p / 4;
1006
        }
1007
    	else {
1008
            var s = p/(2*Math.PI) * Math.asin (c/a);
1009
        }
1010
        
1011
    	return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
1012
    },
1013
    
1014
    /**
1015
     * Snap both elastic effect.
1016
     * @method elasticBoth
1017
     * @param {Number} t Time value used to compute current value
1018
     * @param {Number} b Starting value
1019
     * @param {Number} c Delta between start and end values
1020
     * @param {Number} d Total length of animation
1021
     * @param {Number} a Amplitude (optional)
1022
     * @param {Number} p Period (optional)
1023
     * @return {Number} The computed value for the current animation frame
1024
     */
1025
    elasticBoth: function (t, b, c, d, a, p) {
1026
    	if (t == 0) {
1027
            return b;
1028
        }
1029
        
1030
        if ( (t /= d/2) == 2 ) {
1031
            return b+c;
1032
        }
1033
        
1034
        if (!p) {
1035
            p = d*(.3*1.5);
1036
        }
1037
        
1038
    	if ( !a || a < Math.abs(c) ) {
1039
            a = c; 
1040
            var s = p/4;
1041
        }
1042
    	else {
1043
            var s = p/(2*Math.PI) * Math.asin (c/a);
1044
        }
1045
        
1046
    	if (t < 1) {
1047
            return -.5*(a*Math.pow(2,10*(t-=1)) * 
1048
                    Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
1049
        }
1050
    	return a*Math.pow(2,-10*(t-=1)) * 
1051
                Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
1052
    },
1053
1054
1055
    /**
1056
     * Backtracks slightly, then reverses direction and moves to end.
1057
     * @method backIn
1058
     * @param {Number} t Time value used to compute current value
1059
     * @param {Number} b Starting value
1060
     * @param {Number} c Delta between start and end values
1061
     * @param {Number} d Total length of animation
1062
     * @param {Number} s Overshoot (optional)
1063
     * @return {Number} The computed value for the current animation frame
1064
     */
1065
    backIn: function (t, b, c, d, s) {
1066
    	if (typeof s == 'undefined') {
1067
            s = 1.70158;
1068
        }
1069
    	return c*(t/=d)*t*((s+1)*t - s) + b;
1070
    },
1071
1072
    /**
1073
     * Overshoots end, then reverses and comes back to end.
1074
     * @method backOut
1075
     * @param {Number} t Time value used to compute current value
1076
     * @param {Number} b Starting value
1077
     * @param {Number} c Delta between start and end values
1078
     * @param {Number} d Total length of animation
1079
     * @param {Number} s Overshoot (optional)
1080
     * @return {Number} The computed value for the current animation frame
1081
     */
1082
    backOut: function (t, b, c, d, s) {
1083
    	if (typeof s == 'undefined') {
1084
            s = 1.70158;
1085
        }
1086
    	return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
1087
    },
1088
    
1089
    /**
1090
     * Backtracks slightly, then reverses direction, overshoots end, 
1091
     * then reverses and comes back to end.
1092
     * @method backBoth
1093
     * @param {Number} t Time value used to compute current value
1094
     * @param {Number} b Starting value
1095
     * @param {Number} c Delta between start and end values
1096
     * @param {Number} d Total length of animation
1097
     * @param {Number} s Overshoot (optional)
1098
     * @return {Number} The computed value for the current animation frame
1099
     */
1100
    backBoth: function (t, b, c, d, s) {
1101
    	if (typeof s == 'undefined') {
1102
            s = 1.70158; 
1103
        }
1104
        
1105
    	if ((t /= d/2 ) < 1) {
1106
            return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
1107
        }
1108
    	return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
1109
    },
1110
1111
    /**
1112
     * Bounce off of start.
1113
     * @method bounceIn
1114
     * @param {Number} t Time value used to compute current value
1115
     * @param {Number} b Starting value
1116
     * @param {Number} c Delta between start and end values
1117
     * @param {Number} d Total length of animation
1118
     * @return {Number} The computed value for the current animation frame
1119
     */
1120
    bounceIn: function (t, b, c, d) {
1121
    	return c - YAHOO.util.Easing.bounceOut(d-t, 0, c, d) + b;
1122
    },
1123
    
1124
    /**
1125
     * Bounces off end.
1126
     * @method bounceOut
1127
     * @param {Number} t Time value used to compute current value
1128
     * @param {Number} b Starting value
1129
     * @param {Number} c Delta between start and end values
1130
     * @param {Number} d Total length of animation
1131
     * @return {Number} The computed value for the current animation frame
1132
     */
1133
    bounceOut: function (t, b, c, d) {
1134
    	if ((t/=d) < (1/2.75)) {
1135
    		return c*(7.5625*t*t) + b;
1136
    	} else if (t < (2/2.75)) {
1137
    		return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
1138
    	} else if (t < (2.5/2.75)) {
1139
    		return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
1140
    	}
1141
        return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
1142
    },
1143
    
1144
    /**
1145
     * Bounces off start and end.
1146
     * @method bounceBoth
1147
     * @param {Number} t Time value used to compute current value
1148
     * @param {Number} b Starting value
1149
     * @param {Number} c Delta between start and end values
1150
     * @param {Number} d Total length of animation
1151
     * @return {Number} The computed value for the current animation frame
1152
     */
1153
    bounceBoth: function (t, b, c, d) {
1154
    	if (t < d/2) {
1155
            return YAHOO.util.Easing.bounceIn(t*2, 0, c, d) * .5 + b;
1156
        }
1157
    	return YAHOO.util.Easing.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
1158
    }
1159
};
1160
1161
(function() {
1162
/**
1163
 * Anim subclass for moving elements along a path defined by the "points" 
1164
 * member of "attributes".  All "points" are arrays with x, y coordinates.
1165
 * <p>Usage: <code>var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1166
 * @class Motion
1167
 * @namespace YAHOO.util
1168
 * @requires YAHOO.util.Anim
1169
 * @requires YAHOO.util.AnimMgr
1170
 * @requires YAHOO.util.Easing
1171
 * @requires YAHOO.util.Bezier
1172
 * @requires YAHOO.util.Dom
1173
 * @requires YAHOO.util.Event
1174
 * @requires YAHOO.util.CustomEvent 
1175
 * @constructor
1176
 * @extends YAHOO.util.ColorAnim
1177
 * @param {String | HTMLElement} el Reference to the element that will be animated
1178
 * @param {Object} attributes The attribute(s) to be animated.  
1179
 * Each attribute is an object with at minimum a "to" or "by" member defined.  
1180
 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").  
1181
 * All attribute names use camelCase.
1182
 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1183
 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
1184
 */
1185
    var Motion = function(el, attributes, duration,  method) {
1186
        if (el) { // dont break existing subclasses not using YAHOO.extend
1187
            Motion.superclass.constructor.call(this, el, attributes, duration, method);
1188
        }
1189
    };
1190
1191
1192
    Motion.NAME = 'Motion';
1193
1194
    // shorthand
1195
    var Y = YAHOO.util;
1196
    YAHOO.extend(Motion, Y.ColorAnim);
1197
    
1198
    var superclass = Motion.superclass;
1199
    var proto = Motion.prototype;
1200
1201
    proto.patterns.points = /^points$/i;
1202
    
1203
    proto.setAttribute = function(attr, val, unit) {
1204
        if (  this.patterns.points.test(attr) ) {
1205
            unit = unit || 'px';
1206
            superclass.setAttribute.call(this, 'left', val[0], unit);
1207
            superclass.setAttribute.call(this, 'top', val[1], unit);
1208
        } else {
1209
            superclass.setAttribute.call(this, attr, val, unit);
1210
        }
1211
    };
1212
1213
    proto.getAttribute = function(attr) {
1214
        if (  this.patterns.points.test(attr) ) {
1215
            var val = [
1216
                superclass.getAttribute.call(this, 'left'),
1217
                superclass.getAttribute.call(this, 'top')
1218
            ];
1219
        } else {
1220
            val = superclass.getAttribute.call(this, attr);
1221
        }
1222
1223
        return val;
1224
    };
1225
1226
    proto.doMethod = function(attr, start, end) {
1227
        var val = null;
1228
1229
        if ( this.patterns.points.test(attr) ) {
1230
            var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;				
1231
            val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
1232
        } else {
1233
            val = superclass.doMethod.call(this, attr, start, end);
1234
        }
1235
        return val;
1236
    };
1237
1238
    proto.setRuntimeAttribute = function(attr) {
1239
        if ( this.patterns.points.test(attr) ) {
1240
            var el = this.getEl();
1241
            var attributes = this.attributes;
1242
            var start;
1243
            var control = attributes['points']['control'] || [];
1244
            var end;
1245
            var i, len;
1246
            
1247
            if (control.length > 0 && !(control[0] instanceof Array) ) { // could be single point or array of points
1248
                control = [control];
1249
            } else { // break reference to attributes.points.control
1250
                var tmp = []; 
1251
                for (i = 0, len = control.length; i< len; ++i) {
1252
                    tmp[i] = control[i];
1253
                }
1254
                control = tmp;
1255
            }
1256
1257
            if (Y.Dom.getStyle(el, 'position') == 'static') { // default to relative
1258
                Y.Dom.setStyle(el, 'position', 'relative');
1259
            }
1260
    
1261
            if ( isset(attributes['points']['from']) ) {
1262
                Y.Dom.setXY(el, attributes['points']['from']); // set position to from point
1263
            } 
1264
            else { Y.Dom.setXY( el, Y.Dom.getXY(el) ); } // set it to current position
1265
            
1266
            start = this.getAttribute('points'); // get actual top & left
1267
            
1268
            // TO beats BY, per SMIL 2.1 spec
1269
            if ( isset(attributes['points']['to']) ) {
1270
                end = translateValues.call(this, attributes['points']['to'], start);
1271
                
1272
                var pageXY = Y.Dom.getXY(this.getEl());
1273
                for (i = 0, len = control.length; i < len; ++i) {
1274
                    control[i] = translateValues.call(this, control[i], start);
1275
                }
1276
1277
                
1278
            } else if ( isset(attributes['points']['by']) ) {
1279
                end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
1280
                
1281
                for (i = 0, len = control.length; i < len; ++i) {
1282
                    control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
1283
                }
1284
            }
1285
1286
            this.runtimeAttributes[attr] = [start];
1287
            
1288
            if (control.length > 0) {
1289
                this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control); 
1290
            }
1291
1292
            this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
1293
        }
1294
        else {
1295
            superclass.setRuntimeAttribute.call(this, attr);
1296
        }
1297
    };
1298
    
1299
    var translateValues = function(val, start) {
1300
        var pageXY = Y.Dom.getXY(this.getEl());
1301
        val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
1302
1303
        return val; 
1304
    };
1305
    
1306
    var isset = function(prop) {
1307
        return (typeof prop !== 'undefined');
1308
    };
1309
1310
    Y.Motion = Motion;
1311
})();
1312
(function() {
1313
/**
1314
 * Anim subclass for scrolling elements to a position defined by the "scroll"
1315
 * member of "attributes".  All "scroll" members are arrays with x, y scroll positions.
1316
 * <p>Usage: <code>var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1317
 * @class Scroll
1318
 * @namespace YAHOO.util
1319
 * @requires YAHOO.util.Anim
1320
 * @requires YAHOO.util.AnimMgr
1321
 * @requires YAHOO.util.Easing
1322
 * @requires YAHOO.util.Bezier
1323
 * @requires YAHOO.util.Dom
1324
 * @requires YAHOO.util.Event
1325
 * @requires YAHOO.util.CustomEvent 
1326
 * @extends YAHOO.util.ColorAnim
1327
 * @constructor
1328
 * @param {String or HTMLElement} el Reference to the element that will be animated
1329
 * @param {Object} attributes The attribute(s) to be animated.  
1330
 * Each attribute is an object with at minimum a "to" or "by" member defined.  
1331
 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").  
1332
 * All attribute names use camelCase.
1333
 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1334
 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
1335
 */
1336
    var Scroll = function(el, attributes, duration,  method) {
1337
        if (el) { // dont break existing subclasses not using YAHOO.extend
1338
            Scroll.superclass.constructor.call(this, el, attributes, duration, method);
1339
        }
1340
    };
1341
1342
    Scroll.NAME = 'Scroll';
1343
1344
    // shorthand
1345
    var Y = YAHOO.util;
1346
    YAHOO.extend(Scroll, Y.ColorAnim);
1347
    
1348
    var superclass = Scroll.superclass;
1349
    var proto = Scroll.prototype;
1350
1351
    proto.doMethod = function(attr, start, end) {
1352
        var val = null;
1353
    
1354
        if (attr == 'scroll') {
1355
            val = [
1356
                this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
1357
                this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
1358
            ];
1359
            
1360
        } else {
1361
            val = superclass.doMethod.call(this, attr, start, end);
1362
        }
1363
        return val;
1364
    };
1365
1366
    proto.getAttribute = function(attr) {
1367
        var val = null;
1368
        var el = this.getEl();
1369
        
1370
        if (attr == 'scroll') {
1371
            val = [ el.scrollLeft, el.scrollTop ];
1372
        } else {
1373
            val = superclass.getAttribute.call(this, attr);
1374
        }
1375
        
1376
        return val;
1377
    };
1378
1379
    proto.setAttribute = function(attr, val, unit) {
1380
        var el = this.getEl();
1381
        
1382
        if (attr == 'scroll') {
1383
            el.scrollLeft = val[0];
1384
            el.scrollTop = val[1];
1385
        } else {
1386
            superclass.setAttribute.call(this, attr, val, unit);
1387
        }
1388
    };
1389
1390
    Y.Scroll = Scroll;
1391
})();
1392
YAHOO.register("animation", YAHOO.util.Anim, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/button/assets/button-core.css (-44 lines)
Lines 1-44 Link Here
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.8.0r4
6
*/
7
.yui-button  {
8
9
    display: -moz-inline-box; /* Gecko */
10
    display: inline-block; /* IE, Opera and Safari */
11
    vertical-align: text-bottom;
12
    
13
}
14
15
.yui-button .first-child {
16
17
    display: block;
18
    *display: inline-block; /* IE */
19
20
}
21
22
.yui-button button,
23
.yui-button a {
24
25
    display: block;
26
    *display: inline-block; /* IE */
27
    border: none;
28
    margin: 0;
29
30
}
31
32
.yui-button button {
33
34
    background-color: transparent;
35
    *overflow: visible; /* Remove superfluous padding for IE */
36
    cursor: pointer;
37
38
}
39
40
.yui-button a {
41
42
    text-decoration: none;
43
44
}
(-)a/koha-tmpl/intranet-tmpl/lib/yui/button/assets/skins/sam/button-skin.css (-219 lines)
Lines 1-219 Link Here
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.8.0r4
6
*/
7
.yui-skin-sam .yui-button  {
8
9
    border-width: 1px 0;
10
    border-style: solid;
11
    border-color: #808080;
12
    background: url(../../../../assets/skins/sam/sprite.png) repeat-x 0 0;
13
    margin: auto .25em;
14
    
15
}
16
17
.yui-skin-sam .yui-button .first-child {
18
19
    border-width: 0 1px;
20
    border-style: solid;
21
    border-color: #808080;
22
    margin: 0 -1px;
23
24
	/*
25
		Using negative margins for rounded corners won't work in IE 6 and IE 7 
26
		(Quirks Mode Only), so set the "margin" property to "0" for those 
27
		browsers.
28
	*/
29
 	_margin: 0;
30
31
}
32
33
.yui-skin-sam .yui-button button,
34
.yui-skin-sam .yui-button a,
35
.yui-skin-sam .yui-button a:visited {
36
37
    padding: 0 10px;
38
    font-size: 93%;  /* 12px */
39
    line-height: 2;  /* ~24px */
40
    *line-height: 1.7; /* For IE */
41
    min-height: 2em; /* For Gecko */
42
    *min-height: auto; /* For IE */
43
    color: #000; 
44
45
}
46
47
.yui-skin-sam .yui-button a {
48
49
    /*
50
        Necessary to get Buttons of type "link" to be the correct 
51
        height in IE.
52
    */
53
    *line-height: 1.875;
54
	*padding-bottom: 1px;
55
56
}
57
58
.yui-skin-sam .yui-split-button button,
59
.yui-skin-sam .yui-menu-button button {
60
61
    padding-right: 20px;
62
    background-position: right center;
63
    background-repeat: no-repeat;
64
    
65
}
66
67
.yui-skin-sam .yui-menu-button button {
68
69
    background-image: url(menu-button-arrow.png);
70
71
}
72
73
.yui-skin-sam .yui-split-button button {
74
75
    background-image: url(split-button-arrow.png);
76
77
}
78
79
80
/* Focus state */
81
82
83
.yui-skin-sam .yui-button-focus {
84
85
    border-color: #7D98B8;
86
    background-position: 0 -1300px;
87
88
}
89
90
.yui-skin-sam .yui-button-focus .first-child {
91
92
    border-color: #7D98B8;
93
94
}
95
96
.yui-skin-sam .yui-split-button-focus button {
97
98
    background-image: url(split-button-arrow-focus.png);
99
100
}
101
102
103
/* Hover state */
104
105
.yui-skin-sam .yui-button-hover {
106
107
    border-color: #7D98B8;
108
    background-position: 0 -1300px;
109
110
}
111
112
.yui-skin-sam .yui-button-hover .first-child {
113
114
    border-color: #7D98B8;
115
116
}
117
118
.yui-skin-sam .yui-split-button-hover button {
119
120
    background-image: url(split-button-arrow-hover.png);
121
122
}
123
124
125
/* Active state */
126
127
.yui-skin-sam .yui-button-active {
128
    
129
    border-color: #7D98B8;
130
    background-position: 0 -1700px;
131
    
132
}
133
134
.yui-skin-sam .yui-button-active .first-child {
135
136
    border-color: #7D98B8;
137
138
}
139
140
.yui-skin-sam .yui-split-button-activeoption {
141
142
    border-color: #808080;
143
    background-position: 0 0;
144
145
}
146
147
.yui-skin-sam .yui-split-button-activeoption .first-child {
148
149
    border-color: #808080;
150
151
}
152
153
.yui-skin-sam .yui-split-button-activeoption button {
154
155
    background-image: url(split-button-arrow-active.png);
156
157
}
158
159
160
/* Checked state */
161
162
.yui-skin-sam .yui-radio-button-checked,
163
.yui-skin-sam .yui-checkbox-button-checked {
164
    
165
    border-color: #304369;
166
    background-position: 0 -1400px;
167
    
168
}
169
170
.yui-skin-sam .yui-radio-button-checked .first-child,
171
.yui-skin-sam .yui-checkbox-button-checked .first-child {
172
173
    border-color: #304369;
174
175
}
176
177
.yui-skin-sam .yui-radio-button-checked button,
178
.yui-skin-sam .yui-checkbox-button-checked button { 
179
180
    color: #fff;
181
182
}
183
184
185
/* Disabled state */
186
187
.yui-skin-sam .yui-button-disabled {
188
    
189
    border-color: #ccc;
190
    background-position: 0 -1500px;
191
    
192
}
193
194
.yui-skin-sam .yui-button-disabled .first-child {
195
196
    border-color: #ccc;
197
198
}
199
200
.yui-skin-sam .yui-button-disabled button, 
201
.yui-skin-sam .yui-button-disabled a,
202
.yui-skin-sam .yui-button-disabled a:visited {
203
204
    color: #A6A6A6;
205
    cursor: default;
206
207
}
208
209
.yui-skin-sam .yui-menu-button-disabled button {
210
211
    background-image: url(menu-button-arrow-disabled.png);
212
    
213
}
214
215
.yui-skin-sam .yui-split-button-disabled button {
216
217
    background-image: url(split-button-arrow-disabled.png);
218
    
219
}
(-)a/koha-tmpl/intranet-tmpl/lib/yui/button/assets/skins/sam/button.css (-7 lines)
Lines 1-7 Link Here
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.8.0r4
6
*/
7
.yui-button{display:-moz-inline-box;display:inline-block;vertical-align:text-bottom;}.yui-button .first-child{display:block;*display:inline-block;}.yui-button button,.yui-button a{display:block;*display:inline-block;border:none;margin:0;}.yui-button button{background-color:transparent;*overflow:visible;cursor:pointer;}.yui-button a{text-decoration:none;}.yui-skin-sam .yui-button{border-width:1px 0;border-style:solid;border-color:#808080;background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 0;margin:auto .25em;}.yui-skin-sam .yui-button .first-child{border-width:0 1px;border-style:solid;border-color:#808080;margin:0 -1px;_margin:0;}.yui-skin-sam .yui-button button,.yui-skin-sam .yui-button a,.yui-skin-sam .yui-button a:visited{padding:0 10px;font-size:93%;line-height:2;*line-height:1.7;min-height:2em;*min-height:auto;color:#000;}.yui-skin-sam .yui-button a{*line-height:1.875;*padding-bottom:1px;}.yui-skin-sam .yui-split-button button,.yui-skin-sam .yui-menu-button button{padding-right:20px;background-position:right center;background-repeat:no-repeat;}.yui-skin-sam .yui-menu-button button{background-image:url(menu-button-arrow.png);}.yui-skin-sam .yui-split-button button{background-image:url(split-button-arrow.png);}.yui-skin-sam .yui-button-focus{border-color:#7D98B8;background-position:0 -1300px;}.yui-skin-sam .yui-button-focus .first-child{border-color:#7D98B8;}.yui-skin-sam .yui-split-button-focus button{background-image:url(split-button-arrow-focus.png);}.yui-skin-sam .yui-button-hover{border-color:#7D98B8;background-position:0 -1300px;}.yui-skin-sam .yui-button-hover .first-child{border-color:#7D98B8;}.yui-skin-sam .yui-split-button-hover button{background-image:url(split-button-arrow-hover.png);}.yui-skin-sam .yui-button-active{border-color:#7D98B8;background-position:0 -1700px;}.yui-skin-sam .yui-button-active .first-child{border-color:#7D98B8;}.yui-skin-sam .yui-split-button-activeoption{border-color:#808080;background-position:0 0;}.yui-skin-sam .yui-split-button-activeoption .first-child{border-color:#808080;}.yui-skin-sam .yui-split-button-activeoption button{background-image:url(split-button-arrow-active.png);}.yui-skin-sam .yui-radio-button-checked,.yui-skin-sam .yui-checkbox-button-checked{border-color:#304369;background-position:0 -1400px;}.yui-skin-sam .yui-radio-button-checked .first-child,.yui-skin-sam .yui-checkbox-button-checked .first-child{border-color:#304369;}.yui-skin-sam .yui-radio-button-checked button,.yui-skin-sam .yui-checkbox-button-checked button{color:#fff;}.yui-skin-sam .yui-button-disabled{border-color:#ccc;background-position:0 -1500px;}.yui-skin-sam .yui-button-disabled .first-child{border-color:#ccc;}.yui-skin-sam .yui-button-disabled button,.yui-skin-sam .yui-button-disabled a,.yui-skin-sam .yui-button-disabled a:visited{color:#A6A6A6;cursor:default;}.yui-skin-sam .yui-menu-button-disabled button{background-image:url(menu-button-arrow-disabled.png);}.yui-skin-sam .yui-split-button-disabled button{background-image:url(split-button-arrow-disabled.png);}
(-)a/koha-tmpl/intranet-tmpl/lib/yui/button/button-beta-min.js (-11 lines)
Lines 1-11 Link Here
1
/*
2
Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3
Code licensed under the BSD License:
4
http://developer.yahoo.net/yui/license.txt
5
version: 2.3.1
6
*/
7
(function(){var G=YAHOO.util.Dom,L=YAHOO.util.Event,I=YAHOO.lang,B=YAHOO.widget.Overlay,J=YAHOO.widget.Menu,D={},K=null,E=null,C=null;function F(N,M,Q,O){var R,P;if(I.isString(N)&&I.isString(M)){if(YAHOO.env.ua.ie){P="<input type=\""+N+"\" name=\""+M+"\"";if(O){P+=" checked";}P+=">";R=document.createElement(P);}else{R=document.createElement("input");R.name=M;R.type=N;if(O){R.checked=true;}}R.value=Q;return R;}}function H(N,T){var M=N.nodeName.toUpperCase(),R=this,S,O,P;function U(V){if(!(V in T)){S=N.getAttributeNode(V);if(S&&("value" in S)){T[V]=S.value;}}}function Q(){U("type");if(T.type=="button"){T.type="push";}if(!("disabled" in T)){T.disabled=N.disabled;}U("name");U("value");U("title");}switch(M){case"A":T.type="link";U("href");U("target");break;case"INPUT":Q();if(!("checked" in T)){T.checked=N.checked;}break;case"BUTTON":Q();O=N.parentNode.parentNode;if(G.hasClass(O,this.CSS_CLASS_NAME+"-checked")){T.checked=true;}if(G.hasClass(O,this.CSS_CLASS_NAME+"-disabled")){T.disabled=true;}N.removeAttribute("value");N.setAttribute("type","button");break;}N.removeAttribute("id");N.removeAttribute("name");if(!("tabindex" in T)){T.tabindex=N.tabIndex;}if(!("label" in T)){P=M=="INPUT"?N.value:N.innerHTML;if(P&&P.length>0){T.label=P;}}}function A(O){var N=O.attributes,M=N.srcelement,Q=M.nodeName.toUpperCase(),P=this;if(Q==this.NODE_NAME){O.element=M;O.id=M.id;G.getElementsBy(function(R){switch(R.nodeName.toUpperCase()){case"BUTTON":case"A":case"INPUT":H.call(P,R,N);break;}},"*",M);}else{switch(Q){case"BUTTON":case"A":case"INPUT":H.call(this,M,N);break;}}}YAHOO.widget.Button=function(Q,N){var P=YAHOO.widget.Button.superclass.constructor,O,M;if(arguments.length==1&&!I.isString(Q)&&!Q.nodeName){if(!Q.id){Q.id=G.generateId();}P.call(this,(this.createButtonElement(Q.type)),Q);}else{O={element:null,attributes:(N||{})};if(I.isString(Q)){M=G.get(Q);if(M){if(!O.attributes.id){O.attributes.id=Q;}O.attributes.srcelement=M;A.call(this,O);if(!O.element){O.element=this.createButtonElement(O.attributes.type);}P.call(this,O.element,O.attributes);}}else{if(Q.nodeName){if(!O.attributes.id){if(Q.id){O.attributes.id=Q.id;}else{O.attributes.id=G.generateId();}}O.attributes.srcelement=Q;A.call(this,O);if(!O.element){O.element=this.createButtonElement(O.attributes.type);}P.call(this,O.element,O.attributes);}}}};YAHOO.extend(YAHOO.widget.Button,YAHOO.util.Element,{_button:null,_menu:null,_hiddenFields:null,_onclickAttributeValue:null,_activationKeyPressed:false,_activationButtonPressed:false,_hasKeyEventHandlers:false,_hasMouseEventHandlers:false,NODE_NAME:"SPAN",CHECK_ACTIVATION_KEYS:[32],ACTIVATION_KEYS:[13,32],OPTION_AREA_WIDTH:20,CSS_CLASS_NAME:"yui-button",RADIO_DEFAULT_TITLE:"Unchecked.  Click to check.",RADIO_CHECKED_TITLE:"Checked.  Click to uncheck.",CHECKBOX_DEFAULT_TITLE:"Unchecked.  Click to check.",CHECKBOX_CHECKED_TITLE:"Checked.  Click to uncheck.",MENUBUTTON_DEFAULT_TITLE:"Menu collapsed.  Click to expand.",MENUBUTTON_MENU_VISIBLE_TITLE:"Menu expanded.  Click or press Esc to collapse.",SPLITBUTTON_DEFAULT_TITLE:("Menu collapsed.  Click inside option region or press Ctrl + Shift + M to show the menu."),SPLITBUTTON_OPTION_VISIBLE_TITLE:"Menu expanded.  Press Esc or Ctrl + Shift + M to hide the menu.",SUBMIT_TITLE:"Click to submit form.",_setType:function(M){if(M=="split"){this.on("option",this._onOption);}},_setLabel:function(M){this._button.innerHTML=M;var O,N;if(YAHOO.env.ua.gecko&&G.inDocument(this.get("element"))){N=this;O=this.CSS_CLASS_NAME;this.removeClass(O);window.setTimeout(function(){N.addClass(O);},0);}},_setTabIndex:function(M){this._button.tabIndex=M;},_setTitle:function(N){var M=N;if(this.get("type")!="link"){if(!M){switch(this.get("type")){case"radio":M=this.RADIO_DEFAULT_TITLE;break;case"checkbox":M=this.CHECKBOX_DEFAULT_TITLE;break;case"menu":M=this.MENUBUTTON_DEFAULT_TITLE;break;case"split":M=this.SPLITBUTTON_DEFAULT_TITLE;break;case"submit":M=this.SUBMIT_TITLE;break;}}this._button.title=M;}},_setDisabled:function(M){if(this.get("type")!="link"){if(M){if(this._menu){this._menu.hide();}if(this.hasFocus()){this.blur();}this._button.setAttribute("disabled","disabled");this.addStateCSSClasses("disabled");this.removeStateCSSClasses("hover");this.removeStateCSSClasses("active");this.removeStateCSSClasses("focus");}else{this._button.removeAttribute("disabled");this.removeStateCSSClasses("disabled");}}},_setHref:function(M){if(this.get("type")=="link"){this._button.href=M;}},_setTarget:function(M){if(this.get("type")=="link"){this._button.setAttribute("target",M);}},_setChecked:function(N){var O=this.get("type"),M;if(O=="checkbox"||O=="radio"){if(N){this.addStateCSSClasses("checked");M=(O=="radio")?this.RADIO_CHECKED_TITLE:this.CHECKBOX_CHECKED_TITLE;}else{this.removeStateCSSClasses("checked");M=(O=="radio")?this.RADIO_DEFAULT_TITLE:this.CHECKBOX_DEFAULT_TITLE;}this.set("title",M);}},_setMenu:function(W){var Q=this.get("lazyloadmenu"),T=this.get("element"),M=J.prototype.CSS_CLASS_NAME,Y=false,Z,P,S,O,N,V,R;if(!B){return false;}if(!J){return false;}function X(){Z.render(T.parentNode);this.removeListener("appendTo",X);}function U(){if(Z){G.addClass(Z.element,this.get("menuclassname"));G.addClass(Z.element,"yui-"+this.get("type")+"-button-menu");Z.showEvent.subscribe(this._onMenuShow,null,this);Z.hideEvent.subscribe(this._onMenuHide,null,this);Z.renderEvent.subscribe(this._onMenuRender,null,this);if(Z instanceof J){Z.keyDownEvent.subscribe(this._onMenuKeyDown,this,true);Z.subscribe("click",this._onMenuClick,this,true);Z.itemAddedEvent.subscribe(this._onMenuItemAdded,this,true);S=Z.srcElement;if(S&&S.nodeName.toUpperCase()=="SELECT"){S.style.display="none";S.parentNode.removeChild(S);}}else{if(Z instanceof B){if(!K){K=new YAHOO.widget.OverlayManager();}K.register(Z);}}this._menu=Z;if(!Y){if(Q&&!(Z instanceof J)){Z.beforeShowEvent.subscribe(this._onOverlayBeforeShow,null,this);}else{if(!Q){if(G.inDocument(T)){Z.render(T.parentNode);}else{this.on("appendTo",X);}}}}}}if(W&&(W instanceof J)){Z=W;O=Z.getItems();
8
N=O.length;Y=true;if(N>0){R=N-1;do{V=O[R];if(V){V.cfg.subscribeToConfigEvent("selected",this._onMenuItemSelected,V,this);}}while(R--);}U.call(this);}else{if(W&&(W instanceof B)){Z=W;Y=true;Z.cfg.setProperty("visible",false);Z.cfg.setProperty("context",[T,"tl","bl"]);U.call(this);}else{if(I.isArray(W)){this.on("appendTo",function(){Z=new J(G.generateId(),{lazyload:Q,itemdata:W});U.call(this);});}else{if(I.isString(W)){P=G.get(W);if(P){if(G.hasClass(P,M)||P.nodeName.toUpperCase()=="SELECT"){Z=new J(W,{lazyload:Q});U.call(this);}else{Z=new B(W,{visible:false,context:[T,"tl","bl"]});U.call(this);}}}else{if(W&&W.nodeName){if(G.hasClass(W,M)||W.nodeName.toUpperCase()=="SELECT"){Z=new J(W,{lazyload:Q});U.call(this);}else{if(!W.id){G.generateId(W);}Z=new B(W,{visible:false,context:[T,"tl","bl"]});U.call(this);}}}}}}},_setOnClick:function(M){if(this._onclickAttributeValue&&(this._onclickAttributeValue!=M)){this.removeListener("click",this._onclickAttributeValue.fn);this._onclickAttributeValue=null;}if(!this._onclickAttributeValue&&I.isObject(M)&&I.isFunction(M.fn)){this.on("click",M.fn,M.obj,M.scope);this._onclickAttributeValue=M;}},_setSelectedMenuItem:function(N){var M=this._menu,O;if(M&&M instanceof J){O=M.getItem(N);if(O&&!O.cfg.getProperty("selected")){O.cfg.setProperty("selected",true);}}},_isActivationKey:function(M){var Q=this.get("type"),N=(Q=="checkbox"||Q=="radio")?this.CHECK_ACTIVATION_KEYS:this.ACTIVATION_KEYS,P=N.length,O;if(P>0){O=P-1;do{if(M==N[O]){return true;}}while(O--);}},_isSplitButtonOptionKey:function(M){return(M.ctrlKey&&M.shiftKey&&L.getCharCode(M)==77);},_addListenersToForm:function(){var S=this.getForm(),R=YAHOO.widget.Button.onFormKeyPress,Q,M,P,O,N;if(S){L.on(S,"reset",this._onFormReset,null,this);L.on(S,"submit",this.createHiddenFields,null,this);M=this.get("srcelement");if(this.get("type")=="submit"||(M&&M.type=="submit")){P=L.getListeners(S,"keypress");Q=false;if(P){O=P.length;if(O>0){N=O-1;do{if(P[N].fn==R){Q=true;break;}}while(N--);}}if(!Q){L.on(S,"keypress",R);}}}},_originalMaxHeight:-1,_showMenu:function(O){YAHOO.widget.MenuManager.hideVisible();if(K){K.hideAll();}var M=this._menu,N=G.getViewportHeight(),Q,R,P;if(M&&(M instanceof J)){M.cfg.applyConfig({context:[this.get("id"),"tl","bl"],constraintoviewport:false,clicktohide:false,visible:true});M.cfg.fireQueue();M.align("tl","bl");if(O.type=="mousedown"){L.stopPropagation(O);}if(this.get("focusmenu")){this._menu.focus();}Q=M.element.offsetHeight;if((M.cfg.getProperty("y")+Q)>N){M.align("bl","tl");P=M.cfg.getProperty("y");R=G.getDocumentScrollTop();if(R>=P){if(this._originalMaxHeight==-1){this._originalMaxHeight=M.cfg.getProperty("maxheight");}M.cfg.setProperty("maxheight",(Q-((R-P)+20)));M.align("bl","tl");}}}else{if(M&&(M instanceof B)){M.show();M.align("tl","bl");Q=M.element.offsetHeight;if((M.cfg.getProperty("y")+Q)>N){M.align("bl","tl");}}}},_hideMenu:function(){var M=this._menu;if(M){M.hide();}},_onMouseOver:function(M){if(!this._hasMouseEventHandlers){this.on("mouseout",this._onMouseOut);this.on("mousedown",this._onMouseDown);this.on("mouseup",this._onMouseUp);this._hasMouseEventHandlers=true;}this.addStateCSSClasses("hover");if(this._activationButtonPressed){this.addStateCSSClasses("active");}if(this._bOptionPressed){this.addStateCSSClasses("activeoption");}},_onMouseOut:function(M){this.removeStateCSSClasses("hover");if(this.get("type")!="menu"){this.removeStateCSSClasses("active");}if(this._activationButtonPressed||this._bOptionPressed){L.on(document,"mouseup",this._onDocumentMouseUp,null,this);}},_onDocumentMouseUp:function(M){this._activationButtonPressed=false;this._bOptionPressed=false;var N=this.get("type");if(N=="menu"||N=="split"){this.removeStateCSSClasses((N=="menu"?"active":"activeoption"));this._hideMenu();}L.removeListener(document,"mouseup",this._onDocumentMouseUp);},_onMouseDown:function(P){var R,N,Q,O;function M(){this._hideMenu();this.removeListener("mouseup",M);}if((P.which||P.button)==1){if(!this.hasFocus()){this.focus();}R=this.get("type");if(R=="split"){N=this.get("element");Q=L.getPageX(P)-G.getX(N);if((N.offsetWidth-this.OPTION_AREA_WIDTH)<Q){this.fireEvent("option",P);}else{this.addStateCSSClasses("active");this._activationButtonPressed=true;}}else{if(R=="menu"){if(this.isActive()){this._hideMenu();this._activationButtonPressed=false;}else{this._showMenu(P);this._activationButtonPressed=true;}}else{this.addStateCSSClasses("active");this._activationButtonPressed=true;}}if(R=="split"||R=="menu"){O=this;this._hideMenuTimerId=window.setTimeout(function(){O.on("mouseup",M);},250);}}},_onMouseUp:function(M){var N=this.get("type");if(this._hideMenuTimerId){window.clearTimeout(this._hideMenuTimerId);}if(N=="checkbox"||N=="radio"){this.set("checked",!(this.get("checked")));}this._activationButtonPressed=false;if(this.get("type")!="menu"){this.removeStateCSSClasses("active");}},_onFocus:function(N){var M;this.addStateCSSClasses("focus");if(this._activationKeyPressed){this.addStateCSSClasses("active");}C=this;if(!this._hasKeyEventHandlers){M=this._button;L.on(M,"blur",this._onBlur,null,this);L.on(M,"keydown",this._onKeyDown,null,this);L.on(M,"keyup",this._onKeyUp,null,this);this._hasKeyEventHandlers=true;}this.fireEvent("focus",N);},_onBlur:function(M){this.removeStateCSSClasses("focus");if(this.get("type")!="menu"){this.removeStateCSSClasses("active");}if(this._activationKeyPressed){L.on(document,"keyup",this._onDocumentKeyUp,null,this);}C=null;this.fireEvent("blur",M);},_onDocumentKeyUp:function(M){if(this._isActivationKey(L.getCharCode(M))){this._activationKeyPressed=false;L.removeListener(document,"keyup",this._onDocumentKeyUp);}},_onKeyDown:function(N){var M=this._menu;if(this.get("type")=="split"&&this._isSplitButtonOptionKey(N)){this.fireEvent("option",N);}else{if(this._isActivationKey(L.getCharCode(N))){if(this.get("type")=="menu"){this._showMenu(N);}else{this._activationKeyPressed=true;this.addStateCSSClasses("active");}}}if(M&&M.cfg.getProperty("visible")&&L.getCharCode(N)==27){M.hide();
9
this.focus();}},_onKeyUp:function(M){var N;if(this._isActivationKey(L.getCharCode(M))){N=this.get("type");if(N=="checkbox"||N=="radio"){this.set("checked",!(this.get("checked")));}this._activationKeyPressed=false;if(this.get("type")!="menu"){this.removeStateCSSClasses("active");}}},_onClick:function(P){var S=this.get("type"),M,Q,N,O,R;switch(S){case"radio":case"checkbox":if(this.get("checked")){M=(S=="radio")?this.RADIO_CHECKED_TITLE:this.CHECKBOX_CHECKED_TITLE;}else{M=(S=="radio")?this.RADIO_DEFAULT_TITLE:this.CHECKBOX_DEFAULT_TITLE;}this.set("title",M);break;case"submit":this.submitForm();break;case"reset":Q=this.getForm();if(Q){Q.reset();}break;case"menu":M=this._menu.cfg.getProperty("visible")?this.MENUBUTTON_MENU_VISIBLE_TITLE:this.MENUBUTTON_DEFAULT_TITLE;this.set("title",M);break;case"split":O=this.get("element");R=L.getPageX(P)-G.getX(O);if((O.offsetWidth-this.OPTION_AREA_WIDTH)<R){return false;}else{this._hideMenu();N=this.get("srcelement");if(N&&N.type=="submit"){this.submitForm();}}M=this._menu.cfg.getProperty("visible")?this.SPLITBUTTON_OPTION_VISIBLE_TITLE:this.SPLITBUTTON_DEFAULT_TITLE;this.set("title",M);break;}},_onAppendTo:function(N){var M=this;window.setTimeout(function(){M._addListenersToForm();},0);},_onFormReset:function(N){var O=this.get("type"),M=this._menu;if(O=="checkbox"||O=="radio"){this.resetValue("checked");}if(M&&(M instanceof J)){this.resetValue("selectedMenuItem");}},_onDocumentMouseDown:function(P){var M=L.getTarget(P),O=this.get("element"),N=this._menu.element;if(M!=O&&!G.isAncestor(O,M)&&M!=N&&!G.isAncestor(N,M)){this._hideMenu();L.removeListener(document,"mousedown",this._onDocumentMouseDown);}},_onOption:function(M){if(this.hasClass("yui-split-button-activeoption")){this._hideMenu();this._bOptionPressed=false;}else{this._showMenu(M);this._bOptionPressed=true;}},_onOverlayBeforeShow:function(N){var M=this._menu;M.render(this.get("element").parentNode);M.beforeShowEvent.unsubscribe(this._onOverlayBeforeShow);},_onMenuShow:function(N){L.on(document,"mousedown",this._onDocumentMouseDown,null,this);var M,O;if(this.get("type")=="split"){M=this.SPLITBUTTON_OPTION_VISIBLE_TITLE;O="activeoption";}else{M=this.MENUBUTTON_MENU_VISIBLE_TITLE;O="active";}this.addStateCSSClasses(O);this.set("title",M);},_onMenuHide:function(O){var N=this._menu,M,P;if(N&&(N instanceof J)&&this._originalMaxHeight!=-1){this._menu.cfg.setProperty("maxheight",this._originalMaxHeight);}if(this.get("type")=="split"){M=this.SPLITBUTTON_DEFAULT_TITLE;P="activeoption";}else{M=this.MENUBUTTON_DEFAULT_TITLE;P="active";}this.removeStateCSSClasses(P);this.set("title",M);if(this.get("type")=="split"){this._bOptionPressed=false;}},_onMenuKeyDown:function(O,N){var M=N[0];if(L.getCharCode(M)==27){this.focus();if(this.get("type")=="split"){this._bOptionPressed=false;}}},_onMenuRender:function(N){var P=this.get("element"),M=P.parentNode,O=this._menu.element;if(M!=O.parentNode){M.appendChild(O);}this.set("selectedMenuItem",this.get("selectedMenuItem"));},_onMenuItemSelected:function(N,M,P){var O=M[0];if(O){this.set("selectedMenuItem",P);}},_onMenuItemAdded:function(O,N,M){var P=N[0];P.cfg.subscribeToConfigEvent("selected",this._onMenuItemSelected,P.index,this);},_onMenuClick:function(N,M){var P=M[1],O;if(P){O=this.get("srcelement");if(O&&O.type=="submit"){this.submitForm();}this._hideMenu();}},createButtonElement:function(M){var O=this.NODE_NAME,N=document.createElement(O);N.innerHTML="<"+O+" class=\"first-child\">"+(M=="link"?"<a></a>":"<button type=\"button\"></button>")+"</"+O+">";return N;},addStateCSSClasses:function(M){var N=this.get("type");if(I.isString(M)){if(M!="activeoption"){this.addClass(this.CSS_CLASS_NAME+("-"+M));}this.addClass("yui-"+N+("-button-"+M));}},removeStateCSSClasses:function(M){var N=this.get("type");if(I.isString(M)){this.removeClass(this.CSS_CLASS_NAME+("-"+M));this.removeClass("yui-"+N+("-button-"+M));}},createHiddenFields:function(){this.removeHiddenFields();var R=this.getForm(),U,N,P,S,T,O,Q,M;if(R&&!this.get("disabled")){N=this.get("type");P=(N=="checkbox"||N=="radio");if(P||(E==this)){U=F((P?N:"hidden"),this.get("name"),this.get("value"),this.get("checked"));if(U){if(P){U.style.display="none";}R.appendChild(U);}}S=this._menu;if(S&&(S instanceof J)){M=S.srcElement;T=S.getItem(this.get("selectedMenuItem"));if(T){if(M&&M.nodeName.toUpperCase()=="SELECT"){R.appendChild(M);M.selectedIndex=T.index;}else{Q=(T.value===null||T.value==="")?T.cfg.getProperty("text"):T.value;O=this.get("name");if(Q&&O){M=F("hidden",(O+"_options"),Q);R.appendChild(M);}}}}if(U&&M){this._hiddenFields=[U,M];}else{if(!U&&M){this._hiddenFields=M;}else{if(U&&!M){this._hiddenFields=U;}}}return this._hiddenFields;}},removeHiddenFields:function(){var P=this._hiddenFields,N,O;function M(Q){if(G.inDocument(Q)){Q.parentNode.removeChild(Q);}}if(P){if(I.isArray(P)){N=P.length;if(N>0){O=N-1;do{M(P[O]);}while(O--);}}else{M(P);}this._hiddenFields=null;}},submitForm:function(){var P=this.getForm(),O=this.get("srcelement"),N=false,M;if(P){if(this.get("type")=="submit"||(O&&O.type=="submit")){E=this;}if(YAHOO.env.ua.ie){N=P.fireEvent("onsubmit");}else{M=document.createEvent("HTMLEvents");M.initEvent("submit",true,true);N=P.dispatchEvent(M);}if((YAHOO.env.ua.ie||YAHOO.env.ua.webkit)&&N){P.submit();}}return N;},init:function(M,T){var O=T.type=="link"?"a":"button",Q=T.srcelement,S=M.getElementsByTagName(O)[0],R;if(!S){R=M.getElementsByTagName("input")[0];if(R){S=document.createElement("button");S.setAttribute("type","button");R.parentNode.replaceChild(S,R);}}this._button=S;YAHOO.widget.Button.superclass.init.call(this,M,T);D[this.get("id")]=this;this.addClass(this.CSS_CLASS_NAME);this.addClass("yui-"+this.get("type")+"-button");L.on(this._button,"focus",this._onFocus,null,this);this.on("mouseover",this._onMouseOver);this.on("click",this._onClick);this.on("appendTo",this._onAppendTo);var V=this.get("container"),N=this.get("element"),U=G.inDocument(N),P;if(V){if(Q&&Q!=N){P=Q.parentNode;if(P){P.removeChild(Q);}}if(I.isString(V)){L.onContentReady(V,function(){this.appendTo(V);
10
},null,this);}else{this.appendTo(V);}}else{if(!U&&Q&&Q!=N){P=Q.parentNode;if(P){this.fireEvent("beforeAppendTo",{type:"beforeAppendTo",target:P});P.replaceChild(N,Q);this.fireEvent("appendTo",{type:"appendTo",target:P});}}else{if(this.get("type")!="link"&&U&&Q&&Q==N){this._addListenersToForm();}}}},initAttributes:function(N){var M=N||{};YAHOO.widget.Button.superclass.initAttributes.call(this,M);this.setAttributeConfig("type",{value:(M.type||"push"),validator:I.isString,writeOnce:true,method:this._setType});this.setAttributeConfig("label",{value:M.label,validator:I.isString,method:this._setLabel});this.setAttributeConfig("value",{value:M.value});this.setAttributeConfig("name",{value:M.name,validator:I.isString});this.setAttributeConfig("tabindex",{value:M.tabindex,validator:I.isNumber,method:this._setTabIndex});this.configureAttribute("title",{value:M.title,validator:I.isString,method:this._setTitle});this.setAttributeConfig("disabled",{value:(M.disabled||false),validator:I.isBoolean,method:this._setDisabled});this.setAttributeConfig("href",{value:M.href,validator:I.isString,method:this._setHref});this.setAttributeConfig("target",{value:M.target,validator:I.isString,method:this._setTarget});this.setAttributeConfig("checked",{value:(M.checked||false),validator:I.isBoolean,method:this._setChecked});this.setAttributeConfig("container",{value:M.container,writeOnce:true});this.setAttributeConfig("srcelement",{value:M.srcelement,writeOnce:true});this.setAttributeConfig("menu",{value:null,method:this._setMenu,writeOnce:true});this.setAttributeConfig("lazyloadmenu",{value:(M.lazyloadmenu===false?false:true),validator:I.isBoolean,writeOnce:true});this.setAttributeConfig("menuclassname",{value:(M.menuclassname||"yui-button-menu"),validator:I.isString,method:this._setMenuClassName,writeOnce:true});this.setAttributeConfig("selectedMenuItem",{value:0,validator:I.isNumber,method:this._setSelectedMenuItem});this.setAttributeConfig("onclick",{value:M.onclick,method:this._setOnClick});this.setAttributeConfig("focusmenu",{value:(M.focusmenu===false?false:true),validator:I.isBoolean});},focus:function(){if(!this.get("disabled")){this._button.focus();}},blur:function(){if(!this.get("disabled")){this._button.blur();}},hasFocus:function(){return(C==this);},isActive:function(){return this.hasClass(this.CSS_CLASS_NAME+"-active");},getMenu:function(){return this._menu;},getForm:function(){return this._button.form;},getHiddenFields:function(){return this._hiddenFields;},destroy:function(){var O=this.get("element"),N=O.parentNode,M=this._menu,Q;if(M){if(K.find(M)){K.remove(M);}M.destroy();}L.purgeElement(O);L.purgeElement(this._button);L.removeListener(document,"mouseup",this._onDocumentMouseUp);L.removeListener(document,"keyup",this._onDocumentKeyUp);L.removeListener(document,"mousedown",this._onDocumentMouseDown);var P=this.getForm();if(P){L.removeListener(P,"reset",this._onFormReset);L.removeListener(P,"submit",this.createHiddenFields);}this.unsubscribeAll();if(N){N.removeChild(O);}delete D[this.get("id")];Q=G.getElementsByClassName(this.CSS_CLASS_NAME,this.NODE_NAME,P);if(I.isArray(Q)&&Q.length===0){L.removeListener(P,"keypress",YAHOO.widget.Button.onFormKeyPress);}},fireEvent:function(N,M){if(this.DOM_EVENTS[N]&&this.get("disabled")){return ;}YAHOO.widget.Button.superclass.fireEvent.call(this,N,M);},toString:function(){return("Button "+this.get("id"));}});YAHOO.widget.Button.onFormKeyPress=function(Q){var O=L.getTarget(Q),R=L.getCharCode(Q),P=O.nodeName&&O.nodeName.toUpperCase(),M=O.type,S=false,U,V,N,W;function T(Z){var Y,X;switch(Z.nodeName.toUpperCase()){case"INPUT":case"BUTTON":if(Z.type=="submit"&&!Z.disabled){if(!S&&!N){N=Z;}if(V&&!W){W=Z;}}break;default:Y=Z.id;if(Y){U=D[Y];if(U){S=true;if(!U.get("disabled")){X=U.get("srcelement");if(!V&&(U.get("type")=="submit"||(X&&X.type=="submit"))){V=U;}}}}break;}}if(R==13&&((P=="INPUT"&&(M=="text"||M=="password"||M=="checkbox"||M=="radio"||M=="file"))||P=="SELECT")){G.getElementsBy(T,"*",this);if(N){N.focus();}else{if(!N&&V){if(W){L.preventDefault(Q);}V.submitForm();}}}};YAHOO.widget.Button.addHiddenFieldsToForm=function(M){var R=G.getElementsByClassName(YAHOO.widget.Button.prototype.CSS_CLASS_NAME,"*",M),P=R.length,Q,N,O;if(P>0){for(O=0;O<P;O++){N=R[O].id;if(N){Q=D[N];if(Q){Q.createHiddenFields();}}}}};})();(function(){var C=YAHOO.util.Dom,B=YAHOO.util.Event,D=YAHOO.lang,A=YAHOO.widget.Button,E={};YAHOO.widget.ButtonGroup=function(J,H){var I=YAHOO.widget.ButtonGroup.superclass.constructor,K,G,F;if(arguments.length==1&&!D.isString(J)&&!J.nodeName){if(!J.id){F=C.generateId();J.id=F;}I.call(this,(this._createGroupElement()),J);}else{if(D.isString(J)){G=C.get(J);if(G){if(G.nodeName.toUpperCase()==this.NODE_NAME){I.call(this,G,H);}}}else{K=J.nodeName.toUpperCase();if(K&&K==this.NODE_NAME){if(!J.id){J.id=C.generateId();}I.call(this,J,H);}}}};YAHOO.extend(YAHOO.widget.ButtonGroup,YAHOO.util.Element,{_buttons:null,NODE_NAME:"DIV",CSS_CLASS_NAME:"yui-buttongroup",_createGroupElement:function(){var F=document.createElement(this.NODE_NAME);return F;},_setDisabled:function(G){var H=this.getCount(),F;if(H>0){F=H-1;do{this._buttons[F].set("disabled",G);}while(F--);}},_onKeyDown:function(K){var G=B.getTarget(K),I=B.getCharCode(K),H=G.parentNode.parentNode.id,J=E[H],F=-1;if(I==37||I==38){F=(J.index===0)?(this._buttons.length-1):(J.index-1);}else{if(I==39||I==40){F=(J.index===(this._buttons.length-1))?0:(J.index+1);}}if(F>-1){this.check(F);this.getButton(F).focus();}},_onAppendTo:function(H){var I=this._buttons,G=I.length,F;for(F=0;F<G;F++){I[F].appendTo(this.get("element"));}},_onButtonCheckedChange:function(G,F){var I=G.newValue,H=this.get("checkedButton");if(I&&H!=F){if(H){H.set("checked",false,true);}this.set("checkedButton",F);this.set("value",F.get("value"));}else{if(H&&!H.set("checked")){H.set("checked",true,true);}}},init:function(I,H){this._buttons=[];YAHOO.widget.ButtonGroup.superclass.init.call(this,I,H);this.addClass(this.CSS_CLASS_NAME);var J=this.getElementsByClassName("yui-radio-button");
11
if(J.length>0){this.addButtons(J);}function F(K){return(K.type=="radio");}J=C.getElementsBy(F,"input",this.get("element"));if(J.length>0){this.addButtons(J);}this.on("keydown",this._onKeyDown);this.on("appendTo",this._onAppendTo);var G=this.get("container");if(G){if(D.isString(G)){B.onContentReady(G,function(){this.appendTo(G);},null,this);}else{this.appendTo(G);}}},initAttributes:function(G){var F=G||{};YAHOO.widget.ButtonGroup.superclass.initAttributes.call(this,F);this.setAttributeConfig("name",{value:F.name,validator:D.isString});this.setAttributeConfig("disabled",{value:(F.disabled||false),validator:D.isBoolean,method:this._setDisabled});this.setAttributeConfig("value",{value:F.value});this.setAttributeConfig("container",{value:F.container,writeOnce:true});this.setAttributeConfig("checkedButton",{value:null});},addButton:function(J){var L,K,G,F,H,I;if(J instanceof A&&J.get("type")=="radio"){L=J;}else{if(!D.isString(J)&&!J.nodeName){J.type="radio";L=new A(J);}else{L=new A(J,{type:"radio"});}}if(L){F=this._buttons.length;H=L.get("name");I=this.get("name");L.index=F;this._buttons[F]=L;E[L.get("id")]=L;if(H!=I){L.set("name",I);}if(this.get("disabled")){L.set("disabled",true);}if(L.get("checked")){this.set("checkedButton",L);}K=L.get("element");G=this.get("element");if(K.parentNode!=G){G.appendChild(K);}L.on("checkedChange",this._onButtonCheckedChange,L,this);return L;}},addButtons:function(G){var H,I,J,F;if(D.isArray(G)){H=G.length;J=[];if(H>0){for(F=0;F<H;F++){I=this.addButton(G[F]);if(I){J[J.length]=I;}}if(J.length>0){return J;}}}},removeButton:function(H){var I=this.getButton(H),G,F;if(I){this._buttons.splice(H,1);delete E[I.get("id")];I.removeListener("checkedChange",this._onButtonCheckedChange);I.destroy();G=this._buttons.length;if(G>0){F=this._buttons.length-1;do{this._buttons[F].index=F;}while(F--);}}},getButton:function(F){if(D.isNumber(F)){return this._buttons[F];}},getButtons:function(){return this._buttons;},getCount:function(){return this._buttons.length;},focus:function(H){var I,G,F;if(D.isNumber(H)){I=this._buttons[H];if(I){I.focus();}}else{G=this.getCount();for(F=0;F<G;F++){I=this._buttons[F];if(!I.get("disabled")){I.focus();break;}}}},check:function(F){var G=this.getButton(F);if(G){G.set("checked",true);}},destroy:function(){var I=this._buttons.length,H=this.get("element"),F=H.parentNode,G;if(I>0){G=this._buttons.length-1;do{this._buttons[G].destroy();}while(G--);}B.purgeElement(H);F.removeChild(H);},toString:function(){return("ButtonGroup "+this.get("id"));}});})();YAHOO.register("button",YAHOO.widget.Button,{version:"2.3.1",build:"541"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/button/button-debug.js (-4694 lines)
Lines 1-4694 Link Here
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.8.0r4
6
*/
7
/**
8
* @module button
9
* @description <p>The Button Control enables the creation of rich, graphical 
10
* buttons that function like traditional HTML form buttons.  <em>Unlike</em> 
11
* traditional HTML form buttons, buttons created with the Button Control can have 
12
* a label that is different from its value.  With the inclusion of the optional 
13
* <a href="module_menu.html">Menu Control</a>, the Button Control can also be
14
* used to create menu buttons and split buttons, controls that are not 
15
* available natively in HTML.  The Button Control can also be thought of as a 
16
* way to create more visually engaging implementations of the browser's 
17
* default radio-button and check-box controls.</p>
18
* <p>The Button Control supports the following types:</p>
19
* <dl>
20
* <dt>push</dt>
21
* <dd>Basic push button that can execute a user-specified command when 
22
* pressed.</dd>
23
* <dt>link</dt>
24
* <dd>Navigates to a specified url when pressed.</dd>
25
* <dt>submit</dt>
26
* <dd>Submits the parent form when pressed.</dd>
27
* <dt>reset</dt>
28
* <dd>Resets the parent form when pressed.</dd>
29
* <dt>checkbox</dt>
30
* <dd>Maintains a "checked" state that can be toggled on and off.</dd>
31
* <dt>radio</dt>
32
* <dd>Maintains a "checked" state that can be toggled on and off.  Use with 
33
* the ButtonGroup class to create a set of controls that are mutually 
34
* exclusive; checking one button in the set will uncheck all others in 
35
* the group.</dd>
36
* <dt>menu</dt>
37
* <dd>When pressed will show/hide a menu.</dd>
38
* <dt>split</dt>
39
* <dd>Can execute a user-specified command or display a menu when pressed.</dd>
40
* </dl>
41
* @title Button
42
* @namespace YAHOO.widget
43
* @requires yahoo, dom, element, event
44
* @optional container, menu
45
*/
46
47
48
(function () {
49
50
51
    /**
52
    * The Button class creates a rich, graphical button.
53
    * @param {String} p_oElement String specifying the id attribute of the 
54
    * <code>&#60;input&#62;</code>, <code>&#60;button&#62;</code>,
55
    * <code>&#60;a&#62;</code>, or <code>&#60;span&#62;</code> element to 
56
    * be used to create the button.
57
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
58
    * one-html.html#ID-6043025">HTMLInputElement</a>|<a href="http://www.w3.org
59
    * /TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-34812697">
60
    * HTMLButtonElement</a>|<a href="
61
    * http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#
62
    * ID-33759296">HTMLElement</a>} p_oElement Object reference for the 
63
    * <code>&#60;input&#62;</code>, <code>&#60;button&#62;</code>, 
64
    * <code>&#60;a&#62;</code>, or <code>&#60;span&#62;</code> element to be 
65
    * used to create the button.
66
    * @param {Object} p_oElement Object literal specifying a set of   
67
    * configuration attributes used to create the button.
68
    * @param {Object} p_oAttributes Optional. Object literal specifying a set  
69
    * of configuration attributes used to create the button.
70
    * @namespace YAHOO.widget
71
    * @class Button
72
    * @constructor
73
    * @extends YAHOO.util.Element
74
    */
75
76
77
78
    // Shorthard for utilities
79
80
    var Dom = YAHOO.util.Dom,
81
        Event = YAHOO.util.Event,
82
        Lang = YAHOO.lang,
83
        UA = YAHOO.env.ua,
84
        Overlay = YAHOO.widget.Overlay,
85
        Menu = YAHOO.widget.Menu,
86
    
87
    
88
        // Private member variables
89
    
90
        m_oButtons = {},    // Collection of all Button instances
91
        m_oOverlayManager = null,   // YAHOO.widget.OverlayManager instance
92
        m_oSubmitTrigger = null,    // The button that submitted the form 
93
        m_oFocusedButton = null;    // The button that has focus
94
95
96
97
    // Private methods
98
99
    
100
    
101
    /**
102
    * @method createInputElement
103
    * @description Creates an <code>&#60;input&#62;</code> element of the 
104
    * specified type.
105
    * @private
106
    * @param {String} p_sType String specifying the type of 
107
    * <code>&#60;input&#62;</code> element to create.
108
    * @param {String} p_sName String specifying the name of 
109
    * <code>&#60;input&#62;</code> element to create.
110
    * @param {String} p_sValue String specifying the value of 
111
    * <code>&#60;input&#62;</code> element to create.
112
    * @param {String} p_bChecked Boolean specifying if the  
113
    * <code>&#60;input&#62;</code> element is to be checked.
114
    * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
115
    * one-html.html#ID-6043025">HTMLInputElement</a>}
116
    */
117
    function createInputElement(p_sType, p_sName, p_sValue, p_bChecked) {
118
    
119
        var oInput,
120
            sInput;
121
    
122
        if (Lang.isString(p_sType) && Lang.isString(p_sName)) {
123
        
124
            if (UA.ie) {
125
        
126
                /*
127
                    For IE it is necessary to create the element with the 
128
                    "type," "name," "value," and "checked" properties set all 
129
                    at once.
130
                */
131
            
132
                sInput = "<input type=\"" + p_sType + "\" name=\"" + 
133
                    p_sName + "\"";
134
        
135
                if (p_bChecked) {
136
        
137
                    sInput += " checked";
138
                
139
                }
140
                
141
                sInput += ">";
142
        
143
                oInput = document.createElement(sInput);
144
        
145
            }
146
            else {
147
            
148
                oInput = document.createElement("input");
149
                oInput.name = p_sName;
150
                oInput.type = p_sType;
151
        
152
                if (p_bChecked) {
153
        
154
                    oInput.checked = true;
155
                
156
                }
157
        
158
            }
159
        
160
            oInput.value = p_sValue;
161
        
162
        }
163
164
		return oInput;
165
    
166
    }
167
    
168
    
169
    /**
170
    * @method setAttributesFromSrcElement
171
    * @description Gets the values for all the attributes of the source element 
172
    * (either <code>&#60;input&#62;</code> or <code>&#60;a&#62;</code>) that 
173
    * map to Button configuration attributes and sets them into a collection 
174
    * that is passed to the Button constructor.
175
    * @private
176
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
177
    * one-html.html#ID-6043025">HTMLInputElement</a>|<a href="http://www.w3.org/
178
    * TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-
179
    * 48250443">HTMLAnchorElement</a>} p_oElement Object reference to the HTML 
180
    * element (either <code>&#60;input&#62;</code> or <code>&#60;span&#62;
181
    * </code>) used to create the button.
182
    * @param {Object} p_oAttributes Object reference for the collection of 
183
    * configuration attributes used to create the button.
184
    */
185
    function setAttributesFromSrcElement(p_oElement, p_oAttributes) {
186
    
187
        var sSrcElementNodeName = p_oElement.nodeName.toUpperCase(),
188
			sClass = (this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME),
189
            me = this,
190
            oAttribute,
191
            oRootNode,
192
            sText;
193
            
194
    
195
        /**
196
        * @method setAttributeFromDOMAttribute
197
        * @description Gets the value of the specified DOM attribute and sets it 
198
        * into the collection of configuration attributes used to configure 
199
        * the button.
200
        * @private
201
        * @param {String} p_sAttribute String representing the name of the 
202
        * attribute to retrieve from the DOM element.
203
        */
204
        function setAttributeFromDOMAttribute(p_sAttribute) {
205
    
206
            if (!(p_sAttribute in p_oAttributes)) {
207
    
208
                /*
209
                    Need to use "getAttributeNode" instead of "getAttribute" 
210
                    because using "getAttribute," IE will return the innerText 
211
                    of a <code>&#60;button&#62;</code> for the value attribute  
212
                    rather than the value of the "value" attribute.
213
                */
214
        
215
                oAttribute = p_oElement.getAttributeNode(p_sAttribute);
216
        
217
    
218
                if (oAttribute && ("value" in oAttribute)) {
219
    
220
                    YAHOO.log("Setting attribute \"" + p_sAttribute + 
221
                        "\" using source element's attribute value of \"" + 
222
                        oAttribute.value + "\"", "info", me.toString());
223
    
224
                    p_oAttributes[p_sAttribute] = oAttribute.value;
225
    
226
                }
227
    
228
            }
229
        
230
        }
231
    
232
    
233
        /**
234
        * @method setFormElementProperties
235
        * @description Gets the value of the attributes from the form element  
236
        * and sets them into the collection of configuration attributes used to 
237
        * configure the button.
238
        * @private
239
        */
240
        function setFormElementProperties() {
241
    
242
            setAttributeFromDOMAttribute("type");
243
    
244
            if (p_oAttributes.type == "button") {
245
            
246
                p_oAttributes.type = "push";
247
            
248
            }
249
    
250
            if (!("disabled" in p_oAttributes)) {
251
    
252
                p_oAttributes.disabled = p_oElement.disabled;
253
    
254
            }
255
    
256
            setAttributeFromDOMAttribute("name");
257
            setAttributeFromDOMAttribute("value");
258
            setAttributeFromDOMAttribute("title");
259
    
260
        }
261
262
    
263
        switch (sSrcElementNodeName) {
264
        
265
        case "A":
266
            
267
            p_oAttributes.type = "link";
268
            
269
            setAttributeFromDOMAttribute("href");
270
            setAttributeFromDOMAttribute("target");
271
        
272
            break;
273
    
274
        case "INPUT":
275
276
            setFormElementProperties();
277
278
            if (!("checked" in p_oAttributes)) {
279
    
280
                p_oAttributes.checked = p_oElement.checked;
281
    
282
            }
283
284
            break;
285
286
        case "BUTTON":
287
288
            setFormElementProperties();
289
290
            oRootNode = p_oElement.parentNode.parentNode;
291
292
            if (Dom.hasClass(oRootNode, sClass + "-checked")) {
293
            
294
                p_oAttributes.checked = true;
295
            
296
            }
297
298
            if (Dom.hasClass(oRootNode, sClass + "-disabled")) {
299
300
                p_oAttributes.disabled = true;
301
            
302
            }
303
304
            p_oElement.removeAttribute("value");
305
306
            p_oElement.setAttribute("type", "button");
307
308
            break;
309
        
310
        }
311
312
        p_oElement.removeAttribute("id");
313
        p_oElement.removeAttribute("name");
314
        
315
        if (!("tabindex" in p_oAttributes)) {
316
317
            p_oAttributes.tabindex = p_oElement.tabIndex;
318
319
        }
320
    
321
        if (!("label" in p_oAttributes)) {
322
    
323
            // Set the "label" property
324
        
325
            sText = sSrcElementNodeName == "INPUT" ? 
326
                            p_oElement.value : p_oElement.innerHTML;
327
        
328
    
329
            if (sText && sText.length > 0) {
330
                
331
                p_oAttributes.label = sText;
332
                
333
            } 
334
    
335
        }
336
    
337
    }
338
    
339
    
340
    /**
341
    * @method initConfig
342
    * @description Initializes the set of configuration attributes that are 
343
    * used to instantiate the button.
344
    * @private
345
    * @param {Object} Object representing the button's set of 
346
    * configuration attributes.
347
    */
348
    function initConfig(p_oConfig) {
349
    
350
        var oAttributes = p_oConfig.attributes,
351
            oSrcElement = oAttributes.srcelement,
352
            sSrcElementNodeName = oSrcElement.nodeName.toUpperCase(),
353
            me = this;
354
    
355
    
356
        if (sSrcElementNodeName == this.NODE_NAME) {
357
    
358
            p_oConfig.element = oSrcElement;
359
            p_oConfig.id = oSrcElement.id;
360
361
            Dom.getElementsBy(function (p_oElement) {
362
            
363
                switch (p_oElement.nodeName.toUpperCase()) {
364
                
365
                case "BUTTON":
366
                case "A":
367
                case "INPUT":
368
369
                    setAttributesFromSrcElement.call(me, p_oElement, 
370
                        oAttributes);
371
372
                    break;                        
373
                
374
                }
375
            
376
            }, "*", oSrcElement);
377
        
378
        }
379
        else {
380
    
381
            switch (sSrcElementNodeName) {
382
383
            case "BUTTON":
384
            case "A":
385
            case "INPUT":
386
387
                setAttributesFromSrcElement.call(this, oSrcElement, 
388
                    oAttributes);
389
390
                break;
391
392
            }
393
        
394
        }
395
    
396
    }
397
398
399
400
    //  Constructor
401
402
    YAHOO.widget.Button = function (p_oElement, p_oAttributes) {
403
    
404
		if (!Overlay && YAHOO.widget.Overlay) {
405
		
406
			Overlay = YAHOO.widget.Overlay;
407
		
408
		}
409
410
411
		if (!Menu && YAHOO.widget.Menu) {
412
		
413
			Menu = YAHOO.widget.Menu;
414
		
415
		}
416
417
418
        var fnSuperClass = YAHOO.widget.Button.superclass.constructor,
419
            oConfig,
420
            oElement;
421
    
422
423
        if (arguments.length == 1 && !Lang.isString(p_oElement) && !p_oElement.nodeName) {
424
    
425
            if (!p_oElement.id) {
426
    
427
                p_oElement.id = Dom.generateId();
428
    
429
                YAHOO.log("No value specified for the button's \"id\" " + 
430
                    "attribute. Setting button id to \"" + p_oElement.id + 
431
                    "\".", "info", this.toString());
432
    
433
            }
434
    
435
            YAHOO.log("No source HTML element.  Building the button " +
436
                    "using the set of configuration attributes.", "info", this.toString());
437
    
438
            fnSuperClass.call(this, (this.createButtonElement(p_oElement.type)), p_oElement);
439
    
440
        }
441
        else {
442
    
443
            oConfig = { element: null, attributes: (p_oAttributes || {}) };
444
    
445
    
446
            if (Lang.isString(p_oElement)) {
447
    
448
                oElement = Dom.get(p_oElement);
449
    
450
                if (oElement) {
451
452
                    if (!oConfig.attributes.id) {
453
                    
454
                        oConfig.attributes.id = p_oElement;
455
                    
456
                    }
457
    
458
                    YAHOO.log("Building the button using an existing " + 
459
                            "HTML element as a source element.", "info", this.toString());
460
                
461
                
462
                    oConfig.attributes.srcelement = oElement;
463
                
464
                    initConfig.call(this, oConfig);
465
                
466
                
467
                    if (!oConfig.element) {
468
                
469
                        YAHOO.log("Source element could not be used " +
470
                                "as is.  Creating a new HTML element for " + 
471
                                "the button.", "info", this.toString());
472
                
473
                        oConfig.element = this.createButtonElement(oConfig.attributes.type);
474
                
475
                    }
476
                
477
                    fnSuperClass.call(this, oConfig.element, oConfig.attributes);
478
    
479
                }
480
    
481
            }
482
            else if (p_oElement.nodeName) {
483
    
484
                if (!oConfig.attributes.id) {
485
    
486
                    if (p_oElement.id) {
487
        
488
                        oConfig.attributes.id = p_oElement.id;
489
                    
490
                    }
491
                    else {
492
        
493
                        oConfig.attributes.id = Dom.generateId();
494
        
495
                        YAHOO.log("No value specified for the button's " +
496
                            "\"id\" attribute. Setting button id to \"" + 
497
                            oConfig.attributes.id + "\".", "info", this.toString());
498
        
499
                    }
500
    
501
                }
502
    
503
                YAHOO.log("Building the button using an existing HTML " + 
504
                    "element as a source element.", "info", this.toString());
505
    
506
    
507
                oConfig.attributes.srcelement = p_oElement;
508
        
509
                initConfig.call(this, oConfig);
510
        
511
        
512
                if (!oConfig.element) {
513
    
514
                    YAHOO.log("Source element could not be used as is." +
515
                            "  Creating a new HTML element for the button.", 
516
                            "info", this.toString());
517
            
518
                    oConfig.element = this.createButtonElement(oConfig.attributes.type);
519
            
520
                }
521
            
522
                fnSuperClass.call(this, oConfig.element, oConfig.attributes);
523
            
524
            }
525
    
526
        }
527
    
528
    };
529
530
531
532
    YAHOO.extend(YAHOO.widget.Button, YAHOO.util.Element, {
533
    
534
    
535
        // Protected properties
536
        
537
        
538
        /** 
539
        * @property _button
540
        * @description Object reference to the button's internal 
541
        * <code>&#60;a&#62;</code> or <code>&#60;button&#62;</code> element.
542
        * @default null
543
        * @protected
544
        * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
545
        * level-one-html.html#ID-48250443">HTMLAnchorElement</a>|<a href="
546
        * http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html
547
        * #ID-34812697">HTMLButtonElement</a>
548
        */
549
        _button: null,
550
        
551
        
552
        /** 
553
        * @property _menu
554
        * @description Object reference to the button's menu.
555
        * @default null
556
        * @protected
557
        * @type {<a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>|
558
        * <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a>}
559
        */
560
        _menu: null,
561
        
562
        
563
        /** 
564
        * @property _hiddenFields
565
        * @description Object reference to the <code>&#60;input&#62;</code>  
566
        * element, or array of HTML form elements used to represent the button
567
        *  when its parent form is submitted.
568
        * @default null
569
        * @protected
570
        * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
571
        * level-one-html.html#ID-6043025">HTMLInputElement</a>|Array
572
        */
573
        _hiddenFields: null,
574
        
575
        
576
        /** 
577
        * @property _onclickAttributeValue
578
        * @description Object reference to the button's current value for the 
579
        * "onclick" configuration attribute.
580
        * @default null
581
        * @protected
582
        * @type Object
583
        */
584
        _onclickAttributeValue: null,
585
        
586
        
587
        /** 
588
        * @property _activationKeyPressed
589
        * @description Boolean indicating if the key(s) that toggle the button's 
590
        * "active" state have been pressed.
591
        * @default false
592
        * @protected
593
        * @type Boolean
594
        */
595
        _activationKeyPressed: false,
596
        
597
        
598
        /** 
599
        * @property _activationButtonPressed
600
        * @description Boolean indicating if the mouse button that toggles 
601
        * the button's "active" state has been pressed.
602
        * @default false
603
        * @protected
604
        * @type Boolean
605
        */
606
        _activationButtonPressed: false,
607
        
608
        
609
        /** 
610
        * @property _hasKeyEventHandlers
611
        * @description Boolean indicating if the button's "blur", "keydown" and 
612
        * "keyup" event handlers are assigned
613
        * @default false
614
        * @protected
615
        * @type Boolean
616
        */
617
        _hasKeyEventHandlers: false,
618
        
619
        
620
        /** 
621
        * @property _hasMouseEventHandlers
622
        * @description Boolean indicating if the button's "mouseout," 
623
        * "mousedown," and "mouseup" event handlers are assigned
624
        * @default false
625
        * @protected
626
        * @type Boolean
627
        */
628
        _hasMouseEventHandlers: false,
629
630
631
        /** 
632
        * @property _nOptionRegionX
633
        * @description Number representing the X coordinate of the leftmost edge of the Button's 
634
        * option region.  Applies only to Buttons of type "split".
635
        * @default 0
636
        * @protected
637
        * @type Number
638
        */        
639
        _nOptionRegionX: 0,
640
        
641
642
643
        // Constants
644
645
        /**
646
        * @property CLASS_NAME_PREFIX
647
        * @description Prefix used for all class names applied to a Button.
648
        * @default "yui-"
649
        * @final
650
        * @type String
651
        */
652
        CLASS_NAME_PREFIX: "yui-",
653
        
654
        
655
        /**
656
        * @property NODE_NAME
657
        * @description The name of the node to be used for the button's 
658
        * root element.
659
        * @default "SPAN"
660
        * @final
661
        * @type String
662
        */
663
        NODE_NAME: "SPAN",
664
        
665
        
666
        /**
667
        * @property CHECK_ACTIVATION_KEYS
668
        * @description Array of numbers representing keys that (when pressed) 
669
        * toggle the button's "checked" attribute.
670
        * @default [32]
671
        * @final
672
        * @type Array
673
        */
674
        CHECK_ACTIVATION_KEYS: [32],
675
        
676
        
677
        /**
678
        * @property ACTIVATION_KEYS
679
        * @description Array of numbers representing keys that (when presed) 
680
        * toggle the button's "active" state.
681
        * @default [13, 32]
682
        * @final
683
        * @type Array
684
        */
685
        ACTIVATION_KEYS: [13, 32],
686
        
687
        
688
        /**
689
        * @property OPTION_AREA_WIDTH
690
        * @description Width (in pixels) of the area of a split button that  
691
        * when pressed will display a menu.
692
        * @default 20
693
        * @final
694
        * @type Number
695
        */
696
        OPTION_AREA_WIDTH: 20,
697
        
698
        
699
        /**
700
        * @property CSS_CLASS_NAME
701
        * @description String representing the CSS class(es) to be applied to  
702
        * the button's root element.
703
        * @default "button"
704
        * @final
705
        * @type String
706
        */
707
        CSS_CLASS_NAME: "button",
708
        
709
        
710
        
711
        // Protected attribute setter methods
712
        
713
        
714
        /**
715
        * @method _setType
716
        * @description Sets the value of the button's "type" attribute.
717
        * @protected
718
        * @param {String} p_sType String indicating the value for the button's 
719
        * "type" attribute.
720
        */
721
        _setType: function (p_sType) {
722
        
723
            if (p_sType == "split") {
724
        
725
                this.on("option", this._onOption);
726
        
727
            }
728
        
729
        },
730
        
731
        
732
        /**
733
        * @method _setLabel
734
        * @description Sets the value of the button's "label" attribute.
735
        * @protected
736
        * @param {String} p_sLabel String indicating the value for the button's 
737
        * "label" attribute.
738
        */
739
        _setLabel: function (p_sLabel) {
740
741
            this._button.innerHTML = p_sLabel;
742
743
            
744
            /*
745
                Remove and add the default class name from the root element
746
                for Gecko to ensure that the button shrinkwraps to the label.
747
                Without this the button will not be rendered at the correct 
748
                width when the label changes.  The most likely cause for this 
749
                bug is button's use of the Gecko-specific CSS display type of 
750
                "-moz-inline-box" to simulate "inline-block" supported by IE, 
751
                Safari and Opera.
752
            */
753
            
754
            var sClass,
755
                nGeckoVersion = UA.gecko;
756
				
757
            
758
            if (nGeckoVersion && nGeckoVersion < 1.9 && Dom.inDocument(this.get("element"))) {
759
            
760
                sClass = (this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME);
761
762
                this.removeClass(sClass);
763
                
764
                Lang.later(0, this, this.addClass, sClass);
765
766
            }
767
        
768
        },
769
        
770
        
771
        /**
772
        * @method _setTabIndex
773
        * @description Sets the value of the button's "tabindex" attribute.
774
        * @protected
775
        * @param {Number} p_nTabIndex Number indicating the value for the 
776
        * button's "tabindex" attribute.
777
        */
778
        _setTabIndex: function (p_nTabIndex) {
779
        
780
            this._button.tabIndex = p_nTabIndex;
781
        
782
        },
783
        
784
        
785
        /**
786
        * @method _setTitle
787
        * @description Sets the value of the button's "title" attribute.
788
        * @protected
789
        * @param {String} p_nTabIndex Number indicating the value for 
790
        * the button's "title" attribute.
791
        */
792
        _setTitle: function (p_sTitle) {
793
        
794
            if (this.get("type") != "link") {
795
        
796
                this._button.title = p_sTitle;
797
        
798
            }
799
        
800
        },
801
        
802
        
803
        /**
804
        * @method _setDisabled
805
        * @description Sets the value of the button's "disabled" attribute.
806
        * @protected
807
        * @param {Boolean} p_bDisabled Boolean indicating the value for 
808
        * the button's "disabled" attribute.
809
        */
810
        _setDisabled: function (p_bDisabled) {
811
        
812
            if (this.get("type") != "link") {
813
        
814
                if (p_bDisabled) {
815
        
816
                    if (this._menu) {
817
        
818
                        this._menu.hide();
819
        
820
                    }
821
        
822
                    if (this.hasFocus()) {
823
                    
824
                        this.blur();
825
                    
826
                    }
827
        
828
                    this._button.setAttribute("disabled", "disabled");
829
        
830
                    this.addStateCSSClasses("disabled");
831
832
                    this.removeStateCSSClasses("hover");
833
                    this.removeStateCSSClasses("active");
834
                    this.removeStateCSSClasses("focus");
835
        
836
                }
837
                else {
838
        
839
                    this._button.removeAttribute("disabled");
840
        
841
                    this.removeStateCSSClasses("disabled");
842
                
843
                }
844
        
845
            }
846
        
847
        },
848
849
        
850
        /**
851
        * @method _setHref
852
        * @description Sets the value of the button's "href" attribute.
853
        * @protected
854
        * @param {String} p_sHref String indicating the value for the button's 
855
        * "href" attribute.
856
        */
857
        _setHref: function (p_sHref) {
858
        
859
            if (this.get("type") == "link") {
860
        
861
                this._button.href = p_sHref;
862
            
863
            }
864
        
865
        },
866
        
867
        
868
        /**
869
        * @method _setTarget
870
        * @description Sets the value of the button's "target" attribute.
871
        * @protected
872
        * @param {String} p_sTarget String indicating the value for the button's 
873
        * "target" attribute.
874
        */
875
        _setTarget: function (p_sTarget) {
876
        
877
            if (this.get("type") == "link") {
878
        
879
                this._button.setAttribute("target", p_sTarget);
880
            
881
            }
882
        
883
        },
884
        
885
        
886
        /**
887
        * @method _setChecked
888
        * @description Sets the value of the button's "target" attribute.
889
        * @protected
890
        * @param {Boolean} p_bChecked Boolean indicating the value for  
891
        * the button's "checked" attribute.
892
        */
893
        _setChecked: function (p_bChecked) {
894
        
895
            var sType = this.get("type");
896
        
897
            if (sType == "checkbox" || sType == "radio") {
898
        
899
                if (p_bChecked) {
900
                    this.addStateCSSClasses("checked");
901
                }
902
                else {
903
                    this.removeStateCSSClasses("checked");
904
                }
905
        
906
            }
907
        
908
        },
909
910
        
911
        /**
912
        * @method _setMenu
913
        * @description Sets the value of the button's "menu" attribute.
914
        * @protected
915
        * @param {Object} p_oMenu Object indicating the value for the button's 
916
        * "menu" attribute.
917
        */
918
        _setMenu: function (p_oMenu) {
919
920
            var bLazyLoad = this.get("lazyloadmenu"),
921
                oButtonElement = this.get("element"),
922
                sMenuCSSClassName,
923
        
924
                /*
925
                    Boolean indicating if the value of p_oMenu is an instance 
926
                    of YAHOO.widget.Menu or YAHOO.widget.Overlay.
927
                */
928
        
929
                bInstance = false,
930
                oMenu,
931
                oMenuElement,
932
                oSrcElement;
933
        
934
935
			function onAppendTo() {
936
937
				oMenu.render(oButtonElement.parentNode);
938
				
939
				this.removeListener("appendTo", onAppendTo);
940
			
941
			}
942
			
943
			
944
			function setMenuContainer() {
945
946
				oMenu.cfg.queueProperty("container", oButtonElement.parentNode);
947
				
948
				this.removeListener("appendTo", setMenuContainer);
949
			
950
			}
951
952
953
			function initMenu() {
954
		
955
				var oContainer;
956
		
957
				if (oMenu) {
958
959
					Dom.addClass(oMenu.element, this.get("menuclassname"));
960
					Dom.addClass(oMenu.element, this.CLASS_NAME_PREFIX + this.get("type") + "-button-menu");
961
962
					oMenu.showEvent.subscribe(this._onMenuShow, null, this);
963
					oMenu.hideEvent.subscribe(this._onMenuHide, null, this);
964
					oMenu.renderEvent.subscribe(this._onMenuRender, null, this);
965
966
967
					if (Menu && oMenu instanceof Menu) {
968
969
						if (bLazyLoad) {
970
971
							oContainer = this.get("container");
972
973
							if (oContainer) {
974
975
								oMenu.cfg.queueProperty("container", oContainer);
976
977
							}
978
							else {
979
980
								this.on("appendTo", setMenuContainer);
981
982
							}
983
984
						}
985
986
						oMenu.cfg.queueProperty("clicktohide", false);
987
988
						oMenu.keyDownEvent.subscribe(this._onMenuKeyDown, this, true);
989
						oMenu.subscribe("click", this._onMenuClick, this, true);
990
991
						this.on("selectedMenuItemChange", this._onSelectedMenuItemChange);
992
		
993
						oSrcElement = oMenu.srcElement;
994
		
995
						if (oSrcElement && oSrcElement.nodeName.toUpperCase() == "SELECT") {
996
997
							oSrcElement.style.display = "none";
998
							oSrcElement.parentNode.removeChild(oSrcElement);
999
		
1000
						}
1001
		
1002
					}
1003
					else if (Overlay && oMenu instanceof Overlay) {
1004
		
1005
						if (!m_oOverlayManager) {
1006
		
1007
							m_oOverlayManager = new YAHOO.widget.OverlayManager();
1008
						
1009
						}
1010
						
1011
						m_oOverlayManager.register(oMenu);
1012
						
1013
					}
1014
		
1015
		
1016
					this._menu = oMenu;
1017
1018
		
1019
					if (!bInstance && !bLazyLoad) {
1020
		
1021
						if (Dom.inDocument(oButtonElement)) {
1022
	
1023
							oMenu.render(oButtonElement.parentNode);
1024
						
1025
						}
1026
						else {
1027
		
1028
							this.on("appendTo", onAppendTo);
1029
						
1030
						}
1031
					
1032
					}
1033
		
1034
				}
1035
		
1036
			}
1037
1038
        
1039
            if (Overlay) {
1040
        
1041
				if (Menu) {
1042
				
1043
					sMenuCSSClassName = Menu.prototype.CSS_CLASS_NAME;
1044
				
1045
				}
1046
			
1047
				if (p_oMenu && Menu && (p_oMenu instanceof Menu)) {
1048
			
1049
					oMenu = p_oMenu;
1050
					bInstance = true;
1051
			
1052
					initMenu.call(this);
1053
			
1054
				}
1055
				else if (Overlay && p_oMenu && (p_oMenu instanceof Overlay)) {
1056
			
1057
					oMenu = p_oMenu;
1058
					bInstance = true;
1059
			
1060
					oMenu.cfg.queueProperty("visible", false);
1061
			
1062
					initMenu.call(this);
1063
			
1064
				}
1065
				else if (Menu && Lang.isArray(p_oMenu)) {
1066
1067
					oMenu = new Menu(Dom.generateId(), { lazyload: bLazyLoad, itemdata: p_oMenu });
1068
						
1069
					this._menu = oMenu;
1070
			
1071
					this.on("appendTo", initMenu);
1072
			
1073
				}
1074
				else if (Lang.isString(p_oMenu)) {
1075
			
1076
					oMenuElement = Dom.get(p_oMenu);
1077
			
1078
					if (oMenuElement) {
1079
			
1080
						if (Menu && Dom.hasClass(oMenuElement, sMenuCSSClassName) || 
1081
							oMenuElement.nodeName.toUpperCase() == "SELECT") {
1082
				
1083
							oMenu = new Menu(p_oMenu, { lazyload: bLazyLoad });
1084
				
1085
							initMenu.call(this);
1086
				
1087
						}
1088
						else if (Overlay) {
1089
			
1090
							oMenu = new Overlay(p_oMenu, { visible: false });
1091
				
1092
							initMenu.call(this);
1093
				
1094
						}
1095
			
1096
					}
1097
			
1098
				}
1099
				else if (p_oMenu && p_oMenu.nodeName) {
1100
			
1101
					if (Menu && Dom.hasClass(p_oMenu, sMenuCSSClassName) || 
1102
							p_oMenu.nodeName.toUpperCase() == "SELECT") {
1103
			
1104
						oMenu = new Menu(p_oMenu, { lazyload: bLazyLoad });
1105
					
1106
						initMenu.call(this);
1107
			
1108
					}
1109
					else if (Overlay) {
1110
			
1111
						if (!p_oMenu.id) {
1112
						
1113
							Dom.generateId(p_oMenu);
1114
						
1115
						}
1116
			
1117
						oMenu = new Overlay(p_oMenu, { visible: false });
1118
			
1119
						initMenu.call(this);
1120
					
1121
					}
1122
				
1123
				}
1124
            
1125
            }
1126
        
1127
        },
1128
        
1129
        
1130
        /**
1131
        * @method _setOnClick
1132
        * @description Sets the value of the button's "onclick" attribute.
1133
        * @protected
1134
        * @param {Object} p_oObject Object indicating the value for the button's 
1135
        * "onclick" attribute.
1136
        */
1137
        _setOnClick: function (p_oObject) {
1138
        
1139
            /*
1140
                Remove any existing listeners if a "click" event handler 
1141
                has already been specified.
1142
            */
1143
        
1144
            if (this._onclickAttributeValue && 
1145
                (this._onclickAttributeValue != p_oObject)) {
1146
        
1147
                this.removeListener("click", this._onclickAttributeValue.fn);
1148
        
1149
                this._onclickAttributeValue = null;
1150
        
1151
            }
1152
        
1153
        
1154
            if (!this._onclickAttributeValue && 
1155
                Lang.isObject(p_oObject) && 
1156
                Lang.isFunction(p_oObject.fn)) {
1157
        
1158
                this.on("click", p_oObject.fn, p_oObject.obj, p_oObject.scope);
1159
        
1160
                this._onclickAttributeValue = p_oObject;
1161
        
1162
            }
1163
        
1164
        },
1165
1166
        
1167
        
1168
        // Protected methods
1169
1170
        
1171
        
1172
        /**
1173
        * @method _isActivationKey
1174
        * @description Determines if the specified keycode is one that toggles  
1175
        * the button's "active" state.
1176
        * @protected
1177
        * @param {Number} p_nKeyCode Number representing the keycode to 
1178
        * be evaluated.
1179
        * @return {Boolean}
1180
        */
1181
        _isActivationKey: function (p_nKeyCode) {
1182
        
1183
            var sType = this.get("type"),
1184
                aKeyCodes = (sType == "checkbox" || sType == "radio") ? 
1185
                    this.CHECK_ACTIVATION_KEYS : this.ACTIVATION_KEYS,
1186
        
1187
                nKeyCodes = aKeyCodes.length,
1188
                bReturnVal = false,
1189
                i;
1190
        
1191
1192
            if (nKeyCodes > 0) {
1193
        
1194
                i = nKeyCodes - 1;
1195
        
1196
                do {
1197
        
1198
                    if (p_nKeyCode == aKeyCodes[i]) {
1199
        
1200
                        bReturnVal = true;
1201
                        break;
1202
        
1203
                    }
1204
        
1205
                }
1206
                while (i--);
1207
            
1208
            }
1209
            
1210
            return bReturnVal;
1211
        
1212
        },
1213
        
1214
        
1215
        /**
1216
        * @method _isSplitButtonOptionKey
1217
        * @description Determines if the specified keycode is one that toggles  
1218
        * the display of the split button's menu.
1219
        * @protected
1220
        * @param {Event} p_oEvent Object representing the DOM event object  
1221
        * passed back by the event utility (YAHOO.util.Event).
1222
        * @return {Boolean}
1223
        */
1224
        _isSplitButtonOptionKey: function (p_oEvent) {
1225
1226
			var bShowMenu = (Event.getCharCode(p_oEvent) == 40);
1227
1228
1229
			var onKeyPress = function (p_oEvent) {
1230
1231
				Event.preventDefault(p_oEvent);
1232
1233
				this.removeListener("keypress", onKeyPress);
1234
			
1235
			};
1236
1237
1238
			// Prevent the browser from scrolling the window
1239
			if (bShowMenu) {
1240
1241
				if (UA.opera) {
1242
	
1243
					this.on("keypress", onKeyPress);
1244
	
1245
				}
1246
1247
				Event.preventDefault(p_oEvent);
1248
			}
1249
1250
            return bShowMenu;
1251
        
1252
        },
1253
        
1254
        
1255
        /**
1256
        * @method _addListenersToForm
1257
        * @description Adds event handlers to the button's form.
1258
        * @protected
1259
        */
1260
        _addListenersToForm: function () {
1261
        
1262
            var oForm = this.getForm(),
1263
                onFormKeyPress = YAHOO.widget.Button.onFormKeyPress,
1264
                bHasKeyPressListener,
1265
                oSrcElement,
1266
                aListeners,
1267
                nListeners,
1268
                i;
1269
        
1270
        
1271
            if (oForm) {
1272
        
1273
                Event.on(oForm, "reset", this._onFormReset, null, this);
1274
                Event.on(oForm, "submit", this._onFormSubmit, null, this);
1275
        
1276
                oSrcElement = this.get("srcelement");
1277
        
1278
        
1279
                if (this.get("type") == "submit" || 
1280
                    (oSrcElement && oSrcElement.type == "submit")) 
1281
                {
1282
                
1283
                    aListeners = Event.getListeners(oForm, "keypress");
1284
                    bHasKeyPressListener = false;
1285
            
1286
                    if (aListeners) {
1287
            
1288
                        nListeners = aListeners.length;
1289
        
1290
                        if (nListeners > 0) {
1291
            
1292
                            i = nListeners - 1;
1293
                            
1294
                            do {
1295
               
1296
                                if (aListeners[i].fn == onFormKeyPress) {
1297
                
1298
                                    bHasKeyPressListener = true;
1299
                                    break;
1300
                                
1301
                                }
1302
                
1303
                            }
1304
                            while (i--);
1305
                        
1306
                        }
1307
                    
1308
                    }
1309
            
1310
            
1311
                    if (!bHasKeyPressListener) {
1312
               
1313
                        Event.on(oForm, "keypress", onFormKeyPress);
1314
            
1315
                    }
1316
        
1317
                }
1318
            
1319
            }
1320
        
1321
        },
1322
        
1323
        
1324
        
1325
        /**
1326
        * @method _showMenu
1327
        * @description Shows the button's menu.
1328
        * @protected
1329
        * @param {Event} p_oEvent Object representing the DOM event object 
1330
        * passed back by the event utility (YAHOO.util.Event) that triggered 
1331
        * the display of the menu.
1332
        */
1333
        _showMenu: function (p_oEvent) {
1334
1335
            if (YAHOO.widget.MenuManager) {
1336
                YAHOO.widget.MenuManager.hideVisible();
1337
            }
1338
1339
        
1340
            if (m_oOverlayManager) {
1341
                m_oOverlayManager.hideAll();
1342
            }
1343
1344
1345
            var oMenu = this._menu,
1346
            	aMenuAlignment = this.get("menualignment"),
1347
            	bFocusMenu = this.get("focusmenu"),
1348
				fnFocusMethod;
1349
1350
1351
			if (this._renderedMenu) {
1352
1353
				oMenu.cfg.setProperty("context", 
1354
								[this.get("element"), aMenuAlignment[0], aMenuAlignment[1]]);
1355
	
1356
				oMenu.cfg.setProperty("preventcontextoverlap", true);
1357
				oMenu.cfg.setProperty("constraintoviewport", true);
1358
1359
			}
1360
			else {
1361
1362
				oMenu.cfg.queueProperty("context", 
1363
								[this.get("element"), aMenuAlignment[0], aMenuAlignment[1]]);
1364
	
1365
				oMenu.cfg.queueProperty("preventcontextoverlap", true);
1366
				oMenu.cfg.queueProperty("constraintoviewport", true);
1367
			
1368
			}
1369
1370
1371
			/*
1372
				 Refocus the Button before showing its Menu in case the call to 
1373
				 YAHOO.widget.MenuManager.hideVisible() resulted in another element in the 
1374
				 DOM being focused after another Menu was hidden.
1375
			*/
1376
			
1377
			this.focus();
1378
1379
1380
            if (Menu && oMenu && (oMenu instanceof Menu)) {
1381
1382
				// Since Menus automatically focus themselves when made visible, temporarily 
1383
				// replace the Menu focus method so that the value of the Button's "focusmenu"
1384
				// attribute determines if the Menu should be focus when made visible.
1385
1386
				fnFocusMethod = oMenu.focus;
1387
1388
				oMenu.focus = function () {};
1389
1390
				if (this._renderedMenu) {
1391
1392
					oMenu.cfg.setProperty("minscrollheight", this.get("menuminscrollheight"));
1393
					oMenu.cfg.setProperty("maxheight", this.get("menumaxheight"));
1394
				
1395
				}
1396
				else {
1397
1398
					oMenu.cfg.queueProperty("minscrollheight", this.get("menuminscrollheight"));
1399
					oMenu.cfg.queueProperty("maxheight", this.get("menumaxheight"));
1400
				
1401
				}
1402
1403
1404
                oMenu.show();
1405
1406
        		oMenu.focus = fnFocusMethod;
1407
1408
				oMenu.align();
1409
        
1410
1411
                /*
1412
                    Stop the propagation of the event so that the MenuManager 
1413
                    doesn't blur the menu after it gets focus.
1414
                */
1415
        
1416
                if (p_oEvent.type == "mousedown") {
1417
                    Event.stopPropagation(p_oEvent);
1418
                }
1419
1420
        
1421
                if (bFocusMenu) { 
1422
                    oMenu.focus();
1423
                }
1424
1425
            }
1426
            else if (Overlay && oMenu && (oMenu instanceof Overlay)) {
1427
1428
				if (!this._renderedMenu) {
1429
		            oMenu.render(this.get("element").parentNode);
1430
				}
1431
1432
                oMenu.show();
1433
				oMenu.align();
1434
1435
            }
1436
        
1437
        },
1438
        
1439
        
1440
        /**
1441
        * @method _hideMenu
1442
        * @description Hides the button's menu.
1443
        * @protected
1444
        */
1445
        _hideMenu: function () {
1446
        
1447
            var oMenu = this._menu;
1448
        
1449
            if (oMenu) {
1450
        
1451
                oMenu.hide();
1452
        
1453
            }
1454
        
1455
        },
1456
        
1457
        
1458
        
1459
        
1460
        // Protected event handlers
1461
        
1462
        
1463
        /**
1464
        * @method _onMouseOver
1465
        * @description "mouseover" event handler for the button.
1466
        * @protected
1467
        * @param {Event} p_oEvent Object representing the DOM event object  
1468
        * passed back by the event utility (YAHOO.util.Event).
1469
        */
1470
        _onMouseOver: function (p_oEvent) {
1471
        
1472
        	var sType = this.get("type"),
1473
        		oElement,
1474
				nOptionRegionX;
1475
1476
1477
			if (sType === "split") {
1478
1479
				oElement = this.get("element");
1480
				nOptionRegionX = 
1481
					(Dom.getX(oElement) + (oElement.offsetWidth - this.OPTION_AREA_WIDTH));
1482
					
1483
				this._nOptionRegionX = nOptionRegionX;
1484
			
1485
			}
1486
        
1487
1488
            if (!this._hasMouseEventHandlers) {
1489
        
1490
				if (sType === "split") {
1491
        
1492
	        		this.on("mousemove", this._onMouseMove);
1493
1494
        		}
1495
1496
                this.on("mouseout", this._onMouseOut);
1497
        
1498
                this._hasMouseEventHandlers = true;
1499
        
1500
            }
1501
        
1502
1503
            this.addStateCSSClasses("hover");
1504
1505
1506
			if (sType === "split" && (Event.getPageX(p_oEvent) > nOptionRegionX)) {
1507
	
1508
				this.addStateCSSClasses("hoveroption");
1509
	
1510
			}
1511
1512
        
1513
            if (this._activationButtonPressed) {
1514
        
1515
                this.addStateCSSClasses("active");
1516
        
1517
            }
1518
        
1519
        
1520
            if (this._bOptionPressed) {
1521
        
1522
                this.addStateCSSClasses("activeoption");
1523
            
1524
            }
1525
1526
1527
            if (this._activationButtonPressed || this._bOptionPressed) {
1528
        
1529
                Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
1530
        
1531
            }
1532
1533
        },
1534
1535
1536
        /**
1537
        * @method _onMouseMove
1538
        * @description "mousemove" event handler for the button.
1539
        * @protected
1540
        * @param {Event} p_oEvent Object representing the DOM event object  
1541
        * passed back by the event utility (YAHOO.util.Event).
1542
        */        
1543
        _onMouseMove: function (p_oEvent) {
1544
        
1545
        	var nOptionRegionX = this._nOptionRegionX;
1546
        
1547
        	if (nOptionRegionX) {
1548
1549
				if (Event.getPageX(p_oEvent) > nOptionRegionX) {
1550
					
1551
					this.addStateCSSClasses("hoveroption");
1552
	
1553
				}
1554
				else {
1555
1556
					this.removeStateCSSClasses("hoveroption");
1557
				
1558
				}
1559
				
1560
        	}
1561
        
1562
        },
1563
        
1564
        /**
1565
        * @method _onMouseOut
1566
        * @description "mouseout" event handler for the button.
1567
        * @protected
1568
        * @param {Event} p_oEvent Object representing the DOM event object  
1569
        * passed back by the event utility (YAHOO.util.Event).
1570
        */
1571
        _onMouseOut: function (p_oEvent) {
1572
1573
			var sType = this.get("type");
1574
        
1575
            this.removeStateCSSClasses("hover");
1576
        
1577
1578
            if (sType != "menu") {
1579
        
1580
                this.removeStateCSSClasses("active");
1581
        
1582
            }
1583
        
1584
1585
            if (this._activationButtonPressed || this._bOptionPressed) {
1586
        
1587
                Event.on(document, "mouseup", this._onDocumentMouseUp, null, this);
1588
        
1589
            }
1590
1591
1592
			if (sType === "split" && (Event.getPageX(p_oEvent) > this._nOptionRegionX)) {
1593
			
1594
				this.removeStateCSSClasses("hoveroption");
1595
	
1596
			}
1597
            
1598
        },
1599
        
1600
        
1601
        /**
1602
        * @method _onDocumentMouseUp
1603
        * @description "mouseup" event handler for the button.
1604
        * @protected
1605
        * @param {Event} p_oEvent Object representing the DOM event object  
1606
        * passed back by the event utility (YAHOO.util.Event).
1607
        */
1608
        _onDocumentMouseUp: function (p_oEvent) {
1609
        
1610
            this._activationButtonPressed = false;
1611
            this._bOptionPressed = false;
1612
        
1613
            var sType = this.get("type"),
1614
                oTarget,
1615
                oMenuElement;
1616
        
1617
            if (sType == "menu" || sType == "split") {
1618
1619
                oTarget = Event.getTarget(p_oEvent);
1620
                oMenuElement = this._menu.element;
1621
        
1622
                if (oTarget != oMenuElement && 
1623
                    !Dom.isAncestor(oMenuElement, oTarget)) {
1624
1625
                    this.removeStateCSSClasses((sType == "menu" ? 
1626
                        "active" : "activeoption"));
1627
            
1628
                    this._hideMenu();
1629
1630
                }
1631
        
1632
            }
1633
        
1634
            Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
1635
        
1636
        },
1637
        
1638
        
1639
        /**
1640
        * @method _onMouseDown
1641
        * @description "mousedown" event handler for the button.
1642
        * @protected
1643
        * @param {Event} p_oEvent Object representing the DOM event object  
1644
        * passed back by the event utility (YAHOO.util.Event).
1645
        */
1646
        _onMouseDown: function (p_oEvent) {
1647
        
1648
            var sType,
1649
            	bReturnVal = true;
1650
        
1651
        
1652
            function onMouseUp() {
1653
            
1654
                this._hideMenu();
1655
                this.removeListener("mouseup", onMouseUp);
1656
            
1657
            }
1658
        
1659
        
1660
            if ((p_oEvent.which || p_oEvent.button) == 1) {
1661
        
1662
        
1663
                if (!this.hasFocus()) {
1664
                
1665
                    this.focus();
1666
                
1667
                }
1668
        
1669
        
1670
                sType = this.get("type");
1671
        
1672
        
1673
                if (sType == "split") {
1674
                
1675
                    if (Event.getPageX(p_oEvent) > this._nOptionRegionX) {
1676
                        
1677
                        this.fireEvent("option", p_oEvent);
1678
						bReturnVal = false;
1679
        
1680
                    }
1681
                    else {
1682
        
1683
                        this.addStateCSSClasses("active");
1684
        
1685
                        this._activationButtonPressed = true;
1686
        
1687
                    }
1688
        
1689
                }
1690
                else if (sType == "menu") {
1691
        
1692
                    if (this.isActive()) {
1693
        
1694
                        this._hideMenu();
1695
        
1696
                        this._activationButtonPressed = false;
1697
        
1698
                    }
1699
                    else {
1700
        
1701
                        this._showMenu(p_oEvent);
1702
        
1703
                        this._activationButtonPressed = true;
1704
                    
1705
                    }
1706
        
1707
                }
1708
                else {
1709
        
1710
                    this.addStateCSSClasses("active");
1711
        
1712
                    this._activationButtonPressed = true;
1713
                
1714
                }
1715
        
1716
        
1717
        
1718
                if (sType == "split" || sType == "menu") {
1719
1720
                    this._hideMenuTimer = Lang.later(250, this, this.on, ["mouseup", onMouseUp]);
1721
        
1722
                }
1723
        
1724
            }
1725
            
1726
            return bReturnVal;
1727
            
1728
        },
1729
        
1730
        
1731
        /**
1732
        * @method _onMouseUp
1733
        * @description "mouseup" event handler for the button.
1734
        * @protected
1735
        * @param {Event} p_oEvent Object representing the DOM event object  
1736
        * passed back by the event utility (YAHOO.util.Event).
1737
        */
1738
        _onMouseUp: function (p_oEvent) {
1739
        
1740
            var sType = this.get("type"),
1741
            	oHideMenuTimer = this._hideMenuTimer,
1742
            	bReturnVal = true;
1743
        
1744
        
1745
            if (oHideMenuTimer) {
1746
  
1747
  				oHideMenuTimer.cancel();
1748
        
1749
            }
1750
        
1751
        
1752
            if (sType == "checkbox" || sType == "radio") {
1753
        
1754
                this.set("checked", !(this.get("checked")));
1755
            
1756
            }
1757
        
1758
        
1759
            this._activationButtonPressed = false;
1760
            
1761
        
1762
            if (sType != "menu") {
1763
        
1764
                this.removeStateCSSClasses("active");
1765
            
1766
            }
1767
1768
                
1769
			if (sType == "split" && Event.getPageX(p_oEvent) > this._nOptionRegionX) {
1770
				
1771
				bReturnVal = false;
1772
1773
			}
1774
1775
			return bReturnVal;
1776
            
1777
        },
1778
        
1779
        
1780
        /**
1781
        * @method _onFocus
1782
        * @description "focus" event handler for the button.
1783
        * @protected
1784
        * @param {Event} p_oEvent Object representing the DOM event object  
1785
        * passed back by the event utility (YAHOO.util.Event).
1786
        */
1787
        _onFocus: function (p_oEvent) {
1788
        
1789
            var oElement;
1790
        
1791
            this.addStateCSSClasses("focus");
1792
        
1793
            if (this._activationKeyPressed) {
1794
        
1795
                this.addStateCSSClasses("active");
1796
           
1797
            }
1798
        
1799
            m_oFocusedButton = this;
1800
        
1801
        
1802
            if (!this._hasKeyEventHandlers) {
1803
        
1804
                oElement = this._button;
1805
        
1806
                Event.on(oElement, "blur", this._onBlur, null, this);
1807
                Event.on(oElement, "keydown", this._onKeyDown, null, this);
1808
                Event.on(oElement, "keyup", this._onKeyUp, null, this);
1809
        
1810
                this._hasKeyEventHandlers = true;
1811
        
1812
            }
1813
        
1814
        
1815
            this.fireEvent("focus", p_oEvent);
1816
        
1817
        },
1818
        
1819
        
1820
        /**
1821
        * @method _onBlur
1822
        * @description "blur" event handler for the button.
1823
        * @protected
1824
        * @param {Event} p_oEvent Object representing the DOM event object  
1825
        * passed back by the event utility (YAHOO.util.Event).
1826
        */
1827
        _onBlur: function (p_oEvent) {
1828
        
1829
            this.removeStateCSSClasses("focus");
1830
        
1831
            if (this.get("type") != "menu") {
1832
        
1833
                this.removeStateCSSClasses("active");
1834
1835
            }    
1836
        
1837
            if (this._activationKeyPressed) {
1838
        
1839
                Event.on(document, "keyup", this._onDocumentKeyUp, null, this);
1840
        
1841
            }
1842
        
1843
        
1844
            m_oFocusedButton = null;
1845
        
1846
            this.fireEvent("blur", p_oEvent);
1847
           
1848
        },
1849
        
1850
        
1851
        /**
1852
        * @method _onDocumentKeyUp
1853
        * @description "keyup" event handler for the document.
1854
        * @protected
1855
        * @param {Event} p_oEvent Object representing the DOM event object  
1856
        * passed back by the event utility (YAHOO.util.Event).
1857
        */
1858
        _onDocumentKeyUp: function (p_oEvent) {
1859
        
1860
            if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
1861
        
1862
                this._activationKeyPressed = false;
1863
                
1864
                Event.removeListener(document, "keyup", this._onDocumentKeyUp);
1865
            
1866
            }
1867
        
1868
        },
1869
        
1870
        
1871
        /**
1872
        * @method _onKeyDown
1873
        * @description "keydown" event handler for the button.
1874
        * @protected
1875
        * @param {Event} p_oEvent Object representing the DOM event object  
1876
        * passed back by the event utility (YAHOO.util.Event).
1877
        */
1878
        _onKeyDown: function (p_oEvent) {
1879
        
1880
            var oMenu = this._menu;
1881
        
1882
        
1883
            if (this.get("type") == "split" && 
1884
                this._isSplitButtonOptionKey(p_oEvent)) {
1885
        
1886
                this.fireEvent("option", p_oEvent);
1887
        
1888
            }
1889
            else if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
1890
        
1891
                if (this.get("type") == "menu") {
1892
        
1893
                    this._showMenu(p_oEvent);
1894
        
1895
                }
1896
                else {
1897
        
1898
                    this._activationKeyPressed = true;
1899
                    
1900
                    this.addStateCSSClasses("active");
1901
                
1902
                }
1903
            
1904
            }
1905
        
1906
        
1907
            if (oMenu && oMenu.cfg.getProperty("visible") && 
1908
                Event.getCharCode(p_oEvent) == 27) {
1909
            
1910
                oMenu.hide();
1911
                this.focus();
1912
            
1913
            }
1914
        
1915
        },
1916
        
1917
        
1918
        /**
1919
        * @method _onKeyUp
1920
        * @description "keyup" event handler for the button.
1921
        * @protected
1922
        * @param {Event} p_oEvent Object representing the DOM event object  
1923
        * passed back by the event utility (YAHOO.util.Event).
1924
        */
1925
        _onKeyUp: function (p_oEvent) {
1926
        
1927
            var sType;
1928
        
1929
            if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
1930
        
1931
                sType = this.get("type");
1932
        
1933
                if (sType == "checkbox" || sType == "radio") {
1934
        
1935
                    this.set("checked", !(this.get("checked")));
1936
                
1937
                }
1938
        
1939
                this._activationKeyPressed = false;
1940
        
1941
                if (this.get("type") != "menu") {
1942
        
1943
                    this.removeStateCSSClasses("active");
1944
        
1945
                }
1946
        
1947
            }
1948
        
1949
        },
1950
        
1951
        
1952
        /**
1953
        * @method _onClick
1954
        * @description "click" event handler for the button.
1955
        * @protected
1956
        * @param {Event} p_oEvent Object representing the DOM event object  
1957
        * passed back by the event utility (YAHOO.util.Event).
1958
        */
1959
        _onClick: function (p_oEvent) {
1960
        
1961
            var sType = this.get("type"),
1962
                oForm,
1963
                oSrcElement,
1964
                bReturnVal;
1965
        
1966
1967
			switch (sType) {
1968
1969
			case "submit":
1970
1971
				if (p_oEvent.returnValue !== false) {
1972
1973
					this.submitForm();
1974
1975
				}
1976
1977
				break;
1978
1979
			case "reset":
1980
1981
				oForm = this.getForm();
1982
1983
				if (oForm) {
1984
1985
					oForm.reset();
1986
1987
				}
1988
1989
				break;
1990
1991
1992
			case "split":
1993
1994
				if (this._nOptionRegionX > 0 && 
1995
						(Event.getPageX(p_oEvent) > this._nOptionRegionX)) {
1996
1997
					bReturnVal = false;
1998
1999
				}
2000
				else {
2001
2002
					this._hideMenu();
2003
2004
					oSrcElement = this.get("srcelement");
2005
2006
					if (oSrcElement && oSrcElement.type == "submit" && 
2007
							p_oEvent.returnValue !== false) {
2008
2009
						this.submitForm();
2010
2011
					}
2012
2013
				}
2014
2015
				break;
2016
2017
			}
2018
2019
			return bReturnVal;
2020
        
2021
        },
2022
        
2023
        
2024
        /**
2025
        * @method _onDblClick
2026
        * @description "dblclick" event handler for the button.
2027
        * @protected
2028
        * @param {Event} p_oEvent Object representing the DOM event object  
2029
        * passed back by the event utility (YAHOO.util.Event).
2030
        */
2031
        _onDblClick: function (p_oEvent) {
2032
        
2033
            var bReturnVal = true;
2034
    
2035
			if (this.get("type") == "split" && Event.getPageX(p_oEvent) > this._nOptionRegionX) {
2036
2037
				bReturnVal = false;
2038
			
2039
			}
2040
        
2041
        	return bReturnVal;
2042
        
2043
        },        
2044
        
2045
        
2046
        /**
2047
        * @method _onAppendTo
2048
        * @description "appendTo" event handler for the button.
2049
        * @protected
2050
        * @param {Event} p_oEvent Object representing the DOM event object  
2051
        * passed back by the event utility (YAHOO.util.Event).
2052
        */
2053
        _onAppendTo: function (p_oEvent) {
2054
        
2055
            /*
2056
                It is necessary to call "_addListenersToForm" using 
2057
                "setTimeout" to make sure that the button's "form" property 
2058
                returns a node reference.  Sometimes, if you try to get the 
2059
                reference immediately after appending the field, it is null.
2060
            */
2061
        
2062
            Lang.later(0, this, this._addListenersToForm);
2063
        
2064
        },
2065
        
2066
        
2067
        /**
2068
        * @method _onFormReset
2069
        * @description "reset" event handler for the button's form.
2070
        * @protected
2071
        * @param {Event} p_oEvent Object representing the DOM event 
2072
        * object passed back by the event utility (YAHOO.util.Event).
2073
        */
2074
        _onFormReset: function (p_oEvent) {
2075
        
2076
            var sType = this.get("type"),
2077
                oMenu = this._menu;
2078
        
2079
            if (sType == "checkbox" || sType == "radio") {
2080
        
2081
                this.resetValue("checked");
2082
        
2083
            }
2084
        
2085
        
2086
            if (Menu && oMenu && (oMenu instanceof Menu)) {
2087
        
2088
                this.resetValue("selectedMenuItem");
2089
        
2090
            }
2091
        
2092
        },
2093
2094
2095
        /**
2096
        * @method _onFormSubmit
2097
        * @description "submit" event handler for the button's form.
2098
        * @protected
2099
        * @param {Event} p_oEvent Object representing the DOM event 
2100
        * object passed back by the event utility (YAHOO.util.Event).
2101
        */        
2102
        _onFormSubmit: function (p_oEvent) {
2103
        
2104
        	this.createHiddenFields();
2105
        
2106
        },
2107
        
2108
        
2109
        /**
2110
        * @method _onDocumentMouseDown
2111
        * @description "mousedown" event handler for the document.
2112
        * @protected
2113
        * @param {Event} p_oEvent Object representing the DOM event object  
2114
        * passed back by the event utility (YAHOO.util.Event).
2115
        */
2116
        _onDocumentMouseDown: function (p_oEvent) {
2117
2118
            var oTarget = Event.getTarget(p_oEvent),
2119
                oButtonElement = this.get("element"),
2120
                oMenuElement = this._menu.element;
2121
           
2122
        
2123
            if (oTarget != oButtonElement && 
2124
                !Dom.isAncestor(oButtonElement, oTarget) && 
2125
                oTarget != oMenuElement && 
2126
                !Dom.isAncestor(oMenuElement, oTarget)) {
2127
        
2128
                this._hideMenu();
2129
2130
				//	In IE when the user mouses down on a focusable element
2131
				//	that element will be focused and become the "activeElement".
2132
				//	(http://msdn.microsoft.com/en-us/library/ms533065(VS.85).aspx)
2133
				//	However, there is a bug in IE where if there is a  
2134
				//	positioned element with a focused descendant that is 
2135
				//	hidden in response to the mousedown event, the target of 
2136
				//	the mousedown event will appear to have focus, but will 
2137
				//	not be set as the activeElement.  This will result 
2138
				//	in the element not firing key events, even though it
2139
				//	appears to have focus.	The following call to "setActive"
2140
				//	fixes this bug.
2141
2142
				if (UA.ie && oTarget.focus) {
2143
					oTarget.setActive();
2144
				}
2145
        
2146
                Event.removeListener(document, "mousedown", 
2147
                    this._onDocumentMouseDown);    
2148
            
2149
            }
2150
        
2151
        },
2152
        
2153
        
2154
        /**
2155
        * @method _onOption
2156
        * @description "option" event handler for the button.
2157
        * @protected
2158
        * @param {Event} p_oEvent Object representing the DOM event object  
2159
        * passed back by the event utility (YAHOO.util.Event).
2160
        */
2161
        _onOption: function (p_oEvent) {
2162
        
2163
            if (this.hasClass(this.CLASS_NAME_PREFIX + "split-button-activeoption")) {
2164
        
2165
                this._hideMenu();
2166
        
2167
                this._bOptionPressed = false;
2168
        
2169
            }
2170
            else {
2171
        
2172
                this._showMenu(p_oEvent);    
2173
        
2174
                this._bOptionPressed = true;
2175
        
2176
            }
2177
        
2178
        },
2179
        
2180
        
2181
        /**
2182
        * @method _onMenuShow
2183
        * @description "show" event handler for the button's menu.
2184
        * @private
2185
        * @param {String} p_sType String representing the name of the event  
2186
        * that was fired.
2187
        */
2188
        _onMenuShow: function (p_sType) {
2189
        
2190
            Event.on(document, "mousedown", this._onDocumentMouseDown, 
2191
                null, this);
2192
        
2193
            var sState = (this.get("type") == "split") ? "activeoption" : "active";
2194
        
2195
            this.addStateCSSClasses(sState);
2196
        
2197
        },
2198
        
2199
        
2200
        /**
2201
        * @method _onMenuHide
2202
        * @description "hide" event handler for the button's menu.
2203
        * @private
2204
        * @param {String} p_sType String representing the name of the event  
2205
        * that was fired.
2206
        */
2207
        _onMenuHide: function (p_sType) {
2208
            
2209
            var sState = (this.get("type") == "split") ? "activeoption" : "active";
2210
        
2211
            this.removeStateCSSClasses(sState);
2212
        
2213
        
2214
            if (this.get("type") == "split") {
2215
        
2216
                this._bOptionPressed = false;
2217
            
2218
            }
2219
        
2220
        },
2221
        
2222
        
2223
        /**
2224
        * @method _onMenuKeyDown
2225
        * @description "keydown" event handler for the button's menu.
2226
        * @private
2227
        * @param {String} p_sType String representing the name of the event  
2228
        * that was fired.
2229
        * @param {Array} p_aArgs Array of arguments sent when the event 
2230
        * was fired.
2231
        */
2232
        _onMenuKeyDown: function (p_sType, p_aArgs) {
2233
        
2234
            var oEvent = p_aArgs[0];
2235
        
2236
            if (Event.getCharCode(oEvent) == 27) {
2237
        
2238
                this.focus();
2239
        
2240
                if (this.get("type") == "split") {
2241
                
2242
                    this._bOptionPressed = false;
2243
                
2244
                }
2245
        
2246
            }
2247
        
2248
        },
2249
        
2250
        
2251
        /**
2252
        * @method _onMenuRender
2253
        * @description "render" event handler for the button's menu.
2254
        * @private
2255
        * @param {String} p_sType String representing the name of the  
2256
        * event thatwas fired.
2257
        */
2258
        _onMenuRender: function (p_sType) {
2259
        
2260
            var oButtonElement = this.get("element"),
2261
                oButtonParent = oButtonElement.parentNode,
2262
				oMenu = this._menu,
2263
                oMenuElement = oMenu.element,
2264
				oSrcElement = oMenu.srcElement,
2265
				oItem;
2266
        
2267
        
2268
            if (oButtonParent != oMenuElement.parentNode) {
2269
        
2270
                oButtonParent.appendChild(oMenuElement);
2271
            
2272
            }
2273
2274
			this._renderedMenu = true;
2275
2276
			//	If the user has designated an <option> of the Menu's source 
2277
			//	<select> element to be selected, sync the selectedIndex with 
2278
			//	the "selectedMenuItem" Attribute.
2279
2280
			if (oSrcElement && 
2281
					oSrcElement.nodeName.toLowerCase() === "select" && 
2282
					oSrcElement.value) {
2283
				
2284
				
2285
				oItem = oMenu.getItem(oSrcElement.selectedIndex);
2286
				
2287
				//	Set the value of the "selectedMenuItem" attribute
2288
				//	silently since this is the initial set--synchronizing 
2289
				//	the value of the source <SELECT> element in the DOM with 
2290
				//	its corresponding Menu instance.
2291
2292
				this.set("selectedMenuItem", oItem, true);
2293
				
2294
				//	Call the "_onSelectedMenuItemChange" method since the 
2295
				//	attribute was set silently.
2296
2297
				this._onSelectedMenuItemChange({ newValue: oItem });
2298
				
2299
			}
2300
2301
        },
2302
2303
        
2304
        
2305
        /**
2306
        * @method _onMenuClick
2307
        * @description "click" event handler for the button's menu.
2308
        * @private
2309
        * @param {String} p_sType String representing the name of the event  
2310
        * that was fired.
2311
        * @param {Array} p_aArgs Array of arguments sent when the event 
2312
        * was fired.
2313
        */
2314
        _onMenuClick: function (p_sType, p_aArgs) {
2315
2316
            var oItem = p_aArgs[1],
2317
                oSrcElement;
2318
        
2319
            if (oItem) {
2320
        
2321
				this.set("selectedMenuItem", oItem);
2322
2323
                oSrcElement = this.get("srcelement");
2324
            
2325
                if (oSrcElement && oSrcElement.type == "submit") {
2326
        
2327
                    this.submitForm();
2328
            
2329
                }
2330
            
2331
                this._hideMenu();
2332
            
2333
            }
2334
        
2335
        },
2336
2337
2338
        /**
2339
        * @method _onSelectedMenuItemChange
2340
        * @description "selectedMenuItemChange" event handler for the Button's
2341
		* "selectedMenuItem" attribute.
2342
        * @param {Event} event Object representing the DOM event object  
2343
        * passed back by the event utility (YAHOO.util.Event).
2344
        */
2345
		_onSelectedMenuItemChange: function (event) {
2346
		
2347
			var oSelected = event.prevValue,
2348
				oItem = event.newValue,
2349
				sPrefix = this.CLASS_NAME_PREFIX;
2350
2351
			if (oSelected) {
2352
				Dom.removeClass(oSelected.element, (sPrefix + "button-selectedmenuitem"));
2353
			}
2354
			
2355
			if (oItem) {
2356
				Dom.addClass(oItem.element, (sPrefix + "button-selectedmenuitem"));
2357
			}
2358
			
2359
		},        
2360
        
2361
2362
        /**
2363
        * @method _onLabelClick
2364
        * @description "click" event handler for the Button's
2365
		* <code>&#60;label&#62;</code> element.
2366
        * @param {Event} event Object representing the DOM event object  
2367
        * passed back by the event utility (YAHOO.util.Event).
2368
        */
2369
		_onLabelClick: function (event) {
2370
2371
			this.focus();
2372
2373
			var sType = this.get("type");
2374
2375
			if (sType == "radio" || sType == "checkbox") {
2376
				this.set("checked", (!this.get("checked")));						
2377
			}
2378
			
2379
		},
2380
2381
        
2382
        // Public methods
2383
        
2384
        
2385
        /**
2386
        * @method createButtonElement
2387
        * @description Creates the button's HTML elements.
2388
        * @param {String} p_sType String indicating the type of element 
2389
        * to create.
2390
        * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
2391
        * level-one-html.html#ID-58190037">HTMLElement</a>}
2392
        */
2393
        createButtonElement: function (p_sType) {
2394
        
2395
            var sNodeName = this.NODE_NAME,
2396
                oElement = document.createElement(sNodeName);
2397
        
2398
            oElement.innerHTML =  "<" + sNodeName + " class=\"first-child\">" + 
2399
                (p_sType == "link" ? "<a></a>" : 
2400
                "<button type=\"button\"></button>") + "</" + sNodeName + ">";
2401
        
2402
            return oElement;
2403
        
2404
        },
2405
2406
        
2407
        /**
2408
        * @method addStateCSSClasses
2409
        * @description Appends state-specific CSS classes to the button's root 
2410
        * DOM element.
2411
        */
2412
        addStateCSSClasses: function (p_sState) {
2413
        
2414
            var sType = this.get("type"),
2415
				sPrefix = this.CLASS_NAME_PREFIX;
2416
        
2417
            if (Lang.isString(p_sState)) {
2418
        
2419
                if (p_sState != "activeoption" && p_sState != "hoveroption") {
2420
        
2421
                    this.addClass(sPrefix + this.CSS_CLASS_NAME + ("-" + p_sState));
2422
        
2423
                }
2424
        
2425
                this.addClass(sPrefix + sType + ("-button-" + p_sState));
2426
            
2427
            }
2428
        
2429
        },
2430
        
2431
        
2432
        /**
2433
        * @method removeStateCSSClasses
2434
        * @description Removes state-specific CSS classes to the button's root 
2435
        * DOM element.
2436
        */
2437
        removeStateCSSClasses: function (p_sState) {
2438
        
2439
            var sType = this.get("type"),
2440
				sPrefix = this.CLASS_NAME_PREFIX;
2441
        
2442
            if (Lang.isString(p_sState)) {
2443
        
2444
                this.removeClass(sPrefix + this.CSS_CLASS_NAME + ("-" + p_sState));
2445
                this.removeClass(sPrefix + sType + ("-button-" + p_sState));
2446
            
2447
            }
2448
        
2449
        },
2450
        
2451
        
2452
        /**
2453
        * @method createHiddenFields
2454
        * @description Creates the button's hidden form field and appends it 
2455
        * to its parent form.
2456
        * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
2457
        * level-one-html.html#ID-6043025">HTMLInputElement</a>|Array}
2458
        */
2459
        createHiddenFields: function () {
2460
        
2461
            this.removeHiddenFields();
2462
        
2463
            var oForm = this.getForm(),
2464
                oButtonField,
2465
                sType,
2466
                bCheckable,
2467
                oMenu,
2468
                oMenuItem,
2469
                sButtonName,
2470
                oValue,
2471
                oMenuField,
2472
                oReturnVal,
2473
				sMenuFieldName,
2474
				oMenuSrcElement,
2475
				bMenuSrcElementIsSelect = false;
2476
        
2477
        
2478
            if (oForm && !this.get("disabled")) {
2479
        
2480
                sType = this.get("type");
2481
                bCheckable = (sType == "checkbox" || sType == "radio");
2482
        
2483
        
2484
                if ((bCheckable && this.get("checked")) || (m_oSubmitTrigger == this)) {
2485
                
2486
                    YAHOO.log("Creating hidden field.", "info", this.toString());
2487
        
2488
                    oButtonField = createInputElement((bCheckable ? sType : "hidden"),
2489
                                    this.get("name"), this.get("value"), this.get("checked"));
2490
            
2491
            
2492
                    if (oButtonField) {
2493
            
2494
                        if (bCheckable) {
2495
            
2496
                            oButtonField.style.display = "none";
2497
            
2498
                        }
2499
            
2500
                        oForm.appendChild(oButtonField);
2501
            
2502
                    }
2503
        
2504
                }
2505
                    
2506
        
2507
                oMenu = this._menu;
2508
            
2509
            
2510
                if (Menu && oMenu && (oMenu instanceof Menu)) {
2511
        
2512
                    YAHOO.log("Creating hidden field for menu.", "info", this.toString());
2513
        
2514
                    oMenuItem = this.get("selectedMenuItem");
2515
					oMenuSrcElement = oMenu.srcElement;
2516
					bMenuSrcElementIsSelect = (oMenuSrcElement && 
2517
												oMenuSrcElement.nodeName.toUpperCase() == "SELECT");
2518
2519
                    if (oMenuItem) {
2520
2521
						oValue = (oMenuItem.value === null || oMenuItem.value === "") ? 
2522
									oMenuItem.cfg.getProperty("text") : oMenuItem.value;
2523
2524
						sButtonName = this.get("name");
2525
2526
2527
						if (bMenuSrcElementIsSelect) {
2528
						
2529
							sMenuFieldName = oMenuSrcElement.name;
2530
						
2531
						}
2532
						else if (sButtonName) {
2533
2534
							sMenuFieldName = (sButtonName + "_options");
2535
						
2536
						}
2537
						
2538
2539
						if (oValue && sMenuFieldName) {
2540
		
2541
							oMenuField = createInputElement("hidden", sMenuFieldName, oValue);
2542
							oForm.appendChild(oMenuField);
2543
		
2544
						}
2545
                    
2546
                    }
2547
                    else if (bMenuSrcElementIsSelect) {
2548
					
2549
						oMenuField = oForm.appendChild(oMenuSrcElement);
2550
                    
2551
                    }
2552
        
2553
                }
2554
            
2555
            
2556
                if (oButtonField && oMenuField) {
2557
        
2558
                    this._hiddenFields = [oButtonField, oMenuField];
2559
        
2560
                }
2561
                else if (!oButtonField && oMenuField) {
2562
        
2563
                    this._hiddenFields = oMenuField;
2564
                
2565
                }
2566
                else if (oButtonField && !oMenuField) {
2567
        
2568
                    this._hiddenFields = oButtonField;
2569
                
2570
                }
2571
        
2572
        		oReturnVal = this._hiddenFields;
2573
        
2574
            }
2575
2576
			return oReturnVal;
2577
        
2578
        },
2579
        
2580
        
2581
        /**
2582
        * @method removeHiddenFields
2583
        * @description Removes the button's hidden form field(s) from its 
2584
        * parent form.
2585
        */
2586
        removeHiddenFields: function () {
2587
        
2588
            var oField = this._hiddenFields,
2589
                nFields,
2590
                i;
2591
        
2592
            function removeChild(p_oElement) {
2593
        
2594
                if (Dom.inDocument(p_oElement)) {
2595
        
2596
                    p_oElement.parentNode.removeChild(p_oElement);
2597
2598
                }
2599
                
2600
            }
2601
            
2602
        
2603
            if (oField) {
2604
        
2605
                if (Lang.isArray(oField)) {
2606
        
2607
                    nFields = oField.length;
2608
                    
2609
                    if (nFields > 0) {
2610
                    
2611
                        i = nFields - 1;
2612
                        
2613
                        do {
2614
        
2615
                            removeChild(oField[i]);
2616
        
2617
                        }
2618
                        while (i--);
2619
                    
2620
                    }
2621
                
2622
                }
2623
                else {
2624
        
2625
                    removeChild(oField);
2626
        
2627
                }
2628
        
2629
                this._hiddenFields = null;
2630
            
2631
            }
2632
        
2633
        },
2634
        
2635
        
2636
        /**
2637
        * @method submitForm
2638
        * @description Submits the form to which the button belongs.  Returns  
2639
        * true if the form was submitted successfully, false if the submission 
2640
        * was cancelled.
2641
        * @protected
2642
        * @return {Boolean}
2643
        */
2644
        submitForm: function () {
2645
        
2646
            var oForm = this.getForm(),
2647
        
2648
                oSrcElement = this.get("srcelement"),
2649
        
2650
                /*
2651
                    Boolean indicating if the event fired successfully 
2652
                    (was not cancelled by any handlers)
2653
                */
2654
        
2655
                bSubmitForm = false,
2656
                
2657
                oEvent;
2658
        
2659
        
2660
            if (oForm) {
2661
        
2662
                if (this.get("type") == "submit" || (oSrcElement && oSrcElement.type == "submit")) {
2663
        
2664
                    m_oSubmitTrigger = this;
2665
                    
2666
                }
2667
        
2668
        
2669
                if (UA.ie) {
2670
        
2671
                    bSubmitForm = oForm.fireEvent("onsubmit");
2672
        
2673
                }
2674
                else {  // Gecko, Opera, and Safari
2675
        
2676
                    oEvent = document.createEvent("HTMLEvents");
2677
                    oEvent.initEvent("submit", true, true);
2678
        
2679
                    bSubmitForm = oForm.dispatchEvent(oEvent);
2680
        
2681
                }
2682
        
2683
        
2684
                /*
2685
                    In IE and Safari, dispatching a "submit" event to a form 
2686
                    WILL cause the form's "submit" event to fire, but WILL NOT 
2687
                    submit the form.  Therefore, we need to call the "submit" 
2688
                    method as well.
2689
                */
2690
              
2691
                if ((UA.ie || UA.webkit) && bSubmitForm) {
2692
        
2693
                    oForm.submit();
2694
                
2695
                }
2696
            
2697
            }
2698
        
2699
            return bSubmitForm;
2700
            
2701
        },
2702
        
2703
        
2704
        /**
2705
        * @method init
2706
        * @description The Button class's initialization method.
2707
        * @param {String} p_oElement String specifying the id attribute of the 
2708
        * <code>&#60;input&#62;</code>, <code>&#60;button&#62;</code>,
2709
        * <code>&#60;a&#62;</code>, or <code>&#60;span&#62;</code> element to 
2710
        * be used to create the button.
2711
        * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
2712
        * level-one-html.html#ID-6043025">HTMLInputElement</a>|<a href="http://
2713
        * www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html
2714
        * #ID-34812697">HTMLButtonElement</a>|<a href="http://www.w3.org/TR
2715
        * /2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-33759296">
2716
        * HTMLElement</a>} p_oElement Object reference for the 
2717
        * <code>&#60;input&#62;</code>, <code>&#60;button&#62;</code>, 
2718
        * <code>&#60;a&#62;</code>, or <code>&#60;span&#62;</code> element to be 
2719
        * used to create the button.
2720
        * @param {Object} p_oElement Object literal specifying a set of 
2721
        * configuration attributes used to create the button.
2722
        * @param {Object} p_oAttributes Optional. Object literal specifying a 
2723
        * set of configuration attributes used to create the button.
2724
        */
2725
        init: function (p_oElement, p_oAttributes) {
2726
        
2727
            var sNodeName = p_oAttributes.type == "link" ? "a" : "button",
2728
                oSrcElement = p_oAttributes.srcelement,
2729
                oButton = p_oElement.getElementsByTagName(sNodeName)[0],
2730
                oInput;
2731
2732
2733
            if (!oButton) {
2734
2735
                oInput = p_oElement.getElementsByTagName("input")[0];
2736
2737
2738
                if (oInput) {
2739
2740
                    oButton = document.createElement("button");
2741
                    oButton.setAttribute("type", "button");
2742
2743
                    oInput.parentNode.replaceChild(oButton, oInput);
2744
                
2745
                }
2746
2747
            }
2748
2749
            this._button = oButton;
2750
2751
2752
            YAHOO.widget.Button.superclass.init.call(this, p_oElement, p_oAttributes);
2753
2754
2755
			var sId = this.get("id"),
2756
				sButtonId = sId + "-button";
2757
2758
2759
        	oButton.id = sButtonId;
2760
2761
2762
			var aLabels,
2763
				oLabel;
2764
2765
2766
        	var hasLabel = function (element) {
2767
        	
2768
				return (element.htmlFor === sId);
2769
2770
        	};
2771
2772
2773
			var setLabel = function () {
2774
2775
				oLabel.setAttribute((UA.ie ? "htmlFor" : "for"), sButtonId);
2776
			
2777
			};
2778
2779
2780
			if (oSrcElement && this.get("type") != "link") {
2781
2782
				aLabels = Dom.getElementsBy(hasLabel, "label");
2783
2784
				if (Lang.isArray(aLabels) && aLabels.length > 0) {
2785
				
2786
					oLabel = aLabels[0];
2787
				
2788
				}
2789
2790
			}
2791
        
2792
2793
            m_oButtons[sId] = this;
2794
2795
        	var sPrefix = this.CLASS_NAME_PREFIX;
2796
2797
            this.addClass(sPrefix + this.CSS_CLASS_NAME);
2798
            this.addClass(sPrefix + this.get("type") + "-button");
2799
        
2800
            Event.on(this._button, "focus", this._onFocus, null, this);
2801
            this.on("mouseover", this._onMouseOver);
2802
			this.on("mousedown", this._onMouseDown);
2803
			this.on("mouseup", this._onMouseUp);
2804
            this.on("click", this._onClick);
2805
2806
			//	Need to reset the value of the "onclick" Attribute so that any
2807
			//	handlers registered via the "onclick" Attribute are fired after 
2808
			//	Button's default "_onClick" listener.
2809
2810
			var fnOnClick = this.get("onclick");
2811
2812
			this.set("onclick", null);
2813
			this.set("onclick", fnOnClick);
2814
2815
            this.on("dblclick", this._onDblClick);
2816
2817
2818
			var oParentNode;
2819
2820
            if (oLabel) {
2821
            
2822
				if (this.get("replaceLabel")) {
2823
2824
					this.set("label", oLabel.innerHTML);
2825
					
2826
					oParentNode = oLabel.parentNode;
2827
					
2828
					oParentNode.removeChild(oLabel);
2829
					
2830
				}
2831
				else {
2832
2833
					this.on("appendTo", setLabel); 
2834
2835
					Event.on(oLabel, "click", this._onLabelClick, null, this);
2836
2837
					this._label = oLabel;
2838
					
2839
				}
2840
            
2841
            }
2842
            
2843
            this.on("appendTo", this._onAppendTo);
2844
       
2845
        
2846
2847
            var oContainer = this.get("container"),
2848
                oElement = this.get("element"),
2849
                bElInDoc = Dom.inDocument(oElement);
2850
2851
2852
            if (oContainer) {
2853
        
2854
                if (oSrcElement && oSrcElement != oElement) {
2855
                
2856
                    oParentNode = oSrcElement.parentNode;
2857
2858
                    if (oParentNode) {
2859
                    
2860
                        oParentNode.removeChild(oSrcElement);
2861
                    
2862
                    }
2863
2864
                }
2865
        
2866
                if (Lang.isString(oContainer)) {
2867
        
2868
                    Event.onContentReady(oContainer, this.appendTo, oContainer, this);
2869
        
2870
                }
2871
                else {
2872
        
2873
        			this.on("init", function () {
2874
        			
2875
        				Lang.later(0, this, this.appendTo, oContainer);
2876
        			
2877
        			});
2878
        
2879
                }
2880
        
2881
            }
2882
            else if (!bElInDoc && oSrcElement && oSrcElement != oElement) {
2883
2884
                oParentNode = oSrcElement.parentNode;
2885
        
2886
                if (oParentNode) {
2887
        
2888
                    this.fireEvent("beforeAppendTo", {
2889
                        type: "beforeAppendTo",
2890
                        target: oParentNode
2891
                    });
2892
            
2893
                    oParentNode.replaceChild(oElement, oSrcElement);
2894
            
2895
                    this.fireEvent("appendTo", {
2896
                        type: "appendTo",
2897
                        target: oParentNode
2898
                    });
2899
                
2900
                }
2901
        
2902
            }
2903
            else if (this.get("type") != "link" && bElInDoc && oSrcElement && 
2904
                oSrcElement == oElement) {
2905
        
2906
                this._addListenersToForm();
2907
        
2908
            }
2909
        
2910
            YAHOO.log("Initialization completed.", "info", this.toString());
2911
        
2912
2913
			this.fireEvent("init", {
2914
				type: "init",
2915
				target: this
2916
			});        
2917
        
2918
        },
2919
        
2920
        
2921
        /**
2922
        * @method initAttributes
2923
        * @description Initializes all of the configuration attributes used to  
2924
        * create the button.
2925
        * @param {Object} p_oAttributes Object literal specifying a set of 
2926
        * configuration attributes used to create the button.
2927
        */
2928
        initAttributes: function (p_oAttributes) {
2929
        
2930
            var oAttributes = p_oAttributes || {};
2931
        
2932
            YAHOO.widget.Button.superclass.initAttributes.call(this, 
2933
                oAttributes);
2934
        
2935
        
2936
            /**
2937
            * @attribute type
2938
            * @description String specifying the button's type.  Possible 
2939
            * values are: "push," "link," "submit," "reset," "checkbox," 
2940
            * "radio," "menu," and "split."
2941
            * @default "push"
2942
            * @type String
2943
			* @writeonce
2944
            */
2945
            this.setAttributeConfig("type", {
2946
        
2947
                value: (oAttributes.type || "push"),
2948
                validator: Lang.isString,
2949
                writeOnce: true,
2950
                method: this._setType
2951
2952
            });
2953
        
2954
        
2955
            /**
2956
            * @attribute label
2957
            * @description String specifying the button's text label 
2958
            * or innerHTML.
2959
            * @default null
2960
            * @type String
2961
            */
2962
            this.setAttributeConfig("label", {
2963
        
2964
                value: oAttributes.label,
2965
                validator: Lang.isString,
2966
                method: this._setLabel
2967
        
2968
            });
2969
        
2970
        
2971
            /**
2972
            * @attribute value
2973
            * @description Object specifying the value for the button.
2974
            * @default null
2975
            * @type Object
2976
            */
2977
            this.setAttributeConfig("value", {
2978
        
2979
                value: oAttributes.value
2980
        
2981
            });
2982
        
2983
        
2984
            /**
2985
            * @attribute name
2986
            * @description String specifying the name for the button.
2987
            * @default null
2988
            * @type String
2989
            */
2990
            this.setAttributeConfig("name", {
2991
        
2992
                value: oAttributes.name,
2993
                validator: Lang.isString
2994
        
2995
            });
2996
        
2997
        
2998
            /**
2999
            * @attribute tabindex
3000
            * @description Number specifying the tabindex for the button.
3001
            * @default null
3002
            * @type Number
3003
            */
3004
            this.setAttributeConfig("tabindex", {
3005
        
3006
                value: oAttributes.tabindex,
3007
                validator: Lang.isNumber,
3008
                method: this._setTabIndex
3009
        
3010
            });
3011
        
3012
        
3013
            /**
3014
            * @attribute title
3015
            * @description String specifying the title for the button.
3016
            * @default null
3017
            * @type String
3018
            */
3019
            this.configureAttribute("title", {
3020
        
3021
                value: oAttributes.title,
3022
                validator: Lang.isString,
3023
                method: this._setTitle
3024
        
3025
            });
3026
        
3027
        
3028
            /**
3029
            * @attribute disabled
3030
            * @description Boolean indicating if the button should be disabled.  
3031
            * (Disabled buttons are dimmed and will not respond to user input 
3032
            * or fire events.  Does not apply to button's of type "link.")
3033
            * @default false
3034
            * @type Boolean
3035
            */
3036
            this.setAttributeConfig("disabled", {
3037
        
3038
                value: (oAttributes.disabled || false),
3039
                validator: Lang.isBoolean,
3040
                method: this._setDisabled
3041
        
3042
            });
3043
        
3044
        
3045
            /**
3046
            * @attribute href
3047
            * @description String specifying the href for the button.  Applies
3048
            * only to buttons of type "link."
3049
            * @type String
3050
            */
3051
            this.setAttributeConfig("href", {
3052
        
3053
                value: oAttributes.href,
3054
                validator: Lang.isString,
3055
                method: this._setHref
3056
        
3057
            });
3058
        
3059
        
3060
            /**
3061
            * @attribute target
3062
            * @description String specifying the target for the button.  
3063
            * Applies only to buttons of type "link."
3064
            * @type String
3065
            */
3066
            this.setAttributeConfig("target", {
3067
        
3068
                value: oAttributes.target,
3069
                validator: Lang.isString,
3070
                method: this._setTarget
3071
        
3072
            });
3073
        
3074
        
3075
            /**
3076
            * @attribute checked
3077
            * @description Boolean indicating if the button is checked. 
3078
            * Applies only to buttons of type "radio" and "checkbox."
3079
            * @default false
3080
            * @type Boolean
3081
            */
3082
            this.setAttributeConfig("checked", {
3083
        
3084
                value: (oAttributes.checked || false),
3085
                validator: Lang.isBoolean,
3086
                method: this._setChecked
3087
        
3088
            });
3089
        
3090
        
3091
            /**
3092
            * @attribute container
3093
            * @description HTML element reference or string specifying the id 
3094
            * attribute of the HTML element that the button's markup should be 
3095
            * rendered into.
3096
            * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3097
            * level-one-html.html#ID-58190037">HTMLElement</a>|String
3098
            * @default null
3099
			* @writeonce
3100
            */
3101
            this.setAttributeConfig("container", {
3102
        
3103
                value: oAttributes.container,
3104
                writeOnce: true
3105
        
3106
            });
3107
        
3108
        
3109
            /**
3110
            * @attribute srcelement
3111
            * @description Object reference to the HTML element (either 
3112
            * <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code>) 
3113
            * used to create the button.
3114
            * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3115
            * level-one-html.html#ID-58190037">HTMLElement</a>|String
3116
            * @default null
3117
			* @writeonce
3118
            */
3119
            this.setAttributeConfig("srcelement", {
3120
        
3121
                value: oAttributes.srcelement,
3122
                writeOnce: true
3123
        
3124
            });
3125
        
3126
        
3127
            /**
3128
            * @attribute menu
3129
            * @description Object specifying the menu for the button.  
3130
            * The value can be one of the following:
3131
            * <ul>
3132
            * <li>Object specifying a rendered <a href="YAHOO.widget.Menu.html">
3133
            * YAHOO.widget.Menu</a> instance.</li>
3134
            * <li>Object specifying a rendered <a href="YAHOO.widget.Overlay.html">
3135
            * YAHOO.widget.Overlay</a> instance.</li>
3136
            * <li>String specifying the id attribute of the <code>&#60;div&#62;
3137
            * </code> element used to create the menu.  By default the menu 
3138
            * will be created as an instance of 
3139
            * <a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>.  
3140
            * If the <a href="YAHOO.widget.Menu.html#CSS_CLASS_NAME">
3141
            * default CSS class name for YAHOO.widget.Menu</a> is applied to 
3142
            * the <code>&#60;div&#62;</code> element, it will be created as an
3143
            * instance of <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu
3144
            * </a>.</li><li>String specifying the id attribute of the 
3145
            * <code>&#60;select&#62;</code> element used to create the menu.
3146
            * </li><li>Object specifying the <code>&#60;div&#62;</code> element
3147
            * used to create the menu.</li>
3148
            * <li>Object specifying the <code>&#60;select&#62;</code> element
3149
            * used to create the menu.</li>
3150
            * <li>Array of object literals, each representing a set of 
3151
            * <a href="YAHOO.widget.MenuItem.html">YAHOO.widget.MenuItem</a> 
3152
            * configuration attributes.</li>
3153
            * <li>Array of strings representing the text labels for each menu 
3154
            * item in the menu.</li>
3155
            * </ul>
3156
            * @type <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a>|<a 
3157
            * href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>|<a 
3158
            * href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
3159
            * one-html.html#ID-58190037">HTMLElement</a>|String|Array
3160
            * @default null
3161
			* @writeonce
3162
            */
3163
            this.setAttributeConfig("menu", {
3164
        
3165
                value: null,
3166
                method: this._setMenu,
3167
                writeOnce: true
3168
            
3169
            });
3170
        
3171
        
3172
            /**
3173
            * @attribute lazyloadmenu
3174
            * @description Boolean indicating the value to set for the 
3175
            * <a href="YAHOO.widget.Menu.html#lazyLoad">"lazyload"</a>
3176
            * configuration property of the button's menu.  Setting 
3177
            * "lazyloadmenu" to <code>true </code> will defer rendering of 
3178
            * the button's menu until the first time it is made visible.  
3179
            * If "lazyloadmenu" is set to <code>false</code>, the button's 
3180
            * menu will be rendered immediately if the button is in the 
3181
            * document, or in response to the button's "appendTo" event if 
3182
            * the button is not yet in the document.  In either case, the 
3183
            * menu is rendered into the button's parent HTML element.  
3184
            * <em>This attribute does not apply if a 
3185
            * <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a> or 
3186
            * <a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a> 
3187
            * instance is passed as the value of the button's "menu" 
3188
            * configuration attribute. <a href="YAHOO.widget.Menu.html">
3189
            * YAHOO.widget.Menu</a> or <a href="YAHOO.widget.Overlay.html">
3190
            * YAHOO.widget.Overlay</a> instances should be rendered before 
3191
            * being set as the value for the "menu" configuration 
3192
            * attribute.</em>
3193
            * @default true
3194
            * @type Boolean
3195
			* @writeonce
3196
            */
3197
            this.setAttributeConfig("lazyloadmenu", {
3198
        
3199
                value: (oAttributes.lazyloadmenu === false ? false : true),
3200
                validator: Lang.isBoolean,
3201
                writeOnce: true
3202
        
3203
            });
3204
3205
3206
            /**
3207
            * @attribute menuclassname
3208
            * @description String representing the CSS class name to be 
3209
            * applied to the root element of the button's menu.
3210
            * @type String
3211
            * @default "yui-button-menu"
3212
			* @writeonce
3213
            */
3214
            this.setAttributeConfig("menuclassname", {
3215
        
3216
                value: (oAttributes.menuclassname || (this.CLASS_NAME_PREFIX + "button-menu")),
3217
                validator: Lang.isString,
3218
                method: this._setMenuClassName,
3219
                writeOnce: true
3220
        
3221
            });        
3222
3223
3224
			/**
3225
			* @attribute menuminscrollheight
3226
			* @description Number defining the minimum threshold for the "menumaxheight" 
3227
			* configuration attribute.  When set this attribute is automatically applied 
3228
			* to all submenus.
3229
			* @default 90
3230
			* @type Number
3231
			*/
3232
            this.setAttributeConfig("menuminscrollheight", {
3233
        
3234
                value: (oAttributes.menuminscrollheight || 90),
3235
                validator: Lang.isNumber
3236
        
3237
            });
3238
3239
3240
            /**
3241
            * @attribute menumaxheight
3242
			* @description Number defining the maximum height (in pixels) for a menu's 
3243
			* body element (<code>&#60;div class="bd"&#60;</code>).  Once a menu's body 
3244
			* exceeds this height, the contents of the body are scrolled to maintain 
3245
			* this value.  This value cannot be set lower than the value of the 
3246
			* "minscrollheight" configuration property.
3247
            * @type Number
3248
            * @default 0
3249
            */
3250
            this.setAttributeConfig("menumaxheight", {
3251
        
3252
                value: (oAttributes.menumaxheight || 0),
3253
                validator: Lang.isNumber
3254
        
3255
            });
3256
3257
3258
            /**
3259
            * @attribute menualignment
3260
			* @description Array defining how the Button's Menu is aligned to the Button.  
3261
            * The default value of ["tl", "bl"] aligns the Menu's top left corner to the Button's 
3262
            * bottom left corner.
3263
            * @type Array
3264
            * @default ["tl", "bl"]
3265
            */
3266
            this.setAttributeConfig("menualignment", {
3267
        
3268
                value: (oAttributes.menualignment || ["tl", "bl"]),
3269
                validator: Lang.isArray
3270
        
3271
            });
3272
            
3273
3274
            /**
3275
            * @attribute selectedMenuItem
3276
            * @description Object representing the item in the button's menu 
3277
            * that is currently selected.
3278
            * @type YAHOO.widget.MenuItem
3279
            * @default null
3280
            */
3281
            this.setAttributeConfig("selectedMenuItem", {
3282
        
3283
                value: null
3284
        
3285
            });
3286
        
3287
        
3288
            /**
3289
            * @attribute onclick
3290
            * @description Object literal representing the code to be executed  
3291
            * when the button is clicked.  Format:<br> <code> {<br> 
3292
            * <strong>fn:</strong> Function,   &#47;&#47; The handler to call 
3293
            * when the event fires.<br> <strong>obj:</strong> Object, 
3294
            * &#47;&#47; An object to pass back to the handler.<br> 
3295
            * <strong>scope:</strong> Object &#47;&#47;  The object to use 
3296
            * for the scope of the handler.<br> } </code>
3297
            * @type Object
3298
            * @default null
3299
            */
3300
            this.setAttributeConfig("onclick", {
3301
        
3302
                value: oAttributes.onclick,
3303
                method: this._setOnClick
3304
            
3305
            });
3306
3307
3308
            /**
3309
            * @attribute focusmenu
3310
            * @description Boolean indicating whether or not the button's menu 
3311
            * should be focused when it is made visible.
3312
            * @type Boolean
3313
            * @default true
3314
            */
3315
            this.setAttributeConfig("focusmenu", {
3316
        
3317
                value: (oAttributes.focusmenu === false ? false : true),
3318
                validator: Lang.isBoolean
3319
        
3320
            });
3321
3322
3323
            /**
3324
            * @attribute replaceLabel
3325
            * @description Boolean indicating whether or not the text of the 
3326
			* button's <code>&#60;label&#62;</code> element should be used as
3327
			* the source for the button's label configuration attribute and 
3328
			* removed from the DOM.
3329
            * @type Boolean
3330
            * @default false
3331
            */
3332
            this.setAttributeConfig("replaceLabel", {
3333
        
3334
                value: false,
3335
                validator: Lang.isBoolean,
3336
                writeOnce: true
3337
        
3338
            });
3339
3340
        },
3341
        
3342
        
3343
        /**
3344
        * @method focus
3345
        * @description Causes the button to receive the focus and fires the 
3346
        * button's "focus" event.
3347
        */
3348
        focus: function () {
3349
        
3350
            if (!this.get("disabled")) {
3351
        
3352
                this._button.focus();
3353
            
3354
            }
3355
        
3356
        },
3357
        
3358
        
3359
        /**
3360
        * @method blur
3361
        * @description Causes the button to lose focus and fires the button's
3362
        * "blur" event.
3363
        */
3364
        blur: function () {
3365
        
3366
            if (!this.get("disabled")) {
3367
        
3368
                this._button.blur();
3369
        
3370
            }
3371
        
3372
        },
3373
        
3374
        
3375
        /**
3376
        * @method hasFocus
3377
        * @description Returns a boolean indicating whether or not the button 
3378
        * has focus.
3379
        * @return {Boolean}
3380
        */
3381
        hasFocus: function () {
3382
        
3383
            return (m_oFocusedButton == this);
3384
        
3385
        },
3386
        
3387
        
3388
        /**
3389
        * @method isActive
3390
        * @description Returns a boolean indicating whether or not the button 
3391
        * is active.
3392
        * @return {Boolean}
3393
        */
3394
        isActive: function () {
3395
        
3396
            return this.hasClass(this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME + "-active");
3397
        
3398
        },
3399
        
3400
        
3401
        /**
3402
        * @method getMenu
3403
        * @description Returns a reference to the button's menu.
3404
        * @return {<a href="YAHOO.widget.Overlay.html">
3405
        * YAHOO.widget.Overlay</a>|<a 
3406
        * href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a>}
3407
        */
3408
        getMenu: function () {
3409
        
3410
            return this._menu;
3411
        
3412
        },
3413
        
3414
        
3415
        /**
3416
        * @method getForm
3417
        * @description Returns a reference to the button's parent form.
3418
        * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-
3419
        * 20000929/level-one-html.html#ID-40002357">HTMLFormElement</a>}
3420
        */
3421
        getForm: function () {
3422
        
3423
        	var oButton = this._button,
3424
        		oForm;
3425
        
3426
            if (oButton) {
3427
            
3428
            	oForm = oButton.form;
3429
            
3430
            }
3431
        
3432
        	return oForm;
3433
        
3434
        },
3435
        
3436
        
3437
        /** 
3438
        * @method getHiddenFields
3439
        * @description Returns an <code>&#60;input&#62;</code> element or 
3440
        * array of form elements used to represent the button when its parent 
3441
        * form is submitted.  
3442
        * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3443
        * level-one-html.html#ID-6043025">HTMLInputElement</a>|Array}
3444
        */
3445
        getHiddenFields: function () {
3446
        
3447
            return this._hiddenFields;
3448
        
3449
        },
3450
        
3451
        
3452
        /**
3453
        * @method destroy
3454
        * @description Removes the button's element from its parent element and 
3455
        * removes all event handlers.
3456
        */
3457
        destroy: function () {
3458
        
3459
            YAHOO.log("Destroying ...", "info", this.toString());
3460
        
3461
            var oElement = this.get("element"),
3462
                oMenu = this._menu,
3463
				oLabel = this._label,
3464
                oParentNode,
3465
                aButtons;
3466
        
3467
            if (oMenu) {
3468
        
3469
                YAHOO.log("Destroying menu.", "info", this.toString());
3470
3471
                if (m_oOverlayManager && m_oOverlayManager.find(oMenu)) {
3472
3473
                    m_oOverlayManager.remove(oMenu);
3474
3475
                }
3476
        
3477
                oMenu.destroy();
3478
        
3479
            }
3480
        
3481
            YAHOO.log("Removing DOM event listeners.", "info", this.toString());
3482
        
3483
            Event.purgeElement(oElement);
3484
            Event.purgeElement(this._button);
3485
            Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
3486
            Event.removeListener(document, "keyup", this._onDocumentKeyUp);
3487
            Event.removeListener(document, "mousedown", this._onDocumentMouseDown);
3488
3489
3490
			if (oLabel) {
3491
3492
            	Event.removeListener(oLabel, "click", this._onLabelClick);
3493
				
3494
				oParentNode = oLabel.parentNode;
3495
				oParentNode.removeChild(oLabel);
3496
				
3497
			}
3498
        
3499
        
3500
            var oForm = this.getForm();
3501
            
3502
            if (oForm) {
3503
        
3504
                Event.removeListener(oForm, "reset", this._onFormReset);
3505
                Event.removeListener(oForm, "submit", this._onFormSubmit);
3506
        
3507
            }
3508
3509
            YAHOO.log("Removing CustomEvent listeners.", "info", this.toString());
3510
3511
            this.unsubscribeAll();
3512
3513
			oParentNode = oElement.parentNode;
3514
3515
            if (oParentNode) {
3516
3517
                oParentNode.removeChild(oElement);
3518
            
3519
            }
3520
        
3521
            YAHOO.log("Removing from document.", "info", this.toString());
3522
        
3523
            delete m_oButtons[this.get("id")];
3524
3525
			var sClass = (this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME);
3526
3527
            aButtons = Dom.getElementsByClassName(sClass, 
3528
                                this.NODE_NAME, oForm); 
3529
3530
            if (Lang.isArray(aButtons) && aButtons.length === 0) {
3531
3532
                Event.removeListener(oForm, "keypress", 
3533
                        YAHOO.widget.Button.onFormKeyPress);
3534
3535
            }
3536
3537
            YAHOO.log("Destroyed.", "info", this.toString());
3538
        
3539
        },
3540
        
3541
        
3542
        fireEvent: function (p_sType , p_aArgs) {
3543
        
3544
			var sType = arguments[0];
3545
		
3546
			//  Disabled buttons should not respond to DOM events
3547
		
3548
			if (this.DOM_EVENTS[sType] && this.get("disabled")) {
3549
		
3550
				return false;
3551
		
3552
			}
3553
		
3554
			return YAHOO.widget.Button.superclass.fireEvent.apply(this, arguments);
3555
        
3556
        },
3557
        
3558
        
3559
        /**
3560
        * @method toString
3561
        * @description Returns a string representing the button.
3562
        * @return {String}
3563
        */
3564
        toString: function () {
3565
        
3566
            return ("Button " + this.get("id"));
3567
        
3568
        }
3569
    
3570
    });
3571
    
3572
    
3573
    /**
3574
    * @method YAHOO.widget.Button.onFormKeyPress
3575
    * @description "keypress" event handler for the button's form.
3576
    * @param {Event} p_oEvent Object representing the DOM event object passed 
3577
    * back by the event utility (YAHOO.util.Event).
3578
    */
3579
    YAHOO.widget.Button.onFormKeyPress = function (p_oEvent) {
3580
    
3581
        var oTarget = Event.getTarget(p_oEvent),
3582
            nCharCode = Event.getCharCode(p_oEvent),
3583
            sNodeName = oTarget.nodeName && oTarget.nodeName.toUpperCase(),
3584
            sType = oTarget.type,
3585
    
3586
            /*
3587
                Boolean indicating if the form contains any enabled or 
3588
                disabled YUI submit buttons
3589
            */
3590
    
3591
            bFormContainsYUIButtons = false,
3592
    
3593
            oButton,
3594
    
3595
            oYUISubmitButton,   // The form's first, enabled YUI submit button
3596
    
3597
            /*
3598
                 The form's first, enabled HTML submit button that precedes any 
3599
                 YUI submit button
3600
            */
3601
    
3602
            oPrecedingSubmitButton,
3603
            
3604
            oEvent; 
3605
    
3606
    
3607
        function isSubmitButton(p_oElement) {
3608
    
3609
            var sId,
3610
                oSrcElement;
3611
    
3612
            switch (p_oElement.nodeName.toUpperCase()) {
3613
    
3614
            case "INPUT":
3615
            case "BUTTON":
3616
            
3617
                if (p_oElement.type == "submit" && !p_oElement.disabled) {
3618
                    
3619
                    if (!bFormContainsYUIButtons && !oPrecedingSubmitButton) {
3620
3621
                        oPrecedingSubmitButton = p_oElement;
3622
3623
                    }
3624
                
3625
                }
3626
3627
                break;
3628
            
3629
3630
            default:
3631
            
3632
                sId = p_oElement.id;
3633
    
3634
                if (sId) {
3635
    
3636
                    oButton = m_oButtons[sId];
3637
        
3638
                    if (oButton) {
3639
3640
                        bFormContainsYUIButtons = true;
3641
        
3642
                        if (!oButton.get("disabled")) {
3643
3644
                            oSrcElement = oButton.get("srcelement");
3645
    
3646
                            if (!oYUISubmitButton && (oButton.get("type") == "submit" || 
3647
                                (oSrcElement && oSrcElement.type == "submit"))) {
3648
3649
                                oYUISubmitButton = oButton;
3650
                            
3651
                            }
3652
                        
3653
                        }
3654
                        
3655
                    }
3656
                
3657
                }
3658
3659
                break;
3660
    
3661
            }
3662
    
3663
        }
3664
    
3665
    
3666
        if (nCharCode == 13 && ((sNodeName == "INPUT" && (sType == "text" || 
3667
            sType == "password" || sType == "checkbox" || sType == "radio" || 
3668
            sType == "file")) || sNodeName == "SELECT")) {
3669
    
3670
            Dom.getElementsBy(isSubmitButton, "*", this);
3671
    
3672
    
3673
            if (oPrecedingSubmitButton) {
3674
    
3675
                /*
3676
                     Need to set focus to the first enabled submit button
3677
                     to make sure that IE includes its name and value 
3678
                     in the form's data set.
3679
                */
3680
    
3681
                oPrecedingSubmitButton.focus();
3682
            
3683
            }
3684
            else if (!oPrecedingSubmitButton && oYUISubmitButton) {
3685
    
3686
				/*
3687
					Need to call "preventDefault" to ensure that the form doesn't end up getting
3688
					submitted twice.
3689
				*/
3690
    
3691
    			Event.preventDefault(p_oEvent);
3692
3693
3694
				if (UA.ie) {
3695
				
3696
					oYUISubmitButton.get("element").fireEvent("onclick");
3697
				
3698
				}
3699
				else {
3700
3701
					oEvent = document.createEvent("HTMLEvents");
3702
					oEvent.initEvent("click", true, true);
3703
			
3704
3705
					if (UA.gecko < 1.9) {
3706
					
3707
						oYUISubmitButton.fireEvent("click", oEvent);
3708
					
3709
					}
3710
					else {
3711
3712
						oYUISubmitButton.get("element").dispatchEvent(oEvent);
3713
					
3714
					}
3715
  
3716
                }
3717
3718
            }
3719
            
3720
        }
3721
    
3722
    };
3723
    
3724
    
3725
    /**
3726
    * @method YAHOO.widget.Button.addHiddenFieldsToForm
3727
    * @description Searches the specified form and adds hidden fields for  
3728
    * instances of YAHOO.widget.Button that are of type "radio," "checkbox," 
3729
    * "menu," and "split."
3730
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
3731
    * one-html.html#ID-40002357">HTMLFormElement</a>} p_oForm Object reference 
3732
    * for the form to search.
3733
    */
3734
    YAHOO.widget.Button.addHiddenFieldsToForm = function (p_oForm) {
3735
    
3736
        var proto = YAHOO.widget.Button.prototype,
3737
			aButtons = Dom.getElementsByClassName(
3738
							(proto.CLASS_NAME_PREFIX + proto.CSS_CLASS_NAME), 
3739
                            "*", 
3740
                            p_oForm),
3741
    
3742
            nButtons = aButtons.length,
3743
            oButton,
3744
            sId,
3745
            i;
3746
    
3747
        if (nButtons > 0) {
3748
    
3749
            YAHOO.log("Form contains " + nButtons + " YUI buttons.", "info", this.toString());
3750
    
3751
            for (i = 0; i < nButtons; i++) {
3752
    
3753
                sId = aButtons[i].id;
3754
    
3755
                if (sId) {
3756
    
3757
                    oButton = m_oButtons[sId];
3758
        
3759
                    if (oButton) {
3760
           
3761
                        oButton.createHiddenFields();
3762
                        
3763
                    }
3764
                
3765
                }
3766
            
3767
            }
3768
    
3769
        }
3770
    
3771
    };
3772
    
3773
3774
    /**
3775
    * @method YAHOO.widget.Button.getButton
3776
    * @description Returns a button with the specified id.
3777
    * @param {String} p_sId String specifying the id of the root node of the 
3778
    * HTML element representing the button to be retrieved.
3779
    * @return {YAHOO.widget.Button}
3780
    */
3781
    YAHOO.widget.Button.getButton = function (p_sId) {
3782
3783
		return m_oButtons[p_sId];
3784
3785
    };
3786
    
3787
    
3788
    // Events
3789
    
3790
    
3791
    /**
3792
    * @event focus
3793
    * @description Fires when the menu item receives focus.  Passes back a  
3794
    * single object representing the original DOM event object passed back by 
3795
    * the event utility (YAHOO.util.Event) when the event was fired.  See 
3796
    * <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> 
3797
    * for more information on listening for this event.
3798
    * @type YAHOO.util.CustomEvent
3799
    */
3800
    
3801
    
3802
    /**
3803
    * @event blur
3804
    * @description Fires when the menu item loses the input focus.  Passes back  
3805
    * a single object representing the original DOM event object passed back by 
3806
    * the event utility (YAHOO.util.Event) when the event was fired.  See 
3807
    * <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for  
3808
    * more information on listening for this event.
3809
    * @type YAHOO.util.CustomEvent
3810
    */
3811
    
3812
    
3813
    /**
3814
    * @event option
3815
    * @description Fires when the user invokes the button's option.  Passes 
3816
    * back a single object representing the original DOM event (either 
3817
    * "mousedown" or "keydown") that caused the "option" event to fire.  See 
3818
    * <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> 
3819
    * for more information on listening for this event.
3820
    * @type YAHOO.util.CustomEvent
3821
    */
3822
3823
})();
3824
(function () {
3825
3826
    // Shorthard for utilities
3827
    
3828
    var Dom = YAHOO.util.Dom,
3829
        Event = YAHOO.util.Event,
3830
        Lang = YAHOO.lang,
3831
        Button = YAHOO.widget.Button,  
3832
    
3833
        // Private collection of radio buttons
3834
    
3835
        m_oButtons = {};
3836
3837
3838
3839
    /**
3840
    * The ButtonGroup class creates a set of buttons that are mutually 
3841
    * exclusive; checking one button in the set will uncheck all others in the 
3842
    * button group.
3843
    * @param {String} p_oElement String specifying the id attribute of the 
3844
    * <code>&#60;div&#62;</code> element of the button group.
3845
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3846
    * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object 
3847
    * specifying the <code>&#60;div&#62;</code> element of the button group.
3848
    * @param {Object} p_oElement Object literal specifying a set of 
3849
    * configuration attributes used to create the button group.
3850
    * @param {Object} p_oAttributes Optional. Object literal specifying a set 
3851
    * of configuration attributes used to create the button group.
3852
    * @namespace YAHOO.widget
3853
    * @class ButtonGroup
3854
    * @constructor
3855
    * @extends YAHOO.util.Element
3856
    */
3857
    YAHOO.widget.ButtonGroup = function (p_oElement, p_oAttributes) {
3858
    
3859
        var fnSuperClass = YAHOO.widget.ButtonGroup.superclass.constructor,
3860
            sNodeName,
3861
            oElement,
3862
            sId;
3863
    
3864
        if (arguments.length == 1 && !Lang.isString(p_oElement) && 
3865
            !p_oElement.nodeName) {
3866
    
3867
            if (!p_oElement.id) {
3868
    
3869
                sId = Dom.generateId();
3870
    
3871
                p_oElement.id = sId;
3872
    
3873
                YAHOO.log("No value specified for the button group's \"id\"" +
3874
                    " attribute. Setting button group id to \"" + sId + "\".",
3875
                    "info");
3876
    
3877
            }
3878
    
3879
            this.logger = new YAHOO.widget.LogWriter("ButtonGroup " + sId);
3880
    
3881
            this.logger.log("No source HTML element.  Building the button " +
3882
                    "group using the set of configuration attributes.");
3883
    
3884
            fnSuperClass.call(this, (this._createGroupElement()), p_oElement);
3885
    
3886
        }
3887
        else if (Lang.isString(p_oElement)) {
3888
    
3889
            oElement = Dom.get(p_oElement);
3890
    
3891
            if (oElement) {
3892
            
3893
                if (oElement.nodeName.toUpperCase() == this.NODE_NAME) {
3894
    
3895
                    this.logger = 
3896
                        new YAHOO.widget.LogWriter("ButtonGroup " + p_oElement);
3897
            
3898
                    fnSuperClass.call(this, oElement, p_oAttributes);
3899
    
3900
                }
3901
    
3902
            }
3903
        
3904
        }
3905
        else {
3906
    
3907
            sNodeName = p_oElement.nodeName.toUpperCase();
3908
    
3909
            if (sNodeName && sNodeName == this.NODE_NAME) {
3910
        
3911
                if (!p_oElement.id) {
3912
        
3913
                    p_oElement.id = Dom.generateId();
3914
        
3915
                    YAHOO.log("No value specified for the button group's" +
3916
                        " \"id\" attribute. Setting button group id " +
3917
                        "to \"" + p_oElement.id + "\".", "warn");
3918
        
3919
                }
3920
        
3921
                this.logger = 
3922
                    new YAHOO.widget.LogWriter("ButtonGroup " + p_oElement.id);
3923
        
3924
                fnSuperClass.call(this, p_oElement, p_oAttributes);
3925
    
3926
            }
3927
    
3928
        }
3929
    
3930
    };
3931
    
3932
    
3933
    YAHOO.extend(YAHOO.widget.ButtonGroup, YAHOO.util.Element, {
3934
    
3935
    
3936
        // Protected properties
3937
        
3938
        
3939
        /** 
3940
        * @property _buttons
3941
        * @description Array of buttons in the button group.
3942
        * @default null
3943
        * @protected
3944
        * @type Array
3945
        */
3946
        _buttons: null,
3947
        
3948
        
3949
        
3950
        // Constants
3951
        
3952
        
3953
        /**
3954
        * @property NODE_NAME
3955
        * @description The name of the tag to be used for the button 
3956
        * group's element. 
3957
        * @default "DIV"
3958
        * @final
3959
        * @type String
3960
        */
3961
        NODE_NAME: "DIV",
3962
3963
3964
        /**
3965
        * @property CLASS_NAME_PREFIX
3966
        * @description Prefix used for all class names applied to a ButtonGroup.
3967
        * @default "yui-"
3968
        * @final
3969
        * @type String
3970
        */
3971
        CLASS_NAME_PREFIX: "yui-",
3972
        
3973
        
3974
        /**
3975
        * @property CSS_CLASS_NAME
3976
        * @description String representing the CSS class(es) to be applied  
3977
        * to the button group's element.
3978
        * @default "buttongroup"
3979
        * @final
3980
        * @type String
3981
        */
3982
        CSS_CLASS_NAME: "buttongroup",
3983
    
3984
    
3985
    
3986
        // Protected methods
3987
        
3988
        
3989
        /**
3990
        * @method _createGroupElement
3991
        * @description Creates the button group's element.
3992
        * @protected
3993
        * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3994
        * level-one-html.html#ID-22445964">HTMLDivElement</a>}
3995
        */
3996
        _createGroupElement: function () {
3997
        
3998
            var oElement = document.createElement(this.NODE_NAME);
3999
        
4000
            return oElement;
4001
        
4002
        },
4003
        
4004
        
4005
        
4006
        // Protected attribute setter methods
4007
        
4008
        
4009
        /**
4010
        * @method _setDisabled
4011
        * @description Sets the value of the button groups's 
4012
        * "disabled" attribute.
4013
        * @protected
4014
        * @param {Boolean} p_bDisabled Boolean indicating the value for
4015
        * the button group's "disabled" attribute.
4016
        */
4017
        _setDisabled: function (p_bDisabled) {
4018
        
4019
            var nButtons = this.getCount(),
4020
                i;
4021
        
4022
            if (nButtons > 0) {
4023
        
4024
                i = nButtons - 1;
4025
                
4026
                do {
4027
        
4028
                    this._buttons[i].set("disabled", p_bDisabled);
4029
                
4030
                }
4031
                while (i--);
4032
        
4033
            }
4034
        
4035
        },
4036
        
4037
        
4038
        
4039
        // Protected event handlers
4040
        
4041
        
4042
        /**
4043
        * @method _onKeyDown
4044
        * @description "keydown" event handler for the button group.
4045
        * @protected
4046
        * @param {Event} p_oEvent Object representing the DOM event object  
4047
        * passed back by the event utility (YAHOO.util.Event).
4048
        */
4049
        _onKeyDown: function (p_oEvent) {
4050
        
4051
            var oTarget = Event.getTarget(p_oEvent),
4052
                nCharCode = Event.getCharCode(p_oEvent),
4053
                sId = oTarget.parentNode.parentNode.id,
4054
                oButton = m_oButtons[sId],
4055
                nIndex = -1;
4056
        
4057
        
4058
            if (nCharCode == 37 || nCharCode == 38) {
4059
        
4060
                nIndex = (oButton.index === 0) ? 
4061
                            (this._buttons.length - 1) : (oButton.index - 1);
4062
            
4063
            }
4064
            else if (nCharCode == 39 || nCharCode == 40) {
4065
        
4066
                nIndex = (oButton.index === (this._buttons.length - 1)) ? 
4067
                            0 : (oButton.index + 1);
4068
        
4069
            }
4070
        
4071
        
4072
            if (nIndex > -1) {
4073
        
4074
                this.check(nIndex);
4075
                this.getButton(nIndex).focus();
4076
            
4077
            }        
4078
        
4079
        },
4080
        
4081
        
4082
        /**
4083
        * @method _onAppendTo
4084
        * @description "appendTo" event handler for the button group.
4085
        * @protected
4086
        * @param {Event} p_oEvent Object representing the event that was fired.
4087
        */
4088
        _onAppendTo: function (p_oEvent) {
4089
        
4090
            var aButtons = this._buttons,
4091
                nButtons = aButtons.length,
4092
                i;
4093
        
4094
            for (i = 0; i < nButtons; i++) {
4095
        
4096
                aButtons[i].appendTo(this.get("element"));
4097
        
4098
            }
4099
        
4100
        },
4101
        
4102
        
4103
        /**
4104
        * @method _onButtonCheckedChange
4105
        * @description "checkedChange" event handler for each button in the 
4106
        * button group.
4107
        * @protected
4108
        * @param {Event} p_oEvent Object representing the event that was fired.
4109
        * @param {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}  
4110
        * p_oButton Object representing the button that fired the event.
4111
        */
4112
        _onButtonCheckedChange: function (p_oEvent, p_oButton) {
4113
        
4114
            var bChecked = p_oEvent.newValue,
4115
                oCheckedButton = this.get("checkedButton");
4116
        
4117
            if (bChecked && oCheckedButton != p_oButton) {
4118
        
4119
                if (oCheckedButton) {
4120
        
4121
                    oCheckedButton.set("checked", false, true);
4122
        
4123
                }
4124
        
4125
                this.set("checkedButton", p_oButton);
4126
                this.set("value", p_oButton.get("value"));
4127
        
4128
            }
4129
            else if (oCheckedButton && !oCheckedButton.set("checked")) {
4130
        
4131
                oCheckedButton.set("checked", true, true);
4132
        
4133
            }
4134
           
4135
        },
4136
        
4137
        
4138
        
4139
        // Public methods
4140
        
4141
        
4142
        /**
4143
        * @method init
4144
        * @description The ButtonGroup class's initialization method.
4145
        * @param {String} p_oElement String specifying the id attribute of the 
4146
        * <code>&#60;div&#62;</code> element of the button group.
4147
        * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
4148
        * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object 
4149
        * specifying the <code>&#60;div&#62;</code> element of the button group.
4150
        * @param {Object} p_oElement Object literal specifying a set of  
4151
        * configuration attributes used to create the button group.
4152
        * @param {Object} p_oAttributes Optional. Object literal specifying a
4153
        * set of configuration attributes used to create the button group.
4154
        */
4155
        init: function (p_oElement, p_oAttributes) {
4156
        
4157
            this._buttons = [];
4158
        
4159
            YAHOO.widget.ButtonGroup.superclass.init.call(this, p_oElement, 
4160
                    p_oAttributes);
4161
        
4162
            this.addClass(this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME);
4163
4164
        
4165
            var sClass = (YAHOO.widget.Button.prototype.CLASS_NAME_PREFIX + "radio-button"),
4166
				aButtons = this.getElementsByClassName(sClass);
4167
4168
            this.logger.log("Searching for child nodes with the class name " +
4169
                sClass + " to add to the button group.");
4170
        
4171
        
4172
            if (aButtons.length > 0) {
4173
        
4174
                this.logger.log("Found " + aButtons.length + 
4175
                    " child nodes with the class name " + sClass + 
4176
                    "  Attempting to add to button group.");
4177
        
4178
                this.addButtons(aButtons);
4179
        
4180
            }
4181
        
4182
        
4183
            this.logger.log("Searching for child nodes with the type of " +
4184
                " \"radio\" to add to the button group.");
4185
        
4186
            function isRadioButton(p_oElement) {
4187
        
4188
                return (p_oElement.type == "radio");
4189
        
4190
            }
4191
        
4192
            aButtons = 
4193
                Dom.getElementsBy(isRadioButton, "input", this.get("element"));
4194
        
4195
        
4196
            if (aButtons.length > 0) {
4197
        
4198
                this.logger.log("Found " + aButtons.length + " child nodes" +
4199
                    " with the type of \"radio.\"  Attempting to add to" +
4200
                    " button group.");
4201
        
4202
                this.addButtons(aButtons);
4203
        
4204
            }
4205
        
4206
            this.on("keydown", this._onKeyDown);
4207
            this.on("appendTo", this._onAppendTo);
4208
        
4209
4210
            var oContainer = this.get("container");
4211
4212
            if (oContainer) {
4213
        
4214
                if (Lang.isString(oContainer)) {
4215
        
4216
                    Event.onContentReady(oContainer, function () {
4217
        
4218
                        this.appendTo(oContainer);            
4219
                    
4220
                    }, null, this);
4221
        
4222
                }
4223
                else {
4224
        
4225
                    this.appendTo(oContainer);
4226
        
4227
                }
4228
        
4229
            }
4230
        
4231
        
4232
            this.logger.log("Initialization completed.");
4233
        
4234
        },
4235
        
4236
        
4237
        /**
4238
        * @method initAttributes
4239
        * @description Initializes all of the configuration attributes used to  
4240
        * create the button group.
4241
        * @param {Object} p_oAttributes Object literal specifying a set of 
4242
        * configuration attributes used to create the button group.
4243
        */
4244
        initAttributes: function (p_oAttributes) {
4245
        
4246
            var oAttributes = p_oAttributes || {};
4247
        
4248
            YAHOO.widget.ButtonGroup.superclass.initAttributes.call(
4249
                this, oAttributes);
4250
        
4251
        
4252
            /**
4253
            * @attribute name
4254
            * @description String specifying the name for the button group.  
4255
            * This name will be applied to each button in the button group.
4256
            * @default null
4257
            * @type String
4258
            */
4259
            this.setAttributeConfig("name", {
4260
        
4261
                value: oAttributes.name,
4262
                validator: Lang.isString
4263
        
4264
            });
4265
        
4266
        
4267
            /**
4268
            * @attribute disabled
4269
            * @description Boolean indicating if the button group should be 
4270
            * disabled.  Disabling the button group will disable each button 
4271
            * in the button group.  Disabled buttons are dimmed and will not 
4272
            * respond to user input or fire events.
4273
            * @default false
4274
            * @type Boolean
4275
            */
4276
            this.setAttributeConfig("disabled", {
4277
        
4278
                value: (oAttributes.disabled || false),
4279
                validator: Lang.isBoolean,
4280
                method: this._setDisabled
4281
        
4282
            });
4283
        
4284
        
4285
            /**
4286
            * @attribute value
4287
            * @description Object specifying the value for the button group.
4288
            * @default null
4289
            * @type Object
4290
            */
4291
            this.setAttributeConfig("value", {
4292
        
4293
                value: oAttributes.value
4294
        
4295
            });
4296
        
4297
        
4298
            /**
4299
            * @attribute container
4300
            * @description HTML element reference or string specifying the id 
4301
            * attribute of the HTML element that the button group's markup
4302
            * should be rendered into.
4303
            * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
4304
            * level-one-html.html#ID-58190037">HTMLElement</a>|String
4305
            * @default null
4306
			* @writeonce
4307
            */
4308
            this.setAttributeConfig("container", {
4309
        
4310
                value: oAttributes.container,
4311
                writeOnce: true
4312
        
4313
            });
4314
        
4315
        
4316
            /**
4317
            * @attribute checkedButton
4318
            * @description Reference for the button in the button group that 
4319
            * is checked.
4320
            * @type {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
4321
            * @default null
4322
            */
4323
            this.setAttributeConfig("checkedButton", {
4324
        
4325
                value: null
4326
        
4327
            });
4328
        
4329
        },
4330
        
4331
        
4332
        /**
4333
        * @method addButton
4334
        * @description Adds the button to the button group.
4335
        * @param {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}  
4336
        * p_oButton Object reference for the <a href="YAHOO.widget.Button.html">
4337
        * YAHOO.widget.Button</a> instance to be added to the button group.
4338
        * @param {String} p_oButton String specifying the id attribute of the 
4339
        * <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code> element 
4340
        * to be used to create the button to be added to the button group.
4341
        * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
4342
        * level-one-html.html#ID-6043025">HTMLInputElement</a>|<a href="
4343
        * http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#
4344
        * ID-33759296">HTMLElement</a>} p_oButton Object reference for the 
4345
        * <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code> element 
4346
        * to be used to create the button to be added to the button group.
4347
        * @param {Object} p_oButton Object literal specifying a set of 
4348
        * <a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a> 
4349
        * configuration attributes used to configure the button to be added to 
4350
        * the button group.
4351
        * @return {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>} 
4352
        */
4353
        addButton: function (p_oButton) {
4354
        
4355
            var oButton,
4356
                oButtonElement,
4357
                oGroupElement,
4358
                nIndex,
4359
                sButtonName,
4360
                sGroupName;
4361
        
4362
        
4363
            if (p_oButton instanceof Button && 
4364
                p_oButton.get("type") == "radio") {
4365
        
4366
                oButton = p_oButton;
4367
        
4368
            }
4369
            else if (!Lang.isString(p_oButton) && !p_oButton.nodeName) {
4370
        
4371
                p_oButton.type = "radio";
4372
        
4373
                oButton = new Button(p_oButton);
4374
4375
            }
4376
            else {
4377
        
4378
                oButton = new Button(p_oButton, { type: "radio" });
4379
        
4380
            }
4381
        
4382
        
4383
            if (oButton) {
4384
        
4385
                nIndex = this._buttons.length;
4386
                sButtonName = oButton.get("name");
4387
                sGroupName = this.get("name");
4388
        
4389
                oButton.index = nIndex;
4390
        
4391
                this._buttons[nIndex] = oButton;
4392
                m_oButtons[oButton.get("id")] = oButton;
4393
        
4394
        
4395
                if (sButtonName != sGroupName) {
4396
        
4397
                    oButton.set("name", sGroupName);
4398
                
4399
                }
4400
        
4401
        
4402
                if (this.get("disabled")) {
4403
        
4404
                    oButton.set("disabled", true);
4405
        
4406
                }
4407
        
4408
        
4409
                if (oButton.get("checked")) {
4410
        
4411
                    this.set("checkedButton", oButton);
4412
        
4413
                }
4414
4415
                
4416
                oButtonElement = oButton.get("element");
4417
                oGroupElement = this.get("element");
4418
                
4419
                if (oButtonElement.parentNode != oGroupElement) {
4420
                
4421
                    oGroupElement.appendChild(oButtonElement);
4422
                
4423
                }
4424
        
4425
                
4426
                oButton.on("checkedChange", 
4427
                    this._onButtonCheckedChange, oButton, this);
4428
        
4429
                this.logger.log("Button " + oButton.get("id") + " added.");
4430
        
4431
            }
4432
4433
			return oButton;
4434
        
4435
        },
4436
        
4437
        
4438
        /**
4439
        * @method addButtons
4440
        * @description Adds the array of buttons to the button group.
4441
        * @param {Array} p_aButtons Array of <a href="YAHOO.widget.Button.html">
4442
        * YAHOO.widget.Button</a> instances to be added 
4443
        * to the button group.
4444
        * @param {Array} p_aButtons Array of strings specifying the id 
4445
        * attribute of the <code>&#60;input&#62;</code> or <code>&#60;span&#62;
4446
        * </code> elements to be used to create the buttons to be added to the 
4447
        * button group.
4448
        * @param {Array} p_aButtons Array of object references for the 
4449
        * <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code> elements 
4450
        * to be used to create the buttons to be added to the button group.
4451
        * @param {Array} p_aButtons Array of object literals, each containing
4452
        * a set of <a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>  
4453
        * configuration attributes used to configure each button to be added 
4454
        * to the button group.
4455
        * @return {Array}
4456
        */
4457
        addButtons: function (p_aButtons) {
4458
    
4459
            var nButtons,
4460
                oButton,
4461
                aButtons,
4462
                i;
4463
        
4464
            if (Lang.isArray(p_aButtons)) {
4465
            
4466
                nButtons = p_aButtons.length;
4467
                aButtons = [];
4468
        
4469
                if (nButtons > 0) {
4470
        
4471
                    for (i = 0; i < nButtons; i++) {
4472
        
4473
                        oButton = this.addButton(p_aButtons[i]);
4474
                        
4475
                        if (oButton) {
4476
        
4477
                            aButtons[aButtons.length] = oButton;
4478
        
4479
                        }
4480
                    
4481
                    }
4482
                
4483
                }
4484
        
4485
            }
4486
4487
			return aButtons;
4488
        
4489
        },
4490
        
4491
        
4492
        /**
4493
        * @method removeButton
4494
        * @description Removes the button at the specified index from the 
4495
        * button group.
4496
        * @param {Number} p_nIndex Number specifying the index of the button 
4497
        * to be removed from the button group.
4498
        */
4499
        removeButton: function (p_nIndex) {
4500
        
4501
            var oButton = this.getButton(p_nIndex),
4502
                nButtons,
4503
                i;
4504
            
4505
            if (oButton) {
4506
        
4507
                this.logger.log("Removing button " + oButton.get("id") + ".");
4508
        
4509
                this._buttons.splice(p_nIndex, 1);
4510
                delete m_oButtons[oButton.get("id")];
4511
        
4512
                oButton.removeListener("checkedChange", 
4513
                    this._onButtonCheckedChange);
4514
4515
                oButton.destroy();
4516
        
4517
        
4518
                nButtons = this._buttons.length;
4519
                
4520
                if (nButtons > 0) {
4521
        
4522
                    i = this._buttons.length - 1;
4523
                    
4524
                    do {
4525
        
4526
                        this._buttons[i].index = i;
4527
        
4528
                    }
4529
                    while (i--);
4530
                
4531
                }
4532
        
4533
                this.logger.log("Button " + oButton.get("id") + " removed.");
4534
        
4535
            }
4536
        
4537
        },
4538
        
4539
        
4540
        /**
4541
        * @method getButton
4542
        * @description Returns the button at the specified index.
4543
        * @param {Number} p_nIndex The index of the button to retrieve from the 
4544
        * button group.
4545
        * @return {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
4546
        */
4547
        getButton: function (p_nIndex) {
4548
        
4549
            return this._buttons[p_nIndex];
4550
        
4551
        },
4552
        
4553
        
4554
        /**
4555
        * @method getButtons
4556
        * @description Returns an array of the buttons in the button group.
4557
        * @return {Array}
4558
        */
4559
        getButtons: function () {
4560
        
4561
            return this._buttons;
4562
        
4563
        },
4564
        
4565
        
4566
        /**
4567
        * @method getCount
4568
        * @description Returns the number of buttons in the button group.
4569
        * @return {Number}
4570
        */
4571
        getCount: function () {
4572
        
4573
            return this._buttons.length;
4574
        
4575
        },
4576
        
4577
        
4578
        /**
4579
        * @method focus
4580
        * @description Sets focus to the button at the specified index.
4581
        * @param {Number} p_nIndex Number indicating the index of the button 
4582
        * to focus. 
4583
        */
4584
        focus: function (p_nIndex) {
4585
        
4586
            var oButton,
4587
                nButtons,
4588
                i;
4589
        
4590
            if (Lang.isNumber(p_nIndex)) {
4591
        
4592
                oButton = this._buttons[p_nIndex];
4593
                
4594
                if (oButton) {
4595
        
4596
                    oButton.focus();
4597
        
4598
                }
4599
            
4600
            }
4601
            else {
4602
        
4603
                nButtons = this.getCount();
4604
        
4605
                for (i = 0; i < nButtons; i++) {
4606
        
4607
                    oButton = this._buttons[i];
4608
        
4609
                    if (!oButton.get("disabled")) {
4610
        
4611
                        oButton.focus();
4612
                        break;
4613
        
4614
                    }
4615
        
4616
                }
4617
        
4618
            }
4619
        
4620
        },
4621
        
4622
        
4623
        /**
4624
        * @method check
4625
        * @description Checks the button at the specified index.
4626
        * @param {Number} p_nIndex Number indicating the index of the button 
4627
        * to check. 
4628
        */
4629
        check: function (p_nIndex) {
4630
        
4631
            var oButton = this.getButton(p_nIndex);
4632
            
4633
            if (oButton) {
4634
        
4635
                oButton.set("checked", true);
4636
            
4637
            }
4638
        
4639
        },
4640
        
4641
        
4642
        /**
4643
        * @method destroy
4644
        * @description Removes the button group's element from its parent 
4645
        * element and removes all event handlers.
4646
        */
4647
        destroy: function () {
4648
        
4649
            this.logger.log("Destroying...");
4650
        
4651
            var nButtons = this._buttons.length,
4652
                oElement = this.get("element"),
4653
                oParentNode = oElement.parentNode,
4654
                i;
4655
            
4656
            if (nButtons > 0) {
4657
        
4658
                i = this._buttons.length - 1;
4659
        
4660
                do {
4661
        
4662
                    this._buttons[i].destroy();
4663
        
4664
                }
4665
                while (i--);
4666
            
4667
            }
4668
        
4669
            this.logger.log("Removing DOM event handlers.");
4670
        
4671
            Event.purgeElement(oElement);
4672
            
4673
            this.logger.log("Removing from document.");
4674
        
4675
            oParentNode.removeChild(oElement);
4676
        
4677
        },
4678
        
4679
        
4680
        /**
4681
        * @method toString
4682
        * @description Returns a string representing the button group.
4683
        * @return {String}
4684
        */
4685
        toString: function () {
4686
        
4687
            return ("ButtonGroup " + this.get("id"));
4688
        
4689
        }
4690
    
4691
    });
4692
4693
})();
4694
YAHOO.register("button", YAHOO.widget.Button, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/button/button-min.js (-11 lines)
Lines 1-11 Link Here
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.8.0r4
6
*/
7
(function(){var G=YAHOO.util.Dom,M=YAHOO.util.Event,I=YAHOO.lang,L=YAHOO.env.ua,B=YAHOO.widget.Overlay,J=YAHOO.widget.Menu,D={},K=null,E=null,C=null;function F(O,N,R,P){var S,Q;if(I.isString(O)&&I.isString(N)){if(L.ie){Q='<input type="'+O+'" name="'+N+'"';if(P){Q+=" checked";}Q+=">";S=document.createElement(Q);}else{S=document.createElement("input");S.name=N;S.type=O;if(P){S.checked=true;}}S.value=R;}return S;}function H(O,V){var N=O.nodeName.toUpperCase(),S=(this.CLASS_NAME_PREFIX+this.CSS_CLASS_NAME),T=this,U,P,Q;function W(X){if(!(X in V)){U=O.getAttributeNode(X);if(U&&("value" in U)){V[X]=U.value;}}}function R(){W("type");if(V.type=="button"){V.type="push";}if(!("disabled" in V)){V.disabled=O.disabled;}W("name");W("value");W("title");}switch(N){case"A":V.type="link";W("href");W("target");break;case"INPUT":R();if(!("checked" in V)){V.checked=O.checked;}break;case"BUTTON":R();P=O.parentNode.parentNode;if(G.hasClass(P,S+"-checked")){V.checked=true;}if(G.hasClass(P,S+"-disabled")){V.disabled=true;}O.removeAttribute("value");O.setAttribute("type","button");break;}O.removeAttribute("id");O.removeAttribute("name");if(!("tabindex" in V)){V.tabindex=O.tabIndex;}if(!("label" in V)){Q=N=="INPUT"?O.value:O.innerHTML;if(Q&&Q.length>0){V.label=Q;}}}function A(P){var O=P.attributes,N=O.srcelement,R=N.nodeName.toUpperCase(),Q=this;if(R==this.NODE_NAME){P.element=N;P.id=N.id;G.getElementsBy(function(S){switch(S.nodeName.toUpperCase()){case"BUTTON":case"A":case"INPUT":H.call(Q,S,O);break;}},"*",N);}else{switch(R){case"BUTTON":case"A":case"INPUT":H.call(this,N,O);break;}}}YAHOO.widget.Button=function(R,O){if(!B&&YAHOO.widget.Overlay){B=YAHOO.widget.Overlay;}if(!J&&YAHOO.widget.Menu){J=YAHOO.widget.Menu;}var Q=YAHOO.widget.Button.superclass.constructor,P,N;if(arguments.length==1&&!I.isString(R)&&!R.nodeName){if(!R.id){R.id=G.generateId();}Q.call(this,(this.createButtonElement(R.type)),R);}else{P={element:null,attributes:(O||{})};if(I.isString(R)){N=G.get(R);if(N){if(!P.attributes.id){P.attributes.id=R;}P.attributes.srcelement=N;A.call(this,P);if(!P.element){P.element=this.createButtonElement(P.attributes.type);}Q.call(this,P.element,P.attributes);}}else{if(R.nodeName){if(!P.attributes.id){if(R.id){P.attributes.id=R.id;}else{P.attributes.id=G.generateId();}}P.attributes.srcelement=R;A.call(this,P);if(!P.element){P.element=this.createButtonElement(P.attributes.type);}Q.call(this,P.element,P.attributes);}}}};YAHOO.extend(YAHOO.widget.Button,YAHOO.util.Element,{_button:null,_menu:null,_hiddenFields:null,_onclickAttributeValue:null,_activationKeyPressed:false,_activationButtonPressed:false,_hasKeyEventHandlers:false,_hasMouseEventHandlers:false,_nOptionRegionX:0,CLASS_NAME_PREFIX:"yui-",NODE_NAME:"SPAN",CHECK_ACTIVATION_KEYS:[32],ACTIVATION_KEYS:[13,32],OPTION_AREA_WIDTH:20,CSS_CLASS_NAME:"button",_setType:function(N){if(N=="split"){this.on("option",this._onOption);}},_setLabel:function(O){this._button.innerHTML=O;var P,N=L.gecko;if(N&&N<1.9&&G.inDocument(this.get("element"))){P=(this.CLASS_NAME_PREFIX+this.CSS_CLASS_NAME);this.removeClass(P);I.later(0,this,this.addClass,P);}},_setTabIndex:function(N){this._button.tabIndex=N;},_setTitle:function(N){if(this.get("type")!="link"){this._button.title=N;}},_setDisabled:function(N){if(this.get("type")!="link"){if(N){if(this._menu){this._menu.hide();}if(this.hasFocus()){this.blur();}this._button.setAttribute("disabled","disabled");this.addStateCSSClasses("disabled");this.removeStateCSSClasses("hover");this.removeStateCSSClasses("active");this.removeStateCSSClasses("focus");}else{this._button.removeAttribute("disabled");this.removeStateCSSClasses("disabled");}}},_setHref:function(N){if(this.get("type")=="link"){this._button.href=N;}},_setTarget:function(N){if(this.get("type")=="link"){this._button.setAttribute("target",N);}},_setChecked:function(N){var O=this.get("type");if(O=="checkbox"||O=="radio"){if(N){this.addStateCSSClasses("checked");}else{this.removeStateCSSClasses("checked");}}},_setMenu:function(U){var P=this.get("lazyloadmenu"),R=this.get("element"),N,W=false,X,O,Q;function V(){X.render(R.parentNode);this.removeListener("appendTo",V);}function T(){X.cfg.queueProperty("container",R.parentNode);this.removeListener("appendTo",T);}function S(){var Y;if(X){G.addClass(X.element,this.get("menuclassname"));G.addClass(X.element,this.CLASS_NAME_PREFIX+this.get("type")+"-button-menu");X.showEvent.subscribe(this._onMenuShow,null,this);X.hideEvent.subscribe(this._onMenuHide,null,this);X.renderEvent.subscribe(this._onMenuRender,null,this);if(J&&X instanceof J){if(P){Y=this.get("container");if(Y){X.cfg.queueProperty("container",Y);}else{this.on("appendTo",T);}}X.cfg.queueProperty("clicktohide",false);X.keyDownEvent.subscribe(this._onMenuKeyDown,this,true);X.subscribe("click",this._onMenuClick,this,true);this.on("selectedMenuItemChange",this._onSelectedMenuItemChange);Q=X.srcElement;if(Q&&Q.nodeName.toUpperCase()=="SELECT"){Q.style.display="none";Q.parentNode.removeChild(Q);}}else{if(B&&X instanceof B){if(!K){K=new YAHOO.widget.OverlayManager();}K.register(X);}}this._menu=X;if(!W&&!P){if(G.inDocument(R)){X.render(R.parentNode);}else{this.on("appendTo",V);}}}}if(B){if(J){N=J.prototype.CSS_CLASS_NAME;}if(U&&J&&(U instanceof J)){X=U;W=true;S.call(this);}else{if(B&&U&&(U instanceof B)){X=U;W=true;X.cfg.queueProperty("visible",false);S.call(this);}else{if(J&&I.isArray(U)){X=new J(G.generateId(),{lazyload:P,itemdata:U});this._menu=X;this.on("appendTo",S);}else{if(I.isString(U)){O=G.get(U);if(O){if(J&&G.hasClass(O,N)||O.nodeName.toUpperCase()=="SELECT"){X=new J(U,{lazyload:P});S.call(this);}else{if(B){X=new B(U,{visible:false});S.call(this);}}}}else{if(U&&U.nodeName){if(J&&G.hasClass(U,N)||U.nodeName.toUpperCase()=="SELECT"){X=new J(U,{lazyload:P});S.call(this);}else{if(B){if(!U.id){G.generateId(U);}X=new B(U,{visible:false});S.call(this);}}}}}}}}},_setOnClick:function(N){if(this._onclickAttributeValue&&(this._onclickAttributeValue!=N)){this.removeListener("click",this._onclickAttributeValue.fn);
8
this._onclickAttributeValue=null;}if(!this._onclickAttributeValue&&I.isObject(N)&&I.isFunction(N.fn)){this.on("click",N.fn,N.obj,N.scope);this._onclickAttributeValue=N;}},_isActivationKey:function(N){var S=this.get("type"),O=(S=="checkbox"||S=="radio")?this.CHECK_ACTIVATION_KEYS:this.ACTIVATION_KEYS,Q=O.length,R=false,P;if(Q>0){P=Q-1;do{if(N==O[P]){R=true;break;}}while(P--);}return R;},_isSplitButtonOptionKey:function(P){var O=(M.getCharCode(P)==40);var N=function(Q){M.preventDefault(Q);this.removeListener("keypress",N);};if(O){if(L.opera){this.on("keypress",N);}M.preventDefault(P);}return O;},_addListenersToForm:function(){var T=this.getForm(),S=YAHOO.widget.Button.onFormKeyPress,R,N,Q,P,O;if(T){M.on(T,"reset",this._onFormReset,null,this);M.on(T,"submit",this._onFormSubmit,null,this);N=this.get("srcelement");if(this.get("type")=="submit"||(N&&N.type=="submit")){Q=M.getListeners(T,"keypress");R=false;if(Q){P=Q.length;if(P>0){O=P-1;do{if(Q[O].fn==S){R=true;break;}}while(O--);}}if(!R){M.on(T,"keypress",S);}}}},_showMenu:function(R){if(YAHOO.widget.MenuManager){YAHOO.widget.MenuManager.hideVisible();}if(K){K.hideAll();}var N=this._menu,Q=this.get("menualignment"),P=this.get("focusmenu"),O;if(this._renderedMenu){N.cfg.setProperty("context",[this.get("element"),Q[0],Q[1]]);N.cfg.setProperty("preventcontextoverlap",true);N.cfg.setProperty("constraintoviewport",true);}else{N.cfg.queueProperty("context",[this.get("element"),Q[0],Q[1]]);N.cfg.queueProperty("preventcontextoverlap",true);N.cfg.queueProperty("constraintoviewport",true);}this.focus();if(J&&N&&(N instanceof J)){O=N.focus;N.focus=function(){};if(this._renderedMenu){N.cfg.setProperty("minscrollheight",this.get("menuminscrollheight"));N.cfg.setProperty("maxheight",this.get("menumaxheight"));}else{N.cfg.queueProperty("minscrollheight",this.get("menuminscrollheight"));N.cfg.queueProperty("maxheight",this.get("menumaxheight"));}N.show();N.focus=O;N.align();if(R.type=="mousedown"){M.stopPropagation(R);}if(P){N.focus();}}else{if(B&&N&&(N instanceof B)){if(!this._renderedMenu){N.render(this.get("element").parentNode);}N.show();N.align();}}},_hideMenu:function(){var N=this._menu;if(N){N.hide();}},_onMouseOver:function(O){var Q=this.get("type"),N,P;if(Q==="split"){N=this.get("element");P=(G.getX(N)+(N.offsetWidth-this.OPTION_AREA_WIDTH));this._nOptionRegionX=P;}if(!this._hasMouseEventHandlers){if(Q==="split"){this.on("mousemove",this._onMouseMove);}this.on("mouseout",this._onMouseOut);this._hasMouseEventHandlers=true;}this.addStateCSSClasses("hover");if(Q==="split"&&(M.getPageX(O)>P)){this.addStateCSSClasses("hoveroption");}if(this._activationButtonPressed){this.addStateCSSClasses("active");}if(this._bOptionPressed){this.addStateCSSClasses("activeoption");}if(this._activationButtonPressed||this._bOptionPressed){M.removeListener(document,"mouseup",this._onDocumentMouseUp);}},_onMouseMove:function(N){var O=this._nOptionRegionX;if(O){if(M.getPageX(N)>O){this.addStateCSSClasses("hoveroption");}else{this.removeStateCSSClasses("hoveroption");}}},_onMouseOut:function(N){var O=this.get("type");this.removeStateCSSClasses("hover");if(O!="menu"){this.removeStateCSSClasses("active");}if(this._activationButtonPressed||this._bOptionPressed){M.on(document,"mouseup",this._onDocumentMouseUp,null,this);}if(O==="split"&&(M.getPageX(N)>this._nOptionRegionX)){this.removeStateCSSClasses("hoveroption");}},_onDocumentMouseUp:function(P){this._activationButtonPressed=false;this._bOptionPressed=false;var Q=this.get("type"),N,O;if(Q=="menu"||Q=="split"){N=M.getTarget(P);O=this._menu.element;if(N!=O&&!G.isAncestor(O,N)){this.removeStateCSSClasses((Q=="menu"?"active":"activeoption"));this._hideMenu();}}M.removeListener(document,"mouseup",this._onDocumentMouseUp);},_onMouseDown:function(P){var Q,O=true;function N(){this._hideMenu();this.removeListener("mouseup",N);}if((P.which||P.button)==1){if(!this.hasFocus()){this.focus();}Q=this.get("type");if(Q=="split"){if(M.getPageX(P)>this._nOptionRegionX){this.fireEvent("option",P);O=false;}else{this.addStateCSSClasses("active");this._activationButtonPressed=true;}}else{if(Q=="menu"){if(this.isActive()){this._hideMenu();this._activationButtonPressed=false;}else{this._showMenu(P);this._activationButtonPressed=true;}}else{this.addStateCSSClasses("active");this._activationButtonPressed=true;}}if(Q=="split"||Q=="menu"){this._hideMenuTimer=I.later(250,this,this.on,["mouseup",N]);}}return O;},_onMouseUp:function(P){var Q=this.get("type"),N=this._hideMenuTimer,O=true;if(N){N.cancel();}if(Q=="checkbox"||Q=="radio"){this.set("checked",!(this.get("checked")));}this._activationButtonPressed=false;if(Q!="menu"){this.removeStateCSSClasses("active");}if(Q=="split"&&M.getPageX(P)>this._nOptionRegionX){O=false;}return O;},_onFocus:function(O){var N;this.addStateCSSClasses("focus");if(this._activationKeyPressed){this.addStateCSSClasses("active");}C=this;if(!this._hasKeyEventHandlers){N=this._button;M.on(N,"blur",this._onBlur,null,this);M.on(N,"keydown",this._onKeyDown,null,this);M.on(N,"keyup",this._onKeyUp,null,this);this._hasKeyEventHandlers=true;}this.fireEvent("focus",O);},_onBlur:function(N){this.removeStateCSSClasses("focus");if(this.get("type")!="menu"){this.removeStateCSSClasses("active");}if(this._activationKeyPressed){M.on(document,"keyup",this._onDocumentKeyUp,null,this);}C=null;this.fireEvent("blur",N);},_onDocumentKeyUp:function(N){if(this._isActivationKey(M.getCharCode(N))){this._activationKeyPressed=false;M.removeListener(document,"keyup",this._onDocumentKeyUp);}},_onKeyDown:function(O){var N=this._menu;if(this.get("type")=="split"&&this._isSplitButtonOptionKey(O)){this.fireEvent("option",O);}else{if(this._isActivationKey(M.getCharCode(O))){if(this.get("type")=="menu"){this._showMenu(O);}else{this._activationKeyPressed=true;this.addStateCSSClasses("active");}}}if(N&&N.cfg.getProperty("visible")&&M.getCharCode(O)==27){N.hide();this.focus();}},_onKeyUp:function(N){var O;if(this._isActivationKey(M.getCharCode(N))){O=this.get("type");if(O=="checkbox"||O=="radio"){this.set("checked",!(this.get("checked")));
9
}this._activationKeyPressed=false;if(this.get("type")!="menu"){this.removeStateCSSClasses("active");}}},_onClick:function(P){var R=this.get("type"),Q,N,O;switch(R){case"submit":if(P.returnValue!==false){this.submitForm();}break;case"reset":Q=this.getForm();if(Q){Q.reset();}break;case"split":if(this._nOptionRegionX>0&&(M.getPageX(P)>this._nOptionRegionX)){O=false;}else{this._hideMenu();N=this.get("srcelement");if(N&&N.type=="submit"&&P.returnValue!==false){this.submitForm();}}break;}return O;},_onDblClick:function(O){var N=true;if(this.get("type")=="split"&&M.getPageX(O)>this._nOptionRegionX){N=false;}return N;},_onAppendTo:function(N){I.later(0,this,this._addListenersToForm);},_onFormReset:function(O){var P=this.get("type"),N=this._menu;if(P=="checkbox"||P=="radio"){this.resetValue("checked");}if(J&&N&&(N instanceof J)){this.resetValue("selectedMenuItem");}},_onFormSubmit:function(N){this.createHiddenFields();},_onDocumentMouseDown:function(Q){var N=M.getTarget(Q),P=this.get("element"),O=this._menu.element;if(N!=P&&!G.isAncestor(P,N)&&N!=O&&!G.isAncestor(O,N)){this._hideMenu();if(L.ie&&N.focus){N.setActive();}M.removeListener(document,"mousedown",this._onDocumentMouseDown);}},_onOption:function(N){if(this.hasClass(this.CLASS_NAME_PREFIX+"split-button-activeoption")){this._hideMenu();this._bOptionPressed=false;}else{this._showMenu(N);this._bOptionPressed=true;}},_onMenuShow:function(N){M.on(document,"mousedown",this._onDocumentMouseDown,null,this);var O=(this.get("type")=="split")?"activeoption":"active";this.addStateCSSClasses(O);},_onMenuHide:function(N){var O=(this.get("type")=="split")?"activeoption":"active";this.removeStateCSSClasses(O);if(this.get("type")=="split"){this._bOptionPressed=false;}},_onMenuKeyDown:function(P,O){var N=O[0];if(M.getCharCode(N)==27){this.focus();if(this.get("type")=="split"){this._bOptionPressed=false;}}},_onMenuRender:function(P){var S=this.get("element"),O=S.parentNode,N=this._menu,R=N.element,Q=N.srcElement,T;if(O!=R.parentNode){O.appendChild(R);}this._renderedMenu=true;if(Q&&Q.nodeName.toLowerCase()==="select"&&Q.value){T=N.getItem(Q.selectedIndex);this.set("selectedMenuItem",T,true);this._onSelectedMenuItemChange({newValue:T});}},_onMenuClick:function(O,N){var Q=N[1],P;if(Q){this.set("selectedMenuItem",Q);P=this.get("srcelement");if(P&&P.type=="submit"){this.submitForm();}this._hideMenu();}},_onSelectedMenuItemChange:function(O){var P=O.prevValue,Q=O.newValue,N=this.CLASS_NAME_PREFIX;if(P){G.removeClass(P.element,(N+"button-selectedmenuitem"));}if(Q){G.addClass(Q.element,(N+"button-selectedmenuitem"));}},_onLabelClick:function(N){this.focus();var O=this.get("type");if(O=="radio"||O=="checkbox"){this.set("checked",(!this.get("checked")));}},createButtonElement:function(N){var P=this.NODE_NAME,O=document.createElement(P);O.innerHTML="<"+P+' class="first-child">'+(N=="link"?"<a></a>":'<button type="button"></button>')+"</"+P+">";return O;},addStateCSSClasses:function(O){var P=this.get("type"),N=this.CLASS_NAME_PREFIX;if(I.isString(O)){if(O!="activeoption"&&O!="hoveroption"){this.addClass(N+this.CSS_CLASS_NAME+("-"+O));}this.addClass(N+P+("-button-"+O));}},removeStateCSSClasses:function(O){var P=this.get("type"),N=this.CLASS_NAME_PREFIX;if(I.isString(O)){this.removeClass(N+this.CSS_CLASS_NAME+("-"+O));this.removeClass(N+P+("-button-"+O));}},createHiddenFields:function(){this.removeHiddenFields();var V=this.getForm(),Z,O,S,X,Y,T,U,N,R,W,P,Q=false;if(V&&!this.get("disabled")){O=this.get("type");S=(O=="checkbox"||O=="radio");if((S&&this.get("checked"))||(E==this)){Z=F((S?O:"hidden"),this.get("name"),this.get("value"),this.get("checked"));if(Z){if(S){Z.style.display="none";}V.appendChild(Z);}}X=this._menu;if(J&&X&&(X instanceof J)){Y=this.get("selectedMenuItem");P=X.srcElement;Q=(P&&P.nodeName.toUpperCase()=="SELECT");if(Y){U=(Y.value===null||Y.value==="")?Y.cfg.getProperty("text"):Y.value;T=this.get("name");if(Q){W=P.name;}else{if(T){W=(T+"_options");}}if(U&&W){N=F("hidden",W,U);V.appendChild(N);}}else{if(Q){N=V.appendChild(P);}}}if(Z&&N){this._hiddenFields=[Z,N];}else{if(!Z&&N){this._hiddenFields=N;}else{if(Z&&!N){this._hiddenFields=Z;}}}R=this._hiddenFields;}return R;},removeHiddenFields:function(){var Q=this._hiddenFields,O,P;function N(R){if(G.inDocument(R)){R.parentNode.removeChild(R);}}if(Q){if(I.isArray(Q)){O=Q.length;if(O>0){P=O-1;do{N(Q[P]);}while(P--);}}else{N(Q);}this._hiddenFields=null;}},submitForm:function(){var Q=this.getForm(),P=this.get("srcelement"),O=false,N;if(Q){if(this.get("type")=="submit"||(P&&P.type=="submit")){E=this;}if(L.ie){O=Q.fireEvent("onsubmit");}else{N=document.createEvent("HTMLEvents");N.initEvent("submit",true,true);O=Q.dispatchEvent(N);}if((L.ie||L.webkit)&&O){Q.submit();}}return O;},init:function(P,d){var V=d.type=="link"?"a":"button",a=d.srcelement,S=P.getElementsByTagName(V)[0],U;if(!S){U=P.getElementsByTagName("input")[0];if(U){S=document.createElement("button");S.setAttribute("type","button");U.parentNode.replaceChild(S,U);}}this._button=S;YAHOO.widget.Button.superclass.init.call(this,P,d);var T=this.get("id"),Z=T+"-button";S.id=Z;var X,Q;var e=function(f){return(f.htmlFor===T);};var c=function(){Q.setAttribute((L.ie?"htmlFor":"for"),Z);};if(a&&this.get("type")!="link"){X=G.getElementsBy(e,"label");if(I.isArray(X)&&X.length>0){Q=X[0];}}D[T]=this;var b=this.CLASS_NAME_PREFIX;this.addClass(b+this.CSS_CLASS_NAME);this.addClass(b+this.get("type")+"-button");M.on(this._button,"focus",this._onFocus,null,this);this.on("mouseover",this._onMouseOver);this.on("mousedown",this._onMouseDown);this.on("mouseup",this._onMouseUp);this.on("click",this._onClick);var R=this.get("onclick");this.set("onclick",null);this.set("onclick",R);this.on("dblclick",this._onDblClick);var O;if(Q){if(this.get("replaceLabel")){this.set("label",Q.innerHTML);O=Q.parentNode;O.removeChild(Q);}else{this.on("appendTo",c);M.on(Q,"click",this._onLabelClick,null,this);this._label=Q;}}this.on("appendTo",this._onAppendTo);var N=this.get("container"),Y=this.get("element"),W=G.inDocument(Y);
10
if(N){if(a&&a!=Y){O=a.parentNode;if(O){O.removeChild(a);}}if(I.isString(N)){M.onContentReady(N,this.appendTo,N,this);}else{this.on("init",function(){I.later(0,this,this.appendTo,N);});}}else{if(!W&&a&&a!=Y){O=a.parentNode;if(O){this.fireEvent("beforeAppendTo",{type:"beforeAppendTo",target:O});O.replaceChild(Y,a);this.fireEvent("appendTo",{type:"appendTo",target:O});}}else{if(this.get("type")!="link"&&W&&a&&a==Y){this._addListenersToForm();}}}this.fireEvent("init",{type:"init",target:this});},initAttributes:function(O){var N=O||{};YAHOO.widget.Button.superclass.initAttributes.call(this,N);this.setAttributeConfig("type",{value:(N.type||"push"),validator:I.isString,writeOnce:true,method:this._setType});this.setAttributeConfig("label",{value:N.label,validator:I.isString,method:this._setLabel});this.setAttributeConfig("value",{value:N.value});this.setAttributeConfig("name",{value:N.name,validator:I.isString});this.setAttributeConfig("tabindex",{value:N.tabindex,validator:I.isNumber,method:this._setTabIndex});this.configureAttribute("title",{value:N.title,validator:I.isString,method:this._setTitle});this.setAttributeConfig("disabled",{value:(N.disabled||false),validator:I.isBoolean,method:this._setDisabled});this.setAttributeConfig("href",{value:N.href,validator:I.isString,method:this._setHref});this.setAttributeConfig("target",{value:N.target,validator:I.isString,method:this._setTarget});this.setAttributeConfig("checked",{value:(N.checked||false),validator:I.isBoolean,method:this._setChecked});this.setAttributeConfig("container",{value:N.container,writeOnce:true});this.setAttributeConfig("srcelement",{value:N.srcelement,writeOnce:true});this.setAttributeConfig("menu",{value:null,method:this._setMenu,writeOnce:true});this.setAttributeConfig("lazyloadmenu",{value:(N.lazyloadmenu===false?false:true),validator:I.isBoolean,writeOnce:true});this.setAttributeConfig("menuclassname",{value:(N.menuclassname||(this.CLASS_NAME_PREFIX+"button-menu")),validator:I.isString,method:this._setMenuClassName,writeOnce:true});this.setAttributeConfig("menuminscrollheight",{value:(N.menuminscrollheight||90),validator:I.isNumber});this.setAttributeConfig("menumaxheight",{value:(N.menumaxheight||0),validator:I.isNumber});this.setAttributeConfig("menualignment",{value:(N.menualignment||["tl","bl"]),validator:I.isArray});this.setAttributeConfig("selectedMenuItem",{value:null});this.setAttributeConfig("onclick",{value:N.onclick,method:this._setOnClick});this.setAttributeConfig("focusmenu",{value:(N.focusmenu===false?false:true),validator:I.isBoolean});this.setAttributeConfig("replaceLabel",{value:false,validator:I.isBoolean,writeOnce:true});},focus:function(){if(!this.get("disabled")){this._button.focus();}},blur:function(){if(!this.get("disabled")){this._button.blur();}},hasFocus:function(){return(C==this);},isActive:function(){return this.hasClass(this.CLASS_NAME_PREFIX+this.CSS_CLASS_NAME+"-active");},getMenu:function(){return this._menu;},getForm:function(){var N=this._button,O;if(N){O=N.form;}return O;},getHiddenFields:function(){return this._hiddenFields;},destroy:function(){var P=this.get("element"),N=this._menu,T=this._label,O,S;if(N){if(K&&K.find(N)){K.remove(N);}N.destroy();}M.purgeElement(P);M.purgeElement(this._button);M.removeListener(document,"mouseup",this._onDocumentMouseUp);M.removeListener(document,"keyup",this._onDocumentKeyUp);M.removeListener(document,"mousedown",this._onDocumentMouseDown);if(T){M.removeListener(T,"click",this._onLabelClick);O=T.parentNode;O.removeChild(T);}var Q=this.getForm();if(Q){M.removeListener(Q,"reset",this._onFormReset);M.removeListener(Q,"submit",this._onFormSubmit);}this.unsubscribeAll();O=P.parentNode;if(O){O.removeChild(P);}delete D[this.get("id")];var R=(this.CLASS_NAME_PREFIX+this.CSS_CLASS_NAME);S=G.getElementsByClassName(R,this.NODE_NAME,Q);if(I.isArray(S)&&S.length===0){M.removeListener(Q,"keypress",YAHOO.widget.Button.onFormKeyPress);}},fireEvent:function(O,N){var P=arguments[0];if(this.DOM_EVENTS[P]&&this.get("disabled")){return false;}return YAHOO.widget.Button.superclass.fireEvent.apply(this,arguments);},toString:function(){return("Button "+this.get("id"));}});YAHOO.widget.Button.onFormKeyPress=function(R){var P=M.getTarget(R),S=M.getCharCode(R),Q=P.nodeName&&P.nodeName.toUpperCase(),N=P.type,T=false,V,X,O,W;function U(a){var Z,Y;switch(a.nodeName.toUpperCase()){case"INPUT":case"BUTTON":if(a.type=="submit"&&!a.disabled){if(!T&&!O){O=a;}}break;default:Z=a.id;if(Z){V=D[Z];if(V){T=true;if(!V.get("disabled")){Y=V.get("srcelement");if(!X&&(V.get("type")=="submit"||(Y&&Y.type=="submit"))){X=V;}}}}break;}}if(S==13&&((Q=="INPUT"&&(N=="text"||N=="password"||N=="checkbox"||N=="radio"||N=="file"))||Q=="SELECT")){G.getElementsBy(U,"*",this);if(O){O.focus();}else{if(!O&&X){M.preventDefault(R);if(L.ie){X.get("element").fireEvent("onclick");}else{W=document.createEvent("HTMLEvents");W.initEvent("click",true,true);if(L.gecko<1.9){X.fireEvent("click",W);}else{X.get("element").dispatchEvent(W);}}}}}};YAHOO.widget.Button.addHiddenFieldsToForm=function(N){var R=YAHOO.widget.Button.prototype,T=G.getElementsByClassName((R.CLASS_NAME_PREFIX+R.CSS_CLASS_NAME),"*",N),Q=T.length,S,O,P;if(Q>0){for(P=0;P<Q;P++){O=T[P].id;if(O){S=D[O];if(S){S.createHiddenFields();}}}}};YAHOO.widget.Button.getButton=function(N){return D[N];};})();(function(){var C=YAHOO.util.Dom,B=YAHOO.util.Event,D=YAHOO.lang,A=YAHOO.widget.Button,E={};YAHOO.widget.ButtonGroup=function(J,H){var I=YAHOO.widget.ButtonGroup.superclass.constructor,K,G,F;if(arguments.length==1&&!D.isString(J)&&!J.nodeName){if(!J.id){F=C.generateId();J.id=F;}I.call(this,(this._createGroupElement()),J);}else{if(D.isString(J)){G=C.get(J);if(G){if(G.nodeName.toUpperCase()==this.NODE_NAME){I.call(this,G,H);}}}else{K=J.nodeName.toUpperCase();if(K&&K==this.NODE_NAME){if(!J.id){J.id=C.generateId();}I.call(this,J,H);}}}};YAHOO.extend(YAHOO.widget.ButtonGroup,YAHOO.util.Element,{_buttons:null,NODE_NAME:"DIV",CLASS_NAME_PREFIX:"yui-",CSS_CLASS_NAME:"buttongroup",_createGroupElement:function(){var F=document.createElement(this.NODE_NAME);
11
return F;},_setDisabled:function(G){var H=this.getCount(),F;if(H>0){F=H-1;do{this._buttons[F].set("disabled",G);}while(F--);}},_onKeyDown:function(K){var G=B.getTarget(K),I=B.getCharCode(K),H=G.parentNode.parentNode.id,J=E[H],F=-1;if(I==37||I==38){F=(J.index===0)?(this._buttons.length-1):(J.index-1);}else{if(I==39||I==40){F=(J.index===(this._buttons.length-1))?0:(J.index+1);}}if(F>-1){this.check(F);this.getButton(F).focus();}},_onAppendTo:function(H){var I=this._buttons,G=I.length,F;for(F=0;F<G;F++){I[F].appendTo(this.get("element"));}},_onButtonCheckedChange:function(G,F){var I=G.newValue,H=this.get("checkedButton");if(I&&H!=F){if(H){H.set("checked",false,true);}this.set("checkedButton",F);this.set("value",F.get("value"));}else{if(H&&!H.set("checked")){H.set("checked",true,true);}}},init:function(I,H){this._buttons=[];YAHOO.widget.ButtonGroup.superclass.init.call(this,I,H);this.addClass(this.CLASS_NAME_PREFIX+this.CSS_CLASS_NAME);var K=(YAHOO.widget.Button.prototype.CLASS_NAME_PREFIX+"radio-button"),J=this.getElementsByClassName(K);if(J.length>0){this.addButtons(J);}function F(L){return(L.type=="radio");}J=C.getElementsBy(F,"input",this.get("element"));if(J.length>0){this.addButtons(J);}this.on("keydown",this._onKeyDown);this.on("appendTo",this._onAppendTo);var G=this.get("container");if(G){if(D.isString(G)){B.onContentReady(G,function(){this.appendTo(G);},null,this);}else{this.appendTo(G);}}},initAttributes:function(G){var F=G||{};YAHOO.widget.ButtonGroup.superclass.initAttributes.call(this,F);this.setAttributeConfig("name",{value:F.name,validator:D.isString});this.setAttributeConfig("disabled",{value:(F.disabled||false),validator:D.isBoolean,method:this._setDisabled});this.setAttributeConfig("value",{value:F.value});this.setAttributeConfig("container",{value:F.container,writeOnce:true});this.setAttributeConfig("checkedButton",{value:null});},addButton:function(J){var L,K,G,F,H,I;if(J instanceof A&&J.get("type")=="radio"){L=J;}else{if(!D.isString(J)&&!J.nodeName){J.type="radio";L=new A(J);}else{L=new A(J,{type:"radio"});}}if(L){F=this._buttons.length;H=L.get("name");I=this.get("name");L.index=F;this._buttons[F]=L;E[L.get("id")]=L;if(H!=I){L.set("name",I);}if(this.get("disabled")){L.set("disabled",true);}if(L.get("checked")){this.set("checkedButton",L);}K=L.get("element");G=this.get("element");if(K.parentNode!=G){G.appendChild(K);}L.on("checkedChange",this._onButtonCheckedChange,L,this);}return L;},addButtons:function(G){var H,I,J,F;if(D.isArray(G)){H=G.length;J=[];if(H>0){for(F=0;F<H;F++){I=this.addButton(G[F]);if(I){J[J.length]=I;}}}}return J;},removeButton:function(H){var I=this.getButton(H),G,F;if(I){this._buttons.splice(H,1);delete E[I.get("id")];I.removeListener("checkedChange",this._onButtonCheckedChange);I.destroy();G=this._buttons.length;if(G>0){F=this._buttons.length-1;do{this._buttons[F].index=F;}while(F--);}}},getButton:function(F){return this._buttons[F];},getButtons:function(){return this._buttons;},getCount:function(){return this._buttons.length;},focus:function(H){var I,G,F;if(D.isNumber(H)){I=this._buttons[H];if(I){I.focus();}}else{G=this.getCount();for(F=0;F<G;F++){I=this._buttons[F];if(!I.get("disabled")){I.focus();break;}}}},check:function(F){var G=this.getButton(F);if(G){G.set("checked",true);}},destroy:function(){var I=this._buttons.length,H=this.get("element"),F=H.parentNode,G;if(I>0){G=this._buttons.length-1;do{this._buttons[G].destroy();}while(G--);}B.purgeElement(H);F.removeChild(H);},toString:function(){return("ButtonGroup "+this.get("id"));}});})();YAHOO.register("button",YAHOO.widget.Button,{version:"2.8.0r4",build:"2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/button/button.js (-4633 lines)
Lines 1-4633 Link Here
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.8.0r4
6
*/
7
/**
8
* @module button
9
* @description <p>The Button Control enables the creation of rich, graphical 
10
* buttons that function like traditional HTML form buttons.  <em>Unlike</em> 
11
* traditional HTML form buttons, buttons created with the Button Control can have 
12
* a label that is different from its value.  With the inclusion of the optional 
13
* <a href="module_menu.html">Menu Control</a>, the Button Control can also be
14
* used to create menu buttons and split buttons, controls that are not 
15
* available natively in HTML.  The Button Control can also be thought of as a 
16
* way to create more visually engaging implementations of the browser's 
17
* default radio-button and check-box controls.</p>
18
* <p>The Button Control supports the following types:</p>
19
* <dl>
20
* <dt>push</dt>
21
* <dd>Basic push button that can execute a user-specified command when 
22
* pressed.</dd>
23
* <dt>link</dt>
24
* <dd>Navigates to a specified url when pressed.</dd>
25
* <dt>submit</dt>
26
* <dd>Submits the parent form when pressed.</dd>
27
* <dt>reset</dt>
28
* <dd>Resets the parent form when pressed.</dd>
29
* <dt>checkbox</dt>
30
* <dd>Maintains a "checked" state that can be toggled on and off.</dd>
31
* <dt>radio</dt>
32
* <dd>Maintains a "checked" state that can be toggled on and off.  Use with 
33
* the ButtonGroup class to create a set of controls that are mutually 
34
* exclusive; checking one button in the set will uncheck all others in 
35
* the group.</dd>
36
* <dt>menu</dt>
37
* <dd>When pressed will show/hide a menu.</dd>
38
* <dt>split</dt>
39
* <dd>Can execute a user-specified command or display a menu when pressed.</dd>
40
* </dl>
41
* @title Button
42
* @namespace YAHOO.widget
43
* @requires yahoo, dom, element, event
44
* @optional container, menu
45
*/
46
47
48
(function () {
49
50
51
    /**
52
    * The Button class creates a rich, graphical button.
53
    * @param {String} p_oElement String specifying the id attribute of the 
54
    * <code>&#60;input&#62;</code>, <code>&#60;button&#62;</code>,
55
    * <code>&#60;a&#62;</code>, or <code>&#60;span&#62;</code> element to 
56
    * be used to create the button.
57
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
58
    * one-html.html#ID-6043025">HTMLInputElement</a>|<a href="http://www.w3.org
59
    * /TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-34812697">
60
    * HTMLButtonElement</a>|<a href="
61
    * http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#
62
    * ID-33759296">HTMLElement</a>} p_oElement Object reference for the 
63
    * <code>&#60;input&#62;</code>, <code>&#60;button&#62;</code>, 
64
    * <code>&#60;a&#62;</code>, or <code>&#60;span&#62;</code> element to be 
65
    * used to create the button.
66
    * @param {Object} p_oElement Object literal specifying a set of   
67
    * configuration attributes used to create the button.
68
    * @param {Object} p_oAttributes Optional. Object literal specifying a set  
69
    * of configuration attributes used to create the button.
70
    * @namespace YAHOO.widget
71
    * @class Button
72
    * @constructor
73
    * @extends YAHOO.util.Element
74
    */
75
76
77
78
    // Shorthard for utilities
79
80
    var Dom = YAHOO.util.Dom,
81
        Event = YAHOO.util.Event,
82
        Lang = YAHOO.lang,
83
        UA = YAHOO.env.ua,
84
        Overlay = YAHOO.widget.Overlay,
85
        Menu = YAHOO.widget.Menu,
86
    
87
    
88
        // Private member variables
89
    
90
        m_oButtons = {},    // Collection of all Button instances
91
        m_oOverlayManager = null,   // YAHOO.widget.OverlayManager instance
92
        m_oSubmitTrigger = null,    // The button that submitted the form 
93
        m_oFocusedButton = null;    // The button that has focus
94
95
96
97
    // Private methods
98
99
    
100
    
101
    /**
102
    * @method createInputElement
103
    * @description Creates an <code>&#60;input&#62;</code> element of the 
104
    * specified type.
105
    * @private
106
    * @param {String} p_sType String specifying the type of 
107
    * <code>&#60;input&#62;</code> element to create.
108
    * @param {String} p_sName String specifying the name of 
109
    * <code>&#60;input&#62;</code> element to create.
110
    * @param {String} p_sValue String specifying the value of 
111
    * <code>&#60;input&#62;</code> element to create.
112
    * @param {String} p_bChecked Boolean specifying if the  
113
    * <code>&#60;input&#62;</code> element is to be checked.
114
    * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
115
    * one-html.html#ID-6043025">HTMLInputElement</a>}
116
    */
117
    function createInputElement(p_sType, p_sName, p_sValue, p_bChecked) {
118
    
119
        var oInput,
120
            sInput;
121
    
122
        if (Lang.isString(p_sType) && Lang.isString(p_sName)) {
123
        
124
            if (UA.ie) {
125
        
126
                /*
127
                    For IE it is necessary to create the element with the 
128
                    "type," "name," "value," and "checked" properties set all 
129
                    at once.
130
                */
131
            
132
                sInput = "<input type=\"" + p_sType + "\" name=\"" + 
133
                    p_sName + "\"";
134
        
135
                if (p_bChecked) {
136
        
137
                    sInput += " checked";
138
                
139
                }
140
                
141
                sInput += ">";
142
        
143
                oInput = document.createElement(sInput);
144
        
145
            }
146
            else {
147
            
148
                oInput = document.createElement("input");
149
                oInput.name = p_sName;
150
                oInput.type = p_sType;
151
        
152
                if (p_bChecked) {
153
        
154
                    oInput.checked = true;
155
                
156
                }
157
        
158
            }
159
        
160
            oInput.value = p_sValue;
161
        
162
        }
163
164
		return oInput;
165
    
166
    }
167
    
168
    
169
    /**
170
    * @method setAttributesFromSrcElement
171
    * @description Gets the values for all the attributes of the source element 
172
    * (either <code>&#60;input&#62;</code> or <code>&#60;a&#62;</code>) that 
173
    * map to Button configuration attributes and sets them into a collection 
174
    * that is passed to the Button constructor.
175
    * @private
176
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
177
    * one-html.html#ID-6043025">HTMLInputElement</a>|<a href="http://www.w3.org/
178
    * TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-
179
    * 48250443">HTMLAnchorElement</a>} p_oElement Object reference to the HTML 
180
    * element (either <code>&#60;input&#62;</code> or <code>&#60;span&#62;
181
    * </code>) used to create the button.
182
    * @param {Object} p_oAttributes Object reference for the collection of 
183
    * configuration attributes used to create the button.
184
    */
185
    function setAttributesFromSrcElement(p_oElement, p_oAttributes) {
186
    
187
        var sSrcElementNodeName = p_oElement.nodeName.toUpperCase(),
188
			sClass = (this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME),
189
            me = this,
190
            oAttribute,
191
            oRootNode,
192
            sText;
193
            
194
    
195
        /**
196
        * @method setAttributeFromDOMAttribute
197
        * @description Gets the value of the specified DOM attribute and sets it 
198
        * into the collection of configuration attributes used to configure 
199
        * the button.
200
        * @private
201
        * @param {String} p_sAttribute String representing the name of the 
202
        * attribute to retrieve from the DOM element.
203
        */
204
        function setAttributeFromDOMAttribute(p_sAttribute) {
205
    
206
            if (!(p_sAttribute in p_oAttributes)) {
207
    
208
                /*
209
                    Need to use "getAttributeNode" instead of "getAttribute" 
210
                    because using "getAttribute," IE will return the innerText 
211
                    of a <code>&#60;button&#62;</code> for the value attribute  
212
                    rather than the value of the "value" attribute.
213
                */
214
        
215
                oAttribute = p_oElement.getAttributeNode(p_sAttribute);
216
        
217
    
218
                if (oAttribute && ("value" in oAttribute)) {
219
    
220
    
221
                    p_oAttributes[p_sAttribute] = oAttribute.value;
222
    
223
                }
224
    
225
            }
226
        
227
        }
228
    
229
    
230
        /**
231
        * @method setFormElementProperties
232
        * @description Gets the value of the attributes from the form element  
233
        * and sets them into the collection of configuration attributes used to 
234
        * configure the button.
235
        * @private
236
        */
237
        function setFormElementProperties() {
238
    
239
            setAttributeFromDOMAttribute("type");
240
    
241
            if (p_oAttributes.type == "button") {
242
            
243
                p_oAttributes.type = "push";
244
            
245
            }
246
    
247
            if (!("disabled" in p_oAttributes)) {
248
    
249
                p_oAttributes.disabled = p_oElement.disabled;
250
    
251
            }
252
    
253
            setAttributeFromDOMAttribute("name");
254
            setAttributeFromDOMAttribute("value");
255
            setAttributeFromDOMAttribute("title");
256
    
257
        }
258
259
    
260
        switch (sSrcElementNodeName) {
261
        
262
        case "A":
263
            
264
            p_oAttributes.type = "link";
265
            
266
            setAttributeFromDOMAttribute("href");
267
            setAttributeFromDOMAttribute("target");
268
        
269
            break;
270
    
271
        case "INPUT":
272
273
            setFormElementProperties();
274
275
            if (!("checked" in p_oAttributes)) {
276
    
277
                p_oAttributes.checked = p_oElement.checked;
278
    
279
            }
280
281
            break;
282
283
        case "BUTTON":
284
285
            setFormElementProperties();
286
287
            oRootNode = p_oElement.parentNode.parentNode;
288
289
            if (Dom.hasClass(oRootNode, sClass + "-checked")) {
290
            
291
                p_oAttributes.checked = true;
292
            
293
            }
294
295
            if (Dom.hasClass(oRootNode, sClass + "-disabled")) {
296
297
                p_oAttributes.disabled = true;
298
            
299
            }
300
301
            p_oElement.removeAttribute("value");
302
303
            p_oElement.setAttribute("type", "button");
304
305
            break;
306
        
307
        }
308
309
        p_oElement.removeAttribute("id");
310
        p_oElement.removeAttribute("name");
311
        
312
        if (!("tabindex" in p_oAttributes)) {
313
314
            p_oAttributes.tabindex = p_oElement.tabIndex;
315
316
        }
317
    
318
        if (!("label" in p_oAttributes)) {
319
    
320
            // Set the "label" property
321
        
322
            sText = sSrcElementNodeName == "INPUT" ? 
323
                            p_oElement.value : p_oElement.innerHTML;
324
        
325
    
326
            if (sText && sText.length > 0) {
327
                
328
                p_oAttributes.label = sText;
329
                
330
            } 
331
    
332
        }
333
    
334
    }
335
    
336
    
337
    /**
338
    * @method initConfig
339
    * @description Initializes the set of configuration attributes that are 
340
    * used to instantiate the button.
341
    * @private
342
    * @param {Object} Object representing the button's set of 
343
    * configuration attributes.
344
    */
345
    function initConfig(p_oConfig) {
346
    
347
        var oAttributes = p_oConfig.attributes,
348
            oSrcElement = oAttributes.srcelement,
349
            sSrcElementNodeName = oSrcElement.nodeName.toUpperCase(),
350
            me = this;
351
    
352
    
353
        if (sSrcElementNodeName == this.NODE_NAME) {
354
    
355
            p_oConfig.element = oSrcElement;
356
            p_oConfig.id = oSrcElement.id;
357
358
            Dom.getElementsBy(function (p_oElement) {
359
            
360
                switch (p_oElement.nodeName.toUpperCase()) {
361
                
362
                case "BUTTON":
363
                case "A":
364
                case "INPUT":
365
366
                    setAttributesFromSrcElement.call(me, p_oElement, 
367
                        oAttributes);
368
369
                    break;                        
370
                
371
                }
372
            
373
            }, "*", oSrcElement);
374
        
375
        }
376
        else {
377
    
378
            switch (sSrcElementNodeName) {
379
380
            case "BUTTON":
381
            case "A":
382
            case "INPUT":
383
384
                setAttributesFromSrcElement.call(this, oSrcElement, 
385
                    oAttributes);
386
387
                break;
388
389
            }
390
        
391
        }
392
    
393
    }
394
395
396
397
    //  Constructor
398
399
    YAHOO.widget.Button = function (p_oElement, p_oAttributes) {
400
    
401
		if (!Overlay && YAHOO.widget.Overlay) {
402
		
403
			Overlay = YAHOO.widget.Overlay;
404
		
405
		}
406
407
408
		if (!Menu && YAHOO.widget.Menu) {
409
		
410
			Menu = YAHOO.widget.Menu;
411
		
412
		}
413
414
415
        var fnSuperClass = YAHOO.widget.Button.superclass.constructor,
416
            oConfig,
417
            oElement;
418
    
419
420
        if (arguments.length == 1 && !Lang.isString(p_oElement) && !p_oElement.nodeName) {
421
    
422
            if (!p_oElement.id) {
423
    
424
                p_oElement.id = Dom.generateId();
425
    
426
    
427
            }
428
    
429
    
430
            fnSuperClass.call(this, (this.createButtonElement(p_oElement.type)), p_oElement);
431
    
432
        }
433
        else {
434
    
435
            oConfig = { element: null, attributes: (p_oAttributes || {}) };
436
    
437
    
438
            if (Lang.isString(p_oElement)) {
439
    
440
                oElement = Dom.get(p_oElement);
441
    
442
                if (oElement) {
443
444
                    if (!oConfig.attributes.id) {
445
                    
446
                        oConfig.attributes.id = p_oElement;
447
                    
448
                    }
449
    
450
                
451
                
452
                    oConfig.attributes.srcelement = oElement;
453
                
454
                    initConfig.call(this, oConfig);
455
                
456
                
457
                    if (!oConfig.element) {
458
                
459
                
460
                        oConfig.element = this.createButtonElement(oConfig.attributes.type);
461
                
462
                    }
463
                
464
                    fnSuperClass.call(this, oConfig.element, oConfig.attributes);
465
    
466
                }
467
    
468
            }
469
            else if (p_oElement.nodeName) {
470
    
471
                if (!oConfig.attributes.id) {
472
    
473
                    if (p_oElement.id) {
474
        
475
                        oConfig.attributes.id = p_oElement.id;
476
                    
477
                    }
478
                    else {
479
        
480
                        oConfig.attributes.id = Dom.generateId();
481
        
482
        
483
                    }
484
    
485
                }
486
    
487
    
488
    
489
                oConfig.attributes.srcelement = p_oElement;
490
        
491
                initConfig.call(this, oConfig);
492
        
493
        
494
                if (!oConfig.element) {
495
    
496
            
497
                    oConfig.element = this.createButtonElement(oConfig.attributes.type);
498
            
499
                }
500
            
501
                fnSuperClass.call(this, oConfig.element, oConfig.attributes);
502
            
503
            }
504
    
505
        }
506
    
507
    };
508
509
510
511
    YAHOO.extend(YAHOO.widget.Button, YAHOO.util.Element, {
512
    
513
    
514
        // Protected properties
515
        
516
        
517
        /** 
518
        * @property _button
519
        * @description Object reference to the button's internal 
520
        * <code>&#60;a&#62;</code> or <code>&#60;button&#62;</code> element.
521
        * @default null
522
        * @protected
523
        * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
524
        * level-one-html.html#ID-48250443">HTMLAnchorElement</a>|<a href="
525
        * http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html
526
        * #ID-34812697">HTMLButtonElement</a>
527
        */
528
        _button: null,
529
        
530
        
531
        /** 
532
        * @property _menu
533
        * @description Object reference to the button's menu.
534
        * @default null
535
        * @protected
536
        * @type {<a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>|
537
        * <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a>}
538
        */
539
        _menu: null,
540
        
541
        
542
        /** 
543
        * @property _hiddenFields
544
        * @description Object reference to the <code>&#60;input&#62;</code>  
545
        * element, or array of HTML form elements used to represent the button
546
        *  when its parent form is submitted.
547
        * @default null
548
        * @protected
549
        * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
550
        * level-one-html.html#ID-6043025">HTMLInputElement</a>|Array
551
        */
552
        _hiddenFields: null,
553
        
554
        
555
        /** 
556
        * @property _onclickAttributeValue
557
        * @description Object reference to the button's current value for the 
558
        * "onclick" configuration attribute.
559
        * @default null
560
        * @protected
561
        * @type Object
562
        */
563
        _onclickAttributeValue: null,
564
        
565
        
566
        /** 
567
        * @property _activationKeyPressed
568
        * @description Boolean indicating if the key(s) that toggle the button's 
569
        * "active" state have been pressed.
570
        * @default false
571
        * @protected
572
        * @type Boolean
573
        */
574
        _activationKeyPressed: false,
575
        
576
        
577
        /** 
578
        * @property _activationButtonPressed
579
        * @description Boolean indicating if the mouse button that toggles 
580
        * the button's "active" state has been pressed.
581
        * @default false
582
        * @protected
583
        * @type Boolean
584
        */
585
        _activationButtonPressed: false,
586
        
587
        
588
        /** 
589
        * @property _hasKeyEventHandlers
590
        * @description Boolean indicating if the button's "blur", "keydown" and 
591
        * "keyup" event handlers are assigned
592
        * @default false
593
        * @protected
594
        * @type Boolean
595
        */
596
        _hasKeyEventHandlers: false,
597
        
598
        
599
        /** 
600
        * @property _hasMouseEventHandlers
601
        * @description Boolean indicating if the button's "mouseout," 
602
        * "mousedown," and "mouseup" event handlers are assigned
603
        * @default false
604
        * @protected
605
        * @type Boolean
606
        */
607
        _hasMouseEventHandlers: false,
608
609
610
        /** 
611
        * @property _nOptionRegionX
612
        * @description Number representing the X coordinate of the leftmost edge of the Button's 
613
        * option region.  Applies only to Buttons of type "split".
614
        * @default 0
615
        * @protected
616
        * @type Number
617
        */        
618
        _nOptionRegionX: 0,
619
        
620
621
622
        // Constants
623
624
        /**
625
        * @property CLASS_NAME_PREFIX
626
        * @description Prefix used for all class names applied to a Button.
627
        * @default "yui-"
628
        * @final
629
        * @type String
630
        */
631
        CLASS_NAME_PREFIX: "yui-",
632
        
633
        
634
        /**
635
        * @property NODE_NAME
636
        * @description The name of the node to be used for the button's 
637
        * root element.
638
        * @default "SPAN"
639
        * @final
640
        * @type String
641
        */
642
        NODE_NAME: "SPAN",
643
        
644
        
645
        /**
646
        * @property CHECK_ACTIVATION_KEYS
647
        * @description Array of numbers representing keys that (when pressed) 
648
        * toggle the button's "checked" attribute.
649
        * @default [32]
650
        * @final
651
        * @type Array
652
        */
653
        CHECK_ACTIVATION_KEYS: [32],
654
        
655
        
656
        /**
657
        * @property ACTIVATION_KEYS
658
        * @description Array of numbers representing keys that (when presed) 
659
        * toggle the button's "active" state.
660
        * @default [13, 32]
661
        * @final
662
        * @type Array
663
        */
664
        ACTIVATION_KEYS: [13, 32],
665
        
666
        
667
        /**
668
        * @property OPTION_AREA_WIDTH
669
        * @description Width (in pixels) of the area of a split button that  
670
        * when pressed will display a menu.
671
        * @default 20
672
        * @final
673
        * @type Number
674
        */
675
        OPTION_AREA_WIDTH: 20,
676
        
677
        
678
        /**
679
        * @property CSS_CLASS_NAME
680
        * @description String representing the CSS class(es) to be applied to  
681
        * the button's root element.
682
        * @default "button"
683
        * @final
684
        * @type String
685
        */
686
        CSS_CLASS_NAME: "button",
687
        
688
        
689
        
690
        // Protected attribute setter methods
691
        
692
        
693
        /**
694
        * @method _setType
695
        * @description Sets the value of the button's "type" attribute.
696
        * @protected
697
        * @param {String} p_sType String indicating the value for the button's 
698
        * "type" attribute.
699
        */
700
        _setType: function (p_sType) {
701
        
702
            if (p_sType == "split") {
703
        
704
                this.on("option", this._onOption);
705
        
706
            }
707
        
708
        },
709
        
710
        
711
        /**
712
        * @method _setLabel
713
        * @description Sets the value of the button's "label" attribute.
714
        * @protected
715
        * @param {String} p_sLabel String indicating the value for the button's 
716
        * "label" attribute.
717
        */
718
        _setLabel: function (p_sLabel) {
719
720
            this._button.innerHTML = p_sLabel;
721
722
            
723
            /*
724
                Remove and add the default class name from the root element
725
                for Gecko to ensure that the button shrinkwraps to the label.
726
                Without this the button will not be rendered at the correct 
727
                width when the label changes.  The most likely cause for this 
728
                bug is button's use of the Gecko-specific CSS display type of 
729
                "-moz-inline-box" to simulate "inline-block" supported by IE, 
730
                Safari and Opera.
731
            */
732
            
733
            var sClass,
734
                nGeckoVersion = UA.gecko;
735
				
736
            
737
            if (nGeckoVersion && nGeckoVersion < 1.9 && Dom.inDocument(this.get("element"))) {
738
            
739
                sClass = (this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME);
740
741
                this.removeClass(sClass);
742
                
743
                Lang.later(0, this, this.addClass, sClass);
744
745
            }
746
        
747
        },
748
        
749
        
750
        /**
751
        * @method _setTabIndex
752
        * @description Sets the value of the button's "tabindex" attribute.
753
        * @protected
754
        * @param {Number} p_nTabIndex Number indicating the value for the 
755
        * button's "tabindex" attribute.
756
        */
757
        _setTabIndex: function (p_nTabIndex) {
758
        
759
            this._button.tabIndex = p_nTabIndex;
760
        
761
        },
762
        
763
        
764
        /**
765
        * @method _setTitle
766
        * @description Sets the value of the button's "title" attribute.
767
        * @protected
768
        * @param {String} p_nTabIndex Number indicating the value for 
769
        * the button's "title" attribute.
770
        */
771
        _setTitle: function (p_sTitle) {
772
        
773
            if (this.get("type") != "link") {
774
        
775
                this._button.title = p_sTitle;
776
        
777
            }
778
        
779
        },
780
        
781
        
782
        /**
783
        * @method _setDisabled
784
        * @description Sets the value of the button's "disabled" attribute.
785
        * @protected
786
        * @param {Boolean} p_bDisabled Boolean indicating the value for 
787
        * the button's "disabled" attribute.
788
        */
789
        _setDisabled: function (p_bDisabled) {
790
        
791
            if (this.get("type") != "link") {
792
        
793
                if (p_bDisabled) {
794
        
795
                    if (this._menu) {
796
        
797
                        this._menu.hide();
798
        
799
                    }
800
        
801
                    if (this.hasFocus()) {
802
                    
803
                        this.blur();
804
                    
805
                    }
806
        
807
                    this._button.setAttribute("disabled", "disabled");
808
        
809
                    this.addStateCSSClasses("disabled");
810
811
                    this.removeStateCSSClasses("hover");
812
                    this.removeStateCSSClasses("active");
813
                    this.removeStateCSSClasses("focus");
814
        
815
                }
816
                else {
817
        
818
                    this._button.removeAttribute("disabled");
819
        
820
                    this.removeStateCSSClasses("disabled");
821
                
822
                }
823
        
824
            }
825
        
826
        },
827
828
        
829
        /**
830
        * @method _setHref
831
        * @description Sets the value of the button's "href" attribute.
832
        * @protected
833
        * @param {String} p_sHref String indicating the value for the button's 
834
        * "href" attribute.
835
        */
836
        _setHref: function (p_sHref) {
837
        
838
            if (this.get("type") == "link") {
839
        
840
                this._button.href = p_sHref;
841
            
842
            }
843
        
844
        },
845
        
846
        
847
        /**
848
        * @method _setTarget
849
        * @description Sets the value of the button's "target" attribute.
850
        * @protected
851
        * @param {String} p_sTarget String indicating the value for the button's 
852
        * "target" attribute.
853
        */
854
        _setTarget: function (p_sTarget) {
855
        
856
            if (this.get("type") == "link") {
857
        
858
                this._button.setAttribute("target", p_sTarget);
859
            
860
            }
861
        
862
        },
863
        
864
        
865
        /**
866
        * @method _setChecked
867
        * @description Sets the value of the button's "target" attribute.
868
        * @protected
869
        * @param {Boolean} p_bChecked Boolean indicating the value for  
870
        * the button's "checked" attribute.
871
        */
872
        _setChecked: function (p_bChecked) {
873
        
874
            var sType = this.get("type");
875
        
876
            if (sType == "checkbox" || sType == "radio") {
877
        
878
                if (p_bChecked) {
879
                    this.addStateCSSClasses("checked");
880
                }
881
                else {
882
                    this.removeStateCSSClasses("checked");
883
                }
884
        
885
            }
886
        
887
        },
888
889
        
890
        /**
891
        * @method _setMenu
892
        * @description Sets the value of the button's "menu" attribute.
893
        * @protected
894
        * @param {Object} p_oMenu Object indicating the value for the button's 
895
        * "menu" attribute.
896
        */
897
        _setMenu: function (p_oMenu) {
898
899
            var bLazyLoad = this.get("lazyloadmenu"),
900
                oButtonElement = this.get("element"),
901
                sMenuCSSClassName,
902
        
903
                /*
904
                    Boolean indicating if the value of p_oMenu is an instance 
905
                    of YAHOO.widget.Menu or YAHOO.widget.Overlay.
906
                */
907
        
908
                bInstance = false,
909
                oMenu,
910
                oMenuElement,
911
                oSrcElement;
912
        
913
914
			function onAppendTo() {
915
916
				oMenu.render(oButtonElement.parentNode);
917
				
918
				this.removeListener("appendTo", onAppendTo);
919
			
920
			}
921
			
922
			
923
			function setMenuContainer() {
924
925
				oMenu.cfg.queueProperty("container", oButtonElement.parentNode);
926
				
927
				this.removeListener("appendTo", setMenuContainer);
928
			
929
			}
930
931
932
			function initMenu() {
933
		
934
				var oContainer;
935
		
936
				if (oMenu) {
937
938
					Dom.addClass(oMenu.element, this.get("menuclassname"));
939
					Dom.addClass(oMenu.element, this.CLASS_NAME_PREFIX + this.get("type") + "-button-menu");
940
941
					oMenu.showEvent.subscribe(this._onMenuShow, null, this);
942
					oMenu.hideEvent.subscribe(this._onMenuHide, null, this);
943
					oMenu.renderEvent.subscribe(this._onMenuRender, null, this);
944
945
946
					if (Menu && oMenu instanceof Menu) {
947
948
						if (bLazyLoad) {
949
950
							oContainer = this.get("container");
951
952
							if (oContainer) {
953
954
								oMenu.cfg.queueProperty("container", oContainer);
955
956
							}
957
							else {
958
959
								this.on("appendTo", setMenuContainer);
960
961
							}
962
963
						}
964
965
						oMenu.cfg.queueProperty("clicktohide", false);
966
967
						oMenu.keyDownEvent.subscribe(this._onMenuKeyDown, this, true);
968
						oMenu.subscribe("click", this._onMenuClick, this, true);
969
970
						this.on("selectedMenuItemChange", this._onSelectedMenuItemChange);
971
		
972
						oSrcElement = oMenu.srcElement;
973
		
974
						if (oSrcElement && oSrcElement.nodeName.toUpperCase() == "SELECT") {
975
976
							oSrcElement.style.display = "none";
977
							oSrcElement.parentNode.removeChild(oSrcElement);
978
		
979
						}
980
		
981
					}
982
					else if (Overlay && oMenu instanceof Overlay) {
983
		
984
						if (!m_oOverlayManager) {
985
		
986
							m_oOverlayManager = new YAHOO.widget.OverlayManager();
987
						
988
						}
989
						
990
						m_oOverlayManager.register(oMenu);
991
						
992
					}
993
		
994
		
995
					this._menu = oMenu;
996
997
		
998
					if (!bInstance && !bLazyLoad) {
999
		
1000
						if (Dom.inDocument(oButtonElement)) {
1001
	
1002
							oMenu.render(oButtonElement.parentNode);
1003
						
1004
						}
1005
						else {
1006
		
1007
							this.on("appendTo", onAppendTo);
1008
						
1009
						}
1010
					
1011
					}
1012
		
1013
				}
1014
		
1015
			}
1016
1017
        
1018
            if (Overlay) {
1019
        
1020
				if (Menu) {
1021
				
1022
					sMenuCSSClassName = Menu.prototype.CSS_CLASS_NAME;
1023
				
1024
				}
1025
			
1026
				if (p_oMenu && Menu && (p_oMenu instanceof Menu)) {
1027
			
1028
					oMenu = p_oMenu;
1029
					bInstance = true;
1030
			
1031
					initMenu.call(this);
1032
			
1033
				}
1034
				else if (Overlay && p_oMenu && (p_oMenu instanceof Overlay)) {
1035
			
1036
					oMenu = p_oMenu;
1037
					bInstance = true;
1038
			
1039
					oMenu.cfg.queueProperty("visible", false);
1040
			
1041
					initMenu.call(this);
1042
			
1043
				}
1044
				else if (Menu && Lang.isArray(p_oMenu)) {
1045
1046
					oMenu = new Menu(Dom.generateId(), { lazyload: bLazyLoad, itemdata: p_oMenu });
1047
						
1048
					this._menu = oMenu;
1049
			
1050
					this.on("appendTo", initMenu);
1051
			
1052
				}
1053
				else if (Lang.isString(p_oMenu)) {
1054
			
1055
					oMenuElement = Dom.get(p_oMenu);
1056
			
1057
					if (oMenuElement) {
1058
			
1059
						if (Menu && Dom.hasClass(oMenuElement, sMenuCSSClassName) || 
1060
							oMenuElement.nodeName.toUpperCase() == "SELECT") {
1061
				
1062
							oMenu = new Menu(p_oMenu, { lazyload: bLazyLoad });
1063
				
1064
							initMenu.call(this);
1065
				
1066
						}
1067
						else if (Overlay) {
1068
			
1069
							oMenu = new Overlay(p_oMenu, { visible: false });
1070
				
1071
							initMenu.call(this);
1072
				
1073
						}
1074
			
1075
					}
1076
			
1077
				}
1078
				else if (p_oMenu && p_oMenu.nodeName) {
1079
			
1080
					if (Menu && Dom.hasClass(p_oMenu, sMenuCSSClassName) || 
1081
							p_oMenu.nodeName.toUpperCase() == "SELECT") {
1082
			
1083
						oMenu = new Menu(p_oMenu, { lazyload: bLazyLoad });
1084
					
1085
						initMenu.call(this);
1086
			
1087
					}
1088
					else if (Overlay) {
1089
			
1090
						if (!p_oMenu.id) {
1091
						
1092
							Dom.generateId(p_oMenu);
1093
						
1094
						}
1095
			
1096
						oMenu = new Overlay(p_oMenu, { visible: false });
1097
			
1098
						initMenu.call(this);
1099
					
1100
					}
1101
				
1102
				}
1103
            
1104
            }
1105
        
1106
        },
1107
        
1108
        
1109
        /**
1110
        * @method _setOnClick
1111
        * @description Sets the value of the button's "onclick" attribute.
1112
        * @protected
1113
        * @param {Object} p_oObject Object indicating the value for the button's 
1114
        * "onclick" attribute.
1115
        */
1116
        _setOnClick: function (p_oObject) {
1117
        
1118
            /*
1119
                Remove any existing listeners if a "click" event handler 
1120
                has already been specified.
1121
            */
1122
        
1123
            if (this._onclickAttributeValue && 
1124
                (this._onclickAttributeValue != p_oObject)) {
1125
        
1126
                this.removeListener("click", this._onclickAttributeValue.fn);
1127
        
1128
                this._onclickAttributeValue = null;
1129
        
1130
            }
1131
        
1132
        
1133
            if (!this._onclickAttributeValue && 
1134
                Lang.isObject(p_oObject) && 
1135
                Lang.isFunction(p_oObject.fn)) {
1136
        
1137
                this.on("click", p_oObject.fn, p_oObject.obj, p_oObject.scope);
1138
        
1139
                this._onclickAttributeValue = p_oObject;
1140
        
1141
            }
1142
        
1143
        },
1144
1145
        
1146
        
1147
        // Protected methods
1148
1149
        
1150
        
1151
        /**
1152
        * @method _isActivationKey
1153
        * @description Determines if the specified keycode is one that toggles  
1154
        * the button's "active" state.
1155
        * @protected
1156
        * @param {Number} p_nKeyCode Number representing the keycode to 
1157
        * be evaluated.
1158
        * @return {Boolean}
1159
        */
1160
        _isActivationKey: function (p_nKeyCode) {
1161
        
1162
            var sType = this.get("type"),
1163
                aKeyCodes = (sType == "checkbox" || sType == "radio") ? 
1164
                    this.CHECK_ACTIVATION_KEYS : this.ACTIVATION_KEYS,
1165
        
1166
                nKeyCodes = aKeyCodes.length,
1167
                bReturnVal = false,
1168
                i;
1169
        
1170
1171
            if (nKeyCodes > 0) {
1172
        
1173
                i = nKeyCodes - 1;
1174
        
1175
                do {
1176
        
1177
                    if (p_nKeyCode == aKeyCodes[i]) {
1178
        
1179
                        bReturnVal = true;
1180
                        break;
1181
        
1182
                    }
1183
        
1184
                }
1185
                while (i--);
1186
            
1187
            }
1188
            
1189
            return bReturnVal;
1190
        
1191
        },
1192
        
1193
        
1194
        /**
1195
        * @method _isSplitButtonOptionKey
1196
        * @description Determines if the specified keycode is one that toggles  
1197
        * the display of the split button's menu.
1198
        * @protected
1199
        * @param {Event} p_oEvent Object representing the DOM event object  
1200
        * passed back by the event utility (YAHOO.util.Event).
1201
        * @return {Boolean}
1202
        */
1203
        _isSplitButtonOptionKey: function (p_oEvent) {
1204
1205
			var bShowMenu = (Event.getCharCode(p_oEvent) == 40);
1206
1207
1208
			var onKeyPress = function (p_oEvent) {
1209
1210
				Event.preventDefault(p_oEvent);
1211
1212
				this.removeListener("keypress", onKeyPress);
1213
			
1214
			};
1215
1216
1217
			// Prevent the browser from scrolling the window
1218
			if (bShowMenu) {
1219
1220
				if (UA.opera) {
1221
	
1222
					this.on("keypress", onKeyPress);
1223
	
1224
				}
1225
1226
				Event.preventDefault(p_oEvent);
1227
			}
1228
1229
            return bShowMenu;
1230
        
1231
        },
1232
        
1233
        
1234
        /**
1235
        * @method _addListenersToForm
1236
        * @description Adds event handlers to the button's form.
1237
        * @protected
1238
        */
1239
        _addListenersToForm: function () {
1240
        
1241
            var oForm = this.getForm(),
1242
                onFormKeyPress = YAHOO.widget.Button.onFormKeyPress,
1243
                bHasKeyPressListener,
1244
                oSrcElement,
1245
                aListeners,
1246
                nListeners,
1247
                i;
1248
        
1249
        
1250
            if (oForm) {
1251
        
1252
                Event.on(oForm, "reset", this._onFormReset, null, this);
1253
                Event.on(oForm, "submit", this._onFormSubmit, null, this);
1254
        
1255
                oSrcElement = this.get("srcelement");
1256
        
1257
        
1258
                if (this.get("type") == "submit" || 
1259
                    (oSrcElement && oSrcElement.type == "submit")) 
1260
                {
1261
                
1262
                    aListeners = Event.getListeners(oForm, "keypress");
1263
                    bHasKeyPressListener = false;
1264
            
1265
                    if (aListeners) {
1266
            
1267
                        nListeners = aListeners.length;
1268
        
1269
                        if (nListeners > 0) {
1270
            
1271
                            i = nListeners - 1;
1272
                            
1273
                            do {
1274
               
1275
                                if (aListeners[i].fn == onFormKeyPress) {
1276
                
1277
                                    bHasKeyPressListener = true;
1278
                                    break;
1279
                                
1280
                                }
1281
                
1282
                            }
1283
                            while (i--);
1284
                        
1285
                        }
1286
                    
1287
                    }
1288
            
1289
            
1290
                    if (!bHasKeyPressListener) {
1291
               
1292
                        Event.on(oForm, "keypress", onFormKeyPress);
1293
            
1294
                    }
1295
        
1296
                }
1297
            
1298
            }
1299
        
1300
        },
1301
        
1302
        
1303
        
1304
        /**
1305
        * @method _showMenu
1306
        * @description Shows the button's menu.
1307
        * @protected
1308
        * @param {Event} p_oEvent Object representing the DOM event object 
1309
        * passed back by the event utility (YAHOO.util.Event) that triggered 
1310
        * the display of the menu.
1311
        */
1312
        _showMenu: function (p_oEvent) {
1313
1314
            if (YAHOO.widget.MenuManager) {
1315
                YAHOO.widget.MenuManager.hideVisible();
1316
            }
1317
1318
        
1319
            if (m_oOverlayManager) {
1320
                m_oOverlayManager.hideAll();
1321
            }
1322
1323
1324
            var oMenu = this._menu,
1325
            	aMenuAlignment = this.get("menualignment"),
1326
            	bFocusMenu = this.get("focusmenu"),
1327
				fnFocusMethod;
1328
1329
1330
			if (this._renderedMenu) {
1331
1332
				oMenu.cfg.setProperty("context", 
1333
								[this.get("element"), aMenuAlignment[0], aMenuAlignment[1]]);
1334
	
1335
				oMenu.cfg.setProperty("preventcontextoverlap", true);
1336
				oMenu.cfg.setProperty("constraintoviewport", true);
1337
1338
			}
1339
			else {
1340
1341
				oMenu.cfg.queueProperty("context", 
1342
								[this.get("element"), aMenuAlignment[0], aMenuAlignment[1]]);
1343
	
1344
				oMenu.cfg.queueProperty("preventcontextoverlap", true);
1345
				oMenu.cfg.queueProperty("constraintoviewport", true);
1346
			
1347
			}
1348
1349
1350
			/*
1351
				 Refocus the Button before showing its Menu in case the call to 
1352
				 YAHOO.widget.MenuManager.hideVisible() resulted in another element in the 
1353
				 DOM being focused after another Menu was hidden.
1354
			*/
1355
			
1356
			this.focus();
1357
1358
1359
            if (Menu && oMenu && (oMenu instanceof Menu)) {
1360
1361
				// Since Menus automatically focus themselves when made visible, temporarily 
1362
				// replace the Menu focus method so that the value of the Button's "focusmenu"
1363
				// attribute determines if the Menu should be focus when made visible.
1364
1365
				fnFocusMethod = oMenu.focus;
1366
1367
				oMenu.focus = function () {};
1368
1369
				if (this._renderedMenu) {
1370
1371
					oMenu.cfg.setProperty("minscrollheight", this.get("menuminscrollheight"));
1372
					oMenu.cfg.setProperty("maxheight", this.get("menumaxheight"));
1373
				
1374
				}
1375
				else {
1376
1377
					oMenu.cfg.queueProperty("minscrollheight", this.get("menuminscrollheight"));
1378
					oMenu.cfg.queueProperty("maxheight", this.get("menumaxheight"));
1379
				
1380
				}
1381
1382
1383
                oMenu.show();
1384
1385
        		oMenu.focus = fnFocusMethod;
1386
1387
				oMenu.align();
1388
        
1389
1390
                /*
1391
                    Stop the propagation of the event so that the MenuManager 
1392
                    doesn't blur the menu after it gets focus.
1393
                */
1394
        
1395
                if (p_oEvent.type == "mousedown") {
1396
                    Event.stopPropagation(p_oEvent);
1397
                }
1398
1399
        
1400
                if (bFocusMenu) { 
1401
                    oMenu.focus();
1402
                }
1403
1404
            }
1405
            else if (Overlay && oMenu && (oMenu instanceof Overlay)) {
1406
1407
				if (!this._renderedMenu) {
1408
		            oMenu.render(this.get("element").parentNode);
1409
				}
1410
1411
                oMenu.show();
1412
				oMenu.align();
1413
1414
            }
1415
        
1416
        },
1417
        
1418
        
1419
        /**
1420
        * @method _hideMenu
1421
        * @description Hides the button's menu.
1422
        * @protected
1423
        */
1424
        _hideMenu: function () {
1425
        
1426
            var oMenu = this._menu;
1427
        
1428
            if (oMenu) {
1429
        
1430
                oMenu.hide();
1431
        
1432
            }
1433
        
1434
        },
1435
        
1436
        
1437
        
1438
        
1439
        // Protected event handlers
1440
        
1441
        
1442
        /**
1443
        * @method _onMouseOver
1444
        * @description "mouseover" event handler for the button.
1445
        * @protected
1446
        * @param {Event} p_oEvent Object representing the DOM event object  
1447
        * passed back by the event utility (YAHOO.util.Event).
1448
        */
1449
        _onMouseOver: function (p_oEvent) {
1450
        
1451
        	var sType = this.get("type"),
1452
        		oElement,
1453
				nOptionRegionX;
1454
1455
1456
			if (sType === "split") {
1457
1458
				oElement = this.get("element");
1459
				nOptionRegionX = 
1460
					(Dom.getX(oElement) + (oElement.offsetWidth - this.OPTION_AREA_WIDTH));
1461
					
1462
				this._nOptionRegionX = nOptionRegionX;
1463
			
1464
			}
1465
        
1466
1467
            if (!this._hasMouseEventHandlers) {
1468
        
1469
				if (sType === "split") {
1470
        
1471
	        		this.on("mousemove", this._onMouseMove);
1472
1473
        		}
1474
1475
                this.on("mouseout", this._onMouseOut);
1476
        
1477
                this._hasMouseEventHandlers = true;
1478
        
1479
            }
1480
        
1481
1482
            this.addStateCSSClasses("hover");
1483
1484
1485
			if (sType === "split" && (Event.getPageX(p_oEvent) > nOptionRegionX)) {
1486
	
1487
				this.addStateCSSClasses("hoveroption");
1488
	
1489
			}
1490
1491
        
1492
            if (this._activationButtonPressed) {
1493
        
1494
                this.addStateCSSClasses("active");
1495
        
1496
            }
1497
        
1498
        
1499
            if (this._bOptionPressed) {
1500
        
1501
                this.addStateCSSClasses("activeoption");
1502
            
1503
            }
1504
1505
1506
            if (this._activationButtonPressed || this._bOptionPressed) {
1507
        
1508
                Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
1509
        
1510
            }
1511
1512
        },
1513
1514
1515
        /**
1516
        * @method _onMouseMove
1517
        * @description "mousemove" event handler for the button.
1518
        * @protected
1519
        * @param {Event} p_oEvent Object representing the DOM event object  
1520
        * passed back by the event utility (YAHOO.util.Event).
1521
        */        
1522
        _onMouseMove: function (p_oEvent) {
1523
        
1524
        	var nOptionRegionX = this._nOptionRegionX;
1525
        
1526
        	if (nOptionRegionX) {
1527
1528
				if (Event.getPageX(p_oEvent) > nOptionRegionX) {
1529
					
1530
					this.addStateCSSClasses("hoveroption");
1531
	
1532
				}
1533
				else {
1534
1535
					this.removeStateCSSClasses("hoveroption");
1536
				
1537
				}
1538
				
1539
        	}
1540
        
1541
        },
1542
        
1543
        /**
1544
        * @method _onMouseOut
1545
        * @description "mouseout" event handler for the button.
1546
        * @protected
1547
        * @param {Event} p_oEvent Object representing the DOM event object  
1548
        * passed back by the event utility (YAHOO.util.Event).
1549
        */
1550
        _onMouseOut: function (p_oEvent) {
1551
1552
			var sType = this.get("type");
1553
        
1554
            this.removeStateCSSClasses("hover");
1555
        
1556
1557
            if (sType != "menu") {
1558
        
1559
                this.removeStateCSSClasses("active");
1560
        
1561
            }
1562
        
1563
1564
            if (this._activationButtonPressed || this._bOptionPressed) {
1565
        
1566
                Event.on(document, "mouseup", this._onDocumentMouseUp, null, this);
1567
        
1568
            }
1569
1570
1571
			if (sType === "split" && (Event.getPageX(p_oEvent) > this._nOptionRegionX)) {
1572
			
1573
				this.removeStateCSSClasses("hoveroption");
1574
	
1575
			}
1576
            
1577
        },
1578
        
1579
        
1580
        /**
1581
        * @method _onDocumentMouseUp
1582
        * @description "mouseup" event handler for the button.
1583
        * @protected
1584
        * @param {Event} p_oEvent Object representing the DOM event object  
1585
        * passed back by the event utility (YAHOO.util.Event).
1586
        */
1587
        _onDocumentMouseUp: function (p_oEvent) {
1588
        
1589
            this._activationButtonPressed = false;
1590
            this._bOptionPressed = false;
1591
        
1592
            var sType = this.get("type"),
1593
                oTarget,
1594
                oMenuElement;
1595
        
1596
            if (sType == "menu" || sType == "split") {
1597
1598
                oTarget = Event.getTarget(p_oEvent);
1599
                oMenuElement = this._menu.element;
1600
        
1601
                if (oTarget != oMenuElement && 
1602
                    !Dom.isAncestor(oMenuElement, oTarget)) {
1603
1604
                    this.removeStateCSSClasses((sType == "menu" ? 
1605
                        "active" : "activeoption"));
1606
            
1607
                    this._hideMenu();
1608
1609
                }
1610
        
1611
            }
1612
        
1613
            Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
1614
        
1615
        },
1616
        
1617
        
1618
        /**
1619
        * @method _onMouseDown
1620
        * @description "mousedown" event handler for the button.
1621
        * @protected
1622
        * @param {Event} p_oEvent Object representing the DOM event object  
1623
        * passed back by the event utility (YAHOO.util.Event).
1624
        */
1625
        _onMouseDown: function (p_oEvent) {
1626
        
1627
            var sType,
1628
            	bReturnVal = true;
1629
        
1630
        
1631
            function onMouseUp() {
1632
            
1633
                this._hideMenu();
1634
                this.removeListener("mouseup", onMouseUp);
1635
            
1636
            }
1637
        
1638
        
1639
            if ((p_oEvent.which || p_oEvent.button) == 1) {
1640
        
1641
        
1642
                if (!this.hasFocus()) {
1643
                
1644
                    this.focus();
1645
                
1646
                }
1647
        
1648
        
1649
                sType = this.get("type");
1650
        
1651
        
1652
                if (sType == "split") {
1653
                
1654
                    if (Event.getPageX(p_oEvent) > this._nOptionRegionX) {
1655
                        
1656
                        this.fireEvent("option", p_oEvent);
1657
						bReturnVal = false;
1658
        
1659
                    }
1660
                    else {
1661
        
1662
                        this.addStateCSSClasses("active");
1663
        
1664
                        this._activationButtonPressed = true;
1665
        
1666
                    }
1667
        
1668
                }
1669
                else if (sType == "menu") {
1670
        
1671
                    if (this.isActive()) {
1672
        
1673
                        this._hideMenu();
1674
        
1675
                        this._activationButtonPressed = false;
1676
        
1677
                    }
1678
                    else {
1679
        
1680
                        this._showMenu(p_oEvent);
1681
        
1682
                        this._activationButtonPressed = true;
1683
                    
1684
                    }
1685
        
1686
                }
1687
                else {
1688
        
1689
                    this.addStateCSSClasses("active");
1690
        
1691
                    this._activationButtonPressed = true;
1692
                
1693
                }
1694
        
1695
        
1696
        
1697
                if (sType == "split" || sType == "menu") {
1698
1699
                    this._hideMenuTimer = Lang.later(250, this, this.on, ["mouseup", onMouseUp]);
1700
        
1701
                }
1702
        
1703
            }
1704
            
1705
            return bReturnVal;
1706
            
1707
        },
1708
        
1709
        
1710
        /**
1711
        * @method _onMouseUp
1712
        * @description "mouseup" event handler for the button.
1713
        * @protected
1714
        * @param {Event} p_oEvent Object representing the DOM event object  
1715
        * passed back by the event utility (YAHOO.util.Event).
1716
        */
1717
        _onMouseUp: function (p_oEvent) {
1718
        
1719
            var sType = this.get("type"),
1720
            	oHideMenuTimer = this._hideMenuTimer,
1721
            	bReturnVal = true;
1722
        
1723
        
1724
            if (oHideMenuTimer) {
1725
  
1726
  				oHideMenuTimer.cancel();
1727
        
1728
            }
1729
        
1730
        
1731
            if (sType == "checkbox" || sType == "radio") {
1732
        
1733
                this.set("checked", !(this.get("checked")));
1734
            
1735
            }
1736
        
1737
        
1738
            this._activationButtonPressed = false;
1739
            
1740
        
1741
            if (sType != "menu") {
1742
        
1743
                this.removeStateCSSClasses("active");
1744
            
1745
            }
1746
1747
                
1748
			if (sType == "split" && Event.getPageX(p_oEvent) > this._nOptionRegionX) {
1749
				
1750
				bReturnVal = false;
1751
1752
			}
1753
1754
			return bReturnVal;
1755
            
1756
        },
1757
        
1758
        
1759
        /**
1760
        * @method _onFocus
1761
        * @description "focus" event handler for the button.
1762
        * @protected
1763
        * @param {Event} p_oEvent Object representing the DOM event object  
1764
        * passed back by the event utility (YAHOO.util.Event).
1765
        */
1766
        _onFocus: function (p_oEvent) {
1767
        
1768
            var oElement;
1769
        
1770
            this.addStateCSSClasses("focus");
1771
        
1772
            if (this._activationKeyPressed) {
1773
        
1774
                this.addStateCSSClasses("active");
1775
           
1776
            }
1777
        
1778
            m_oFocusedButton = this;
1779
        
1780
        
1781
            if (!this._hasKeyEventHandlers) {
1782
        
1783
                oElement = this._button;
1784
        
1785
                Event.on(oElement, "blur", this._onBlur, null, this);
1786
                Event.on(oElement, "keydown", this._onKeyDown, null, this);
1787
                Event.on(oElement, "keyup", this._onKeyUp, null, this);
1788
        
1789
                this._hasKeyEventHandlers = true;
1790
        
1791
            }
1792
        
1793
        
1794
            this.fireEvent("focus", p_oEvent);
1795
        
1796
        },
1797
        
1798
        
1799
        /**
1800
        * @method _onBlur
1801
        * @description "blur" event handler for the button.
1802
        * @protected
1803
        * @param {Event} p_oEvent Object representing the DOM event object  
1804
        * passed back by the event utility (YAHOO.util.Event).
1805
        */
1806
        _onBlur: function (p_oEvent) {
1807
        
1808
            this.removeStateCSSClasses("focus");
1809
        
1810
            if (this.get("type") != "menu") {
1811
        
1812
                this.removeStateCSSClasses("active");
1813
1814
            }    
1815
        
1816
            if (this._activationKeyPressed) {
1817
        
1818
                Event.on(document, "keyup", this._onDocumentKeyUp, null, this);
1819
        
1820
            }
1821
        
1822
        
1823
            m_oFocusedButton = null;
1824
        
1825
            this.fireEvent("blur", p_oEvent);
1826
           
1827
        },
1828
        
1829
        
1830
        /**
1831
        * @method _onDocumentKeyUp
1832
        * @description "keyup" event handler for the document.
1833
        * @protected
1834
        * @param {Event} p_oEvent Object representing the DOM event object  
1835
        * passed back by the event utility (YAHOO.util.Event).
1836
        */
1837
        _onDocumentKeyUp: function (p_oEvent) {
1838
        
1839
            if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
1840
        
1841
                this._activationKeyPressed = false;
1842
                
1843
                Event.removeListener(document, "keyup", this._onDocumentKeyUp);
1844
            
1845
            }
1846
        
1847
        },
1848
        
1849
        
1850
        /**
1851
        * @method _onKeyDown
1852
        * @description "keydown" event handler for the button.
1853
        * @protected
1854
        * @param {Event} p_oEvent Object representing the DOM event object  
1855
        * passed back by the event utility (YAHOO.util.Event).
1856
        */
1857
        _onKeyDown: function (p_oEvent) {
1858
        
1859
            var oMenu = this._menu;
1860
        
1861
        
1862
            if (this.get("type") == "split" && 
1863
                this._isSplitButtonOptionKey(p_oEvent)) {
1864
        
1865
                this.fireEvent("option", p_oEvent);
1866
        
1867
            }
1868
            else if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
1869
        
1870
                if (this.get("type") == "menu") {
1871
        
1872
                    this._showMenu(p_oEvent);
1873
        
1874
                }
1875
                else {
1876
        
1877
                    this._activationKeyPressed = true;
1878
                    
1879
                    this.addStateCSSClasses("active");
1880
                
1881
                }
1882
            
1883
            }
1884
        
1885
        
1886
            if (oMenu && oMenu.cfg.getProperty("visible") && 
1887
                Event.getCharCode(p_oEvent) == 27) {
1888
            
1889
                oMenu.hide();
1890
                this.focus();
1891
            
1892
            }
1893
        
1894
        },
1895
        
1896
        
1897
        /**
1898
        * @method _onKeyUp
1899
        * @description "keyup" event handler for the button.
1900
        * @protected
1901
        * @param {Event} p_oEvent Object representing the DOM event object  
1902
        * passed back by the event utility (YAHOO.util.Event).
1903
        */
1904
        _onKeyUp: function (p_oEvent) {
1905
        
1906
            var sType;
1907
        
1908
            if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
1909
        
1910
                sType = this.get("type");
1911
        
1912
                if (sType == "checkbox" || sType == "radio") {
1913
        
1914
                    this.set("checked", !(this.get("checked")));
1915
                
1916
                }
1917
        
1918
                this._activationKeyPressed = false;
1919
        
1920
                if (this.get("type") != "menu") {
1921
        
1922
                    this.removeStateCSSClasses("active");
1923
        
1924
                }
1925
        
1926
            }
1927
        
1928
        },
1929
        
1930
        
1931
        /**
1932
        * @method _onClick
1933
        * @description "click" event handler for the button.
1934
        * @protected
1935
        * @param {Event} p_oEvent Object representing the DOM event object  
1936
        * passed back by the event utility (YAHOO.util.Event).
1937
        */
1938
        _onClick: function (p_oEvent) {
1939
        
1940
            var sType = this.get("type"),
1941
                oForm,
1942
                oSrcElement,
1943
                bReturnVal;
1944
        
1945
1946
			switch (sType) {
1947
1948
			case "submit":
1949
1950
				if (p_oEvent.returnValue !== false) {
1951
1952
					this.submitForm();
1953
1954
				}
1955
1956
				break;
1957
1958
			case "reset":
1959
1960
				oForm = this.getForm();
1961
1962
				if (oForm) {
1963
1964
					oForm.reset();
1965
1966
				}
1967
1968
				break;
1969
1970
1971
			case "split":
1972
1973
				if (this._nOptionRegionX > 0 && 
1974
						(Event.getPageX(p_oEvent) > this._nOptionRegionX)) {
1975
1976
					bReturnVal = false;
1977
1978
				}
1979
				else {
1980
1981
					this._hideMenu();
1982
1983
					oSrcElement = this.get("srcelement");
1984
1985
					if (oSrcElement && oSrcElement.type == "submit" && 
1986
							p_oEvent.returnValue !== false) {
1987
1988
						this.submitForm();
1989
1990
					}
1991
1992
				}
1993
1994
				break;
1995
1996
			}
1997
1998
			return bReturnVal;
1999
        
2000
        },
2001
        
2002
        
2003
        /**
2004
        * @method _onDblClick
2005
        * @description "dblclick" event handler for the button.
2006
        * @protected
2007
        * @param {Event} p_oEvent Object representing the DOM event object  
2008
        * passed back by the event utility (YAHOO.util.Event).
2009
        */
2010
        _onDblClick: function (p_oEvent) {
2011
        
2012
            var bReturnVal = true;
2013
    
2014
			if (this.get("type") == "split" && Event.getPageX(p_oEvent) > this._nOptionRegionX) {
2015
2016
				bReturnVal = false;
2017
			
2018
			}
2019
        
2020
        	return bReturnVal;
2021
        
2022
        },        
2023
        
2024
        
2025
        /**
2026
        * @method _onAppendTo
2027
        * @description "appendTo" event handler for the button.
2028
        * @protected
2029
        * @param {Event} p_oEvent Object representing the DOM event object  
2030
        * passed back by the event utility (YAHOO.util.Event).
2031
        */
2032
        _onAppendTo: function (p_oEvent) {
2033
        
2034
            /*
2035
                It is necessary to call "_addListenersToForm" using 
2036
                "setTimeout" to make sure that the button's "form" property 
2037
                returns a node reference.  Sometimes, if you try to get the 
2038
                reference immediately after appending the field, it is null.
2039
            */
2040
        
2041
            Lang.later(0, this, this._addListenersToForm);
2042
        
2043
        },
2044
        
2045
        
2046
        /**
2047
        * @method _onFormReset
2048
        * @description "reset" event handler for the button's form.
2049
        * @protected
2050
        * @param {Event} p_oEvent Object representing the DOM event 
2051
        * object passed back by the event utility (YAHOO.util.Event).
2052
        */
2053
        _onFormReset: function (p_oEvent) {
2054
        
2055
            var sType = this.get("type"),
2056
                oMenu = this._menu;
2057
        
2058
            if (sType == "checkbox" || sType == "radio") {
2059
        
2060
                this.resetValue("checked");
2061
        
2062
            }
2063
        
2064
        
2065
            if (Menu && oMenu && (oMenu instanceof Menu)) {
2066
        
2067
                this.resetValue("selectedMenuItem");
2068
        
2069
            }
2070
        
2071
        },
2072
2073
2074
        /**
2075
        * @method _onFormSubmit
2076
        * @description "submit" event handler for the button's form.
2077
        * @protected
2078
        * @param {Event} p_oEvent Object representing the DOM event 
2079
        * object passed back by the event utility (YAHOO.util.Event).
2080
        */        
2081
        _onFormSubmit: function (p_oEvent) {
2082
        
2083
        	this.createHiddenFields();
2084
        
2085
        },
2086
        
2087
        
2088
        /**
2089
        * @method _onDocumentMouseDown
2090
        * @description "mousedown" event handler for the document.
2091
        * @protected
2092
        * @param {Event} p_oEvent Object representing the DOM event object  
2093
        * passed back by the event utility (YAHOO.util.Event).
2094
        */
2095
        _onDocumentMouseDown: function (p_oEvent) {
2096
2097
            var oTarget = Event.getTarget(p_oEvent),
2098
                oButtonElement = this.get("element"),
2099
                oMenuElement = this._menu.element;
2100
           
2101
        
2102
            if (oTarget != oButtonElement && 
2103
                !Dom.isAncestor(oButtonElement, oTarget) && 
2104
                oTarget != oMenuElement && 
2105
                !Dom.isAncestor(oMenuElement, oTarget)) {
2106
        
2107
                this._hideMenu();
2108
2109
				//	In IE when the user mouses down on a focusable element
2110
				//	that element will be focused and become the "activeElement".
2111
				//	(http://msdn.microsoft.com/en-us/library/ms533065(VS.85).aspx)
2112
				//	However, there is a bug in IE where if there is a  
2113
				//	positioned element with a focused descendant that is 
2114
				//	hidden in response to the mousedown event, the target of 
2115
				//	the mousedown event will appear to have focus, but will 
2116
				//	not be set as the activeElement.  This will result 
2117
				//	in the element not firing key events, even though it
2118
				//	appears to have focus.	The following call to "setActive"
2119
				//	fixes this bug.
2120
2121
				if (UA.ie && oTarget.focus) {
2122
					oTarget.setActive();
2123
				}
2124
        
2125
                Event.removeListener(document, "mousedown", 
2126
                    this._onDocumentMouseDown);    
2127
            
2128
            }
2129
        
2130
        },
2131
        
2132
        
2133
        /**
2134
        * @method _onOption
2135
        * @description "option" event handler for the button.
2136
        * @protected
2137
        * @param {Event} p_oEvent Object representing the DOM event object  
2138
        * passed back by the event utility (YAHOO.util.Event).
2139
        */
2140
        _onOption: function (p_oEvent) {
2141
        
2142
            if (this.hasClass(this.CLASS_NAME_PREFIX + "split-button-activeoption")) {
2143
        
2144
                this._hideMenu();
2145
        
2146
                this._bOptionPressed = false;
2147
        
2148
            }
2149
            else {
2150
        
2151
                this._showMenu(p_oEvent);    
2152
        
2153
                this._bOptionPressed = true;
2154
        
2155
            }
2156
        
2157
        },
2158
        
2159
        
2160
        /**
2161
        * @method _onMenuShow
2162
        * @description "show" event handler for the button's menu.
2163
        * @private
2164
        * @param {String} p_sType String representing the name of the event  
2165
        * that was fired.
2166
        */
2167
        _onMenuShow: function (p_sType) {
2168
        
2169
            Event.on(document, "mousedown", this._onDocumentMouseDown, 
2170
                null, this);
2171
        
2172
            var sState = (this.get("type") == "split") ? "activeoption" : "active";
2173
        
2174
            this.addStateCSSClasses(sState);
2175
        
2176
        },
2177
        
2178
        
2179
        /**
2180
        * @method _onMenuHide
2181
        * @description "hide" event handler for the button's menu.
2182
        * @private
2183
        * @param {String} p_sType String representing the name of the event  
2184
        * that was fired.
2185
        */
2186
        _onMenuHide: function (p_sType) {
2187
            
2188
            var sState = (this.get("type") == "split") ? "activeoption" : "active";
2189
        
2190
            this.removeStateCSSClasses(sState);
2191
        
2192
        
2193
            if (this.get("type") == "split") {
2194
        
2195
                this._bOptionPressed = false;
2196
            
2197
            }
2198
        
2199
        },
2200
        
2201
        
2202
        /**
2203
        * @method _onMenuKeyDown
2204
        * @description "keydown" event handler for the button's menu.
2205
        * @private
2206
        * @param {String} p_sType String representing the name of the event  
2207
        * that was fired.
2208
        * @param {Array} p_aArgs Array of arguments sent when the event 
2209
        * was fired.
2210
        */
2211
        _onMenuKeyDown: function (p_sType, p_aArgs) {
2212
        
2213
            var oEvent = p_aArgs[0];
2214
        
2215
            if (Event.getCharCode(oEvent) == 27) {
2216
        
2217
                this.focus();
2218
        
2219
                if (this.get("type") == "split") {
2220
                
2221
                    this._bOptionPressed = false;
2222
                
2223
                }
2224
        
2225
            }
2226
        
2227
        },
2228
        
2229
        
2230
        /**
2231
        * @method _onMenuRender
2232
        * @description "render" event handler for the button's menu.
2233
        * @private
2234
        * @param {String} p_sType String representing the name of the  
2235
        * event thatwas fired.
2236
        */
2237
        _onMenuRender: function (p_sType) {
2238
        
2239
            var oButtonElement = this.get("element"),
2240
                oButtonParent = oButtonElement.parentNode,
2241
				oMenu = this._menu,
2242
                oMenuElement = oMenu.element,
2243
				oSrcElement = oMenu.srcElement,
2244
				oItem;
2245
        
2246
        
2247
            if (oButtonParent != oMenuElement.parentNode) {
2248
        
2249
                oButtonParent.appendChild(oMenuElement);
2250
            
2251
            }
2252
2253
			this._renderedMenu = true;
2254
2255
			//	If the user has designated an <option> of the Menu's source 
2256
			//	<select> element to be selected, sync the selectedIndex with 
2257
			//	the "selectedMenuItem" Attribute.
2258
2259
			if (oSrcElement && 
2260
					oSrcElement.nodeName.toLowerCase() === "select" && 
2261
					oSrcElement.value) {
2262
				
2263
				
2264
				oItem = oMenu.getItem(oSrcElement.selectedIndex);
2265
				
2266
				//	Set the value of the "selectedMenuItem" attribute
2267
				//	silently since this is the initial set--synchronizing 
2268
				//	the value of the source <SELECT> element in the DOM with 
2269
				//	its corresponding Menu instance.
2270
2271
				this.set("selectedMenuItem", oItem, true);
2272
				
2273
				//	Call the "_onSelectedMenuItemChange" method since the 
2274
				//	attribute was set silently.
2275
2276
				this._onSelectedMenuItemChange({ newValue: oItem });
2277
				
2278
			}
2279
2280
        },
2281
2282
        
2283
        
2284
        /**
2285
        * @method _onMenuClick
2286
        * @description "click" event handler for the button's menu.
2287
        * @private
2288
        * @param {String} p_sType String representing the name of the event  
2289
        * that was fired.
2290
        * @param {Array} p_aArgs Array of arguments sent when the event 
2291
        * was fired.
2292
        */
2293
        _onMenuClick: function (p_sType, p_aArgs) {
2294
2295
            var oItem = p_aArgs[1],
2296
                oSrcElement;
2297
        
2298
            if (oItem) {
2299
        
2300
				this.set("selectedMenuItem", oItem);
2301
2302
                oSrcElement = this.get("srcelement");
2303
            
2304
                if (oSrcElement && oSrcElement.type == "submit") {
2305
        
2306
                    this.submitForm();
2307
            
2308
                }
2309
            
2310
                this._hideMenu();
2311
            
2312
            }
2313
        
2314
        },
2315
2316
2317
        /**
2318
        * @method _onSelectedMenuItemChange
2319
        * @description "selectedMenuItemChange" event handler for the Button's
2320
		* "selectedMenuItem" attribute.
2321
        * @param {Event} event Object representing the DOM event object  
2322
        * passed back by the event utility (YAHOO.util.Event).
2323
        */
2324
		_onSelectedMenuItemChange: function (event) {
2325
		
2326
			var oSelected = event.prevValue,
2327
				oItem = event.newValue,
2328
				sPrefix = this.CLASS_NAME_PREFIX;
2329
2330
			if (oSelected) {
2331
				Dom.removeClass(oSelected.element, (sPrefix + "button-selectedmenuitem"));
2332
			}
2333
			
2334
			if (oItem) {
2335
				Dom.addClass(oItem.element, (sPrefix + "button-selectedmenuitem"));
2336
			}
2337
			
2338
		},        
2339
        
2340
2341
        /**
2342
        * @method _onLabelClick
2343
        * @description "click" event handler for the Button's
2344
		* <code>&#60;label&#62;</code> element.
2345
        * @param {Event} event Object representing the DOM event object  
2346
        * passed back by the event utility (YAHOO.util.Event).
2347
        */
2348
		_onLabelClick: function (event) {
2349
2350
			this.focus();
2351
2352
			var sType = this.get("type");
2353
2354
			if (sType == "radio" || sType == "checkbox") {
2355
				this.set("checked", (!this.get("checked")));						
2356
			}
2357
			
2358
		},
2359
2360
        
2361
        // Public methods
2362
        
2363
        
2364
        /**
2365
        * @method createButtonElement
2366
        * @description Creates the button's HTML elements.
2367
        * @param {String} p_sType String indicating the type of element 
2368
        * to create.
2369
        * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
2370
        * level-one-html.html#ID-58190037">HTMLElement</a>}
2371
        */
2372
        createButtonElement: function (p_sType) {
2373
        
2374
            var sNodeName = this.NODE_NAME,
2375
                oElement = document.createElement(sNodeName);
2376
        
2377
            oElement.innerHTML =  "<" + sNodeName + " class=\"first-child\">" + 
2378
                (p_sType == "link" ? "<a></a>" : 
2379
                "<button type=\"button\"></button>") + "</" + sNodeName + ">";
2380
        
2381
            return oElement;
2382
        
2383
        },
2384
2385
        
2386
        /**
2387
        * @method addStateCSSClasses
2388
        * @description Appends state-specific CSS classes to the button's root 
2389
        * DOM element.
2390
        */
2391
        addStateCSSClasses: function (p_sState) {
2392
        
2393
            var sType = this.get("type"),
2394
				sPrefix = this.CLASS_NAME_PREFIX;
2395
        
2396
            if (Lang.isString(p_sState)) {
2397
        
2398
                if (p_sState != "activeoption" && p_sState != "hoveroption") {
2399
        
2400
                    this.addClass(sPrefix + this.CSS_CLASS_NAME + ("-" + p_sState));
2401
        
2402
                }
2403
        
2404
                this.addClass(sPrefix + sType + ("-button-" + p_sState));
2405
            
2406
            }
2407
        
2408
        },
2409
        
2410
        
2411
        /**
2412
        * @method removeStateCSSClasses
2413
        * @description Removes state-specific CSS classes to the button's root 
2414
        * DOM element.
2415
        */
2416
        removeStateCSSClasses: function (p_sState) {
2417
        
2418
            var sType = this.get("type"),
2419
				sPrefix = this.CLASS_NAME_PREFIX;
2420
        
2421
            if (Lang.isString(p_sState)) {
2422
        
2423
                this.removeClass(sPrefix + this.CSS_CLASS_NAME + ("-" + p_sState));
2424
                this.removeClass(sPrefix + sType + ("-button-" + p_sState));
2425
            
2426
            }
2427
        
2428
        },
2429
        
2430
        
2431
        /**
2432
        * @method createHiddenFields
2433
        * @description Creates the button's hidden form field and appends it 
2434
        * to its parent form.
2435
        * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
2436
        * level-one-html.html#ID-6043025">HTMLInputElement</a>|Array}
2437
        */
2438
        createHiddenFields: function () {
2439
        
2440
            this.removeHiddenFields();
2441
        
2442
            var oForm = this.getForm(),
2443
                oButtonField,
2444
                sType,
2445
                bCheckable,
2446
                oMenu,
2447
                oMenuItem,
2448
                sButtonName,
2449
                oValue,
2450
                oMenuField,
2451
                oReturnVal,
2452
				sMenuFieldName,
2453
				oMenuSrcElement,
2454
				bMenuSrcElementIsSelect = false;
2455
        
2456
        
2457
            if (oForm && !this.get("disabled")) {
2458
        
2459
                sType = this.get("type");
2460
                bCheckable = (sType == "checkbox" || sType == "radio");
2461
        
2462
        
2463
                if ((bCheckable && this.get("checked")) || (m_oSubmitTrigger == this)) {
2464
                
2465
        
2466
                    oButtonField = createInputElement((bCheckable ? sType : "hidden"),
2467
                                    this.get("name"), this.get("value"), this.get("checked"));
2468
            
2469
            
2470
                    if (oButtonField) {
2471
            
2472
                        if (bCheckable) {
2473
            
2474
                            oButtonField.style.display = "none";
2475
            
2476
                        }
2477
            
2478
                        oForm.appendChild(oButtonField);
2479
            
2480
                    }
2481
        
2482
                }
2483
                    
2484
        
2485
                oMenu = this._menu;
2486
            
2487
            
2488
                if (Menu && oMenu && (oMenu instanceof Menu)) {
2489
        
2490
        
2491
                    oMenuItem = this.get("selectedMenuItem");
2492
					oMenuSrcElement = oMenu.srcElement;
2493
					bMenuSrcElementIsSelect = (oMenuSrcElement && 
2494
												oMenuSrcElement.nodeName.toUpperCase() == "SELECT");
2495
2496
                    if (oMenuItem) {
2497
2498
						oValue = (oMenuItem.value === null || oMenuItem.value === "") ? 
2499
									oMenuItem.cfg.getProperty("text") : oMenuItem.value;
2500
2501
						sButtonName = this.get("name");
2502
2503
2504
						if (bMenuSrcElementIsSelect) {
2505
						
2506
							sMenuFieldName = oMenuSrcElement.name;
2507
						
2508
						}
2509
						else if (sButtonName) {
2510
2511
							sMenuFieldName = (sButtonName + "_options");
2512
						
2513
						}
2514
						
2515
2516
						if (oValue && sMenuFieldName) {
2517
		
2518
							oMenuField = createInputElement("hidden", sMenuFieldName, oValue);
2519
							oForm.appendChild(oMenuField);
2520
		
2521
						}
2522
                    
2523
                    }
2524
                    else if (bMenuSrcElementIsSelect) {
2525
					
2526
						oMenuField = oForm.appendChild(oMenuSrcElement);
2527
                    
2528
                    }
2529
        
2530
                }
2531
            
2532
            
2533
                if (oButtonField && oMenuField) {
2534
        
2535
                    this._hiddenFields = [oButtonField, oMenuField];
2536
        
2537
                }
2538
                else if (!oButtonField && oMenuField) {
2539
        
2540
                    this._hiddenFields = oMenuField;
2541
                
2542
                }
2543
                else if (oButtonField && !oMenuField) {
2544
        
2545
                    this._hiddenFields = oButtonField;
2546
                
2547
                }
2548
        
2549
        		oReturnVal = this._hiddenFields;
2550
        
2551
            }
2552
2553
			return oReturnVal;
2554
        
2555
        },
2556
        
2557
        
2558
        /**
2559
        * @method removeHiddenFields
2560
        * @description Removes the button's hidden form field(s) from its 
2561
        * parent form.
2562
        */
2563
        removeHiddenFields: function () {
2564
        
2565
            var oField = this._hiddenFields,
2566
                nFields,
2567
                i;
2568
        
2569
            function removeChild(p_oElement) {
2570
        
2571
                if (Dom.inDocument(p_oElement)) {
2572
        
2573
                    p_oElement.parentNode.removeChild(p_oElement);
2574
2575
                }
2576
                
2577
            }
2578
            
2579
        
2580
            if (oField) {
2581
        
2582
                if (Lang.isArray(oField)) {
2583
        
2584
                    nFields = oField.length;
2585
                    
2586
                    if (nFields > 0) {
2587
                    
2588
                        i = nFields - 1;
2589
                        
2590
                        do {
2591
        
2592
                            removeChild(oField[i]);
2593
        
2594
                        }
2595
                        while (i--);
2596
                    
2597
                    }
2598
                
2599
                }
2600
                else {
2601
        
2602
                    removeChild(oField);
2603
        
2604
                }
2605
        
2606
                this._hiddenFields = null;
2607
            
2608
            }
2609
        
2610
        },
2611
        
2612
        
2613
        /**
2614
        * @method submitForm
2615
        * @description Submits the form to which the button belongs.  Returns  
2616
        * true if the form was submitted successfully, false if the submission 
2617
        * was cancelled.
2618
        * @protected
2619
        * @return {Boolean}
2620
        */
2621
        submitForm: function () {
2622
        
2623
            var oForm = this.getForm(),
2624
        
2625
                oSrcElement = this.get("srcelement"),
2626
        
2627
                /*
2628
                    Boolean indicating if the event fired successfully 
2629
                    (was not cancelled by any handlers)
2630
                */
2631
        
2632
                bSubmitForm = false,
2633
                
2634
                oEvent;
2635
        
2636
        
2637
            if (oForm) {
2638
        
2639
                if (this.get("type") == "submit" || (oSrcElement && oSrcElement.type == "submit")) {
2640
        
2641
                    m_oSubmitTrigger = this;
2642
                    
2643
                }
2644
        
2645
        
2646
                if (UA.ie) {
2647
        
2648
                    bSubmitForm = oForm.fireEvent("onsubmit");
2649
        
2650
                }
2651
                else {  // Gecko, Opera, and Safari
2652
        
2653
                    oEvent = document.createEvent("HTMLEvents");
2654
                    oEvent.initEvent("submit", true, true);
2655
        
2656
                    bSubmitForm = oForm.dispatchEvent(oEvent);
2657
        
2658
                }
2659
        
2660
        
2661
                /*
2662
                    In IE and Safari, dispatching a "submit" event to a form 
2663
                    WILL cause the form's "submit" event to fire, but WILL NOT 
2664
                    submit the form.  Therefore, we need to call the "submit" 
2665
                    method as well.
2666
                */
2667
              
2668
                if ((UA.ie || UA.webkit) && bSubmitForm) {
2669
        
2670
                    oForm.submit();
2671
                
2672
                }
2673
            
2674
            }
2675
        
2676
            return bSubmitForm;
2677
            
2678
        },
2679
        
2680
        
2681
        /**
2682
        * @method init
2683
        * @description The Button class's initialization method.
2684
        * @param {String} p_oElement String specifying the id attribute of the 
2685
        * <code>&#60;input&#62;</code>, <code>&#60;button&#62;</code>,
2686
        * <code>&#60;a&#62;</code>, or <code>&#60;span&#62;</code> element to 
2687
        * be used to create the button.
2688
        * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
2689
        * level-one-html.html#ID-6043025">HTMLInputElement</a>|<a href="http://
2690
        * www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html
2691
        * #ID-34812697">HTMLButtonElement</a>|<a href="http://www.w3.org/TR
2692
        * /2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-33759296">
2693
        * HTMLElement</a>} p_oElement Object reference for the 
2694
        * <code>&#60;input&#62;</code>, <code>&#60;button&#62;</code>, 
2695
        * <code>&#60;a&#62;</code>, or <code>&#60;span&#62;</code> element to be 
2696
        * used to create the button.
2697
        * @param {Object} p_oElement Object literal specifying a set of 
2698
        * configuration attributes used to create the button.
2699
        * @param {Object} p_oAttributes Optional. Object literal specifying a 
2700
        * set of configuration attributes used to create the button.
2701
        */
2702
        init: function (p_oElement, p_oAttributes) {
2703
        
2704
            var sNodeName = p_oAttributes.type == "link" ? "a" : "button",
2705
                oSrcElement = p_oAttributes.srcelement,
2706
                oButton = p_oElement.getElementsByTagName(sNodeName)[0],
2707
                oInput;
2708
2709
2710
            if (!oButton) {
2711
2712
                oInput = p_oElement.getElementsByTagName("input")[0];
2713
2714
2715
                if (oInput) {
2716
2717
                    oButton = document.createElement("button");
2718
                    oButton.setAttribute("type", "button");
2719
2720
                    oInput.parentNode.replaceChild(oButton, oInput);
2721
                
2722
                }
2723
2724
            }
2725
2726
            this._button = oButton;
2727
2728
2729
            YAHOO.widget.Button.superclass.init.call(this, p_oElement, p_oAttributes);
2730
2731
2732
			var sId = this.get("id"),
2733
				sButtonId = sId + "-button";
2734
2735
2736
        	oButton.id = sButtonId;
2737
2738
2739
			var aLabels,
2740
				oLabel;
2741
2742
2743
        	var hasLabel = function (element) {
2744
        	
2745
				return (element.htmlFor === sId);
2746
2747
        	};
2748
2749
2750
			var setLabel = function () {
2751
2752
				oLabel.setAttribute((UA.ie ? "htmlFor" : "for"), sButtonId);
2753
			
2754
			};
2755
2756
2757
			if (oSrcElement && this.get("type") != "link") {
2758
2759
				aLabels = Dom.getElementsBy(hasLabel, "label");
2760
2761
				if (Lang.isArray(aLabels) && aLabels.length > 0) {
2762
				
2763
					oLabel = aLabels[0];
2764
				
2765
				}
2766
2767
			}
2768
        
2769
2770
            m_oButtons[sId] = this;
2771
2772
        	var sPrefix = this.CLASS_NAME_PREFIX;
2773
2774
            this.addClass(sPrefix + this.CSS_CLASS_NAME);
2775
            this.addClass(sPrefix + this.get("type") + "-button");
2776
        
2777
            Event.on(this._button, "focus", this._onFocus, null, this);
2778
            this.on("mouseover", this._onMouseOver);
2779
			this.on("mousedown", this._onMouseDown);
2780
			this.on("mouseup", this._onMouseUp);
2781
            this.on("click", this._onClick);
2782
2783
			//	Need to reset the value of the "onclick" Attribute so that any
2784
			//	handlers registered via the "onclick" Attribute are fired after 
2785
			//	Button's default "_onClick" listener.
2786
2787
			var fnOnClick = this.get("onclick");
2788
2789
			this.set("onclick", null);
2790
			this.set("onclick", fnOnClick);
2791
2792
            this.on("dblclick", this._onDblClick);
2793
2794
2795
			var oParentNode;
2796
2797
            if (oLabel) {
2798
            
2799
				if (this.get("replaceLabel")) {
2800
2801
					this.set("label", oLabel.innerHTML);
2802
					
2803
					oParentNode = oLabel.parentNode;
2804
					
2805
					oParentNode.removeChild(oLabel);
2806
					
2807
				}
2808
				else {
2809
2810
					this.on("appendTo", setLabel); 
2811
2812
					Event.on(oLabel, "click", this._onLabelClick, null, this);
2813
2814
					this._label = oLabel;
2815
					
2816
				}
2817
            
2818
            }
2819
            
2820
            this.on("appendTo", this._onAppendTo);
2821
       
2822
        
2823
2824
            var oContainer = this.get("container"),
2825
                oElement = this.get("element"),
2826
                bElInDoc = Dom.inDocument(oElement);
2827
2828
2829
            if (oContainer) {
2830
        
2831
                if (oSrcElement && oSrcElement != oElement) {
2832
                
2833
                    oParentNode = oSrcElement.parentNode;
2834
2835
                    if (oParentNode) {
2836
                    
2837
                        oParentNode.removeChild(oSrcElement);
2838
                    
2839
                    }
2840
2841
                }
2842
        
2843
                if (Lang.isString(oContainer)) {
2844
        
2845
                    Event.onContentReady(oContainer, this.appendTo, oContainer, this);
2846
        
2847
                }
2848
                else {
2849
        
2850
        			this.on("init", function () {
2851
        			
2852
        				Lang.later(0, this, this.appendTo, oContainer);
2853
        			
2854
        			});
2855
        
2856
                }
2857
        
2858
            }
2859
            else if (!bElInDoc && oSrcElement && oSrcElement != oElement) {
2860
2861
                oParentNode = oSrcElement.parentNode;
2862
        
2863
                if (oParentNode) {
2864
        
2865
                    this.fireEvent("beforeAppendTo", {
2866
                        type: "beforeAppendTo",
2867
                        target: oParentNode
2868
                    });
2869
            
2870
                    oParentNode.replaceChild(oElement, oSrcElement);
2871
            
2872
                    this.fireEvent("appendTo", {
2873
                        type: "appendTo",
2874
                        target: oParentNode
2875
                    });
2876
                
2877
                }
2878
        
2879
            }
2880
            else if (this.get("type") != "link" && bElInDoc && oSrcElement && 
2881
                oSrcElement == oElement) {
2882
        
2883
                this._addListenersToForm();
2884
        
2885
            }
2886
        
2887
        
2888
2889
			this.fireEvent("init", {
2890
				type: "init",
2891
				target: this
2892
			});        
2893
        
2894
        },
2895
        
2896
        
2897
        /**
2898
        * @method initAttributes
2899
        * @description Initializes all of the configuration attributes used to  
2900
        * create the button.
2901
        * @param {Object} p_oAttributes Object literal specifying a set of 
2902
        * configuration attributes used to create the button.
2903
        */
2904
        initAttributes: function (p_oAttributes) {
2905
        
2906
            var oAttributes = p_oAttributes || {};
2907
        
2908
            YAHOO.widget.Button.superclass.initAttributes.call(this, 
2909
                oAttributes);
2910
        
2911
        
2912
            /**
2913
            * @attribute type
2914
            * @description String specifying the button's type.  Possible 
2915
            * values are: "push," "link," "submit," "reset," "checkbox," 
2916
            * "radio," "menu," and "split."
2917
            * @default "push"
2918
            * @type String
2919
			* @writeonce
2920
            */
2921
            this.setAttributeConfig("type", {
2922
        
2923
                value: (oAttributes.type || "push"),
2924
                validator: Lang.isString,
2925
                writeOnce: true,
2926
                method: this._setType
2927
2928
            });
2929
        
2930
        
2931
            /**
2932
            * @attribute label
2933
            * @description String specifying the button's text label 
2934
            * or innerHTML.
2935
            * @default null
2936
            * @type String
2937
            */
2938
            this.setAttributeConfig("label", {
2939
        
2940
                value: oAttributes.label,
2941
                validator: Lang.isString,
2942
                method: this._setLabel
2943
        
2944
            });
2945
        
2946
        
2947
            /**
2948
            * @attribute value
2949
            * @description Object specifying the value for the button.
2950
            * @default null
2951
            * @type Object
2952
            */
2953
            this.setAttributeConfig("value", {
2954
        
2955
                value: oAttributes.value
2956
        
2957
            });
2958
        
2959
        
2960
            /**
2961
            * @attribute name
2962
            * @description String specifying the name for the button.
2963
            * @default null
2964
            * @type String
2965
            */
2966
            this.setAttributeConfig("name", {
2967
        
2968
                value: oAttributes.name,
2969
                validator: Lang.isString
2970
        
2971
            });
2972
        
2973
        
2974
            /**
2975
            * @attribute tabindex
2976
            * @description Number specifying the tabindex for the button.
2977
            * @default null
2978
            * @type Number
2979
            */
2980
            this.setAttributeConfig("tabindex", {
2981
        
2982
                value: oAttributes.tabindex,
2983
                validator: Lang.isNumber,
2984
                method: this._setTabIndex
2985
        
2986
            });
2987
        
2988
        
2989
            /**
2990
            * @attribute title
2991
            * @description String specifying the title for the button.
2992
            * @default null
2993
            * @type String
2994
            */
2995
            this.configureAttribute("title", {
2996
        
2997
                value: oAttributes.title,
2998
                validator: Lang.isString,
2999
                method: this._setTitle
3000
        
3001
            });
3002
        
3003
        
3004
            /**
3005
            * @attribute disabled
3006
            * @description Boolean indicating if the button should be disabled.  
3007
            * (Disabled buttons are dimmed and will not respond to user input 
3008
            * or fire events.  Does not apply to button's of type "link.")
3009
            * @default false
3010
            * @type Boolean
3011
            */
3012
            this.setAttributeConfig("disabled", {
3013
        
3014
                value: (oAttributes.disabled || false),
3015
                validator: Lang.isBoolean,
3016
                method: this._setDisabled
3017
        
3018
            });
3019
        
3020
        
3021
            /**
3022
            * @attribute href
3023
            * @description String specifying the href for the button.  Applies
3024
            * only to buttons of type "link."
3025
            * @type String
3026
            */
3027
            this.setAttributeConfig("href", {
3028
        
3029
                value: oAttributes.href,
3030
                validator: Lang.isString,
3031
                method: this._setHref
3032
        
3033
            });
3034
        
3035
        
3036
            /**
3037
            * @attribute target
3038
            * @description String specifying the target for the button.  
3039
            * Applies only to buttons of type "link."
3040
            * @type String
3041
            */
3042
            this.setAttributeConfig("target", {
3043
        
3044
                value: oAttributes.target,
3045
                validator: Lang.isString,
3046
                method: this._setTarget
3047
        
3048
            });
3049
        
3050
        
3051
            /**
3052
            * @attribute checked
3053
            * @description Boolean indicating if the button is checked. 
3054
            * Applies only to buttons of type "radio" and "checkbox."
3055
            * @default false
3056
            * @type Boolean
3057
            */
3058
            this.setAttributeConfig("checked", {
3059
        
3060
                value: (oAttributes.checked || false),
3061
                validator: Lang.isBoolean,
3062
                method: this._setChecked
3063
        
3064
            });
3065
        
3066
        
3067
            /**
3068
            * @attribute container
3069
            * @description HTML element reference or string specifying the id 
3070
            * attribute of the HTML element that the button's markup should be 
3071
            * rendered into.
3072
            * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3073
            * level-one-html.html#ID-58190037">HTMLElement</a>|String
3074
            * @default null
3075
			* @writeonce
3076
            */
3077
            this.setAttributeConfig("container", {
3078
        
3079
                value: oAttributes.container,
3080
                writeOnce: true
3081
        
3082
            });
3083
        
3084
        
3085
            /**
3086
            * @attribute srcelement
3087
            * @description Object reference to the HTML element (either 
3088
            * <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code>) 
3089
            * used to create the button.
3090
            * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3091
            * level-one-html.html#ID-58190037">HTMLElement</a>|String
3092
            * @default null
3093
			* @writeonce
3094
            */
3095
            this.setAttributeConfig("srcelement", {
3096
        
3097
                value: oAttributes.srcelement,
3098
                writeOnce: true
3099
        
3100
            });
3101
        
3102
        
3103
            /**
3104
            * @attribute menu
3105
            * @description Object specifying the menu for the button.  
3106
            * The value can be one of the following:
3107
            * <ul>
3108
            * <li>Object specifying a rendered <a href="YAHOO.widget.Menu.html">
3109
            * YAHOO.widget.Menu</a> instance.</li>
3110
            * <li>Object specifying a rendered <a href="YAHOO.widget.Overlay.html">
3111
            * YAHOO.widget.Overlay</a> instance.</li>
3112
            * <li>String specifying the id attribute of the <code>&#60;div&#62;
3113
            * </code> element used to create the menu.  By default the menu 
3114
            * will be created as an instance of 
3115
            * <a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>.  
3116
            * If the <a href="YAHOO.widget.Menu.html#CSS_CLASS_NAME">
3117
            * default CSS class name for YAHOO.widget.Menu</a> is applied to 
3118
            * the <code>&#60;div&#62;</code> element, it will be created as an
3119
            * instance of <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu
3120
            * </a>.</li><li>String specifying the id attribute of the 
3121
            * <code>&#60;select&#62;</code> element used to create the menu.
3122
            * </li><li>Object specifying the <code>&#60;div&#62;</code> element
3123
            * used to create the menu.</li>
3124
            * <li>Object specifying the <code>&#60;select&#62;</code> element
3125
            * used to create the menu.</li>
3126
            * <li>Array of object literals, each representing a set of 
3127
            * <a href="YAHOO.widget.MenuItem.html">YAHOO.widget.MenuItem</a> 
3128
            * configuration attributes.</li>
3129
            * <li>Array of strings representing the text labels for each menu 
3130
            * item in the menu.</li>
3131
            * </ul>
3132
            * @type <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a>|<a 
3133
            * href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a>|<a 
3134
            * href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
3135
            * one-html.html#ID-58190037">HTMLElement</a>|String|Array
3136
            * @default null
3137
			* @writeonce
3138
            */
3139
            this.setAttributeConfig("menu", {
3140
        
3141
                value: null,
3142
                method: this._setMenu,
3143
                writeOnce: true
3144
            
3145
            });
3146
        
3147
        
3148
            /**
3149
            * @attribute lazyloadmenu
3150
            * @description Boolean indicating the value to set for the 
3151
            * <a href="YAHOO.widget.Menu.html#lazyLoad">"lazyload"</a>
3152
            * configuration property of the button's menu.  Setting 
3153
            * "lazyloadmenu" to <code>true </code> will defer rendering of 
3154
            * the button's menu until the first time it is made visible.  
3155
            * If "lazyloadmenu" is set to <code>false</code>, the button's 
3156
            * menu will be rendered immediately if the button is in the 
3157
            * document, or in response to the button's "appendTo" event if 
3158
            * the button is not yet in the document.  In either case, the 
3159
            * menu is rendered into the button's parent HTML element.  
3160
            * <em>This attribute does not apply if a 
3161
            * <a href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a> or 
3162
            * <a href="YAHOO.widget.Overlay.html">YAHOO.widget.Overlay</a> 
3163
            * instance is passed as the value of the button's "menu" 
3164
            * configuration attribute. <a href="YAHOO.widget.Menu.html">
3165
            * YAHOO.widget.Menu</a> or <a href="YAHOO.widget.Overlay.html">
3166
            * YAHOO.widget.Overlay</a> instances should be rendered before 
3167
            * being set as the value for the "menu" configuration 
3168
            * attribute.</em>
3169
            * @default true
3170
            * @type Boolean
3171
			* @writeonce
3172
            */
3173
            this.setAttributeConfig("lazyloadmenu", {
3174
        
3175
                value: (oAttributes.lazyloadmenu === false ? false : true),
3176
                validator: Lang.isBoolean,
3177
                writeOnce: true
3178
        
3179
            });
3180
3181
3182
            /**
3183
            * @attribute menuclassname
3184
            * @description String representing the CSS class name to be 
3185
            * applied to the root element of the button's menu.
3186
            * @type String
3187
            * @default "yui-button-menu"
3188
			* @writeonce
3189
            */
3190
            this.setAttributeConfig("menuclassname", {
3191
        
3192
                value: (oAttributes.menuclassname || (this.CLASS_NAME_PREFIX + "button-menu")),
3193
                validator: Lang.isString,
3194
                method: this._setMenuClassName,
3195
                writeOnce: true
3196
        
3197
            });        
3198
3199
3200
			/**
3201
			* @attribute menuminscrollheight
3202
			* @description Number defining the minimum threshold for the "menumaxheight" 
3203
			* configuration attribute.  When set this attribute is automatically applied 
3204
			* to all submenus.
3205
			* @default 90
3206
			* @type Number
3207
			*/
3208
            this.setAttributeConfig("menuminscrollheight", {
3209
        
3210
                value: (oAttributes.menuminscrollheight || 90),
3211
                validator: Lang.isNumber
3212
        
3213
            });
3214
3215
3216
            /**
3217
            * @attribute menumaxheight
3218
			* @description Number defining the maximum height (in pixels) for a menu's 
3219
			* body element (<code>&#60;div class="bd"&#60;</code>).  Once a menu's body 
3220
			* exceeds this height, the contents of the body are scrolled to maintain 
3221
			* this value.  This value cannot be set lower than the value of the 
3222
			* "minscrollheight" configuration property.
3223
            * @type Number
3224
            * @default 0
3225
            */
3226
            this.setAttributeConfig("menumaxheight", {
3227
        
3228
                value: (oAttributes.menumaxheight || 0),
3229
                validator: Lang.isNumber
3230
        
3231
            });
3232
3233
3234
            /**
3235
            * @attribute menualignment
3236
			* @description Array defining how the Button's Menu is aligned to the Button.  
3237
            * The default value of ["tl", "bl"] aligns the Menu's top left corner to the Button's 
3238
            * bottom left corner.
3239
            * @type Array
3240
            * @default ["tl", "bl"]
3241
            */
3242
            this.setAttributeConfig("menualignment", {
3243
        
3244
                value: (oAttributes.menualignment || ["tl", "bl"]),
3245
                validator: Lang.isArray
3246
        
3247
            });
3248
            
3249
3250
            /**
3251
            * @attribute selectedMenuItem
3252
            * @description Object representing the item in the button's menu 
3253
            * that is currently selected.
3254
            * @type YAHOO.widget.MenuItem
3255
            * @default null
3256
            */
3257
            this.setAttributeConfig("selectedMenuItem", {
3258
        
3259
                value: null
3260
        
3261
            });
3262
        
3263
        
3264
            /**
3265
            * @attribute onclick
3266
            * @description Object literal representing the code to be executed  
3267
            * when the button is clicked.  Format:<br> <code> {<br> 
3268
            * <strong>fn:</strong> Function,   &#47;&#47; The handler to call 
3269
            * when the event fires.<br> <strong>obj:</strong> Object, 
3270
            * &#47;&#47; An object to pass back to the handler.<br> 
3271
            * <strong>scope:</strong> Object &#47;&#47;  The object to use 
3272
            * for the scope of the handler.<br> } </code>
3273
            * @type Object
3274
            * @default null
3275
            */
3276
            this.setAttributeConfig("onclick", {
3277
        
3278
                value: oAttributes.onclick,
3279
                method: this._setOnClick
3280
            
3281
            });
3282
3283
3284
            /**
3285
            * @attribute focusmenu
3286
            * @description Boolean indicating whether or not the button's menu 
3287
            * should be focused when it is made visible.
3288
            * @type Boolean
3289
            * @default true
3290
            */
3291
            this.setAttributeConfig("focusmenu", {
3292
        
3293
                value: (oAttributes.focusmenu === false ? false : true),
3294
                validator: Lang.isBoolean
3295
        
3296
            });
3297
3298
3299
            /**
3300
            * @attribute replaceLabel
3301
            * @description Boolean indicating whether or not the text of the 
3302
			* button's <code>&#60;label&#62;</code> element should be used as
3303
			* the source for the button's label configuration attribute and 
3304
			* removed from the DOM.
3305
            * @type Boolean
3306
            * @default false
3307
            */
3308
            this.setAttributeConfig("replaceLabel", {
3309
        
3310
                value: false,
3311
                validator: Lang.isBoolean,
3312
                writeOnce: true
3313
        
3314
            });
3315
3316
        },
3317
        
3318
        
3319
        /**
3320
        * @method focus
3321
        * @description Causes the button to receive the focus and fires the 
3322
        * button's "focus" event.
3323
        */
3324
        focus: function () {
3325
        
3326
            if (!this.get("disabled")) {
3327
        
3328
                this._button.focus();
3329
            
3330
            }
3331
        
3332
        },
3333
        
3334
        
3335
        /**
3336
        * @method blur
3337
        * @description Causes the button to lose focus and fires the button's
3338
        * "blur" event.
3339
        */
3340
        blur: function () {
3341
        
3342
            if (!this.get("disabled")) {
3343
        
3344
                this._button.blur();
3345
        
3346
            }
3347
        
3348
        },
3349
        
3350
        
3351
        /**
3352
        * @method hasFocus
3353
        * @description Returns a boolean indicating whether or not the button 
3354
        * has focus.
3355
        * @return {Boolean}
3356
        */
3357
        hasFocus: function () {
3358
        
3359
            return (m_oFocusedButton == this);
3360
        
3361
        },
3362
        
3363
        
3364
        /**
3365
        * @method isActive
3366
        * @description Returns a boolean indicating whether or not the button 
3367
        * is active.
3368
        * @return {Boolean}
3369
        */
3370
        isActive: function () {
3371
        
3372
            return this.hasClass(this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME + "-active");
3373
        
3374
        },
3375
        
3376
        
3377
        /**
3378
        * @method getMenu
3379
        * @description Returns a reference to the button's menu.
3380
        * @return {<a href="YAHOO.widget.Overlay.html">
3381
        * YAHOO.widget.Overlay</a>|<a 
3382
        * href="YAHOO.widget.Menu.html">YAHOO.widget.Menu</a>}
3383
        */
3384
        getMenu: function () {
3385
        
3386
            return this._menu;
3387
        
3388
        },
3389
        
3390
        
3391
        /**
3392
        * @method getForm
3393
        * @description Returns a reference to the button's parent form.
3394
        * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-
3395
        * 20000929/level-one-html.html#ID-40002357">HTMLFormElement</a>}
3396
        */
3397
        getForm: function () {
3398
        
3399
        	var oButton = this._button,
3400
        		oForm;
3401
        
3402
            if (oButton) {
3403
            
3404
            	oForm = oButton.form;
3405
            
3406
            }
3407
        
3408
        	return oForm;
3409
        
3410
        },
3411
        
3412
        
3413
        /** 
3414
        * @method getHiddenFields
3415
        * @description Returns an <code>&#60;input&#62;</code> element or 
3416
        * array of form elements used to represent the button when its parent 
3417
        * form is submitted.  
3418
        * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3419
        * level-one-html.html#ID-6043025">HTMLInputElement</a>|Array}
3420
        */
3421
        getHiddenFields: function () {
3422
        
3423
            return this._hiddenFields;
3424
        
3425
        },
3426
        
3427
        
3428
        /**
3429
        * @method destroy
3430
        * @description Removes the button's element from its parent element and 
3431
        * removes all event handlers.
3432
        */
3433
        destroy: function () {
3434
        
3435
        
3436
            var oElement = this.get("element"),
3437
                oMenu = this._menu,
3438
				oLabel = this._label,
3439
                oParentNode,
3440
                aButtons;
3441
        
3442
            if (oMenu) {
3443
        
3444
3445
                if (m_oOverlayManager && m_oOverlayManager.find(oMenu)) {
3446
3447
                    m_oOverlayManager.remove(oMenu);
3448
3449
                }
3450
        
3451
                oMenu.destroy();
3452
        
3453
            }
3454
        
3455
        
3456
            Event.purgeElement(oElement);
3457
            Event.purgeElement(this._button);
3458
            Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
3459
            Event.removeListener(document, "keyup", this._onDocumentKeyUp);
3460
            Event.removeListener(document, "mousedown", this._onDocumentMouseDown);
3461
3462
3463
			if (oLabel) {
3464
3465
            	Event.removeListener(oLabel, "click", this._onLabelClick);
3466
				
3467
				oParentNode = oLabel.parentNode;
3468
				oParentNode.removeChild(oLabel);
3469
				
3470
			}
3471
        
3472
        
3473
            var oForm = this.getForm();
3474
            
3475
            if (oForm) {
3476
        
3477
                Event.removeListener(oForm, "reset", this._onFormReset);
3478
                Event.removeListener(oForm, "submit", this._onFormSubmit);
3479
        
3480
            }
3481
3482
3483
            this.unsubscribeAll();
3484
3485
			oParentNode = oElement.parentNode;
3486
3487
            if (oParentNode) {
3488
3489
                oParentNode.removeChild(oElement);
3490
            
3491
            }
3492
        
3493
        
3494
            delete m_oButtons[this.get("id")];
3495
3496
			var sClass = (this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME);
3497
3498
            aButtons = Dom.getElementsByClassName(sClass, 
3499
                                this.NODE_NAME, oForm); 
3500
3501
            if (Lang.isArray(aButtons) && aButtons.length === 0) {
3502
3503
                Event.removeListener(oForm, "keypress", 
3504
                        YAHOO.widget.Button.onFormKeyPress);
3505
3506
            }
3507
3508
        
3509
        },
3510
        
3511
        
3512
        fireEvent: function (p_sType , p_aArgs) {
3513
        
3514
			var sType = arguments[0];
3515
		
3516
			//  Disabled buttons should not respond to DOM events
3517
		
3518
			if (this.DOM_EVENTS[sType] && this.get("disabled")) {
3519
		
3520
				return false;
3521
		
3522
			}
3523
		
3524
			return YAHOO.widget.Button.superclass.fireEvent.apply(this, arguments);
3525
        
3526
        },
3527
        
3528
        
3529
        /**
3530
        * @method toString
3531
        * @description Returns a string representing the button.
3532
        * @return {String}
3533
        */
3534
        toString: function () {
3535
        
3536
            return ("Button " + this.get("id"));
3537
        
3538
        }
3539
    
3540
    });
3541
    
3542
    
3543
    /**
3544
    * @method YAHOO.widget.Button.onFormKeyPress
3545
    * @description "keypress" event handler for the button's form.
3546
    * @param {Event} p_oEvent Object representing the DOM event object passed 
3547
    * back by the event utility (YAHOO.util.Event).
3548
    */
3549
    YAHOO.widget.Button.onFormKeyPress = function (p_oEvent) {
3550
    
3551
        var oTarget = Event.getTarget(p_oEvent),
3552
            nCharCode = Event.getCharCode(p_oEvent),
3553
            sNodeName = oTarget.nodeName && oTarget.nodeName.toUpperCase(),
3554
            sType = oTarget.type,
3555
    
3556
            /*
3557
                Boolean indicating if the form contains any enabled or 
3558
                disabled YUI submit buttons
3559
            */
3560
    
3561
            bFormContainsYUIButtons = false,
3562
    
3563
            oButton,
3564
    
3565
            oYUISubmitButton,   // The form's first, enabled YUI submit button
3566
    
3567
            /*
3568
                 The form's first, enabled HTML submit button that precedes any 
3569
                 YUI submit button
3570
            */
3571
    
3572
            oPrecedingSubmitButton,
3573
            
3574
            oEvent; 
3575
    
3576
    
3577
        function isSubmitButton(p_oElement) {
3578
    
3579
            var sId,
3580
                oSrcElement;
3581
    
3582
            switch (p_oElement.nodeName.toUpperCase()) {
3583
    
3584
            case "INPUT":
3585
            case "BUTTON":
3586
            
3587
                if (p_oElement.type == "submit" && !p_oElement.disabled) {
3588
                    
3589
                    if (!bFormContainsYUIButtons && !oPrecedingSubmitButton) {
3590
3591
                        oPrecedingSubmitButton = p_oElement;
3592
3593
                    }
3594
                
3595
                }
3596
3597
                break;
3598
            
3599
3600
            default:
3601
            
3602
                sId = p_oElement.id;
3603
    
3604
                if (sId) {
3605
    
3606
                    oButton = m_oButtons[sId];
3607
        
3608
                    if (oButton) {
3609
3610
                        bFormContainsYUIButtons = true;
3611
        
3612
                        if (!oButton.get("disabled")) {
3613
3614
                            oSrcElement = oButton.get("srcelement");
3615
    
3616
                            if (!oYUISubmitButton && (oButton.get("type") == "submit" || 
3617
                                (oSrcElement && oSrcElement.type == "submit"))) {
3618
3619
                                oYUISubmitButton = oButton;
3620
                            
3621
                            }
3622
                        
3623
                        }
3624
                        
3625
                    }
3626
                
3627
                }
3628
3629
                break;
3630
    
3631
            }
3632
    
3633
        }
3634
    
3635
    
3636
        if (nCharCode == 13 && ((sNodeName == "INPUT" && (sType == "text" || 
3637
            sType == "password" || sType == "checkbox" || sType == "radio" || 
3638
            sType == "file")) || sNodeName == "SELECT")) {
3639
    
3640
            Dom.getElementsBy(isSubmitButton, "*", this);
3641
    
3642
    
3643
            if (oPrecedingSubmitButton) {
3644
    
3645
                /*
3646
                     Need to set focus to the first enabled submit button
3647
                     to make sure that IE includes its name and value 
3648
                     in the form's data set.
3649
                */
3650
    
3651
                oPrecedingSubmitButton.focus();
3652
            
3653
            }
3654
            else if (!oPrecedingSubmitButton && oYUISubmitButton) {
3655
    
3656
				/*
3657
					Need to call "preventDefault" to ensure that the form doesn't end up getting
3658
					submitted twice.
3659
				*/
3660
    
3661
    			Event.preventDefault(p_oEvent);
3662
3663
3664
				if (UA.ie) {
3665
				
3666
					oYUISubmitButton.get("element").fireEvent("onclick");
3667
				
3668
				}
3669
				else {
3670
3671
					oEvent = document.createEvent("HTMLEvents");
3672
					oEvent.initEvent("click", true, true);
3673
			
3674
3675
					if (UA.gecko < 1.9) {
3676
					
3677
						oYUISubmitButton.fireEvent("click", oEvent);
3678
					
3679
					}
3680
					else {
3681
3682
						oYUISubmitButton.get("element").dispatchEvent(oEvent);
3683
					
3684
					}
3685
  
3686
                }
3687
3688
            }
3689
            
3690
        }
3691
    
3692
    };
3693
    
3694
    
3695
    /**
3696
    * @method YAHOO.widget.Button.addHiddenFieldsToForm
3697
    * @description Searches the specified form and adds hidden fields for  
3698
    * instances of YAHOO.widget.Button that are of type "radio," "checkbox," 
3699
    * "menu," and "split."
3700
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
3701
    * one-html.html#ID-40002357">HTMLFormElement</a>} p_oForm Object reference 
3702
    * for the form to search.
3703
    */
3704
    YAHOO.widget.Button.addHiddenFieldsToForm = function (p_oForm) {
3705
    
3706
        var proto = YAHOO.widget.Button.prototype,
3707
			aButtons = Dom.getElementsByClassName(
3708
							(proto.CLASS_NAME_PREFIX + proto.CSS_CLASS_NAME), 
3709
                            "*", 
3710
                            p_oForm),
3711
    
3712
            nButtons = aButtons.length,
3713
            oButton,
3714
            sId,
3715
            i;
3716
    
3717
        if (nButtons > 0) {
3718
    
3719
    
3720
            for (i = 0; i < nButtons; i++) {
3721
    
3722
                sId = aButtons[i].id;
3723
    
3724
                if (sId) {
3725
    
3726
                    oButton = m_oButtons[sId];
3727
        
3728
                    if (oButton) {
3729
           
3730
                        oButton.createHiddenFields();
3731
                        
3732
                    }
3733
                
3734
                }
3735
            
3736
            }
3737
    
3738
        }
3739
    
3740
    };
3741
    
3742
3743
    /**
3744
    * @method YAHOO.widget.Button.getButton
3745
    * @description Returns a button with the specified id.
3746
    * @param {String} p_sId String specifying the id of the root node of the 
3747
    * HTML element representing the button to be retrieved.
3748
    * @return {YAHOO.widget.Button}
3749
    */
3750
    YAHOO.widget.Button.getButton = function (p_sId) {
3751
3752
		return m_oButtons[p_sId];
3753
3754
    };
3755
    
3756
    
3757
    // Events
3758
    
3759
    
3760
    /**
3761
    * @event focus
3762
    * @description Fires when the menu item receives focus.  Passes back a  
3763
    * single object representing the original DOM event object passed back by 
3764
    * the event utility (YAHOO.util.Event) when the event was fired.  See 
3765
    * <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> 
3766
    * for more information on listening for this event.
3767
    * @type YAHOO.util.CustomEvent
3768
    */
3769
    
3770
    
3771
    /**
3772
    * @event blur
3773
    * @description Fires when the menu item loses the input focus.  Passes back  
3774
    * a single object representing the original DOM event object passed back by 
3775
    * the event utility (YAHOO.util.Event) when the event was fired.  See 
3776
    * <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for  
3777
    * more information on listening for this event.
3778
    * @type YAHOO.util.CustomEvent
3779
    */
3780
    
3781
    
3782
    /**
3783
    * @event option
3784
    * @description Fires when the user invokes the button's option.  Passes 
3785
    * back a single object representing the original DOM event (either 
3786
    * "mousedown" or "keydown") that caused the "option" event to fire.  See 
3787
    * <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> 
3788
    * for more information on listening for this event.
3789
    * @type YAHOO.util.CustomEvent
3790
    */
3791
3792
})();
3793
(function () {
3794
3795
    // Shorthard for utilities
3796
    
3797
    var Dom = YAHOO.util.Dom,
3798
        Event = YAHOO.util.Event,
3799
        Lang = YAHOO.lang,
3800
        Button = YAHOO.widget.Button,  
3801
    
3802
        // Private collection of radio buttons
3803
    
3804
        m_oButtons = {};
3805
3806
3807
3808
    /**
3809
    * The ButtonGroup class creates a set of buttons that are mutually 
3810
    * exclusive; checking one button in the set will uncheck all others in the 
3811
    * button group.
3812
    * @param {String} p_oElement String specifying the id attribute of the 
3813
    * <code>&#60;div&#62;</code> element of the button group.
3814
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3815
    * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object 
3816
    * specifying the <code>&#60;div&#62;</code> element of the button group.
3817
    * @param {Object} p_oElement Object literal specifying a set of 
3818
    * configuration attributes used to create the button group.
3819
    * @param {Object} p_oAttributes Optional. Object literal specifying a set 
3820
    * of configuration attributes used to create the button group.
3821
    * @namespace YAHOO.widget
3822
    * @class ButtonGroup
3823
    * @constructor
3824
    * @extends YAHOO.util.Element
3825
    */
3826
    YAHOO.widget.ButtonGroup = function (p_oElement, p_oAttributes) {
3827
    
3828
        var fnSuperClass = YAHOO.widget.ButtonGroup.superclass.constructor,
3829
            sNodeName,
3830
            oElement,
3831
            sId;
3832
    
3833
        if (arguments.length == 1 && !Lang.isString(p_oElement) && 
3834
            !p_oElement.nodeName) {
3835
    
3836
            if (!p_oElement.id) {
3837
    
3838
                sId = Dom.generateId();
3839
    
3840
                p_oElement.id = sId;
3841
    
3842
    
3843
            }
3844
    
3845
    
3846
    
3847
            fnSuperClass.call(this, (this._createGroupElement()), p_oElement);
3848
    
3849
        }
3850
        else if (Lang.isString(p_oElement)) {
3851
    
3852
            oElement = Dom.get(p_oElement);
3853
    
3854
            if (oElement) {
3855
            
3856
                if (oElement.nodeName.toUpperCase() == this.NODE_NAME) {
3857
    
3858
            
3859
                    fnSuperClass.call(this, oElement, p_oAttributes);
3860
    
3861
                }
3862
    
3863
            }
3864
        
3865
        }
3866
        else {
3867
    
3868
            sNodeName = p_oElement.nodeName.toUpperCase();
3869
    
3870
            if (sNodeName && sNodeName == this.NODE_NAME) {
3871
        
3872
                if (!p_oElement.id) {
3873
        
3874
                    p_oElement.id = Dom.generateId();
3875
        
3876
        
3877
                }
3878
        
3879
        
3880
                fnSuperClass.call(this, p_oElement, p_oAttributes);
3881
    
3882
            }
3883
    
3884
        }
3885
    
3886
    };
3887
    
3888
    
3889
    YAHOO.extend(YAHOO.widget.ButtonGroup, YAHOO.util.Element, {
3890
    
3891
    
3892
        // Protected properties
3893
        
3894
        
3895
        /** 
3896
        * @property _buttons
3897
        * @description Array of buttons in the button group.
3898
        * @default null
3899
        * @protected
3900
        * @type Array
3901
        */
3902
        _buttons: null,
3903
        
3904
        
3905
        
3906
        // Constants
3907
        
3908
        
3909
        /**
3910
        * @property NODE_NAME
3911
        * @description The name of the tag to be used for the button 
3912
        * group's element. 
3913
        * @default "DIV"
3914
        * @final
3915
        * @type String
3916
        */
3917
        NODE_NAME: "DIV",
3918
3919
3920
        /**
3921
        * @property CLASS_NAME_PREFIX
3922
        * @description Prefix used for all class names applied to a ButtonGroup.
3923
        * @default "yui-"
3924
        * @final
3925
        * @type String
3926
        */
3927
        CLASS_NAME_PREFIX: "yui-",
3928
        
3929
        
3930
        /**
3931
        * @property CSS_CLASS_NAME
3932
        * @description String representing the CSS class(es) to be applied  
3933
        * to the button group's element.
3934
        * @default "buttongroup"
3935
        * @final
3936
        * @type String
3937
        */
3938
        CSS_CLASS_NAME: "buttongroup",
3939
    
3940
    
3941
    
3942
        // Protected methods
3943
        
3944
        
3945
        /**
3946
        * @method _createGroupElement
3947
        * @description Creates the button group's element.
3948
        * @protected
3949
        * @return {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
3950
        * level-one-html.html#ID-22445964">HTMLDivElement</a>}
3951
        */
3952
        _createGroupElement: function () {
3953
        
3954
            var oElement = document.createElement(this.NODE_NAME);
3955
        
3956
            return oElement;
3957
        
3958
        },
3959
        
3960
        
3961
        
3962
        // Protected attribute setter methods
3963
        
3964
        
3965
        /**
3966
        * @method _setDisabled
3967
        * @description Sets the value of the button groups's 
3968
        * "disabled" attribute.
3969
        * @protected
3970
        * @param {Boolean} p_bDisabled Boolean indicating the value for
3971
        * the button group's "disabled" attribute.
3972
        */
3973
        _setDisabled: function (p_bDisabled) {
3974
        
3975
            var nButtons = this.getCount(),
3976
                i;
3977
        
3978
            if (nButtons > 0) {
3979
        
3980
                i = nButtons - 1;
3981
                
3982
                do {
3983
        
3984
                    this._buttons[i].set("disabled", p_bDisabled);
3985
                
3986
                }
3987
                while (i--);
3988
        
3989
            }
3990
        
3991
        },
3992
        
3993
        
3994
        
3995
        // Protected event handlers
3996
        
3997
        
3998
        /**
3999
        * @method _onKeyDown
4000
        * @description "keydown" event handler for the button group.
4001
        * @protected
4002
        * @param {Event} p_oEvent Object representing the DOM event object  
4003
        * passed back by the event utility (YAHOO.util.Event).
4004
        */
4005
        _onKeyDown: function (p_oEvent) {
4006
        
4007
            var oTarget = Event.getTarget(p_oEvent),
4008
                nCharCode = Event.getCharCode(p_oEvent),
4009
                sId = oTarget.parentNode.parentNode.id,
4010
                oButton = m_oButtons[sId],
4011
                nIndex = -1;
4012
        
4013
        
4014
            if (nCharCode == 37 || nCharCode == 38) {
4015
        
4016
                nIndex = (oButton.index === 0) ? 
4017
                            (this._buttons.length - 1) : (oButton.index - 1);
4018
            
4019
            }
4020
            else if (nCharCode == 39 || nCharCode == 40) {
4021
        
4022
                nIndex = (oButton.index === (this._buttons.length - 1)) ? 
4023
                            0 : (oButton.index + 1);
4024
        
4025
            }
4026
        
4027
        
4028
            if (nIndex > -1) {
4029
        
4030
                this.check(nIndex);
4031
                this.getButton(nIndex).focus();
4032
            
4033
            }        
4034
        
4035
        },
4036
        
4037
        
4038
        /**
4039
        * @method _onAppendTo
4040
        * @description "appendTo" event handler for the button group.
4041
        * @protected
4042
        * @param {Event} p_oEvent Object representing the event that was fired.
4043
        */
4044
        _onAppendTo: function (p_oEvent) {
4045
        
4046
            var aButtons = this._buttons,
4047
                nButtons = aButtons.length,
4048
                i;
4049
        
4050
            for (i = 0; i < nButtons; i++) {
4051
        
4052
                aButtons[i].appendTo(this.get("element"));
4053
        
4054
            }
4055
        
4056
        },
4057
        
4058
        
4059
        /**
4060
        * @method _onButtonCheckedChange
4061
        * @description "checkedChange" event handler for each button in the 
4062
        * button group.
4063
        * @protected
4064
        * @param {Event} p_oEvent Object representing the event that was fired.
4065
        * @param {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}  
4066
        * p_oButton Object representing the button that fired the event.
4067
        */
4068
        _onButtonCheckedChange: function (p_oEvent, p_oButton) {
4069
        
4070
            var bChecked = p_oEvent.newValue,
4071
                oCheckedButton = this.get("checkedButton");
4072
        
4073
            if (bChecked && oCheckedButton != p_oButton) {
4074
        
4075
                if (oCheckedButton) {
4076
        
4077
                    oCheckedButton.set("checked", false, true);
4078
        
4079
                }
4080
        
4081
                this.set("checkedButton", p_oButton);
4082
                this.set("value", p_oButton.get("value"));
4083
        
4084
            }
4085
            else if (oCheckedButton && !oCheckedButton.set("checked")) {
4086
        
4087
                oCheckedButton.set("checked", true, true);
4088
        
4089
            }
4090
           
4091
        },
4092
        
4093
        
4094
        
4095
        // Public methods
4096
        
4097
        
4098
        /**
4099
        * @method init
4100
        * @description The ButtonGroup class's initialization method.
4101
        * @param {String} p_oElement String specifying the id attribute of the 
4102
        * <code>&#60;div&#62;</code> element of the button group.
4103
        * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
4104
        * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object 
4105
        * specifying the <code>&#60;div&#62;</code> element of the button group.
4106
        * @param {Object} p_oElement Object literal specifying a set of  
4107
        * configuration attributes used to create the button group.
4108
        * @param {Object} p_oAttributes Optional. Object literal specifying a
4109
        * set of configuration attributes used to create the button group.
4110
        */
4111
        init: function (p_oElement, p_oAttributes) {
4112
        
4113
            this._buttons = [];
4114
        
4115
            YAHOO.widget.ButtonGroup.superclass.init.call(this, p_oElement, 
4116
                    p_oAttributes);
4117
        
4118
            this.addClass(this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME);
4119
4120
        
4121
            var sClass = (YAHOO.widget.Button.prototype.CLASS_NAME_PREFIX + "radio-button"),
4122
				aButtons = this.getElementsByClassName(sClass);
4123
4124
        
4125
        
4126
            if (aButtons.length > 0) {
4127
        
4128
        
4129
                this.addButtons(aButtons);
4130
        
4131
            }
4132
        
4133
        
4134
        
4135
            function isRadioButton(p_oElement) {
4136
        
4137
                return (p_oElement.type == "radio");
4138
        
4139
            }
4140
        
4141
            aButtons = 
4142
                Dom.getElementsBy(isRadioButton, "input", this.get("element"));
4143
        
4144
        
4145
            if (aButtons.length > 0) {
4146
        
4147
        
4148
                this.addButtons(aButtons);
4149
        
4150
            }
4151
        
4152
            this.on("keydown", this._onKeyDown);
4153
            this.on("appendTo", this._onAppendTo);
4154
        
4155
4156
            var oContainer = this.get("container");
4157
4158
            if (oContainer) {
4159
        
4160
                if (Lang.isString(oContainer)) {
4161
        
4162
                    Event.onContentReady(oContainer, function () {
4163
        
4164
                        this.appendTo(oContainer);            
4165
                    
4166
                    }, null, this);
4167
        
4168
                }
4169
                else {
4170
        
4171
                    this.appendTo(oContainer);
4172
        
4173
                }
4174
        
4175
            }
4176
        
4177
        
4178
        
4179
        },
4180
        
4181
        
4182
        /**
4183
        * @method initAttributes
4184
        * @description Initializes all of the configuration attributes used to  
4185
        * create the button group.
4186
        * @param {Object} p_oAttributes Object literal specifying a set of 
4187
        * configuration attributes used to create the button group.
4188
        */
4189
        initAttributes: function (p_oAttributes) {
4190
        
4191
            var oAttributes = p_oAttributes || {};
4192
        
4193
            YAHOO.widget.ButtonGroup.superclass.initAttributes.call(
4194
                this, oAttributes);
4195
        
4196
        
4197
            /**
4198
            * @attribute name
4199
            * @description String specifying the name for the button group.  
4200
            * This name will be applied to each button in the button group.
4201
            * @default null
4202
            * @type String
4203
            */
4204
            this.setAttributeConfig("name", {
4205
        
4206
                value: oAttributes.name,
4207
                validator: Lang.isString
4208
        
4209
            });
4210
        
4211
        
4212
            /**
4213
            * @attribute disabled
4214
            * @description Boolean indicating if the button group should be 
4215
            * disabled.  Disabling the button group will disable each button 
4216
            * in the button group.  Disabled buttons are dimmed and will not 
4217
            * respond to user input or fire events.
4218
            * @default false
4219
            * @type Boolean
4220
            */
4221
            this.setAttributeConfig("disabled", {
4222
        
4223
                value: (oAttributes.disabled || false),
4224
                validator: Lang.isBoolean,
4225
                method: this._setDisabled
4226
        
4227
            });
4228
        
4229
        
4230
            /**
4231
            * @attribute value
4232
            * @description Object specifying the value for the button group.
4233
            * @default null
4234
            * @type Object
4235
            */
4236
            this.setAttributeConfig("value", {
4237
        
4238
                value: oAttributes.value
4239
        
4240
            });
4241
        
4242
        
4243
            /**
4244
            * @attribute container
4245
            * @description HTML element reference or string specifying the id 
4246
            * attribute of the HTML element that the button group's markup
4247
            * should be rendered into.
4248
            * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
4249
            * level-one-html.html#ID-58190037">HTMLElement</a>|String
4250
            * @default null
4251
			* @writeonce
4252
            */
4253
            this.setAttributeConfig("container", {
4254
        
4255
                value: oAttributes.container,
4256
                writeOnce: true
4257
        
4258
            });
4259
        
4260
        
4261
            /**
4262
            * @attribute checkedButton
4263
            * @description Reference for the button in the button group that 
4264
            * is checked.
4265
            * @type {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
4266
            * @default null
4267
            */
4268
            this.setAttributeConfig("checkedButton", {
4269
        
4270
                value: null
4271
        
4272
            });
4273
        
4274
        },
4275
        
4276
        
4277
        /**
4278
        * @method addButton
4279
        * @description Adds the button to the button group.
4280
        * @param {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}  
4281
        * p_oButton Object reference for the <a href="YAHOO.widget.Button.html">
4282
        * YAHOO.widget.Button</a> instance to be added to the button group.
4283
        * @param {String} p_oButton String specifying the id attribute of the 
4284
        * <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code> element 
4285
        * to be used to create the button to be added to the button group.
4286
        * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
4287
        * level-one-html.html#ID-6043025">HTMLInputElement</a>|<a href="
4288
        * http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#
4289
        * ID-33759296">HTMLElement</a>} p_oButton Object reference for the 
4290
        * <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code> element 
4291
        * to be used to create the button to be added to the button group.
4292
        * @param {Object} p_oButton Object literal specifying a set of 
4293
        * <a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a> 
4294
        * configuration attributes used to configure the button to be added to 
4295
        * the button group.
4296
        * @return {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>} 
4297
        */
4298
        addButton: function (p_oButton) {
4299
        
4300
            var oButton,
4301
                oButtonElement,
4302
                oGroupElement,
4303
                nIndex,
4304
                sButtonName,
4305
                sGroupName;
4306
        
4307
        
4308
            if (p_oButton instanceof Button && 
4309
                p_oButton.get("type") == "radio") {
4310
        
4311
                oButton = p_oButton;
4312
        
4313
            }
4314
            else if (!Lang.isString(p_oButton) && !p_oButton.nodeName) {
4315
        
4316
                p_oButton.type = "radio";
4317
        
4318
                oButton = new Button(p_oButton);
4319
4320
            }
4321
            else {
4322
        
4323
                oButton = new Button(p_oButton, { type: "radio" });
4324
        
4325
            }
4326
        
4327
        
4328
            if (oButton) {
4329
        
4330
                nIndex = this._buttons.length;
4331
                sButtonName = oButton.get("name");
4332
                sGroupName = this.get("name");
4333
        
4334
                oButton.index = nIndex;
4335
        
4336
                this._buttons[nIndex] = oButton;
4337
                m_oButtons[oButton.get("id")] = oButton;
4338
        
4339
        
4340
                if (sButtonName != sGroupName) {
4341
        
4342
                    oButton.set("name", sGroupName);
4343
                
4344
                }
4345
        
4346
        
4347
                if (this.get("disabled")) {
4348
        
4349
                    oButton.set("disabled", true);
4350
        
4351
                }
4352
        
4353
        
4354
                if (oButton.get("checked")) {
4355
        
4356
                    this.set("checkedButton", oButton);
4357
        
4358
                }
4359
4360
                
4361
                oButtonElement = oButton.get("element");
4362
                oGroupElement = this.get("element");
4363
                
4364
                if (oButtonElement.parentNode != oGroupElement) {
4365
                
4366
                    oGroupElement.appendChild(oButtonElement);
4367
                
4368
                }
4369
        
4370
                
4371
                oButton.on("checkedChange", 
4372
                    this._onButtonCheckedChange, oButton, this);
4373
        
4374
        
4375
            }
4376
4377
			return oButton;
4378
        
4379
        },
4380
        
4381
        
4382
        /**
4383
        * @method addButtons
4384
        * @description Adds the array of buttons to the button group.
4385
        * @param {Array} p_aButtons Array of <a href="YAHOO.widget.Button.html">
4386
        * YAHOO.widget.Button</a> instances to be added 
4387
        * to the button group.
4388
        * @param {Array} p_aButtons Array of strings specifying the id 
4389
        * attribute of the <code>&#60;input&#62;</code> or <code>&#60;span&#62;
4390
        * </code> elements to be used to create the buttons to be added to the 
4391
        * button group.
4392
        * @param {Array} p_aButtons Array of object references for the 
4393
        * <code>&#60;input&#62;</code> or <code>&#60;span&#62;</code> elements 
4394
        * to be used to create the buttons to be added to the button group.
4395
        * @param {Array} p_aButtons Array of object literals, each containing
4396
        * a set of <a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>  
4397
        * configuration attributes used to configure each button to be added 
4398
        * to the button group.
4399
        * @return {Array}
4400
        */
4401
        addButtons: function (p_aButtons) {
4402
    
4403
            var nButtons,
4404
                oButton,
4405
                aButtons,
4406
                i;
4407
        
4408
            if (Lang.isArray(p_aButtons)) {
4409
            
4410
                nButtons = p_aButtons.length;
4411
                aButtons = [];
4412
        
4413
                if (nButtons > 0) {
4414
        
4415
                    for (i = 0; i < nButtons; i++) {
4416
        
4417
                        oButton = this.addButton(p_aButtons[i]);
4418
                        
4419
                        if (oButton) {
4420
        
4421
                            aButtons[aButtons.length] = oButton;
4422
        
4423
                        }
4424
                    
4425
                    }
4426
                
4427
                }
4428
        
4429
            }
4430
4431
			return aButtons;
4432
        
4433
        },
4434
        
4435
        
4436
        /**
4437
        * @method removeButton
4438
        * @description Removes the button at the specified index from the 
4439
        * button group.
4440
        * @param {Number} p_nIndex Number specifying the index of the button 
4441
        * to be removed from the button group.
4442
        */
4443
        removeButton: function (p_nIndex) {
4444
        
4445
            var oButton = this.getButton(p_nIndex),
4446
                nButtons,
4447
                i;
4448
            
4449
            if (oButton) {
4450
        
4451
        
4452
                this._buttons.splice(p_nIndex, 1);
4453
                delete m_oButtons[oButton.get("id")];
4454
        
4455
                oButton.removeListener("checkedChange", 
4456
                    this._onButtonCheckedChange);
4457
4458
                oButton.destroy();
4459
        
4460
        
4461
                nButtons = this._buttons.length;
4462
                
4463
                if (nButtons > 0) {
4464
        
4465
                    i = this._buttons.length - 1;
4466
                    
4467
                    do {
4468
        
4469
                        this._buttons[i].index = i;
4470
        
4471
                    }
4472
                    while (i--);
4473
                
4474
                }
4475
        
4476
        
4477
            }
4478
        
4479
        },
4480
        
4481
        
4482
        /**
4483
        * @method getButton
4484
        * @description Returns the button at the specified index.
4485
        * @param {Number} p_nIndex The index of the button to retrieve from the 
4486
        * button group.
4487
        * @return {<a href="YAHOO.widget.Button.html">YAHOO.widget.Button</a>}
4488
        */
4489
        getButton: function (p_nIndex) {
4490
        
4491
            return this._buttons[p_nIndex];
4492
        
4493
        },
4494
        
4495
        
4496
        /**
4497
        * @method getButtons
4498
        * @description Returns an array of the buttons in the button group.
4499
        * @return {Array}
4500
        */
4501
        getButtons: function () {
4502
        
4503
            return this._buttons;
4504
        
4505
        },
4506
        
4507
        
4508
        /**
4509
        * @method getCount
4510
        * @description Returns the number of buttons in the button group.
4511
        * @return {Number}
4512
        */
4513
        getCount: function () {
4514
        
4515
            return this._buttons.length;
4516
        
4517
        },
4518
        
4519
        
4520
        /**
4521
        * @method focus
4522
        * @description Sets focus to the button at the specified index.
4523
        * @param {Number} p_nIndex Number indicating the index of the button 
4524
        * to focus. 
4525
        */
4526
        focus: function (p_nIndex) {
4527
        
4528
            var oButton,
4529
                nButtons,
4530
                i;
4531
        
4532
            if (Lang.isNumber(p_nIndex)) {
4533
        
4534
                oButton = this._buttons[p_nIndex];
4535
                
4536
                if (oButton) {
4537
        
4538
                    oButton.focus();
4539
        
4540
                }
4541
            
4542
            }
4543
            else {
4544
        
4545
                nButtons = this.getCount();
4546
        
4547
                for (i = 0; i < nButtons; i++) {
4548
        
4549
                    oButton = this._buttons[i];
4550
        
4551
                    if (!oButton.get("disabled")) {
4552
        
4553
                        oButton.focus();
4554
                        break;
4555
        
4556
                    }
4557
        
4558
                }
4559
        
4560
            }
4561
        
4562
        },
4563
        
4564
        
4565
        /**
4566
        * @method check
4567
        * @description Checks the button at the specified index.
4568
        * @param {Number} p_nIndex Number indicating the index of the button 
4569
        * to check. 
4570
        */
4571
        check: function (p_nIndex) {
4572
        
4573
            var oButton = this.getButton(p_nIndex);
4574
            
4575
            if (oButton) {
4576
        
4577
                oButton.set("checked", true);
4578
            
4579
            }
4580
        
4581
        },
4582
        
4583
        
4584
        /**
4585
        * @method destroy
4586
        * @description Removes the button group's element from its parent 
4587
        * element and removes all event handlers.
4588
        */
4589
        destroy: function () {
4590
        
4591
        
4592
            var nButtons = this._buttons.length,
4593
                oElement = this.get("element"),
4594
                oParentNode = oElement.parentNode,
4595
                i;
4596
            
4597
            if (nButtons > 0) {
4598
        
4599
                i = this._buttons.length - 1;
4600
        
4601
                do {
4602
        
4603
                    this._buttons[i].destroy();
4604
        
4605
                }
4606
                while (i--);
4607
            
4608
            }
4609
        
4610
        
4611
            Event.purgeElement(oElement);
4612
            
4613
        
4614
            oParentNode.removeChild(oElement);
4615
        
4616
        },
4617
        
4618
        
4619
        /**
4620
        * @method toString
4621
        * @description Returns a string representing the button group.
4622
        * @return {String}
4623
        */
4624
        toString: function () {
4625
        
4626
            return ("ButtonGroup " + this.get("id"));
4627
        
4628
        }
4629
    
4630
    });
4631
4632
})();
4633
YAHOO.register("button", YAHOO.widget.Button, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/container/assets/container-core.css (-176 lines)
Lines 1-176 Link Here
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.8.0r4
6
*/
7
.yui-overlay,
8
.yui-panel-container {
9
    visibility: hidden;
10
    position: absolute;
11
    z-index: 2;
12
}
13
14
.yui-panel {
15
    position:relative;
16
}
17
18
.yui-panel-container form {
19
    margin: 0;
20
}
21
22
.mask {
23
    z-index: 1;
24
    display: none;
25
    position: absolute;
26
    top: 0;
27
    left: 0;
28
    right: 0;
29
    bottom: 0;
30
}
31
32
.mask.block-scrollbars {
33
    /*
34
        Application of "overflow:auto" prevents Mac scrollbars from bleeding
35
        through the modality mask in Gecko. The block-scollbars class is only 
36
        added for Gecko on MacOS
37
    */
38
    overflow: auto;
39
}
40
41
/* 
42
    PLEASE NOTE:
43
44
    1) ".masked select" is used to prevent <SELECT> elements bleeding through 
45
       the modality mask in IE 6. 
46
47
    2) ".drag select" is used to hide <SELECT> elements when dragging a 
48
       Panel in IE 6.  This is necessary to prevent some redraw problems with 
49
       the <SELECT> elements when a Panel instance is dragged.
50
    
51
    3) ".hide-select select" is appended to an Overlay instance's root HTML 
52
       element when it is being annimated by YAHOO.widget.ContainerEffect.  
53
       This is necessary because <SELECT> elements don't inherit their parent
54
       element's opacity in IE 6.
55
56
*/
57
58
.masked select,
59
.drag select,
60
.hide-select select {
61
    _visibility: hidden;
62
}
63
64
.yui-panel-container select {
65
    _visibility: inherit;
66
}
67
68
/*
69
70
There are two known issues with YAHOO.widget.Overlay (and its subclasses) that 
71
manifest in Gecko-based browsers on Mac OS X:
72
73
    1) Elements with scrollbars will poke through Overlay instances floating 
74
       above them.
75
    
76
    2) An Overlay's scrollbars and the scrollbars of its child nodes remain  
77
       visible when the Overlay is hidden.
78
79
To fix these bugs:
80
81
    1) The "overflow" property of an Overlay instance's root element and child 
82
       nodes is toggled between "hidden" and "auto" (through the application  
83
       and removal of the "hide-scrollbars" and "show-scrollbars" CSS classes)
84
       as its "visibility" configuration property is toggled between 
85
       "false" and "true."
86
    
87
    2) The "display" property of <SELECT> elements that are child nodes of the 
88
       Overlay instance's root element is set to "none" when it is hidden.
89
90
PLEASE NOTE:  
91
  
92
    1) The "hide-scrollbars" and "show-scrollbars" CSS classes classes are 
93
       applied only for Gecko on Mac OS X and are added/removed to/from the 
94
       Overlay's root HTML element (DIV) via the "hideMacGeckoScrollbars" and 
95
       "showMacGeckoScrollbars" methods of YAHOO.widget.Overlay.
96
    
97
    2) There may be instances where the CSS for a web page or application 
98
       contains style rules whose specificity override the rules implemented by 
99
       the Container CSS files to fix this bug.  In such cases, is necessary to 
100
       leverage the provided "hide-scrollbars" and "show-scrollbars" classes to 
101
       write custom style rules to guard against this bug.
102
103
** For more information on this issue, see:
104
105
   + https://bugzilla.mozilla.org/show_bug.cgi?id=187435
106
   + YUILibrary bug #1723530
107
108
*/
109
110
.hide-scrollbars,
111
.hide-scrollbars * {
112
113
    overflow: hidden;
114
115
}
116
117
.hide-scrollbars select {
118
    display: none;
119
}
120
121
.show-scrollbars {
122
    overflow: auto;
123
}
124
125
.yui-panel-container.show-scrollbars,
126
.yui-tt.show-scrollbars {
127
    overflow: visible;
128
}
129
130
.yui-panel-container.show-scrollbars .underlay,
131
.yui-tt.show-scrollbars .yui-tt-shadow {
132
133
    overflow: auto;
134
135
}
136
137
/* 
138
   Workaround for Safari 2.x - the yui-force-redraw class is applied, and then removed when
139
   the Panel's content changes, to force Safari 2.x to redraw the underlay.
140
   We attempt to choose a CSS property which has no visual impact when added,
141
   removed.
142
*/
143
.yui-panel-container.shadow .underlay.yui-force-redraw {
144
    padding-bottom: 1px;
145
}
146
147
.yui-effect-fade .underlay, .yui-effect-fade .yui-tt-shadow {
148
    display:none;
149
}
150
151
/*
152
    PLEASE NOTE: The <DIV> element used for a Tooltip's shadow is appended 
153
    to its root element via JavaScript once it has been rendered.  The 
154
    code that creates the shadow lives in the Tooltip's public "onRender" 
155
    event handler that is a prototype method of YAHOO.widget.Tooltip.  
156
    Implementers wishing to remove a Tooltip's shadow or add any other markup
157
    required for a given skin for Tooltip should override the "onRender" method.
158
*/
159
160
.yui-tt-shadow {
161
    position: absolute;
162
}
163
164
.yui-override-padding {
165
    padding:0 !important;
166
}
167
168
.yui-panel-container .container-close {
169
    overflow:hidden;
170
    text-indent:-10000em;
171
    text-decoration:none;
172
}
173
174
.yui-overlay.yui-force-redraw, .yui-panel-container.yui-force-redraw {
175
    margin-bottom:1px;
176
}
(-)a/koha-tmpl/intranet-tmpl/lib/yui/container/assets/container.css (-324 lines)
Lines 1-324 Link Here
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.8.0r4
6
*/
7
.yui-overlay,
8
.yui-panel-container {
9
    visibility:hidden;
10
    position:absolute;
11
    z-index: 2;
12
}
13
14
.yui-tt {
15
    visibility:hidden;
16
    position:absolute;
17
    color:#333;
18
    background-color:#FDFFB4;
19
    font-family:arial,helvetica,verdana,sans-serif;
20
    padding:2px;
21
    border:1px solid #FCC90D;
22
    font:100% sans-serif;
23
    width:auto;
24
}
25
26
/*
27
    PLEASE NOTE: The <DIV> element used for a Tooltip's shadow is appended 
28
    to its root element via JavaScript once it has been rendered.  The 
29
    code that creates the shadow lives in the Tooltip's public "onRender" 
30
    event handler that is a prototype method of YAHOO.widget.Tooltip.  
31
    Implementers wishing to remove a Tooltip's shadow or add any other markup
32
    required for a given skin for Tooltip should override the "onRender" method.
33
*/
34
35
.yui-tt-shadow {
36
    display: none;
37
}
38
39
* html body.masked select {
40
    visibility:hidden;
41
}
42
43
* html div.yui-panel-container select {
44
    visibility:inherit;
45
}
46
47
* html div.drag select {
48
    visibility:hidden;
49
}
50
51
* html div.hide-select select {
52
    visibility:hidden;
53
}
54
55
.mask {
56
    z-index: 1; 
57
    display:none;
58
    position:absolute;
59
    top:0;
60
    left:0;
61
    -moz-opacity: 0.5;
62
    opacity:.50;
63
    filter: alpha(opacity=50);
64
    background-color:#CCC;
65
}
66
67
/*
68
69
There are two known issues with YAHOO.widget.Overlay (and its subclasses) that 
70
manifest in Gecko-based browsers on Mac OS X:
71
72
    1) Elements with scrollbars will poke through Overlay instances floating 
73
       above them.
74
    
75
    2) An Overlay's scrollbars and the scrollbars of its child nodes remain  
76
       visible when the Overlay is hidden.
77
78
To fix these bugs:
79
80
    1) The "overflow" property of an Overlay instance's root element and child 
81
       nodes is toggled between "hidden" and "auto" (through the application  
82
       and removal of the "hide-scrollbars" and "show-scrollbars" CSS classes)
83
       as its "visibility" configuration property is toggled between 
84
       "false" and "true."
85
    
86
    2) The "display" property of <SELECT> elements that are child nodes of the 
87
       Overlay instance's root element is set to "none" when it is hidden.
88
89
PLEASE NOTE:  
90
  
91
    1) The "hide-scrollbars" and "show-scrollbars" CSS classes classes are 
92
       applied only for Gecko on Mac OS X and are added/removed to/from the 
93
       Overlay's root HTML element (DIV) via the "hideMacGeckoScrollbars" and 
94
       "showMacGeckoScrollbars" methods of YAHOO.widget.Overlay.
95
    
96
    2) There may be instances where the CSS for a web page or application 
97
       contains style rules whose specificity override the rules implemented by 
98
       the Container CSS files to fix this bug.  In such cases, is necessary to 
99
       leverage the provided "hide-scrollbars" and "show-scrollbars" classes to 
100
       write custom style rules to guard against this bug.
101
102
** For more information on this issue, see: 
103
   + https://bugzilla.mozilla.org/show_bug.cgi?id=187435
104
   + YUILibrary bug #1723530
105
106
*/
107
108
.hide-scrollbars,
109
.hide-scrollbars * {
110
111
    overflow: hidden;
112
113
}
114
115
.hide-scrollbars select {
116
117
    display: none;
118
119
}
120
121
.show-scrollbars {
122
123
    overflow: auto;
124
125
}
126
127
.yui-panel-container.show-scrollbars {
128
129
    overflow: visible;
130
131
}
132
133
.yui-panel-container.show-scrollbars .underlay {
134
135
    overflow: auto;
136
137
}
138
139
.yui-panel-container.focused {
140
141
}
142
143
144
/* Panel underlay styles */
145
146
.yui-panel-container .underlay {
147
148
    position: absolute;
149
    top: 0;
150
    right: 0;
151
    bottom: 0;
152
    left: 0;
153
154
}
155
156
.yui-panel-container.matte {
157
158
    padding: 3px;
159
    background-color: #fff;
160
161
}
162
163
.yui-panel-container.shadow .underlay {
164
165
    top: 3px;
166
    bottom: -3px;
167
    right: -3px;
168
    left: 3px;
169
    background-color: #000;
170
    opacity: .12;
171
    filter: alpha(opacity=12);  /* For IE */
172
173
}
174
175
/* 
176
   Workaround for Safari 2.x - the yui-force-redraw class is applied, and then removed when
177
   the Panel's content changes, to force Safari 2.x to redraw the underlay.
178
   We attempt to choose a CSS property which has no visual impact when added,
179
   removed, but still causes Safari to redraw
180
*/
181
.yui-panel-container.shadow .underlay.yui-force-redraw {
182
    padding-bottom: 1px;
183
}
184
185
.yui-effect-fade .underlay {
186
    display:none;
187
}
188
189
.yui-panel {
190
    visibility:hidden;
191
    border-collapse:separate;
192
    position:relative;
193
    left:0;
194
    top:0;
195
    font:1em Arial;
196
    background-color:#FFF;
197
    border:1px solid #000;
198
    z-index:1;
199
    overflow:hidden;
200
}
201
202
.yui-panel .hd {
203
    background-color:#3d77cb;
204
    color:#FFF;
205
    font-size:100%;
206
    line-height:100%;
207
    border:1px solid #FFF;
208
    border-bottom:1px solid #000;
209
    font-weight:bold;
210
    padding:4px;
211
    white-space:nowrap;
212
}
213
214
.yui-panel .bd {
215
    overflow:hidden;
216
    padding:4px;
217
}
218
219
.yui-panel .bd p {
220
    margin:0 0 1em;
221
}
222
223
.yui-panel .container-close {
224
    position:absolute;
225
    top:5px;
226
    right:4px;
227
    z-index:6;
228
    height:12px;
229
    width:12px;
230
    margin:0px;
231
    padding:0px;
232
    background:url(close12_1.gif) no-repeat;
233
    cursor:pointer;
234
    visibility:inherit;
235
    text-indent:-10000em;
236
    overflow:hidden;
237
    text-decoration:none;
238
}
239
240
.yui-panel .ft {
241
    padding:4px;
242
    overflow:hidden;
243
}
244
245
.yui-simple-dialog .bd .yui-icon {
246
    background-repeat:no-repeat;
247
    width:16px;
248
    height:16px;
249
    margin-right:10px;
250
    float:left;
251
}
252
253
.yui-simple-dialog .bd span.blckicon {
254
    background: url("blck16_1.gif") no-repeat;
255
}
256
257
.yui-simple-dialog .bd span.alrticon {
258
    background: url("alrt16_1.gif") no-repeat;
259
}
260
261
.yui-simple-dialog .bd span.hlpicon {
262
    background: url("hlp16_1.gif") no-repeat;
263
}
264
265
.yui-simple-dialog .bd span.infoicon {
266
    background: url("info16_1.gif") no-repeat;
267
}
268
269
.yui-simple-dialog .bd span.warnicon {
270
    background: url("warn16_1.gif") no-repeat;
271
}
272
273
.yui-simple-dialog .bd span.tipicon {
274
    background: url("tip16_1.gif") no-repeat;
275
}
276
277
.yui-dialog .ft, 
278
.yui-simple-dialog .ft {
279
    padding-bottom:5px;
280
    padding-right:5px;
281
    text-align:right;
282
}
283
284
.yui-dialog form, 
285
.yui-simple-dialog form {
286
    margin:0;
287
}
288
289
.button-group button {
290
    font:100 76% verdana;
291
    text-decoration:none;
292
    background-color: #E4E4E4;
293
    color: #333;
294
    cursor: hand;
295
    vertical-align: middle;
296
    border: 2px solid #797979;
297
    border-top-color:#FFF;
298
    border-left-color:#FFF;
299
    margin:2px;
300
    padding:2px;
301
}
302
303
.button-group button.default {
304
    font-weight:bold;
305
}
306
307
.button-group button:hover, 
308
.button-group button.hover {
309
    border:2px solid #90A029;
310
    background-color:#EBF09E;
311
    border-top-color:#FFF;
312
    border-left-color:#FFF;
313
}
314
315
.button-group button:active {
316
    border:2px solid #E4E4E4;
317
    background-color:#BBB;
318
    border-top-color:#333;
319
    border-left-color:#333;
320
}
321
322
.yui-override-padding {
323
    padding:0 !important;
324
}
(-)a/koha-tmpl/intranet-tmpl/lib/yui/container/assets/skins/sam/container-skin.css (-242 lines)
Lines 1-242 Link Here
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.8.0r4
6
*/
7
/* Panel modality mask styles */
8
.yui-skin-sam .mask {
9
    background-color: #000;
10
    opacity: .25;
11
    filter: alpha(opacity=25);  /* Set opacity in IE */
12
}
13
14
/* Panel styles */
15
.yui-skin-sam .yui-panel-container {
16
    padding:0 1px;
17
    /* Padding added for IE to allow 0,0 alignment with shadow */
18
    *padding:2px;
19
}
20
21
.yui-skin-sam .yui-panel {
22
    position: relative;
23
    left:0;
24
    top:0;
25
    border-style: solid;
26
    border-width: 1px 0;
27
    border-color: #808080;
28
    z-index: 1;
29
30
    /* Rollback rounded corner support for IE6/7 */
31
    *border-width:1px;
32
    *zoom:1;
33
    _zoom:normal;
34
}
35
36
.yui-skin-sam .yui-panel .hd,
37
.yui-skin-sam .yui-panel .bd,
38
.yui-skin-sam .yui-panel .ft {
39
    border-style: solid;
40
    border-width: 0 1px;
41
    border-color: #808080;
42
    margin: 0 -1px;
43
44
    /* Rollback rounded corner support for IE6/7 */
45
    *margin:0;
46
    *border:0;
47
}
48
49
.yui-skin-sam .yui-panel .hd {
50
    border-bottom: solid 1px #ccc;
51
}
52
53
.yui-skin-sam .yui-panel .bd,
54
.yui-skin-sam .yui-panel .ft {
55
    background-color: #F2F2F2;
56
}
57
58
.yui-skin-sam .yui-panel .hd {
59
    padding: 0 10px;
60
    font-size: 93%;  /* 12px */
61
    line-height: 2;  /* ~24px */
62
    *line-height: 1.9; /* For IE */
63
    font-weight: bold;
64
    color: #000;
65
    background: url(../../../../assets/skins/sam/sprite.png) repeat-x 0 -200px;
66
}
67
68
.yui-skin-sam .yui-panel .bd {
69
    padding: 10px;
70
}
71
72
.yui-skin-sam .yui-panel .ft {
73
    border-top: solid 1px #808080;
74
    padding: 5px 10px;
75
    font-size: 77%;
76
}
77
78
.yui-skin-sam .yui-panel-container.focused .yui-panel .hd {
79
80
}
81
82
.yui-skin-sam .container-close {
83
    position: absolute;
84
    top: 5px;
85
    right: 6px;
86
    width: 25px;
87
    height: 15px;
88
    background: url(../../../../assets/skins/sam/sprite.png) no-repeat 0 -300px;
89
    cursor:pointer;
90
}
91
92
/* Panel underlay styles */
93
.yui-skin-sam .yui-panel-container .underlay {
94
    right: -1px;
95
    left: -1px;
96
}
97
98
.yui-skin-sam .yui-panel-container.matte {
99
    padding: 9px 10px;
100
    background-color: #fff;
101
}
102
103
.yui-skin-sam .yui-panel-container.shadow {
104
    /* IE 7 Quirks Mode and IE 6 Standards Mode and Quirks mode */
105
    _padding: 2px 4px 0 2px;
106
}
107
108
.yui-skin-sam .yui-panel-container.shadow .underlay {
109
    position: absolute;
110
    top: 2px;
111
    left: -3px;
112
    right: -3px;
113
    bottom: -3px;
114
115
    /* IE7 Strict (provides 3px shadow (when combined with 2px padding applied to container) */
116
    *top: 4px;
117
    *left: -1px;
118
    *right: -1px;
119
    *bottom: -1px;
120
121
    /* IE 7 Quirks Mode and IE 6 Standards Mode and Quirks mode */
122
    _top: 0;
123
    _left: 0;
124
    _right: 0;
125
    _bottom: 0;
126
    _margin-top: 3px;
127
    _margin-left: -1px;
128
129
    background-color: #000;
130
    opacity: .12;
131
    filter: alpha(opacity=12);  /* Set opacity in IE */
132
}
133
134
135
/* Dialog styles */
136
.yui-skin-sam .yui-dialog .ft {
137
    border-top: none;
138
    padding: 0 10px 10px 10px;
139
    font-size: 100%;
140
}
141
142
.yui-skin-sam .yui-dialog .ft .button-group {
143
    display: block;
144
    text-align: right;
145
}
146
147
/* Dialog default button style */
148
.yui-skin-sam .yui-dialog .ft button.default {
149
    font-weight:bold;
150
}
151
152
/* Dialog default YUI Button style */
153
.yui-skin-sam .yui-dialog .ft span.default {
154
    border-color: #304369;
155
    background-position: 0 -1400px;
156
}
157
158
.yui-skin-sam .yui-dialog .ft span.default .first-child {
159
    border-color: #304369;
160
}
161
162
.yui-skin-sam .yui-dialog .ft span.default button {
163
    color: #fff;
164
}
165
166
/* Dialog YUI Button disabled state */
167
.yui-skin-sam .yui-dialog .ft span.yui-button-disabled {
168
    background-position:0pt -1500px;
169
    border-color:#ccc;
170
}
171
172
.yui-skin-sam .yui-dialog .ft span.yui-button-disabled .first-child {
173
    border-color:#ccc;
174
}
175
176
.yui-skin-sam .yui-dialog .ft span.yui-button-disabled button {
177
    color:#a6a6a6;
178
}
179
180
/* SimpleDialog icon styles */
181
.yui-skin-sam .yui-simple-dialog .bd .yui-icon {
182
    background: url(../../../../assets/skins/sam/sprite.png) no-repeat 0 0;
183
    width: 16px;
184
    height: 16px;
185
    margin-right: 10px;
186
    float: left;
187
}
188
189
.yui-skin-sam .yui-simple-dialog .bd span.blckicon {
190
    background-position: 0 -1100px;
191
}
192
193
.yui-skin-sam .yui-simple-dialog .bd span.alrticon {
194
    background-position: 0 -1050px;
195
}
196
197
.yui-skin-sam .yui-simple-dialog .bd span.hlpicon {
198
    background-position: 0 -1150px;
199
}
200
201
.yui-skin-sam .yui-simple-dialog .bd span.infoicon {
202
    background-position: 0 -1200px;
203
}
204
205
.yui-skin-sam .yui-simple-dialog .bd span.warnicon {
206
    background-position: 0 -1900px;
207
}
208
209
.yui-skin-sam .yui-simple-dialog .bd span.tipicon {
210
    background-position: 0 -1250px;
211
}
212
213
/* Tooltip styles */
214
.yui-skin-sam .yui-tt .bd {
215
    position: relative;
216
    top: 0;
217
    left: 0;
218
    z-index: 1;
219
    color: #000;
220
    padding: 2px 5px;
221
    border-color: #D4C237 #A6982B #A6982B #A6982B;
222
    border-width: 1px;
223
    border-style: solid;
224
    background-color: #FFEE69;
225
}
226
227
.yui-skin-sam .yui-tt.show-scrollbars .bd {
228
    overflow: auto;
229
}
230
231
.yui-skin-sam .yui-tt-shadow {
232
    top: 2px;
233
    right: -3px;
234
    left: -3px;
235
    bottom: -3px;
236
    background-color: #000;
237
}
238
239
.yui-skin-sam .yui-tt-shadow-visible {
240
    opacity: .12;
241
    filter: alpha(opacity=12);  /* For IE */
242
}
(-)a/koha-tmpl/intranet-tmpl/lib/yui/container/assets/skins/sam/container.css (-7 lines)
Lines 1-7 Link Here
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.8.0r4
6
*/
7
.yui-overlay,.yui-panel-container{visibility:hidden;position:absolute;z-index:2;}.yui-panel{position:relative;}.yui-panel-container form{margin:0;}.mask{z-index:1;display:none;position:absolute;top:0;left:0;right:0;bottom:0;}.mask.block-scrollbars{overflow:auto;}.masked select,.drag select,.hide-select select{_visibility:hidden;}.yui-panel-container select{_visibility:inherit;}.hide-scrollbars,.hide-scrollbars *{overflow:hidden;}.hide-scrollbars select{display:none;}.show-scrollbars{overflow:auto;}.yui-panel-container.show-scrollbars,.yui-tt.show-scrollbars{overflow:visible;}.yui-panel-container.show-scrollbars .underlay,.yui-tt.show-scrollbars .yui-tt-shadow{overflow:auto;}.yui-panel-container.shadow .underlay.yui-force-redraw{padding-bottom:1px;}.yui-effect-fade .underlay,.yui-effect-fade .yui-tt-shadow{display:none;}.yui-tt-shadow{position:absolute;}.yui-override-padding{padding:0!important;}.yui-panel-container .container-close{overflow:hidden;text-indent:-10000em;text-decoration:none;}.yui-overlay.yui-force-redraw,.yui-panel-container.yui-force-redraw{margin-bottom:1px;}.yui-skin-sam .mask{background-color:#000;opacity:.25;filter:alpha(opacity=25);}.yui-skin-sam .yui-panel-container{padding:0 1px;*padding:2px;}.yui-skin-sam .yui-panel{position:relative;left:0;top:0;border-style:solid;border-width:1px 0;border-color:#808080;z-index:1;*border-width:1px;*zoom:1;_zoom:normal;}.yui-skin-sam .yui-panel .hd,.yui-skin-sam .yui-panel .bd,.yui-skin-sam .yui-panel .ft{border-style:solid;border-width:0 1px;border-color:#808080;margin:0 -1px;*margin:0;*border:0;}.yui-skin-sam .yui-panel .hd{border-bottom:solid 1px #ccc;}.yui-skin-sam .yui-panel .bd,.yui-skin-sam .yui-panel .ft{background-color:#F2F2F2;}.yui-skin-sam .yui-panel .hd{padding:0 10px;font-size:93%;line-height:2;*line-height:1.9;font-weight:bold;color:#000;background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 -200px;}.yui-skin-sam .yui-panel .bd{padding:10px;}.yui-skin-sam .yui-panel .ft{border-top:solid 1px #808080;padding:5px 10px;font-size:77%;}.yui-skin-sam .container-close{position:absolute;top:5px;right:6px;width:25px;height:15px;background:url(../../../../assets/skins/sam/sprite.png) no-repeat 0 -300px;cursor:pointer;}.yui-skin-sam .yui-panel-container .underlay{right:-1px;left:-1px;}.yui-skin-sam .yui-panel-container.matte{padding:9px 10px;background-color:#fff;}.yui-skin-sam .yui-panel-container.shadow{_padding:2px 4px 0 2px;}.yui-skin-sam .yui-panel-container.shadow .underlay{position:absolute;top:2px;left:-3px;right:-3px;bottom:-3px;*top:4px;*left:-1px;*right:-1px;*bottom:-1px;_top:0;_left:0;_right:0;_bottom:0;_margin-top:3px;_margin-left:-1px;background-color:#000;opacity:.12;filter:alpha(opacity=12);}.yui-skin-sam .yui-dialog .ft{border-top:none;padding:0 10px 10px 10px;font-size:100%;}.yui-skin-sam .yui-dialog .ft .button-group{display:block;text-align:right;}.yui-skin-sam .yui-dialog .ft button.default{font-weight:bold;}.yui-skin-sam .yui-dialog .ft span.default{border-color:#304369;background-position:0 -1400px;}.yui-skin-sam .yui-dialog .ft span.default .first-child{border-color:#304369;}.yui-skin-sam .yui-dialog .ft span.default button{color:#fff;}.yui-skin-sam .yui-dialog .ft span.yui-button-disabled{background-position:0 -1500px;border-color:#ccc;}.yui-skin-sam .yui-dialog .ft span.yui-button-disabled .first-child{border-color:#ccc;}.yui-skin-sam .yui-dialog .ft span.yui-button-disabled button{color:#a6a6a6;}.yui-skin-sam .yui-simple-dialog .bd .yui-icon{background:url(../../../../assets/skins/sam/sprite.png) no-repeat 0 0;width:16px;height:16px;margin-right:10px;float:left;}.yui-skin-sam .yui-simple-dialog .bd span.blckicon{background-position:0 -1100px;}.yui-skin-sam .yui-simple-dialog .bd span.alrticon{background-position:0 -1050px;}.yui-skin-sam .yui-simple-dialog .bd span.hlpicon{background-position:0 -1150px;}.yui-skin-sam .yui-simple-dialog .bd span.infoicon{background-position:0 -1200px;}.yui-skin-sam .yui-simple-dialog .bd span.warnicon{background-position:0 -1900px;}.yui-skin-sam .yui-simple-dialog .bd span.tipicon{background-position:0 -1250px;}.yui-skin-sam .yui-tt .bd{position:relative;top:0;left:0;z-index:1;color:#000;padding:2px 5px;border-color:#D4C237 #A6982B #A6982B #A6982B;border-width:1px;border-style:solid;background-color:#FFEE69;}.yui-skin-sam .yui-tt.show-scrollbars .bd{overflow:auto;}.yui-skin-sam .yui-tt-shadow{top:2px;right:-3px;left:-3px;bottom:-3px;background-color:#000;}.yui-skin-sam .yui-tt-shadow-visible{opacity:.12;filter:alpha(opacity=12);}
(-)a/koha-tmpl/intranet-tmpl/lib/yui/container/container-debug.js (-9076 lines)
Lines 1-9076 Link Here
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.8.0r4
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} overrideContext Optional. If true, will override
547
        * "this" within the handler to map to the scope Object passed into the
548
        * method.
549
        * @return {Boolean} True, if the subscription was successful, 
550
        * otherwise false.
551
        */ 
552
        subscribeToConfigEvent: function (key, handler, obj, overrideContext) {
553
    
554
            var property = this.config[key.toLowerCase()];
555
    
556
            if (property && property.event) {
557
                if (!Config.alreadySubscribed(property.event, handler, obj)) {
558
                    property.event.subscribe(handler, obj, overrideContext);
559
                }
560
                return true;
561
            } else {
562
                return false;
563
            }
564
    
565
        },
566
        
567
        /**
568
        * Unsubscribes an external handler from the change event for any 
569
        * given property. 
570
        * @method unsubscribeFromConfigEvent
571
        * @param {String} key The property name
572
        * @param {Function} handler The handler function to use subscribe to 
573
        * the property's event
574
        * @param {Object} obj The Object to use for scoping the event 
575
        * handler (see CustomEvent documentation)
576
        * @return {Boolean} True, if the unsubscription was successful, 
577
        * otherwise false.
578
        */
579
        unsubscribeFromConfigEvent: function (key, handler, obj) {
580
            var property = this.config[key.toLowerCase()];
581
            if (property && property.event) {
582
                return property.event.unsubscribe(handler, obj);
583
            } else {
584
                return false;
585
            }
586
        },
587
        
588
        /**
589
        * Returns a string representation of the Config object
590
        * @method toString
591
        * @return {String} The Config object in string format.
592
        */
593
        toString: function () {
594
            var output = "Config";
595
            if (this.owner) {
596
                output += " [" + this.owner.toString() + "]";
597
            }
598
            return output;
599
        },
600
        
601
        /**
602
        * Returns a string representation of the Config object's current 
603
        * CustomEvent queue
604
        * @method outputEventQueue
605
        * @return {String} The string list of CustomEvents currently queued 
606
        * for execution
607
        */
608
        outputEventQueue: function () {
609
610
            var output = "",
611
                queueItem,
612
                q,
613
                nQueue = this.eventQueue.length;
614
              
615
            for (q = 0; q < nQueue; q++) {
616
                queueItem = this.eventQueue[q];
617
                if (queueItem) {
618
                    output += queueItem[0] + "=" + queueItem[1] + ", ";
619
                }
620
            }
621
            return output;
622
        },
623
624
        /**
625
        * Sets all properties to null, unsubscribes all listeners from each 
626
        * property's change event and all listeners from the configChangedEvent.
627
        * @method destroy
628
        */
629
        destroy: function () {
630
631
            var oConfig = this.config,
632
                sProperty,
633
                oProperty;
634
635
636
            for (sProperty in oConfig) {
637
            
638
                if (Lang.hasOwnProperty(oConfig, sProperty)) {
639
640
                    oProperty = oConfig[sProperty];
641
642
                    oProperty.event.unsubscribeAll();
643
                    oProperty.event = null;
644
645
                }
646
            
647
            }
648
            
649
            this.configChangedEvent.unsubscribeAll();
650
            
651
            this.configChangedEvent = null;
652
            this.owner = null;
653
            this.config = null;
654
            this.initialConfig = null;
655
            this.eventQueue = null;
656
        
657
        }
658
659
    };
660
    
661
    
662
    
663
    /**
664
    * Checks to determine if a particular function/Object pair are already 
665
    * subscribed to the specified CustomEvent
666
    * @method YAHOO.util.Config.alreadySubscribed
667
    * @static
668
    * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check 
669
    * the subscriptions
670
    * @param {Function} fn The function to look for in the subscribers list
671
    * @param {Object} obj The execution scope Object for the subscription
672
    * @return {Boolean} true, if the function/Object pair is already subscribed 
673
    * to the CustomEvent passed in
674
    */
675
    Config.alreadySubscribed = function (evt, fn, obj) {
676
    
677
        var nSubscribers = evt.subscribers.length,
678
            subsc,
679
            i;
680
681
        if (nSubscribers > 0) {
682
            i = nSubscribers - 1;
683
            do {
684
                subsc = evt.subscribers[i];
685
                if (subsc && subsc.obj == obj && subsc.fn == fn) {
686
                    return true;
687
                }
688
            }
689
            while (i--);
690
        }
691
692
        return false;
693
694
    };
695
696
    YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
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
            "DESTROY": "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.DESTROY);
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 YUILibrary 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
                    // Setting the background color fixes an issue with IE6/IE7, where
1418
                    // elements in the DOM, with -ve margin-top which positioned them 
1419
                    // offscreen (so they would be overlapped by the iframe and its -ve top
1420
                    // setting), would have their -ve margin-top ignored, when the iframe 
1421
                    // was added.
1422
                    oIFrame.style.backgroundColor = "transparent";
1423
1424
                    oIFrame.style.borderWidth = "0";
1425
                    oIFrame.style.width = "2em";
1426
                    oIFrame.style.height = "2em";
1427
                    oIFrame.style.left = "0";
1428
                    oIFrame.style.top = (-1 * (oIFrame.offsetHeight + Module.RESIZE_MONITOR_BUFFER)) + "px";
1429
                    oIFrame.style.visibility = "visible";
1430
1431
                    /*
1432
                       Don't open/close the document for Gecko like we used to, since it
1433
                       leads to duplicate cookies. (See YUILibrary bug #1721755)
1434
                    */
1435
                    if (UA.webkit) {
1436
                        oDoc = oIFrame.contentWindow.document;
1437
                        oDoc.open();
1438
                        oDoc.close();
1439
                    }
1440
                }
1441
1442
                if (oIFrame && oIFrame.contentWindow) {
1443
                    Module.textResizeEvent.subscribe(this.onDomResize, this, true);
1444
1445
                    if (!Module.textResizeInitialized) {
1446
                        if (supportsCWResize) {
1447
                            if (!Event.on(oIFrame.contentWindow, "resize", fireTextResize)) {
1448
                                /*
1449
                                     This will fail in IE if document.domain has 
1450
                                     changed, so we must change the listener to 
1451
                                     use the oIFrame element instead
1452
                                */
1453
                                Event.on(oIFrame, "resize", fireTextResize);
1454
                            }
1455
                        }
1456
                        Module.textResizeInitialized = true;
1457
                    }
1458
                    this.resizeMonitor = oIFrame;
1459
                }
1460
            }
1461
        },
1462
1463
        /**
1464
         * Text resize monitor helper method.
1465
         * Determines if the browser supports resize events on iframe content windows.
1466
         * 
1467
         * @private
1468
         * @method _supportsCWResize
1469
         */
1470
        _supportsCWResize : function() {
1471
            /*
1472
                Gecko 1.8.0 (FF1.5), 1.8.1.0-5 (FF2) won't fire resize on contentWindow.
1473
                Gecko 1.8.1.6+ (FF2.0.0.6+) and all other browsers will fire resize on contentWindow.
1474
1475
                We don't want to start sniffing for patch versions, so fire textResize the same
1476
                way on all FF2 flavors
1477
             */
1478
            var bSupported = true;
1479
            if (UA.gecko && UA.gecko <= 1.8) {
1480
                bSupported = false;
1481
            }
1482
            return bSupported;
1483
        },
1484
1485
        /**
1486
        * Event handler fired when the resize monitor element is resized.
1487
        * @method onDomResize
1488
        * @param {DOMEvent} e The DOM resize event
1489
        * @param {Object} obj The scope object passed to the handler
1490
        */
1491
        onDomResize: function (e, obj) {
1492
1493
            var nTop = -1 * (this.resizeMonitor.offsetHeight + Module.RESIZE_MONITOR_BUFFER);
1494
1495
            this.resizeMonitor.style.top = nTop + "px";
1496
            this.resizeMonitor.style.left = "0";
1497
        },
1498
1499
        /**
1500
        * Sets the Module's header content to the string specified, or appends 
1501
        * the passed element to the header. If no header is present, one will 
1502
        * be automatically created. An empty string can be passed to the method
1503
        * to clear the contents of the header.
1504
        * 
1505
        * @method setHeader
1506
        * @param {String} headerContent The string used to set the header.
1507
        * As a convenience, non HTMLElement objects can also be passed into 
1508
        * the method, and will be treated as strings, with the header innerHTML
1509
        * set to their default toString implementations.
1510
        * <em>OR</em>
1511
        * @param {HTMLElement} headerContent The HTMLElement to append to 
1512
        * <em>OR</em>
1513
        * @param {DocumentFragment} headerContent The document fragment 
1514
        * containing elements which are to be added to the header
1515
        */
1516
        setHeader: function (headerContent) {
1517
            var oHeader = this.header || (this.header = createHeader());
1518
1519
            if (headerContent.nodeName) {
1520
                oHeader.innerHTML = "";
1521
                oHeader.appendChild(headerContent);
1522
            } else {
1523
                oHeader.innerHTML = headerContent;
1524
            }
1525
1526
            if (this._rendered) {
1527
                this._renderHeader();
1528
            }
1529
1530
            this.changeHeaderEvent.fire(headerContent);
1531
            this.changeContentEvent.fire();
1532
1533
        },
1534
1535
        /**
1536
        * Appends the passed element to the header. If no header is present, 
1537
        * one will be automatically created.
1538
        * @method appendToHeader
1539
        * @param {HTMLElement | DocumentFragment} element The element to 
1540
        * append to the header. In the case of a document fragment, the
1541
        * children of the fragment will be appended to the header.
1542
        */
1543
        appendToHeader: function (element) {
1544
            var oHeader = this.header || (this.header = createHeader());
1545
1546
            oHeader.appendChild(element);
1547
1548
            this.changeHeaderEvent.fire(element);
1549
            this.changeContentEvent.fire();
1550
1551
        },
1552
1553
        /**
1554
        * Sets the Module's body content to the HTML specified. 
1555
        * 
1556
        * If no body is present, one will be automatically created. 
1557
        * 
1558
        * An empty string can be passed to the method to clear the contents of the body.
1559
        * @method setBody
1560
        * @param {String} bodyContent The HTML used to set the body. 
1561
        * As a convenience, non HTMLElement objects can also be passed into 
1562
        * the method, and will be treated as strings, with the body innerHTML
1563
        * set to their default toString implementations.
1564
        * <em>OR</em>
1565
        * @param {HTMLElement} bodyContent The HTMLElement to add as the first and only
1566
        * child of the body element.
1567
        * <em>OR</em>
1568
        * @param {DocumentFragment} bodyContent The document fragment 
1569
        * containing elements which are to be added to the body
1570
        */
1571
        setBody: function (bodyContent) {
1572
            var oBody = this.body || (this.body = createBody());
1573
1574
            if (bodyContent.nodeName) {
1575
                oBody.innerHTML = "";
1576
                oBody.appendChild(bodyContent);
1577
            } else {
1578
                oBody.innerHTML = bodyContent;
1579
            }
1580
1581
            if (this._rendered) {
1582
                this._renderBody();
1583
            }
1584
1585
            this.changeBodyEvent.fire(bodyContent);
1586
            this.changeContentEvent.fire();
1587
        },
1588
1589
        /**
1590
        * Appends the passed element to the body. If no body is present, one 
1591
        * will be automatically created.
1592
        * @method appendToBody
1593
        * @param {HTMLElement | DocumentFragment} element The element to 
1594
        * append to the body. In the case of a document fragment, the
1595
        * children of the fragment will be appended to the body.
1596
        * 
1597
        */
1598
        appendToBody: function (element) {
1599
            var oBody = this.body || (this.body = createBody());
1600
        
1601
            oBody.appendChild(element);
1602
1603
            this.changeBodyEvent.fire(element);
1604
            this.changeContentEvent.fire();
1605
1606
        },
1607
        
1608
        /**
1609
        * Sets the Module's footer content to the HTML specified, or appends 
1610
        * the passed element to the footer. If no footer is present, one will 
1611
        * be automatically created. An empty string can be passed to the method
1612
        * to clear the contents of the footer.
1613
        * @method setFooter
1614
        * @param {String} footerContent The HTML used to set the footer 
1615
        * As a convenience, non HTMLElement objects can also be passed into 
1616
        * the method, and will be treated as strings, with the footer innerHTML
1617
        * set to their default toString implementations.
1618
        * <em>OR</em>
1619
        * @param {HTMLElement} footerContent The HTMLElement to append to 
1620
        * the footer
1621
        * <em>OR</em>
1622
        * @param {DocumentFragment} footerContent The document fragment containing 
1623
        * elements which are to be added to the footer
1624
        */
1625
        setFooter: function (footerContent) {
1626
1627
            var oFooter = this.footer || (this.footer = createFooter());
1628
1629
            if (footerContent.nodeName) {
1630
                oFooter.innerHTML = "";
1631
                oFooter.appendChild(footerContent);
1632
            } else {
1633
                oFooter.innerHTML = footerContent;
1634
            }
1635
1636
            if (this._rendered) {
1637
                this._renderFooter();
1638
            }
1639
1640
            this.changeFooterEvent.fire(footerContent);
1641
            this.changeContentEvent.fire();
1642
        },
1643
1644
        /**
1645
        * Appends the passed element to the footer. If no footer is present, 
1646
        * one will be automatically created.
1647
        * @method appendToFooter
1648
        * @param {HTMLElement | DocumentFragment} element The element to 
1649
        * append to the footer. In the case of a document fragment, the
1650
        * children of the fragment will be appended to the footer
1651
        */
1652
        appendToFooter: function (element) {
1653
1654
            var oFooter = this.footer || (this.footer = createFooter());
1655
1656
            oFooter.appendChild(element);
1657
1658
            this.changeFooterEvent.fire(element);
1659
            this.changeContentEvent.fire();
1660
1661
        },
1662
1663
        /**
1664
        * Renders the Module by inserting the elements that are not already 
1665
        * in the main Module into their correct places. Optionally appends 
1666
        * the Module to the specified node prior to the render's execution. 
1667
        * <p>
1668
        * For Modules without existing markup, the appendToNode argument 
1669
        * is REQUIRED. If this argument is ommitted and the current element is 
1670
        * not present in the document, the function will return false, 
1671
        * indicating that the render was a failure.
1672
        * </p>
1673
        * <p>
1674
        * NOTE: As of 2.3.1, if the appendToNode is the document's body element
1675
        * then the module is rendered as the first child of the body element, 
1676
        * and not appended to it, to avoid Operation Aborted errors in IE when 
1677
        * rendering the module before window's load event is fired. You can 
1678
        * use the appendtodocumentbody configuration property to change this 
1679
        * to append to document.body if required.
1680
        * </p>
1681
        * @method render
1682
        * @param {String} appendToNode The element id to which the Module 
1683
        * should be appended to prior to rendering <em>OR</em>
1684
        * @param {HTMLElement} appendToNode The element to which the Module 
1685
        * should be appended to prior to rendering
1686
        * @param {HTMLElement} moduleElement OPTIONAL. The element that 
1687
        * represents the actual Standard Module container.
1688
        * @return {Boolean} Success or failure of the render
1689
        */
1690
        render: function (appendToNode, moduleElement) {
1691
1692
            var me = this;
1693
1694
            function appendTo(parentNode) {
1695
                if (typeof parentNode == "string") {
1696
                    parentNode = document.getElementById(parentNode);
1697
                }
1698
1699
                if (parentNode) {
1700
                    me._addToParent(parentNode, me.element);
1701
                    me.appendEvent.fire();
1702
                }
1703
            }
1704
1705
            this.beforeRenderEvent.fire();
1706
1707
            if (! moduleElement) {
1708
                moduleElement = this.element;
1709
            }
1710
1711
            if (appendToNode) {
1712
                appendTo(appendToNode);
1713
            } else { 
1714
                // No node was passed in. If the element is not already in the Dom, this fails
1715
                if (! Dom.inDocument(this.element)) {
1716
                    YAHOO.log("Render failed. Must specify appendTo node if " + " Module isn't already in the DOM.", "error");
1717
                    return false;
1718
                }
1719
            }
1720
1721
            this._renderHeader(moduleElement);
1722
            this._renderBody(moduleElement);
1723
            this._renderFooter(moduleElement);
1724
1725
            this._rendered = true;
1726
1727
            this.renderEvent.fire();
1728
            return true;
1729
        },
1730
1731
        /**
1732
         * Renders the currently set header into it's proper position under the 
1733
         * module element. If the module element is not provided, "this.element" 
1734
         * is used.
1735
         * 
1736
         * @method _renderHeader
1737
         * @protected
1738
         * @param {HTMLElement} moduleElement Optional. A reference to the module element
1739
         */
1740
        _renderHeader: function(moduleElement){
1741
            moduleElement = moduleElement || this.element;
1742
1743
            // Need to get everything into the DOM if it isn't already
1744
            if (this.header && !Dom.inDocument(this.header)) {
1745
                // There is a header, but it's not in the DOM yet. Need to add it.
1746
                var firstChild = moduleElement.firstChild;
1747
                if (firstChild) {
1748
                    moduleElement.insertBefore(this.header, firstChild);
1749
                } else {
1750
                    moduleElement.appendChild(this.header);
1751
                }
1752
            }
1753
        },
1754
1755
        /**
1756
         * Renders the currently set body into it's proper position under the 
1757
         * module element. If the module element is not provided, "this.element" 
1758
         * is used.
1759
         * 
1760
         * @method _renderBody
1761
         * @protected
1762
         * @param {HTMLElement} moduleElement Optional. A reference to the module element.
1763
         */
1764
        _renderBody: function(moduleElement){
1765
            moduleElement = moduleElement || this.element;
1766
1767
            if (this.body && !Dom.inDocument(this.body)) {
1768
                // There is a body, but it's not in the DOM yet. Need to add it.
1769
                if (this.footer && Dom.isAncestor(moduleElement, this.footer)) {
1770
                    moduleElement.insertBefore(this.body, this.footer);
1771
                } else {
1772
                    moduleElement.appendChild(this.body);
1773
                }
1774
            }
1775
        },
1776
1777
        /**
1778
         * Renders the currently set footer into it's proper position under the 
1779
         * module element. If the module element is not provided, "this.element" 
1780
         * is used.
1781
         * 
1782
         * @method _renderFooter
1783
         * @protected
1784
         * @param {HTMLElement} moduleElement Optional. A reference to the module element
1785
         */
1786
        _renderFooter: function(moduleElement){
1787
            moduleElement = moduleElement || this.element;
1788
1789
            if (this.footer && !Dom.inDocument(this.footer)) {
1790
                // There is a footer, but it's not in the DOM yet. Need to add it.
1791
                moduleElement.appendChild(this.footer);
1792
            }
1793
        },
1794
1795
        /**
1796
        * Removes the Module element from the DOM and sets all child elements 
1797
        * to null.
1798
        * @method destroy
1799
        */
1800
        destroy: function () {
1801
1802
            var parent;
1803
1804
            if (this.element) {
1805
                Event.purgeElement(this.element, true);
1806
                parent = this.element.parentNode;
1807
            }
1808
1809
            if (parent) {
1810
                parent.removeChild(this.element);
1811
            }
1812
        
1813
            this.element = null;
1814
            this.header = null;
1815
            this.body = null;
1816
            this.footer = null;
1817
1818
            Module.textResizeEvent.unsubscribe(this.onDomResize, this);
1819
1820
            this.cfg.destroy();
1821
            this.cfg = null;
1822
1823
            this.destroyEvent.fire();
1824
        },
1825
1826
        /**
1827
        * Shows the Module element by setting the visible configuration 
1828
        * property to true. Also fires two events: beforeShowEvent prior to 
1829
        * the visibility change, and showEvent after.
1830
        * @method show
1831
        */
1832
        show: function () {
1833
            this.cfg.setProperty("visible", true);
1834
        },
1835
1836
        /**
1837
        * Hides the Module element by setting the visible configuration 
1838
        * property to false. Also fires two events: beforeHideEvent prior to 
1839
        * the visibility change, and hideEvent after.
1840
        * @method hide
1841
        */
1842
        hide: function () {
1843
            this.cfg.setProperty("visible", false);
1844
        },
1845
        
1846
        // BUILT-IN EVENT HANDLERS FOR MODULE //
1847
        /**
1848
        * Default event handler for changing the visibility property of a 
1849
        * Module. By default, this is achieved by switching the "display" style 
1850
        * between "block" and "none".
1851
        * This method is responsible for firing showEvent and hideEvent.
1852
        * @param {String} type The CustomEvent type (usually the property name)
1853
        * @param {Object[]} args The CustomEvent arguments. For configuration 
1854
        * handlers, args[0] will equal the newly applied value for the property.
1855
        * @param {Object} obj The scope object. For configuration handlers, 
1856
        * this will usually equal the owner.
1857
        * @method configVisible
1858
        */
1859
        configVisible: function (type, args, obj) {
1860
            var visible = args[0];
1861
            if (visible) {
1862
                this.beforeShowEvent.fire();
1863
                Dom.setStyle(this.element, "display", "block");
1864
                this.showEvent.fire();
1865
            } else {
1866
                this.beforeHideEvent.fire();
1867
                Dom.setStyle(this.element, "display", "none");
1868
                this.hideEvent.fire();
1869
            }
1870
        },
1871
1872
        /**
1873
        * Default event handler for the "monitorresize" configuration property
1874
        * @param {String} type The CustomEvent type (usually the property name)
1875
        * @param {Object[]} args The CustomEvent arguments. For configuration 
1876
        * handlers, args[0] will equal the newly applied value for the property.
1877
        * @param {Object} obj The scope object. For configuration handlers, 
1878
        * this will usually equal the owner.
1879
        * @method configMonitorResize
1880
        */
1881
        configMonitorResize: function (type, args, obj) {
1882
            var monitor = args[0];
1883
            if (monitor) {
1884
                this.initResizeMonitor();
1885
            } else {
1886
                Module.textResizeEvent.unsubscribe(this.onDomResize, this, true);
1887
                this.resizeMonitor = null;
1888
            }
1889
        },
1890
1891
        /**
1892
         * This method is a protected helper, used when constructing the DOM structure for the module 
1893
         * to account for situations which may cause Operation Aborted errors in IE. It should not 
1894
         * be used for general DOM construction.
1895
         * <p>
1896
         * If the parentNode is not document.body, the element is appended as the last element.
1897
         * </p>
1898
         * <p>
1899
         * If the parentNode is document.body the element is added as the first child to help
1900
         * prevent Operation Aborted errors in IE.
1901
         * </p>
1902
         *
1903
         * @param {parentNode} The HTML element to which the element will be added
1904
         * @param {element} The HTML element to be added to parentNode's children
1905
         * @method _addToParent
1906
         * @protected
1907
         */
1908
        _addToParent: function(parentNode, element) {
1909
            if (!this.cfg.getProperty("appendtodocumentbody") && parentNode === document.body && parentNode.firstChild) {
1910
                parentNode.insertBefore(element, parentNode.firstChild);
1911
            } else {
1912
                parentNode.appendChild(element);
1913
            }
1914
        },
1915
1916
        /**
1917
        * Returns a String representation of the Object.
1918
        * @method toString
1919
        * @return {String} The string representation of the Module
1920
        */
1921
        toString: function () {
1922
            return "Module " + this.id;
1923
        }
1924
    };
1925
1926
    YAHOO.lang.augmentProto(Module, YAHOO.util.EventProvider);
1927
1928
}());
1929
(function () {
1930
1931
    /**
1932
    * Overlay is a Module that is absolutely positioned above the page flow. It 
1933
    * has convenience methods for positioning and sizing, as well as options for 
1934
    * controlling zIndex and constraining the Overlay's position to the current 
1935
    * visible viewport. Overlay also contains a dynamicly generated IFRAME which 
1936
    * is placed beneath it for Internet Explorer 6 and 5.x so that it will be 
1937
    * properly rendered above SELECT elements.
1938
    * @namespace YAHOO.widget
1939
    * @class Overlay
1940
    * @extends YAHOO.widget.Module
1941
    * @param {String} el The element ID representing the Overlay <em>OR</em>
1942
    * @param {HTMLElement} el The element representing the Overlay
1943
    * @param {Object} userConfig The configuration object literal containing 
1944
    * the configuration that should be set for this Overlay. See configuration 
1945
    * documentation for more details.
1946
    * @constructor
1947
    */
1948
    YAHOO.widget.Overlay = function (el, userConfig) {
1949
        YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
1950
    };
1951
1952
    var Lang = YAHOO.lang,
1953
        CustomEvent = YAHOO.util.CustomEvent,
1954
        Module = YAHOO.widget.Module,
1955
        Event = YAHOO.util.Event,
1956
        Dom = YAHOO.util.Dom,
1957
        Config = YAHOO.util.Config,
1958
        UA = YAHOO.env.ua,
1959
        Overlay = YAHOO.widget.Overlay,
1960
1961
        _SUBSCRIBE = "subscribe",
1962
        _UNSUBSCRIBE = "unsubscribe",
1963
        _CONTAINED = "contained",
1964
1965
        m_oIFrameTemplate,
1966
1967
        /**
1968
        * Constant representing the name of the Overlay's events
1969
        * @property EVENT_TYPES
1970
        * @private
1971
        * @final
1972
        * @type Object
1973
        */
1974
        EVENT_TYPES = {
1975
            "BEFORE_MOVE": "beforeMove",
1976
            "MOVE": "move"
1977
        },
1978
1979
        /**
1980
        * Constant representing the Overlay's configuration properties
1981
        * @property DEFAULT_CONFIG
1982
        * @private
1983
        * @final
1984
        * @type Object
1985
        */
1986
        DEFAULT_CONFIG = {
1987
1988
            "X": { 
1989
                key: "x", 
1990
                validator: Lang.isNumber, 
1991
                suppressEvent: true, 
1992
                supercedes: ["iframe"]
1993
            },
1994
1995
            "Y": { 
1996
                key: "y", 
1997
                validator: Lang.isNumber, 
1998
                suppressEvent: true, 
1999
                supercedes: ["iframe"]
2000
            },
2001
2002
            "XY": { 
2003
                key: "xy", 
2004
                suppressEvent: true, 
2005
                supercedes: ["iframe"] 
2006
            },
2007
2008
            "CONTEXT": { 
2009
                key: "context", 
2010
                suppressEvent: true, 
2011
                supercedes: ["iframe"] 
2012
            },
2013
2014
            "FIXED_CENTER": { 
2015
                key: "fixedcenter", 
2016
                value: false, 
2017
                supercedes: ["iframe", "visible"] 
2018
            },
2019
2020
            "WIDTH": { 
2021
                key: "width",
2022
                suppressEvent: true,
2023
                supercedes: ["context", "fixedcenter", "iframe"]
2024
            }, 
2025
2026
            "HEIGHT": { 
2027
                key: "height", 
2028
                suppressEvent: true, 
2029
                supercedes: ["context", "fixedcenter", "iframe"] 
2030
            },
2031
2032
            "AUTO_FILL_HEIGHT" : {
2033
                key: "autofillheight",
2034
                supercedes: ["height"],
2035
                value:"body"
2036
            },
2037
2038
            "ZINDEX": { 
2039
                key: "zindex", 
2040
                value: null 
2041
            },
2042
2043
            "CONSTRAIN_TO_VIEWPORT": { 
2044
                key: "constraintoviewport", 
2045
                value: false, 
2046
                validator: Lang.isBoolean, 
2047
                supercedes: ["iframe", "x", "y", "xy"]
2048
            }, 
2049
2050
            "IFRAME": { 
2051
                key: "iframe", 
2052
                value: (UA.ie == 6 ? true : false), 
2053
                validator: Lang.isBoolean, 
2054
                supercedes: ["zindex"] 
2055
            },
2056
2057
            "PREVENT_CONTEXT_OVERLAP": {
2058
                key: "preventcontextoverlap",
2059
                value: false,
2060
                validator: Lang.isBoolean,  
2061
                supercedes: ["constraintoviewport"]
2062
            }
2063
2064
        };
2065
2066
    /**
2067
    * The URL that will be placed in the iframe
2068
    * @property YAHOO.widget.Overlay.IFRAME_SRC
2069
    * @static
2070
    * @final
2071
    * @type String
2072
    */
2073
    Overlay.IFRAME_SRC = "javascript:false;";
2074
2075
    /**
2076
    * Number representing how much the iframe shim should be offset from each 
2077
    * side of an Overlay instance, in pixels.
2078
    * @property YAHOO.widget.Overlay.IFRAME_SRC
2079
    * @default 3
2080
    * @static
2081
    * @final
2082
    * @type Number
2083
    */
2084
    Overlay.IFRAME_OFFSET = 3;
2085
2086
    /**
2087
    * Number representing the minimum distance an Overlay instance should be 
2088
    * positioned relative to the boundaries of the browser's viewport, in pixels.
2089
    * @property YAHOO.widget.Overlay.VIEWPORT_OFFSET
2090
    * @default 10
2091
    * @static
2092
    * @final
2093
    * @type Number
2094
    */
2095
    Overlay.VIEWPORT_OFFSET = 10;
2096
2097
    /**
2098
    * Constant representing the top left corner of an element, used for 
2099
    * configuring the context element alignment
2100
    * @property YAHOO.widget.Overlay.TOP_LEFT
2101
    * @static
2102
    * @final
2103
    * @type String
2104
    */
2105
    Overlay.TOP_LEFT = "tl";
2106
2107
    /**
2108
    * Constant representing the top right corner of an element, used for 
2109
    * configuring the context element alignment
2110
    * @property YAHOO.widget.Overlay.TOP_RIGHT
2111
    * @static
2112
    * @final
2113
    * @type String
2114
    */
2115
    Overlay.TOP_RIGHT = "tr";
2116
2117
    /**
2118
    * Constant representing the top bottom left corner of an element, used for 
2119
    * configuring the context element alignment
2120
    * @property YAHOO.widget.Overlay.BOTTOM_LEFT
2121
    * @static
2122
    * @final
2123
    * @type String
2124
    */
2125
    Overlay.BOTTOM_LEFT = "bl";
2126
2127
    /**
2128
    * Constant representing the bottom right corner of an element, used for 
2129
    * configuring the context element alignment
2130
    * @property YAHOO.widget.Overlay.BOTTOM_RIGHT
2131
    * @static
2132
    * @final
2133
    * @type String
2134
    */
2135
    Overlay.BOTTOM_RIGHT = "br";
2136
2137
    Overlay.PREVENT_OVERLAP_X = {
2138
        "tltr": true,
2139
        "blbr": true,
2140
        "brbl": true,
2141
        "trtl": true
2142
    };
2143
            
2144
    Overlay.PREVENT_OVERLAP_Y = {
2145
        "trbr": true,
2146
        "tlbl": true,
2147
        "bltl": true,
2148
        "brtr": true
2149
    };
2150
2151
    /**
2152
    * Constant representing the default CSS class used for an Overlay
2153
    * @property YAHOO.widget.Overlay.CSS_OVERLAY
2154
    * @static
2155
    * @final
2156
    * @type String
2157
    */
2158
    Overlay.CSS_OVERLAY = "yui-overlay";
2159
2160
    /**
2161
    * Constant representing the default hidden CSS class used for an Overlay. This class is 
2162
    * applied to the overlay's outer DIV whenever it's hidden.
2163
    *
2164
    * @property YAHOO.widget.Overlay.CSS_HIDDEN
2165
    * @static
2166
    * @final
2167
    * @type String
2168
    */
2169
    Overlay.CSS_HIDDEN = "yui-overlay-hidden";
2170
2171
    /**
2172
    * Constant representing the default CSS class used for an Overlay iframe shim.
2173
    * 
2174
    * @property YAHOO.widget.Overlay.CSS_IFRAME
2175
    * @static
2176
    * @final
2177
    * @type String
2178
    */
2179
    Overlay.CSS_IFRAME = "yui-overlay-iframe";
2180
2181
    /**
2182
     * Constant representing the names of the standard module elements
2183
     * used in the overlay.
2184
     * @property YAHOO.widget.Overlay.STD_MOD_RE
2185
     * @static
2186
     * @final
2187
     * @type RegExp
2188
     */
2189
    Overlay.STD_MOD_RE = /^\s*?(body|footer|header)\s*?$/i;
2190
2191
    /**
2192
    * A singleton CustomEvent used for reacting to the DOM event for 
2193
    * window scroll
2194
    * @event YAHOO.widget.Overlay.windowScrollEvent
2195
    */
2196
    Overlay.windowScrollEvent = new CustomEvent("windowScroll");
2197
2198
    /**
2199
    * A singleton CustomEvent used for reacting to the DOM event for
2200
    * window resize
2201
    * @event YAHOO.widget.Overlay.windowResizeEvent
2202
    */
2203
    Overlay.windowResizeEvent = new CustomEvent("windowResize");
2204
2205
    /**
2206
    * The DOM event handler used to fire the CustomEvent for window scroll
2207
    * @method YAHOO.widget.Overlay.windowScrollHandler
2208
    * @static
2209
    * @param {DOMEvent} e The DOM scroll event
2210
    */
2211
    Overlay.windowScrollHandler = function (e) {
2212
        var t = Event.getTarget(e);
2213
2214
        // - Webkit (Safari 2/3) and Opera 9.2x bubble scroll events from elements to window
2215
        // - FF2/3 and IE6/7, Opera 9.5x don't bubble scroll events from elements to window
2216
        // - IE doesn't recognize scroll registered on the document.
2217
        //
2218
        // Also, when document view is scrolled, IE doesn't provide a target, 
2219
        // rest of the browsers set target to window.document, apart from opera 
2220
        // which sets target to window.
2221
        if (!t || t === window || t === window.document) {
2222
            if (UA.ie) {
2223
2224
                if (! window.scrollEnd) {
2225
                    window.scrollEnd = -1;
2226
                }
2227
2228
                clearTimeout(window.scrollEnd);
2229
        
2230
                window.scrollEnd = setTimeout(function () { 
2231
                    Overlay.windowScrollEvent.fire(); 
2232
                }, 1);
2233
        
2234
            } else {
2235
                Overlay.windowScrollEvent.fire();
2236
            }
2237
        }
2238
    };
2239
2240
    /**
2241
    * The DOM event handler used to fire the CustomEvent for window resize
2242
    * @method YAHOO.widget.Overlay.windowResizeHandler
2243
    * @static
2244
    * @param {DOMEvent} e The DOM resize event
2245
    */
2246
    Overlay.windowResizeHandler = function (e) {
2247
2248
        if (UA.ie) {
2249
            if (! window.resizeEnd) {
2250
                window.resizeEnd = -1;
2251
            }
2252
2253
            clearTimeout(window.resizeEnd);
2254
2255
            window.resizeEnd = setTimeout(function () {
2256
                Overlay.windowResizeEvent.fire(); 
2257
            }, 100);
2258
        } else {
2259
            Overlay.windowResizeEvent.fire();
2260
        }
2261
    };
2262
2263
    /**
2264
    * A boolean that indicated whether the window resize and scroll events have 
2265
    * already been subscribed to.
2266
    * @property YAHOO.widget.Overlay._initialized
2267
    * @private
2268
    * @type Boolean
2269
    */
2270
    Overlay._initialized = null;
2271
2272
    if (Overlay._initialized === null) {
2273
        Event.on(window, "scroll", Overlay.windowScrollHandler);
2274
        Event.on(window, "resize", Overlay.windowResizeHandler);
2275
        Overlay._initialized = true;
2276
    }
2277
2278
    /**
2279
     * Internal map of special event types, which are provided
2280
     * by the instance. It maps the event type to the custom event 
2281
     * instance. Contains entries for the "windowScroll", "windowResize" and
2282
     * "textResize" static container events.
2283
     *
2284
     * @property YAHOO.widget.Overlay._TRIGGER_MAP
2285
     * @type Object
2286
     * @static
2287
     * @private
2288
     */
2289
    Overlay._TRIGGER_MAP = {
2290
        "windowScroll" : Overlay.windowScrollEvent,
2291
        "windowResize" : Overlay.windowResizeEvent,
2292
        "textResize"   : Module.textResizeEvent
2293
    };
2294
2295
    YAHOO.extend(Overlay, Module, {
2296
2297
        /**
2298
         * <p>
2299
         * Array of default event types which will trigger
2300
         * context alignment for the Overlay class.
2301
         * </p>
2302
         * <p>The array is empty by default for Overlay,
2303
         * but maybe populated in future releases, so classes extending
2304
         * Overlay which need to define their own set of CONTEXT_TRIGGERS
2305
         * should concatenate their super class's prototype.CONTEXT_TRIGGERS 
2306
         * value with their own array of values.
2307
         * </p>
2308
         * <p>
2309
         * E.g.:
2310
         * <code>CustomOverlay.prototype.CONTEXT_TRIGGERS = YAHOO.widget.Overlay.prototype.CONTEXT_TRIGGERS.concat(["windowScroll"]);</code>
2311
         * </p>
2312
         * 
2313
         * @property CONTEXT_TRIGGERS
2314
         * @type Array
2315
         * @final
2316
         */
2317
        CONTEXT_TRIGGERS : [],
2318
2319
        /**
2320
        * The Overlay initialization method, which is executed for Overlay and  
2321
        * all of its subclasses. This method is automatically called by the 
2322
        * constructor, and  sets up all DOM references for pre-existing markup, 
2323
        * and creates required markup if it is not already present.
2324
        * @method init
2325
        * @param {String} el The element ID representing the Overlay <em>OR</em>
2326
        * @param {HTMLElement} el The element representing the Overlay
2327
        * @param {Object} userConfig The configuration object literal 
2328
        * containing the configuration that should be set for this Overlay. 
2329
        * See configuration documentation for more details.
2330
        */
2331
        init: function (el, userConfig) {
2332
2333
            /*
2334
                 Note that we don't pass the user config in here yet because we
2335
                 only want it executed once, at the lowest subclass level
2336
            */
2337
2338
            Overlay.superclass.init.call(this, el/*, userConfig*/);
2339
2340
            this.beforeInitEvent.fire(Overlay);
2341
2342
            Dom.addClass(this.element, Overlay.CSS_OVERLAY);
2343
2344
            if (userConfig) {
2345
                this.cfg.applyConfig(userConfig, true);
2346
            }
2347
2348
            if (this.platform == "mac" && UA.gecko) {
2349
2350
                if (! Config.alreadySubscribed(this.showEvent,
2351
                    this.showMacGeckoScrollbars, this)) {
2352
2353
                    this.showEvent.subscribe(this.showMacGeckoScrollbars, 
2354
                        this, true);
2355
2356
                }
2357
2358
                if (! Config.alreadySubscribed(this.hideEvent, 
2359
                    this.hideMacGeckoScrollbars, this)) {
2360
2361
                    this.hideEvent.subscribe(this.hideMacGeckoScrollbars, 
2362
                        this, true);
2363
2364
                }
2365
            }
2366
2367
            this.initEvent.fire(Overlay);
2368
        },
2369
        
2370
        /**
2371
        * Initializes the custom events for Overlay which are fired  
2372
        * automatically at appropriate times by the Overlay class.
2373
        * @method initEvents
2374
        */
2375
        initEvents: function () {
2376
2377
            Overlay.superclass.initEvents.call(this);
2378
2379
            var SIGNATURE = CustomEvent.LIST;
2380
2381
            /**
2382
            * CustomEvent fired before the Overlay is moved.
2383
            * @event beforeMoveEvent
2384
            * @param {Number} x x coordinate
2385
            * @param {Number} y y coordinate
2386
            */
2387
            this.beforeMoveEvent = this.createEvent(EVENT_TYPES.BEFORE_MOVE);
2388
            this.beforeMoveEvent.signature = SIGNATURE;
2389
2390
            /**
2391
            * CustomEvent fired after the Overlay is moved.
2392
            * @event moveEvent
2393
            * @param {Number} x x coordinate
2394
            * @param {Number} y y coordinate
2395
            */
2396
            this.moveEvent = this.createEvent(EVENT_TYPES.MOVE);
2397
            this.moveEvent.signature = SIGNATURE;
2398
2399
        },
2400
        
2401
        /**
2402
        * Initializes the class's configurable properties which can be changed 
2403
        * using the Overlay's Config object (cfg).
2404
        * @method initDefaultConfig
2405
        */
2406
        initDefaultConfig: function () {
2407
    
2408
            Overlay.superclass.initDefaultConfig.call(this);
2409
2410
            var cfg = this.cfg;
2411
2412
            // Add overlay config properties //
2413
            
2414
            /**
2415
            * The absolute x-coordinate position of the Overlay
2416
            * @config x
2417
            * @type Number
2418
            * @default null
2419
            */
2420
            cfg.addProperty(DEFAULT_CONFIG.X.key, { 
2421
    
2422
                handler: this.configX, 
2423
                validator: DEFAULT_CONFIG.X.validator, 
2424
                suppressEvent: DEFAULT_CONFIG.X.suppressEvent, 
2425
                supercedes: DEFAULT_CONFIG.X.supercedes
2426
    
2427
            });
2428
2429
            /**
2430
            * The absolute y-coordinate position of the Overlay
2431
            * @config y
2432
            * @type Number
2433
            * @default null
2434
            */
2435
            cfg.addProperty(DEFAULT_CONFIG.Y.key, {
2436
2437
                handler: this.configY, 
2438
                validator: DEFAULT_CONFIG.Y.validator, 
2439
                suppressEvent: DEFAULT_CONFIG.Y.suppressEvent, 
2440
                supercedes: DEFAULT_CONFIG.Y.supercedes
2441
2442
            });
2443
2444
            /**
2445
            * An array with the absolute x and y positions of the Overlay
2446
            * @config xy
2447
            * @type Number[]
2448
            * @default null
2449
            */
2450
            cfg.addProperty(DEFAULT_CONFIG.XY.key, {
2451
                handler: this.configXY, 
2452
                suppressEvent: DEFAULT_CONFIG.XY.suppressEvent, 
2453
                supercedes: DEFAULT_CONFIG.XY.supercedes
2454
            });
2455
2456
            /**
2457
            * <p>
2458
            * The array of context arguments for context-sensitive positioning. 
2459
            * </p>
2460
            *
2461
            * <p>
2462
            * The format of the array is: <code>[contextElementOrId, overlayCorner, contextCorner, arrayOfTriggerEvents (optional), xyOffset (optional)]</code>, the
2463
            * the 5 array elements described in detail below:
2464
            * </p>
2465
            *
2466
            * <dl>
2467
            * <dt>contextElementOrId &#60;String|HTMLElement&#62;</dt>
2468
            * <dd>A reference to the context element to which the overlay should be aligned (or it's id).</dd>
2469
            * <dt>overlayCorner &#60;String&#62;</dt>
2470
            * <dd>The corner of the overlay which is to be used for alignment. This corner will be aligned to the 
2471
            * corner of the context element defined by the "contextCorner" entry which follows. Supported string values are: 
2472
            * "tr" (top right), "tl" (top left), "br" (bottom right), or "bl" (bottom left).</dd>
2473
            * <dt>contextCorner &#60;String&#62;</dt>
2474
            * <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>
2475
            * <dt>arrayOfTriggerEvents (optional) &#60;Array[String|CustomEvent]&#62;</dt>
2476
            * <dd>
2477
            * <p>
2478
            * 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> 
2479
            * 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. 
2480
            * This is useful in situations where the layout of the document may change, resulting in the context element's position being modified.
2481
            * </p>
2482
            * <p>
2483
            * The array can contain either event type strings for events the instance publishes (e.g. "beforeShow") or CustomEvent instances. Additionally the following
2484
            * 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).
2485
            * </p>
2486
            * </dd>
2487
            * <dt>xyOffset &#60;Number[]&#62;</dt>
2488
            * <dd>
2489
            * A 2 element Array specifying the X and Y pixel amounts by which the Overlay should be offset from the aligned corner. e.g. [5,0] offsets the Overlay 5 pixels to the left, <em>after</em> aligning the given context corners.
2490
            * NOTE: If using this property and no triggers need to be defined, the arrayOfTriggerEvents property should be set to null to maintain correct array positions for the arguments. 
2491
            * </dd>
2492
            * </dl>
2493
            *
2494
            * <p>
2495
            * For example, setting this property to <code>["img1", "tl", "bl"]</code> will 
2496
            * align the Overlay's top left corner to the bottom left corner of the
2497
            * context element with id "img1".
2498
            * </p>
2499
            * <p>
2500
            * Setting this property to <code>["img1", "tl", "bl", null, [0,5]</code> will 
2501
            * align the Overlay's top left corner to the bottom left corner of the
2502
            * context element with id "img1", and then offset it by 5 pixels on the Y axis (providing a 5 pixel gap between the bottom of the context element and top of the overlay).
2503
            * </p>
2504
            * <p>
2505
            * Adding the optional trigger values: <code>["img1", "tl", "bl", ["beforeShow", "windowResize"], [0,5]]</code>,
2506
            * will re-align the overlay position, whenever the "beforeShow" or "windowResize" events are fired.
2507
            * </p>
2508
            *
2509
            * @config context
2510
            * @type Array
2511
            * @default null
2512
            */
2513
            cfg.addProperty(DEFAULT_CONFIG.CONTEXT.key, {
2514
                handler: this.configContext, 
2515
                suppressEvent: DEFAULT_CONFIG.CONTEXT.suppressEvent, 
2516
                supercedes: DEFAULT_CONFIG.CONTEXT.supercedes
2517
            });
2518
2519
            /**
2520
            * Determines whether or not the Overlay should be anchored 
2521
            * to the center of the viewport.
2522
            * 
2523
            * <p>This property can be set to:</p>
2524
            * 
2525
            * <dl>
2526
            * <dt>true</dt>
2527
            * <dd>
2528
            * To enable fixed center positioning
2529
            * <p>
2530
            * When enabled, the overlay will 
2531
            * be positioned in the center of viewport when initially displayed, and 
2532
            * will remain in the center of the viewport whenever the window is 
2533
            * scrolled or resized.
2534
            * </p>
2535
            * <p>
2536
            * If the overlay is too big for the viewport, 
2537
            * it's top left corner will be aligned with the top left corner of the viewport.
2538
            * </p>
2539
            * </dd>
2540
            * <dt>false</dt>
2541
            * <dd>
2542
            * To disable fixed center positioning.
2543
            * <p>In this case the overlay can still be 
2544
            * centered as a one-off operation, by invoking the <code>center()</code> method,
2545
            * however it will not remain centered when the window is scrolled/resized.
2546
            * </dd>
2547
            * <dt>"contained"<dt>
2548
            * <dd>To enable fixed center positioning, as with the <code>true</code> option.
2549
            * <p>However, unlike setting the property to <code>true</code>, 
2550
            * when the property is set to <code>"contained"</code>, if the overlay is 
2551
            * too big for the viewport, it will not get automatically centered when the 
2552
            * user scrolls or resizes the window (until the window is large enough to contain the 
2553
            * overlay). This is useful in cases where the Overlay has both header and footer 
2554
            * UI controls which the user may need to access.
2555
            * </p>
2556
            * </dd>
2557
            * </dl>
2558
            *
2559
            * @config fixedcenter
2560
            * @type Boolean | String
2561
            * @default false
2562
            */
2563
            cfg.addProperty(DEFAULT_CONFIG.FIXED_CENTER.key, {
2564
                handler: this.configFixedCenter,
2565
                value: DEFAULT_CONFIG.FIXED_CENTER.value, 
2566
                validator: DEFAULT_CONFIG.FIXED_CENTER.validator, 
2567
                supercedes: DEFAULT_CONFIG.FIXED_CENTER.supercedes
2568
            });
2569
    
2570
            /**
2571
            * CSS width of the Overlay.
2572
            * @config width
2573
            * @type String
2574
            * @default null
2575
            */
2576
            cfg.addProperty(DEFAULT_CONFIG.WIDTH.key, {
2577
                handler: this.configWidth, 
2578
                suppressEvent: DEFAULT_CONFIG.WIDTH.suppressEvent, 
2579
                supercedes: DEFAULT_CONFIG.WIDTH.supercedes
2580
            });
2581
2582
            /**
2583
            * CSS height of the Overlay.
2584
            * @config height
2585
            * @type String
2586
            * @default null
2587
            */
2588
            cfg.addProperty(DEFAULT_CONFIG.HEIGHT.key, {
2589
                handler: this.configHeight, 
2590
                suppressEvent: DEFAULT_CONFIG.HEIGHT.suppressEvent, 
2591
                supercedes: DEFAULT_CONFIG.HEIGHT.supercedes
2592
            });
2593
2594
            /**
2595
            * Standard module element which should auto fill out the height of the Overlay if the height config property is set.
2596
            * Supported values are "header", "body", "footer".
2597
            *
2598
            * @config autofillheight
2599
            * @type String
2600
            * @default null
2601
            */
2602
            cfg.addProperty(DEFAULT_CONFIG.AUTO_FILL_HEIGHT.key, {
2603
                handler: this.configAutoFillHeight, 
2604
                value : DEFAULT_CONFIG.AUTO_FILL_HEIGHT.value,
2605
                validator : this._validateAutoFill,
2606
                supercedes: DEFAULT_CONFIG.AUTO_FILL_HEIGHT.supercedes
2607
            });
2608
2609
            /**
2610
            * CSS z-index of the Overlay.
2611
            * @config zIndex
2612
            * @type Number
2613
            * @default null
2614
            */
2615
            cfg.addProperty(DEFAULT_CONFIG.ZINDEX.key, {
2616
                handler: this.configzIndex,
2617
                value: DEFAULT_CONFIG.ZINDEX.value
2618
            });
2619
2620
            /**
2621
            * True if the Overlay should be prevented from being positioned 
2622
            * out of the viewport.
2623
            * @config constraintoviewport
2624
            * @type Boolean
2625
            * @default false
2626
            */
2627
            cfg.addProperty(DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.key, {
2628
2629
                handler: this.configConstrainToViewport, 
2630
                value: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.value, 
2631
                validator: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.validator, 
2632
                supercedes: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.supercedes
2633
2634
            });
2635
2636
            /**
2637
            * @config iframe
2638
            * @description Boolean indicating whether or not the Overlay should 
2639
            * have an IFRAME shim; used to prevent SELECT elements from 
2640
            * poking through an Overlay instance in IE6.  When set to "true", 
2641
            * the iframe shim is created when the Overlay instance is intially
2642
            * made visible.
2643
            * @type Boolean
2644
            * @default true for IE6 and below, false for all other browsers.
2645
            */
2646
            cfg.addProperty(DEFAULT_CONFIG.IFRAME.key, {
2647
2648
                handler: this.configIframe, 
2649
                value: DEFAULT_CONFIG.IFRAME.value, 
2650
                validator: DEFAULT_CONFIG.IFRAME.validator, 
2651
                supercedes: DEFAULT_CONFIG.IFRAME.supercedes
2652
2653
            });
2654
2655
            /**
2656
            * @config preventcontextoverlap
2657
            * @description Boolean indicating whether or not the Overlay should overlap its 
2658
            * context element (defined using the "context" configuration property) when the 
2659
            * "constraintoviewport" configuration property is set to "true".
2660
            * @type Boolean
2661
            * @default false
2662
            */
2663
            cfg.addProperty(DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.key, {
2664
                value: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.value, 
2665
                validator: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.validator, 
2666
                supercedes: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.supercedes
2667
            });
2668
        },
2669
2670
        /**
2671
        * Moves the Overlay to the specified position. This function is  
2672
        * identical to calling this.cfg.setProperty("xy", [x,y]);
2673
        * @method moveTo
2674
        * @param {Number} x The Overlay's new x position
2675
        * @param {Number} y The Overlay's new y position
2676
        */
2677
        moveTo: function (x, y) {
2678
            this.cfg.setProperty("xy", [x, y]);
2679
        },
2680
2681
        /**
2682
        * Adds a CSS class ("hide-scrollbars") and removes a CSS class 
2683
        * ("show-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
2684
        * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2685
        * @method hideMacGeckoScrollbars
2686
        */
2687
        hideMacGeckoScrollbars: function () {
2688
            Dom.replaceClass(this.element, "show-scrollbars", "hide-scrollbars");
2689
        },
2690
2691
        /**
2692
        * Adds a CSS class ("show-scrollbars") and removes a CSS class 
2693
        * ("hide-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
2694
        * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2695
        * @method showMacGeckoScrollbars
2696
        */
2697
        showMacGeckoScrollbars: function () {
2698
            Dom.replaceClass(this.element, "hide-scrollbars", "show-scrollbars");
2699
        },
2700
2701
        /**
2702
         * Internal implementation to set the visibility of the overlay in the DOM.
2703
         *
2704
         * @method _setDomVisibility
2705
         * @param {boolean} visible Whether to show or hide the Overlay's outer element
2706
         * @protected
2707
         */
2708
        _setDomVisibility : function(show) {
2709
            Dom.setStyle(this.element, "visibility", (show) ? "visible" : "hidden");
2710
            var hiddenClass = Overlay.CSS_HIDDEN;
2711
2712
            if (show) {
2713
                Dom.removeClass(this.element, hiddenClass);
2714
            } else {
2715
                Dom.addClass(this.element, hiddenClass);
2716
            }
2717
        },
2718
2719
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
2720
        /**
2721
        * The default event handler fired when the "visible" property is 
2722
        * changed.  This method is responsible for firing showEvent
2723
        * and hideEvent.
2724
        * @method configVisible
2725
        * @param {String} type The CustomEvent type (usually the property name)
2726
        * @param {Object[]} args The CustomEvent arguments. For configuration
2727
        * handlers, args[0] will equal the newly applied value for the property.
2728
        * @param {Object} obj The scope object. For configuration handlers, 
2729
        * this will usually equal the owner.
2730
        */
2731
        configVisible: function (type, args, obj) {
2732
2733
            var visible = args[0],
2734
                currentVis = Dom.getStyle(this.element, "visibility"),
2735
                effect = this.cfg.getProperty("effect"),
2736
                effectInstances = [],
2737
                isMacGecko = (this.platform == "mac" && UA.gecko),
2738
                alreadySubscribed = Config.alreadySubscribed,
2739
                eff, ei, e, i, j, k, h,
2740
                nEffects,
2741
                nEffectInstances;
2742
2743
            if (currentVis == "inherit") {
2744
                e = this.element.parentNode;
2745
2746
                while (e.nodeType != 9 && e.nodeType != 11) {
2747
                    currentVis = Dom.getStyle(e, "visibility");
2748
2749
                    if (currentVis != "inherit") {
2750
                        break;
2751
                    }
2752
2753
                    e = e.parentNode;
2754
                }
2755
2756
                if (currentVis == "inherit") {
2757
                    currentVis = "visible";
2758
                }
2759
            }
2760
2761
            if (effect) {
2762
                if (effect instanceof Array) {
2763
                    nEffects = effect.length;
2764
2765
                    for (i = 0; i < nEffects; i++) {
2766
                        eff = effect[i];
2767
                        effectInstances[effectInstances.length] = 
2768
                            eff.effect(this, eff.duration);
2769
2770
                    }
2771
                } else {
2772
                    effectInstances[effectInstances.length] = 
2773
                        effect.effect(this, effect.duration);
2774
                }
2775
            }
2776
2777
            if (visible) { // Show
2778
                if (isMacGecko) {
2779
                    this.showMacGeckoScrollbars();
2780
                }
2781
2782
                if (effect) { // Animate in
2783
                    if (visible) { // Animate in if not showing
2784
                        if (currentVis != "visible" || currentVis === "") {
2785
                            this.beforeShowEvent.fire();
2786
                            nEffectInstances = effectInstances.length;
2787
2788
                            for (j = 0; j < nEffectInstances; j++) {
2789
                                ei = effectInstances[j];
2790
                                if (j === 0 && !alreadySubscribed(
2791
                                        ei.animateInCompleteEvent, 
2792
                                        this.showEvent.fire, this.showEvent)) {
2793
2794
                                    /*
2795
                                         Delegate showEvent until end 
2796
                                         of animateInComplete
2797
                                    */
2798
2799
                                    ei.animateInCompleteEvent.subscribe(
2800
                                     this.showEvent.fire, this.showEvent, true);
2801
                                }
2802
                                ei.animateIn();
2803
                            }
2804
                        }
2805
                    }
2806
                } else { // Show
2807
                    if (currentVis != "visible" || currentVis === "") {
2808
                        this.beforeShowEvent.fire();
2809
2810
                        this._setDomVisibility(true);
2811
2812
                        this.cfg.refireEvent("iframe");
2813
                        this.showEvent.fire();
2814
                    } else {
2815
                        this._setDomVisibility(true);
2816
                    }
2817
                }
2818
            } else { // Hide
2819
2820
                if (isMacGecko) {
2821
                    this.hideMacGeckoScrollbars();
2822
                }
2823
2824
                if (effect) { // Animate out if showing
2825
                    if (currentVis == "visible") {
2826
                        this.beforeHideEvent.fire();
2827
2828
                        nEffectInstances = effectInstances.length;
2829
                        for (k = 0; k < nEffectInstances; k++) {
2830
                            h = effectInstances[k];
2831
    
2832
                            if (k === 0 && !alreadySubscribed(
2833
                                h.animateOutCompleteEvent, this.hideEvent.fire, 
2834
                                this.hideEvent)) {
2835
    
2836
                                /*
2837
                                     Delegate hideEvent until end 
2838
                                     of animateOutComplete
2839
                                */
2840
    
2841
                                h.animateOutCompleteEvent.subscribe(
2842
                                    this.hideEvent.fire, this.hideEvent, true);
2843
    
2844
                            }
2845
                            h.animateOut();
2846
                        }
2847
2848
                    } else if (currentVis === "") {
2849
                        this._setDomVisibility(false);
2850
                    }
2851
2852
                } else { // Simple hide
2853
2854
                    if (currentVis == "visible" || currentVis === "") {
2855
                        this.beforeHideEvent.fire();
2856
                        this._setDomVisibility(false);
2857
                        this.hideEvent.fire();
2858
                    } else {
2859
                        this._setDomVisibility(false);
2860
                    }
2861
                }
2862
            }
2863
        },
2864
2865
        /**
2866
        * Fixed center event handler used for centering on scroll/resize, but only if 
2867
        * the overlay is visible and, if "fixedcenter" is set to "contained", only if 
2868
        * the overlay fits within the viewport.
2869
        *
2870
        * @method doCenterOnDOMEvent
2871
        */
2872
        doCenterOnDOMEvent: function () {
2873
            var cfg = this.cfg,
2874
                fc = cfg.getProperty("fixedcenter");
2875
2876
            if (cfg.getProperty("visible")) {
2877
                if (fc && (fc !== _CONTAINED || this.fitsInViewport())) {
2878
                    this.center();
2879
                }
2880
            }
2881
        },
2882
2883
        /**
2884
         * Determines if the Overlay (including the offset value defined by Overlay.VIEWPORT_OFFSET) 
2885
         * will fit entirely inside the viewport, in both dimensions - width and height.
2886
         * 
2887
         * @method fitsInViewport
2888
         * @return boolean true if the Overlay will fit, false if not
2889
         */
2890
        fitsInViewport : function() {
2891
            var nViewportOffset = Overlay.VIEWPORT_OFFSET,
2892
                element = this.element,
2893
                elementWidth = element.offsetWidth,
2894
                elementHeight = element.offsetHeight,
2895
                viewportWidth = Dom.getViewportWidth(),
2896
                viewportHeight = Dom.getViewportHeight();
2897
2898
            return ((elementWidth + nViewportOffset < viewportWidth) && (elementHeight + nViewportOffset < viewportHeight));
2899
        },
2900
2901
        /**
2902
        * The default event handler fired when the "fixedcenter" property 
2903
        * is changed.
2904
        * @method configFixedCenter
2905
        * @param {String} type The CustomEvent type (usually the property name)
2906
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2907
        * handlers, args[0] will equal the newly applied value for the property.
2908
        * @param {Object} obj The scope object. For configuration handlers, 
2909
        * this will usually equal the owner.
2910
        */
2911
        configFixedCenter: function (type, args, obj) {
2912
2913
            var val = args[0],
2914
                alreadySubscribed = Config.alreadySubscribed,
2915
                windowResizeEvent = Overlay.windowResizeEvent,
2916
                windowScrollEvent = Overlay.windowScrollEvent;
2917
2918
            if (val) {
2919
                this.center();
2920
2921
                if (!alreadySubscribed(this.beforeShowEvent, this.center)) {
2922
                    this.beforeShowEvent.subscribe(this.center);
2923
                }
2924
2925
                if (!alreadySubscribed(windowResizeEvent, this.doCenterOnDOMEvent, this)) {
2926
                    windowResizeEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2927
                }
2928
2929
                if (!alreadySubscribed(windowScrollEvent, this.doCenterOnDOMEvent, this)) {
2930
                    windowScrollEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2931
                }
2932
2933
            } else {
2934
                this.beforeShowEvent.unsubscribe(this.center);
2935
2936
                windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2937
                windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2938
            }
2939
        },
2940
2941
        /**
2942
        * The default event handler fired when the "height" property is changed.
2943
        * @method configHeight
2944
        * @param {String} type The CustomEvent type (usually the property name)
2945
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2946
        * handlers, args[0] will equal the newly applied value for the property.
2947
        * @param {Object} obj The scope object. For configuration handlers, 
2948
        * this will usually equal the owner.
2949
        */
2950
        configHeight: function (type, args, obj) {
2951
2952
            var height = args[0],
2953
                el = this.element;
2954
2955
            Dom.setStyle(el, "height", height);
2956
            this.cfg.refireEvent("iframe");
2957
        },
2958
2959
        /**
2960
         * The default event handler fired when the "autofillheight" property is changed.
2961
         * @method configAutoFillHeight
2962
         *
2963
         * @param {String} type The CustomEvent type (usually the property name)
2964
         * @param {Object[]} args The CustomEvent arguments. For configuration 
2965
         * handlers, args[0] will equal the newly applied value for the property.
2966
         * @param {Object} obj The scope object. For configuration handlers, 
2967
         * this will usually equal the owner.
2968
         */
2969
        configAutoFillHeight: function (type, args, obj) {
2970
            var fillEl = args[0],
2971
                cfg = this.cfg,
2972
                autoFillHeight = "autofillheight",
2973
                height = "height",
2974
                currEl = cfg.getProperty(autoFillHeight),
2975
                autoFill = this._autoFillOnHeightChange;
2976
2977
            cfg.unsubscribeFromConfigEvent(height, autoFill);
2978
            Module.textResizeEvent.unsubscribe(autoFill);
2979
            this.changeContentEvent.unsubscribe(autoFill);
2980
2981
            if (currEl && fillEl !== currEl && this[currEl]) {
2982
                Dom.setStyle(this[currEl], height, "");
2983
            }
2984
2985
            if (fillEl) {
2986
                fillEl = Lang.trim(fillEl.toLowerCase());
2987
2988
                cfg.subscribeToConfigEvent(height, autoFill, this[fillEl], this);
2989
                Module.textResizeEvent.subscribe(autoFill, this[fillEl], this);
2990
                this.changeContentEvent.subscribe(autoFill, this[fillEl], this);
2991
2992
                cfg.setProperty(autoFillHeight, fillEl, true);
2993
            }
2994
        },
2995
2996
        /**
2997
        * The default event handler fired when the "width" property is changed.
2998
        * @method configWidth
2999
        * @param {String} type The CustomEvent type (usually the property name)
3000
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3001
        * handlers, args[0] will equal the newly applied value for the property.
3002
        * @param {Object} obj The scope object. For configuration handlers, 
3003
        * this will usually equal the owner.
3004
        */
3005
        configWidth: function (type, args, obj) {
3006
3007
            var width = args[0],
3008
                el = this.element;
3009
3010
            Dom.setStyle(el, "width", width);
3011
            this.cfg.refireEvent("iframe");
3012
        },
3013
3014
        /**
3015
        * The default event handler fired when the "zIndex" property is changed.
3016
        * @method configzIndex
3017
        * @param {String} type The CustomEvent type (usually the property name)
3018
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3019
        * handlers, args[0] will equal the newly applied value for the property.
3020
        * @param {Object} obj The scope object. For configuration handlers, 
3021
        * this will usually equal the owner.
3022
        */
3023
        configzIndex: function (type, args, obj) {
3024
3025
            var zIndex = args[0],
3026
                el = this.element;
3027
3028
            if (! zIndex) {
3029
                zIndex = Dom.getStyle(el, "zIndex");
3030
                if (! zIndex || isNaN(zIndex)) {
3031
                    zIndex = 0;
3032
                }
3033
            }
3034
3035
            if (this.iframe || this.cfg.getProperty("iframe") === true) {
3036
                if (zIndex <= 0) {
3037
                    zIndex = 1;
3038
                }
3039
            }
3040
3041
            Dom.setStyle(el, "zIndex", zIndex);
3042
            this.cfg.setProperty("zIndex", zIndex, true);
3043
3044
            if (this.iframe) {
3045
                this.stackIframe();
3046
            }
3047
        },
3048
3049
        /**
3050
        * The default event handler fired when the "xy" property is changed.
3051
        * @method configXY
3052
        * @param {String} type The CustomEvent type (usually the property name)
3053
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3054
        * handlers, args[0] will equal the newly applied value for the property.
3055
        * @param {Object} obj The scope object. For configuration handlers, 
3056
        * this will usually equal the owner.
3057
        */
3058
        configXY: function (type, args, obj) {
3059
3060
            var pos = args[0],
3061
                x = pos[0],
3062
                y = pos[1];
3063
3064
            this.cfg.setProperty("x", x);
3065
            this.cfg.setProperty("y", y);
3066
3067
            this.beforeMoveEvent.fire([x, y]);
3068
3069
            x = this.cfg.getProperty("x");
3070
            y = this.cfg.getProperty("y");
3071
3072
            YAHOO.log(("xy: " + [x, y]), "iframe");
3073
3074
            this.cfg.refireEvent("iframe");
3075
            this.moveEvent.fire([x, y]);
3076
        },
3077
3078
        /**
3079
        * The default event handler fired when the "x" property is changed.
3080
        * @method configX
3081
        * @param {String} type The CustomEvent type (usually the property name)
3082
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3083
        * handlers, args[0] will equal the newly applied value for the property.
3084
        * @param {Object} obj The scope object. For configuration handlers, 
3085
        * this will usually equal the owner.
3086
        */
3087
        configX: function (type, args, obj) {
3088
3089
            var x = args[0],
3090
                y = this.cfg.getProperty("y");
3091
3092
            this.cfg.setProperty("x", x, true);
3093
            this.cfg.setProperty("y", y, true);
3094
3095
            this.beforeMoveEvent.fire([x, y]);
3096
3097
            x = this.cfg.getProperty("x");
3098
            y = this.cfg.getProperty("y");
3099
3100
            Dom.setX(this.element, x, true);
3101
3102
            this.cfg.setProperty("xy", [x, y], true);
3103
3104
            this.cfg.refireEvent("iframe");
3105
            this.moveEvent.fire([x, y]);
3106
        },
3107
3108
        /**
3109
        * The default event handler fired when the "y" property is changed.
3110
        * @method configY
3111
        * @param {String} type The CustomEvent type (usually the property name)
3112
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3113
        * handlers, args[0] will equal the newly applied value for the property.
3114
        * @param {Object} obj The scope object. For configuration handlers, 
3115
        * this will usually equal the owner.
3116
        */
3117
        configY: function (type, args, obj) {
3118
3119
            var x = this.cfg.getProperty("x"),
3120
                y = args[0];
3121
3122
            this.cfg.setProperty("x", x, true);
3123
            this.cfg.setProperty("y", y, true);
3124
3125
            this.beforeMoveEvent.fire([x, y]);
3126
3127
            x = this.cfg.getProperty("x");
3128
            y = this.cfg.getProperty("y");
3129
3130
            Dom.setY(this.element, y, true);
3131
3132
            this.cfg.setProperty("xy", [x, y], true);
3133
3134
            this.cfg.refireEvent("iframe");
3135
            this.moveEvent.fire([x, y]);
3136
        },
3137
        
3138
        /**
3139
        * Shows the iframe shim, if it has been enabled.
3140
        * @method showIframe
3141
        */
3142
        showIframe: function () {
3143
3144
            var oIFrame = this.iframe,
3145
                oParentNode;
3146
3147
            if (oIFrame) {
3148
                oParentNode = this.element.parentNode;
3149
3150
                if (oParentNode != oIFrame.parentNode) {
3151
                    this._addToParent(oParentNode, oIFrame);
3152
                }
3153
                oIFrame.style.display = "block";
3154
            }
3155
        },
3156
3157
        /**
3158
        * Hides the iframe shim, if it has been enabled.
3159
        * @method hideIframe
3160
        */
3161
        hideIframe: function () {
3162
            if (this.iframe) {
3163
                this.iframe.style.display = "none";
3164
            }
3165
        },
3166
3167
        /**
3168
        * Syncronizes the size and position of iframe shim to that of its 
3169
        * corresponding Overlay instance.
3170
        * @method syncIframe
3171
        */
3172
        syncIframe: function () {
3173
3174
            var oIFrame = this.iframe,
3175
                oElement = this.element,
3176
                nOffset = Overlay.IFRAME_OFFSET,
3177
                nDimensionOffset = (nOffset * 2),
3178
                aXY;
3179
3180
            if (oIFrame) {
3181
                // Size <iframe>
3182
                oIFrame.style.width = (oElement.offsetWidth + nDimensionOffset + "px");
3183
                oIFrame.style.height = (oElement.offsetHeight + nDimensionOffset + "px");
3184
3185
                // Position <iframe>
3186
                aXY = this.cfg.getProperty("xy");
3187
3188
                if (!Lang.isArray(aXY) || (isNaN(aXY[0]) || isNaN(aXY[1]))) {
3189
                    this.syncPosition();
3190
                    aXY = this.cfg.getProperty("xy");
3191
                }
3192
                Dom.setXY(oIFrame, [(aXY[0] - nOffset), (aXY[1] - nOffset)]);
3193
            }
3194
        },
3195
3196
        /**
3197
         * Sets the zindex of the iframe shim, if it exists, based on the zindex of
3198
         * the Overlay element. The zindex of the iframe is set to be one less 
3199
         * than the Overlay element's zindex.
3200
         * 
3201
         * <p>NOTE: This method will not bump up the zindex of the Overlay element
3202
         * to ensure that the iframe shim has a non-negative zindex.
3203
         * If you require the iframe zindex to be 0 or higher, the zindex of 
3204
         * the Overlay element should be set to a value greater than 0, before 
3205
         * this method is called.
3206
         * </p>
3207
         * @method stackIframe
3208
         */
3209
        stackIframe: function () {
3210
            if (this.iframe) {
3211
                var overlayZ = Dom.getStyle(this.element, "zIndex");
3212
                if (!YAHOO.lang.isUndefined(overlayZ) && !isNaN(overlayZ)) {
3213
                    Dom.setStyle(this.iframe, "zIndex", (overlayZ - 1));
3214
                }
3215
            }
3216
        },
3217
3218
        /**
3219
        * The default event handler fired when the "iframe" property is changed.
3220
        * @method configIframe
3221
        * @param {String} type The CustomEvent type (usually the property name)
3222
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3223
        * handlers, args[0] will equal the newly applied value for the property.
3224
        * @param {Object} obj The scope object. For configuration handlers, 
3225
        * this will usually equal the owner.
3226
        */
3227
        configIframe: function (type, args, obj) {
3228
3229
            var bIFrame = args[0];
3230
3231
            function createIFrame() {
3232
3233
                var oIFrame = this.iframe,
3234
                    oElement = this.element,
3235
                    oParent;
3236
3237
                if (!oIFrame) {
3238
                    if (!m_oIFrameTemplate) {
3239
                        m_oIFrameTemplate = document.createElement("iframe");
3240
3241
                        if (this.isSecure) {
3242
                            m_oIFrameTemplate.src = Overlay.IFRAME_SRC;
3243
                        }
3244
3245
                        /*
3246
                            Set the opacity of the <iframe> to 0 so that it 
3247
                            doesn't modify the opacity of any transparent 
3248
                            elements that may be on top of it (like a shadow).
3249
                        */
3250
                        if (UA.ie) {
3251
                            m_oIFrameTemplate.style.filter = "alpha(opacity=0)";
3252
                            /*
3253
                                 Need to set the "frameBorder" property to 0 
3254
                                 supress the default <iframe> border in IE.  
3255
                                 Setting the CSS "border" property alone 
3256
                                 doesn't supress it.
3257
                            */
3258
                            m_oIFrameTemplate.frameBorder = 0;
3259
                        }
3260
                        else {
3261
                            m_oIFrameTemplate.style.opacity = "0";
3262
                        }
3263
3264
                        m_oIFrameTemplate.style.position = "absolute";
3265
                        m_oIFrameTemplate.style.border = "none";
3266
                        m_oIFrameTemplate.style.margin = "0";
3267
                        m_oIFrameTemplate.style.padding = "0";
3268
                        m_oIFrameTemplate.style.display = "none";
3269
                        m_oIFrameTemplate.tabIndex = -1;
3270
                        m_oIFrameTemplate.className = Overlay.CSS_IFRAME;
3271
                    }
3272
3273
                    oIFrame = m_oIFrameTemplate.cloneNode(false);
3274
                    oIFrame.id = this.id + "_f";
3275
                    oParent = oElement.parentNode;
3276
3277
                    var parentNode = oParent || document.body;
3278
3279
                    this._addToParent(parentNode, oIFrame);
3280
                    this.iframe = oIFrame;
3281
                }
3282
3283
                /*
3284
                     Show the <iframe> before positioning it since the "setXY" 
3285
                     method of DOM requires the element be in the document 
3286
                     and visible.
3287
                */
3288
                this.showIframe();
3289
3290
                /*
3291
                     Syncronize the size and position of the <iframe> to that 
3292
                     of the Overlay.
3293
                */
3294
                this.syncIframe();
3295
                this.stackIframe();
3296
3297
                // Add event listeners to update the <iframe> when necessary
3298
                if (!this._hasIframeEventListeners) {
3299
                    this.showEvent.subscribe(this.showIframe);
3300
                    this.hideEvent.subscribe(this.hideIframe);
3301
                    this.changeContentEvent.subscribe(this.syncIframe);
3302
3303
                    this._hasIframeEventListeners = true;
3304
                }
3305
            }
3306
3307
            function onBeforeShow() {
3308
                createIFrame.call(this);
3309
                this.beforeShowEvent.unsubscribe(onBeforeShow);
3310
                this._iframeDeferred = false;
3311
            }
3312
3313
            if (bIFrame) { // <iframe> shim is enabled
3314
3315
                if (this.cfg.getProperty("visible")) {
3316
                    createIFrame.call(this);
3317
                } else {
3318
                    if (!this._iframeDeferred) {
3319
                        this.beforeShowEvent.subscribe(onBeforeShow);
3320
                        this._iframeDeferred = true;
3321
                    }
3322
                }
3323
3324
            } else {    // <iframe> shim is disabled
3325
                this.hideIframe();
3326
3327
                if (this._hasIframeEventListeners) {
3328
                    this.showEvent.unsubscribe(this.showIframe);
3329
                    this.hideEvent.unsubscribe(this.hideIframe);
3330
                    this.changeContentEvent.unsubscribe(this.syncIframe);
3331
3332
                    this._hasIframeEventListeners = false;
3333
                }
3334
            }
3335
        },
3336
3337
        /**
3338
         * Set's the container's XY value from DOM if not already set.
3339
         * 
3340
         * Differs from syncPosition, in that the XY value is only sync'd with DOM if 
3341
         * not already set. The method also refire's the XY config property event, so any
3342
         * beforeMove, Move event listeners are invoked.
3343
         * 
3344
         * @method _primeXYFromDOM
3345
         * @protected
3346
         */
3347
        _primeXYFromDOM : function() {
3348
            if (YAHOO.lang.isUndefined(this.cfg.getProperty("xy"))) {
3349
                // Set CFG XY based on DOM XY
3350
                this.syncPosition();
3351
                // Account for XY being set silently in syncPosition (no moveTo fired/called)
3352
                this.cfg.refireEvent("xy");
3353
                this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
3354
            }
3355
        },
3356
3357
        /**
3358
        * The default event handler fired when the "constraintoviewport" 
3359
        * property is changed.
3360
        * @method configConstrainToViewport
3361
        * @param {String} type The CustomEvent type (usually the property name)
3362
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3363
        * handlers, args[0] will equal the newly applied value for 
3364
        * the property.
3365
        * @param {Object} obj The scope object. For configuration handlers, 
3366
        * this will usually equal the owner.
3367
        */
3368
        configConstrainToViewport: function (type, args, obj) {
3369
            var val = args[0];
3370
3371
            if (val) {
3372
                if (! Config.alreadySubscribed(this.beforeMoveEvent, this.enforceConstraints, this)) {
3373
                    this.beforeMoveEvent.subscribe(this.enforceConstraints, this, true);
3374
                }
3375
                if (! Config.alreadySubscribed(this.beforeShowEvent, this._primeXYFromDOM)) {
3376
                    this.beforeShowEvent.subscribe(this._primeXYFromDOM);
3377
                }
3378
            } else {
3379
                this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
3380
                this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
3381
            }
3382
        },
3383
3384
         /**
3385
        * The default event handler fired when the "context" property
3386
        * is changed.
3387
        *
3388
        * @method configContext
3389
        * @param {String} type The CustomEvent type (usually the property name)
3390
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3391
        * handlers, args[0] will equal the newly applied value for the property.
3392
        * @param {Object} obj The scope object. For configuration handlers, 
3393
        * this will usually equal the owner.
3394
        */
3395
        configContext: function (type, args, obj) {
3396
3397
            var contextArgs = args[0],
3398
                contextEl,
3399
                elementMagnetCorner,
3400
                contextMagnetCorner,
3401
                triggers,
3402
                offset,
3403
                defTriggers = this.CONTEXT_TRIGGERS;
3404
3405
            if (contextArgs) {
3406
3407
                contextEl = contextArgs[0];
3408
                elementMagnetCorner = contextArgs[1];
3409
                contextMagnetCorner = contextArgs[2];
3410
                triggers = contextArgs[3];
3411
                offset = contextArgs[4];
3412
3413
                if (defTriggers && defTriggers.length > 0) {
3414
                    triggers = (triggers || []).concat(defTriggers);
3415
                }
3416
3417
                if (contextEl) {
3418
                    if (typeof contextEl == "string") {
3419
                        this.cfg.setProperty("context", [
3420
                                document.getElementById(contextEl), 
3421
                                elementMagnetCorner,
3422
                                contextMagnetCorner,
3423
                                triggers,
3424
                                offset],
3425
                                true);
3426
                    }
3427
3428
                    if (elementMagnetCorner && contextMagnetCorner) {
3429
                        this.align(elementMagnetCorner, contextMagnetCorner, offset);
3430
                    }
3431
3432
                    if (this._contextTriggers) {
3433
                        // Unsubscribe Old Set
3434
                        this._processTriggers(this._contextTriggers, _UNSUBSCRIBE, this._alignOnTrigger);
3435
                    }
3436
3437
                    if (triggers) {
3438
                        // Subscribe New Set
3439
                        this._processTriggers(triggers, _SUBSCRIBE, this._alignOnTrigger);
3440
                        this._contextTriggers = triggers;
3441
                    }
3442
                }
3443
            }
3444
        },
3445
3446
        /**
3447
         * Custom Event handler for context alignment triggers. Invokes the align method
3448
         * 
3449
         * @method _alignOnTrigger
3450
         * @protected
3451
         * 
3452
         * @param {String} type The event type (not used by the default implementation)
3453
         * @param {Any[]} args The array of arguments for the trigger event (not used by the default implementation)
3454
         */
3455
        _alignOnTrigger: function(type, args) {
3456
            this.align();
3457
        },
3458
3459
        /**
3460
         * Helper method to locate the custom event instance for the event name string
3461
         * passed in. As a convenience measure, any custom events passed in are returned.
3462
         *
3463
         * @method _findTriggerCE
3464
         * @private
3465
         *
3466
         * @param {String|CustomEvent} t Either a CustomEvent, or event type (e.g. "windowScroll") for which a 
3467
         * custom event instance needs to be looked up from the Overlay._TRIGGER_MAP.
3468
         */
3469
        _findTriggerCE : function(t) {
3470
            var tce = null;
3471
            if (t instanceof CustomEvent) {
3472
                tce = t;
3473
            } else if (Overlay._TRIGGER_MAP[t]) {
3474
                tce = Overlay._TRIGGER_MAP[t];
3475
            }
3476
            return tce;
3477
        },
3478
3479
        /**
3480
         * Utility method that subscribes or unsubscribes the given 
3481
         * function from the list of trigger events provided.
3482
         *
3483
         * @method _processTriggers
3484
         * @protected 
3485
         *
3486
         * @param {Array[String|CustomEvent]} triggers An array of either CustomEvents, event type strings 
3487
         * (e.g. "beforeShow", "windowScroll") to/from which the provided function should be 
3488
         * subscribed/unsubscribed respectively.
3489
         *
3490
         * @param {String} mode Either "subscribe" or "unsubscribe", specifying whether or not
3491
         * we are subscribing or unsubscribing trigger listeners
3492
         * 
3493
         * @param {Function} fn The function to be subscribed/unsubscribed to/from the trigger event.
3494
         * Context is always set to the overlay instance, and no additional object argument 
3495
         * get passed to the subscribed function.
3496
         */
3497
        _processTriggers : function(triggers, mode, fn) {
3498
            var t, tce;
3499
3500
            for (var i = 0, l = triggers.length; i < l; ++i) {
3501
                t = triggers[i];
3502
                tce = this._findTriggerCE(t);
3503
                if (tce) {
3504
                    tce[mode](fn, this, true);
3505
                } else {
3506
                    this[mode](t, fn);
3507
                }
3508
            }
3509
        },
3510
3511
        // END BUILT-IN PROPERTY EVENT HANDLERS //
3512
        /**
3513
        * Aligns the Overlay to its context element using the specified corner 
3514
        * points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, 
3515
        * and BOTTOM_RIGHT.
3516
        * @method align
3517
        * @param {String} elementAlign  The String representing the corner of 
3518
        * the Overlay that should be aligned to the context element
3519
        * @param {String} contextAlign  The corner of the context element 
3520
        * that the elementAlign corner should stick to.
3521
        * @param {Number[]} xyOffset Optional. A 2 element array specifying the x and y pixel offsets which should be applied
3522
        * after aligning the element and context corners. For example, passing in [5, -10] for this value, would offset the 
3523
        * Overlay by 5 pixels along the X axis (horizontally) and -10 pixels along the Y axis (vertically) after aligning the specified corners.
3524
        */
3525
        align: function (elementAlign, contextAlign, xyOffset) {
3526
3527
            var contextArgs = this.cfg.getProperty("context"),
3528
                me = this,
3529
                context,
3530
                element,
3531
                contextRegion;
3532
3533
            function doAlign(v, h) {
3534
3535
                var alignX = null, alignY = null;
3536
3537
                switch (elementAlign) {
3538
    
3539
                    case Overlay.TOP_LEFT:
3540
                        alignX = h;
3541
                        alignY = v;
3542
                        break;
3543
        
3544
                    case Overlay.TOP_RIGHT:
3545
                        alignX = h - element.offsetWidth;
3546
                        alignY = v;
3547
                        break;
3548
        
3549
                    case Overlay.BOTTOM_LEFT:
3550
                        alignX = h;
3551
                        alignY = v - element.offsetHeight;
3552
                        break;
3553
        
3554
                    case Overlay.BOTTOM_RIGHT:
3555
                        alignX = h - element.offsetWidth; 
3556
                        alignY = v - element.offsetHeight;
3557
                        break;
3558
                }
3559
3560
                if (alignX !== null && alignY !== null) {
3561
                    if (xyOffset) {
3562
                        alignX += xyOffset[0];
3563
                        alignY += xyOffset[1];
3564
                    }
3565
                    me.moveTo(alignX, alignY);
3566
                }
3567
            }
3568
3569
            if (contextArgs) {
3570
                context = contextArgs[0];
3571
                element = this.element;
3572
                me = this;
3573
3574
                if (! elementAlign) {
3575
                    elementAlign = contextArgs[1];
3576
                }
3577
3578
                if (! contextAlign) {
3579
                    contextAlign = contextArgs[2];
3580
                }
3581
3582
                if (!xyOffset && contextArgs[4]) {
3583
                    xyOffset = contextArgs[4];
3584
                }
3585
3586
                if (element && context) {
3587
                    contextRegion = Dom.getRegion(context);
3588
3589
                    switch (contextAlign) {
3590
    
3591
                        case Overlay.TOP_LEFT:
3592
                            doAlign(contextRegion.top, contextRegion.left);
3593
                            break;
3594
        
3595
                        case Overlay.TOP_RIGHT:
3596
                            doAlign(contextRegion.top, contextRegion.right);
3597
                            break;
3598
        
3599
                        case Overlay.BOTTOM_LEFT:
3600
                            doAlign(contextRegion.bottom, contextRegion.left);
3601
                            break;
3602
        
3603
                        case Overlay.BOTTOM_RIGHT:
3604
                            doAlign(contextRegion.bottom, contextRegion.right);
3605
                            break;
3606
                    }
3607
                }
3608
            }
3609
        },
3610
3611
        /**
3612
        * The default event handler executed when the moveEvent is fired, if the 
3613
        * "constraintoviewport" is set to true.
3614
        * @method enforceConstraints
3615
        * @param {String} type The CustomEvent type (usually the property name)
3616
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3617
        * handlers, args[0] will equal the newly applied value for the property.
3618
        * @param {Object} obj The scope object. For configuration handlers, 
3619
        * this will usually equal the owner.
3620
        */
3621
        enforceConstraints: function (type, args, obj) {
3622
            var pos = args[0];
3623
3624
            var cXY = this.getConstrainedXY(pos[0], pos[1]);
3625
            this.cfg.setProperty("x", cXY[0], true);
3626
            this.cfg.setProperty("y", cXY[1], true);
3627
            this.cfg.setProperty("xy", cXY, true);
3628
        },
3629
3630
        /**
3631
         * Shared implementation method for getConstrainedX and getConstrainedY.
3632
         * 
3633
         * <p>
3634
         * Given a coordinate value, returns the calculated coordinate required to 
3635
         * position the Overlay if it is to be constrained to the viewport, based on the 
3636
         * current element size, viewport dimensions, scroll values and preventoverlap 
3637
         * settings
3638
         * </p>
3639
         *
3640
         * @method _getConstrainedPos
3641
         * @protected
3642
         * @param {String} pos The coordinate which needs to be constrained, either "x" or "y"
3643
         * @param {Number} The coordinate value which needs to be constrained
3644
         * @return {Number} The constrained coordinate value
3645
         */
3646
        _getConstrainedPos: function(pos, val) {
3647
3648
            var overlayEl = this.element,
3649
3650
                buffer = Overlay.VIEWPORT_OFFSET,
3651
3652
                x = (pos == "x"),
3653
3654
                overlaySize      = (x) ? overlayEl.offsetWidth : overlayEl.offsetHeight,
3655
                viewportSize     = (x) ? Dom.getViewportWidth() : Dom.getViewportHeight(),
3656
                docScroll        = (x) ? Dom.getDocumentScrollLeft() : Dom.getDocumentScrollTop(),
3657
                overlapPositions = (x) ? Overlay.PREVENT_OVERLAP_X : Overlay.PREVENT_OVERLAP_Y,
3658
3659
                context = this.cfg.getProperty("context"),
3660
3661
                bOverlayFitsInViewport = (overlaySize + buffer < viewportSize),
3662
                bPreventContextOverlap = this.cfg.getProperty("preventcontextoverlap") && context && overlapPositions[(context[1] + context[2])],
3663
3664
                minConstraint = docScroll + buffer,
3665
                maxConstraint = docScroll + viewportSize - overlaySize - buffer,
3666
3667
                constrainedVal = val;
3668
3669
            if (val < minConstraint || val > maxConstraint) {
3670
                if (bPreventContextOverlap) {
3671
                    constrainedVal = this._preventOverlap(pos, context[0], overlaySize, viewportSize, docScroll);
3672
                } else {
3673
                    if (bOverlayFitsInViewport) {
3674
                        if (val < minConstraint) {
3675
                            constrainedVal = minConstraint;
3676
                        } else if (val > maxConstraint) {
3677
                            constrainedVal = maxConstraint;
3678
                        }
3679
                    } else {
3680
                        constrainedVal = minConstraint;
3681
                    }
3682
                }
3683
            }
3684
3685
            return constrainedVal;
3686
        },
3687
3688
        /**
3689
         * Helper method, used to position the Overlap to prevent overlap with the 
3690
         * context element (used when preventcontextoverlap is enabled)
3691
         *
3692
         * @method _preventOverlap
3693
         * @protected
3694
         * @param {String} pos The coordinate to prevent overlap for, either "x" or "y".
3695
         * @param {HTMLElement} contextEl The context element
3696
         * @param {Number} overlaySize The related overlay dimension value (for "x", the width, for "y", the height)
3697
         * @param {Number} viewportSize The related viewport dimension value (for "x", the width, for "y", the height)
3698
         * @param {Object} docScroll  The related document scroll value (for "x", the scrollLeft, for "y", the scrollTop)
3699
         *
3700
         * @return {Number} The new coordinate value which was set to prevent overlap
3701
         */
3702
        _preventOverlap : function(pos, contextEl, overlaySize, viewportSize, docScroll) {
3703
            
3704
            var x = (pos == "x"),
3705
3706
                buffer = Overlay.VIEWPORT_OFFSET,
3707
3708
                overlay = this,
3709
3710
                contextElPos   = ((x) ? Dom.getX(contextEl) : Dom.getY(contextEl)) - docScroll,
3711
                contextElSize  = (x) ? contextEl.offsetWidth : contextEl.offsetHeight,
3712
3713
                minRegionSize = contextElPos - buffer,
3714
                maxRegionSize = (viewportSize - (contextElPos + contextElSize)) - buffer,
3715
3716
                bFlipped = false,
3717
3718
                flip = function () {
3719
                    var flippedVal;
3720
3721
                    if ((overlay.cfg.getProperty(pos) - docScroll) > contextElPos) {
3722
                        flippedVal = (contextElPos - overlaySize);
3723
                    } else {
3724
                        flippedVal = (contextElPos + contextElSize);
3725
                    }
3726
3727
                    overlay.cfg.setProperty(pos, (flippedVal + docScroll), true);
3728
3729
                    return flippedVal;
3730
                },
3731
3732
                setPosition = function () {
3733
3734
                    var displayRegionSize = ((overlay.cfg.getProperty(pos) - docScroll) > contextElPos) ? maxRegionSize : minRegionSize,
3735
                        position;
3736
3737
                    if (overlaySize > displayRegionSize) {
3738
                        if (bFlipped) {
3739
                            /*
3740
                                 All possible positions and values have been 
3741
                                 tried, but none were successful, so fall back 
3742
                                 to the original size and position.
3743
                            */
3744
                            flip();
3745
                        } else {
3746
                            flip();
3747
                            bFlipped = true;
3748
                            position = setPosition();
3749
                        }
3750
                    }
3751
3752
                    return position;
3753
                };
3754
3755
            setPosition();
3756
3757
            return this.cfg.getProperty(pos);
3758
        },
3759
3760
        /**
3761
         * Given x coordinate value, returns the calculated x coordinate required to 
3762
         * position the Overlay if it is to be constrained to the viewport, based on the 
3763
         * current element size, viewport dimensions and scroll values.
3764
         *
3765
         * @param {Number} x The X coordinate value to be constrained
3766
         * @return {Number} The constrained x coordinate
3767
         */		
3768
        getConstrainedX: function (x) {
3769
            return this._getConstrainedPos("x", x);
3770
        },
3771
3772
        /**
3773
         * Given y coordinate value, returns the calculated y coordinate required to 
3774
         * position the Overlay if it is to be constrained to the viewport, based on the 
3775
         * current element size, viewport dimensions and scroll values.
3776
         *
3777
         * @param {Number} y The Y coordinate value to be constrained
3778
         * @return {Number} The constrained y coordinate
3779
         */		
3780
        getConstrainedY : function (y) {
3781
            return this._getConstrainedPos("y", y);
3782
        },
3783
3784
        /**
3785
         * Given x, y coordinate values, returns the calculated coordinates required to 
3786
         * position the Overlay if it is to be constrained to the viewport, based on the 
3787
         * current element size, viewport dimensions and scroll values.
3788
         *
3789
         * @param {Number} x The X coordinate value to be constrained
3790
         * @param {Number} y The Y coordinate value to be constrained
3791
         * @return {Array} The constrained x and y coordinates at index 0 and 1 respectively;
3792
         */
3793
        getConstrainedXY: function(x, y) {
3794
            return [this.getConstrainedX(x), this.getConstrainedY(y)];
3795
        },
3796
3797
        /**
3798
        * Centers the container in the viewport.
3799
        * @method center
3800
        */
3801
        center: function () {
3802
3803
            var nViewportOffset = Overlay.VIEWPORT_OFFSET,
3804
                elementWidth = this.element.offsetWidth,
3805
                elementHeight = this.element.offsetHeight,
3806
                viewPortWidth = Dom.getViewportWidth(),
3807
                viewPortHeight = Dom.getViewportHeight(),
3808
                x,
3809
                y;
3810
3811
            if (elementWidth < viewPortWidth) {
3812
                x = (viewPortWidth / 2) - (elementWidth / 2) + Dom.getDocumentScrollLeft();
3813
            } else {
3814
                x = nViewportOffset + Dom.getDocumentScrollLeft();
3815
            }
3816
3817
            if (elementHeight < viewPortHeight) {
3818
                y = (viewPortHeight / 2) - (elementHeight / 2) + Dom.getDocumentScrollTop();
3819
            } else {
3820
                y = nViewportOffset + Dom.getDocumentScrollTop();
3821
            }
3822
3823
            this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
3824
            this.cfg.refireEvent("iframe");
3825
3826
            if (UA.webkit) {
3827
                this.forceContainerRedraw();
3828
            }
3829
        },
3830
3831
        /**
3832
        * Synchronizes the Panel's "xy", "x", and "y" properties with the 
3833
        * Panel's position in the DOM. This is primarily used to update  
3834
        * position information during drag & drop.
3835
        * @method syncPosition
3836
        */
3837
        syncPosition: function () {
3838
3839
            var pos = Dom.getXY(this.element);
3840
3841
            this.cfg.setProperty("x", pos[0], true);
3842
            this.cfg.setProperty("y", pos[1], true);
3843
            this.cfg.setProperty("xy", pos, true);
3844
3845
        },
3846
3847
        /**
3848
        * Event handler fired when the resize monitor element is resized.
3849
        * @method onDomResize
3850
        * @param {DOMEvent} e The resize DOM event
3851
        * @param {Object} obj The scope object
3852
        */
3853
        onDomResize: function (e, obj) {
3854
3855
            var me = this;
3856
3857
            Overlay.superclass.onDomResize.call(this, e, obj);
3858
3859
            setTimeout(function () {
3860
                me.syncPosition();
3861
                me.cfg.refireEvent("iframe");
3862
                me.cfg.refireEvent("context");
3863
            }, 0);
3864
        },
3865
3866
        /**
3867
         * Determines the content box height of the given element (height of the element, without padding or borders) in pixels.
3868
         *
3869
         * @method _getComputedHeight
3870
         * @private
3871
         * @param {HTMLElement} el The element for which the content height needs to be determined
3872
         * @return {Number} The content box height of the given element, or null if it could not be determined.
3873
         */
3874
        _getComputedHeight : (function() {
3875
3876
            if (document.defaultView && document.defaultView.getComputedStyle) {
3877
                return function(el) {
3878
                    var height = null;
3879
                    if (el.ownerDocument && el.ownerDocument.defaultView) {
3880
                        var computed = el.ownerDocument.defaultView.getComputedStyle(el, '');
3881
                        if (computed) {
3882
                            height = parseInt(computed.height, 10);
3883
                        }
3884
                    }
3885
                    return (Lang.isNumber(height)) ? height : null;
3886
                };
3887
            } else {
3888
                return function(el) {
3889
                    var height = null;
3890
                    if (el.style.pixelHeight) {
3891
                        height = el.style.pixelHeight;
3892
                    }
3893
                    return (Lang.isNumber(height)) ? height : null;
3894
                };
3895
            }
3896
        })(),
3897
3898
        /**
3899
         * autofillheight validator. Verifies that the autofill value is either null 
3900
         * or one of the strings : "body", "header" or "footer".
3901
         *
3902
         * @method _validateAutoFillHeight
3903
         * @protected
3904
         * @param {String} val
3905
         * @return true, if valid, false otherwise
3906
         */
3907
        _validateAutoFillHeight : function(val) {
3908
            return (!val) || (Lang.isString(val) && Overlay.STD_MOD_RE.test(val));
3909
        },
3910
3911
        /**
3912
         * The default custom event handler executed when the overlay's height is changed, 
3913
         * if the autofillheight property has been set.
3914
         *
3915
         * @method _autoFillOnHeightChange
3916
         * @protected
3917
         * @param {String} type The event type
3918
         * @param {Array} args The array of arguments passed to event subscribers
3919
         * @param {HTMLElement} el The header, body or footer element which is to be resized to fill
3920
         * out the containers height
3921
         */
3922
        _autoFillOnHeightChange : function(type, args, el) {
3923
            var height = this.cfg.getProperty("height");
3924
            if ((height && height !== "auto") || (height === 0)) {
3925
                this.fillHeight(el);
3926
            }
3927
        },
3928
3929
        /**
3930
         * Returns the sub-pixel height of the el, using getBoundingClientRect, if available,
3931
         * otherwise returns the offsetHeight
3932
         * @method _getPreciseHeight
3933
         * @private
3934
         * @param {HTMLElement} el
3935
         * @return {Float} The sub-pixel height if supported by the browser, else the rounded height.
3936
         */
3937
        _getPreciseHeight : function(el) {
3938
            var height = el.offsetHeight;
3939
3940
            if (el.getBoundingClientRect) {
3941
                var rect = el.getBoundingClientRect();
3942
                height = rect.bottom - rect.top;
3943
            }
3944
3945
            return height;
3946
        },
3947
3948
        /**
3949
         * <p>
3950
         * Sets the height on the provided header, body or footer element to 
3951
         * fill out the height of the container. It determines the height of the 
3952
         * containers content box, based on it's configured height value, and 
3953
         * sets the height of the autofillheight element to fill out any 
3954
         * space remaining after the other standard module element heights 
3955
         * have been accounted for.
3956
         * </p>
3957
         * <p><strong>NOTE:</strong> This method is not designed to work if an explicit 
3958
         * height has not been set on the container, since for an "auto" height container, 
3959
         * the heights of the header/body/footer will drive the height of the container.</p>
3960
         *
3961
         * @method fillHeight
3962
         * @param {HTMLElement} el The element which should be resized to fill out the height
3963
         * of the container element.
3964
         */
3965
        fillHeight : function(el) {
3966
            if (el) {
3967
                var container = this.innerElement || this.element,
3968
                    containerEls = [this.header, this.body, this.footer],
3969
                    containerEl,
3970
                    total = 0,
3971
                    filled = 0,
3972
                    remaining = 0,
3973
                    validEl = false;
3974
3975
                for (var i = 0, l = containerEls.length; i < l; i++) {
3976
                    containerEl = containerEls[i];
3977
                    if (containerEl) {
3978
                        if (el !== containerEl) {
3979
                            filled += this._getPreciseHeight(containerEl);
3980
                        } else {
3981
                            validEl = true;
3982
                        }
3983
                    }
3984
                }
3985
3986
                if (validEl) {
3987
3988
                    if (UA.ie || UA.opera) {
3989
                        // Need to set height to 0, to allow height to be reduced
3990
                        Dom.setStyle(el, 'height', 0 + 'px');
3991
                    }
3992
3993
                    total = this._getComputedHeight(container);
3994
3995
                    // Fallback, if we can't get computed value for content height
3996
                    if (total === null) {
3997
                        Dom.addClass(container, "yui-override-padding");
3998
                        total = container.clientHeight; // Content, No Border, 0 Padding (set by yui-override-padding)
3999
                        Dom.removeClass(container, "yui-override-padding");
4000
                    }
4001
    
4002
                    remaining = Math.max(total - filled, 0);
4003
    
4004
                    Dom.setStyle(el, "height", remaining + "px");
4005
    
4006
                    // Re-adjust height if required, to account for el padding and border
4007
                    if (el.offsetHeight != remaining) {
4008
                        remaining = Math.max(remaining - (el.offsetHeight - remaining), 0);
4009
                    }
4010
                    Dom.setStyle(el, "height", remaining + "px");
4011
                }
4012
            }
4013
        },
4014
4015
        /**
4016
        * Places the Overlay on top of all other instances of 
4017
        * YAHOO.widget.Overlay.
4018
        * @method bringToTop
4019
        */
4020
        bringToTop: function () {
4021
4022
            var aOverlays = [],
4023
                oElement = this.element;
4024
4025
            function compareZIndexDesc(p_oOverlay1, p_oOverlay2) {
4026
4027
                var sZIndex1 = Dom.getStyle(p_oOverlay1, "zIndex"),
4028
                    sZIndex2 = Dom.getStyle(p_oOverlay2, "zIndex"),
4029
4030
                    nZIndex1 = (!sZIndex1 || isNaN(sZIndex1)) ? 0 : parseInt(sZIndex1, 10),
4031
                    nZIndex2 = (!sZIndex2 || isNaN(sZIndex2)) ? 0 : parseInt(sZIndex2, 10);
4032
4033
                if (nZIndex1 > nZIndex2) {
4034
                    return -1;
4035
                } else if (nZIndex1 < nZIndex2) {
4036
                    return 1;
4037
                } else {
4038
                    return 0;
4039
                }
4040
            }
4041
4042
            function isOverlayElement(p_oElement) {
4043
4044
                var isOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY),
4045
                    Panel = YAHOO.widget.Panel;
4046
4047
                if (isOverlay && !Dom.isAncestor(oElement, p_oElement)) {
4048
                    if (Panel && Dom.hasClass(p_oElement, Panel.CSS_PANEL)) {
4049
                        aOverlays[aOverlays.length] = p_oElement.parentNode;
4050
                    } else {
4051
                        aOverlays[aOverlays.length] = p_oElement;
4052
                    }
4053
                }
4054
            }
4055
4056
            Dom.getElementsBy(isOverlayElement, "DIV", document.body);
4057
4058
            aOverlays.sort(compareZIndexDesc);
4059
4060
            var oTopOverlay = aOverlays[0],
4061
                nTopZIndex;
4062
4063
            if (oTopOverlay) {
4064
                nTopZIndex = Dom.getStyle(oTopOverlay, "zIndex");
4065
4066
                if (!isNaN(nTopZIndex)) {
4067
                    var bRequiresBump = false;
4068
4069
                    if (oTopOverlay != oElement) {
4070
                        bRequiresBump = true;
4071
                    } else if (aOverlays.length > 1) {
4072
                        var nNextZIndex = Dom.getStyle(aOverlays[1], "zIndex");
4073
                        // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
4074
                        if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
4075
                            bRequiresBump = true;
4076
                        }
4077
                    }
4078
                    if (bRequiresBump) {
4079
                        this.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
4080
                    }
4081
                }
4082
            }
4083
        },
4084
4085
        /**
4086
        * Removes the Overlay element from the DOM and sets all child 
4087
        * elements to null.
4088
        * @method destroy
4089
        */
4090
        destroy: function () {
4091
4092
            if (this.iframe) {
4093
                this.iframe.parentNode.removeChild(this.iframe);
4094
            }
4095
4096
            this.iframe = null;
4097
4098
            Overlay.windowResizeEvent.unsubscribe(
4099
                this.doCenterOnDOMEvent, this);
4100
    
4101
            Overlay.windowScrollEvent.unsubscribe(
4102
                this.doCenterOnDOMEvent, this);
4103
4104
            Module.textResizeEvent.unsubscribe(this._autoFillOnHeightChange);
4105
4106
            if (this._contextTriggers) {
4107
                // Unsubscribe context triggers - to cover context triggers which listen for global
4108
                // events such as windowResize and windowScroll. Easier just to unsubscribe all
4109
                this._processTriggers(this._contextTriggers, _UNSUBSCRIBE, this._alignOnTrigger);
4110
            }
4111
4112
            Overlay.superclass.destroy.call(this);
4113
        },
4114
4115
        /**
4116
         * Can be used to force the container to repaint/redraw it's contents.
4117
         * <p>
4118
         * By default applies and then removes a 1px bottom margin through the 
4119
         * application/removal of a "yui-force-redraw" class.
4120
         * </p>
4121
         * <p>
4122
         * It is currently used by Overlay to force a repaint for webkit 
4123
         * browsers, when centering.
4124
         * </p>
4125
         * @method forceContainerRedraw
4126
         */
4127
        forceContainerRedraw : function() {
4128
            var c = this;
4129
            Dom.addClass(c.element, "yui-force-redraw");
4130
            setTimeout(function() {
4131
                Dom.removeClass(c.element, "yui-force-redraw");
4132
            }, 0);
4133
        },
4134
4135
        /**
4136
        * Returns a String representation of the object.
4137
        * @method toString
4138
        * @return {String} The string representation of the Overlay.
4139
        */
4140
        toString: function () {
4141
            return "Overlay " + this.id;
4142
        }
4143
4144
    });
4145
}());
4146
(function () {
4147
4148
    /**
4149
    * OverlayManager is used for maintaining the focus status of 
4150
    * multiple Overlays.
4151
    * @namespace YAHOO.widget
4152
    * @namespace YAHOO.widget
4153
    * @class OverlayManager
4154
    * @constructor
4155
    * @param {Array} overlays Optional. A collection of Overlays to register 
4156
    * with the manager.
4157
    * @param {Object} userConfig  The object literal representing the user 
4158
    * configuration of the OverlayManager
4159
    */
4160
    YAHOO.widget.OverlayManager = function (userConfig) {
4161
        this.init(userConfig);
4162
    };
4163
4164
    var Overlay = YAHOO.widget.Overlay,
4165
        Event = YAHOO.util.Event,
4166
        Dom = YAHOO.util.Dom,
4167
        Config = YAHOO.util.Config,
4168
        CustomEvent = YAHOO.util.CustomEvent,
4169
        OverlayManager = YAHOO.widget.OverlayManager;
4170
4171
    /**
4172
    * The CSS class representing a focused Overlay
4173
    * @property OverlayManager.CSS_FOCUSED
4174
    * @static
4175
    * @final
4176
    * @type String
4177
    */
4178
    OverlayManager.CSS_FOCUSED = "focused";
4179
4180
    OverlayManager.prototype = {
4181
4182
        /**
4183
        * The class's constructor function
4184
        * @property contructor
4185
        * @type Function
4186
        */
4187
        constructor: OverlayManager,
4188
4189
        /**
4190
        * The array of Overlays that are currently registered
4191
        * @property overlays
4192
        * @type YAHOO.widget.Overlay[]
4193
        */
4194
        overlays: null,
4195
4196
        /**
4197
        * Initializes the default configuration of the OverlayManager
4198
        * @method initDefaultConfig
4199
        */
4200
        initDefaultConfig: function () {
4201
            /**
4202
            * The collection of registered Overlays in use by 
4203
            * the OverlayManager
4204
            * @config overlays
4205
            * @type YAHOO.widget.Overlay[]
4206
            * @default null
4207
            */
4208
            this.cfg.addProperty("overlays", { suppressEvent: true } );
4209
4210
            /**
4211
            * The default DOM event that should be used to focus an Overlay
4212
            * @config focusevent
4213
            * @type String
4214
            * @default "mousedown"
4215
            */
4216
            this.cfg.addProperty("focusevent", { value: "mousedown" } );
4217
        },
4218
4219
        /**
4220
        * Initializes the OverlayManager
4221
        * @method init
4222
        * @param {Overlay[]} overlays Optional. A collection of Overlays to 
4223
        * register with the manager.
4224
        * @param {Object} userConfig  The object literal representing the user 
4225
        * configuration of the OverlayManager
4226
        */
4227
        init: function (userConfig) {
4228
4229
            /**
4230
            * The OverlayManager's Config object used for monitoring 
4231
            * configuration properties.
4232
            * @property cfg
4233
            * @type Config
4234
            */
4235
            this.cfg = new Config(this);
4236
4237
            this.initDefaultConfig();
4238
4239
            if (userConfig) {
4240
                this.cfg.applyConfig(userConfig, true);
4241
            }
4242
            this.cfg.fireQueue();
4243
4244
            /**
4245
            * The currently activated Overlay
4246
            * @property activeOverlay
4247
            * @private
4248
            * @type YAHOO.widget.Overlay
4249
            */
4250
            var activeOverlay = null;
4251
4252
            /**
4253
            * Returns the currently focused Overlay
4254
            * @method getActive
4255
            * @return {Overlay} The currently focused Overlay
4256
            */
4257
            this.getActive = function () {
4258
                return activeOverlay;
4259
            };
4260
4261
            /**
4262
            * Focuses the specified Overlay
4263
            * @method focus
4264
            * @param {Overlay} overlay The Overlay to focus
4265
            * @param {String} overlay The id of the Overlay to focus
4266
            */
4267
            this.focus = function (overlay) {
4268
                var o = this.find(overlay);
4269
                if (o) {
4270
                    o.focus();
4271
                }
4272
            };
4273
4274
            /**
4275
            * Removes the specified Overlay from the manager
4276
            * @method remove
4277
            * @param {Overlay} overlay The Overlay to remove
4278
            * @param {String} overlay The id of the Overlay to remove
4279
            */
4280
            this.remove = function (overlay) {
4281
4282
                var o = this.find(overlay), 
4283
                        originalZ;
4284
4285
                if (o) {
4286
                    if (activeOverlay == o) {
4287
                        activeOverlay = null;
4288
                    }
4289
4290
                    var bDestroyed = (o.element === null && o.cfg === null) ? true : false;
4291
4292
                    if (!bDestroyed) {
4293
                        // Set it's zindex so that it's sorted to the end.
4294
                        originalZ = Dom.getStyle(o.element, "zIndex");
4295
                        o.cfg.setProperty("zIndex", -1000, true);
4296
                    }
4297
4298
                    this.overlays.sort(this.compareZIndexDesc);
4299
                    this.overlays = this.overlays.slice(0, (this.overlays.length - 1));
4300
4301
                    o.hideEvent.unsubscribe(o.blur);
4302
                    o.destroyEvent.unsubscribe(this._onOverlayDestroy, o);
4303
                    o.focusEvent.unsubscribe(this._onOverlayFocusHandler, o);
4304
                    o.blurEvent.unsubscribe(this._onOverlayBlurHandler, o);
4305
4306
                    if (!bDestroyed) {
4307
                        Event.removeListener(o.element, this.cfg.getProperty("focusevent"), this._onOverlayElementFocus);
4308
                        o.cfg.setProperty("zIndex", originalZ, true);
4309
                        o.cfg.setProperty("manager", null);
4310
                    }
4311
4312
                    /* _managed Flag for custom or existing. Don't want to remove existing */
4313
                    if (o.focusEvent._managed) { o.focusEvent = null; }
4314
                    if (o.blurEvent._managed) { o.blurEvent = null; }
4315
4316
                    if (o.focus._managed) { o.focus = null; }
4317
                    if (o.blur._managed) { o.blur = null; }
4318
                }
4319
            };
4320
4321
            /**
4322
            * Removes focus from all registered Overlays in the manager
4323
            * @method blurAll
4324
            */
4325
            this.blurAll = function () {
4326
4327
                var nOverlays = this.overlays.length,
4328
                    i;
4329
4330
                if (nOverlays > 0) {
4331
                    i = nOverlays - 1;
4332
                    do {
4333
                        this.overlays[i].blur();
4334
                    }
4335
                    while(i--);
4336
                }
4337
            };
4338
4339
            /**
4340
             * Updates the state of the OverlayManager and overlay, as a result of the overlay
4341
             * being blurred.
4342
             * 
4343
             * @method _manageBlur
4344
             * @param {Overlay} overlay The overlay instance which got blurred.
4345
             * @protected
4346
             */
4347
            this._manageBlur = function (overlay) {
4348
                var changed = false;
4349
                if (activeOverlay == overlay) {
4350
                    Dom.removeClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
4351
                    activeOverlay = null;
4352
                    changed = true;
4353
                }
4354
                return changed;
4355
            };
4356
4357
            /**
4358
             * Updates the state of the OverlayManager and overlay, as a result of the overlay 
4359
             * receiving focus.
4360
             *
4361
             * @method _manageFocus
4362
             * @param {Overlay} overlay The overlay instance which got focus.
4363
             * @protected
4364
             */
4365
            this._manageFocus = function(overlay) {
4366
                var changed = false;
4367
                if (activeOverlay != overlay) {
4368
                    if (activeOverlay) {
4369
                        activeOverlay.blur();
4370
                    }
4371
                    activeOverlay = overlay;
4372
                    this.bringToTop(activeOverlay);
4373
                    Dom.addClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
4374
                    changed = true;
4375
                }
4376
                return changed;
4377
            };
4378
4379
            var overlays = this.cfg.getProperty("overlays");
4380
4381
            if (! this.overlays) {
4382
                this.overlays = [];
4383
            }
4384
4385
            if (overlays) {
4386
                this.register(overlays);
4387
                this.overlays.sort(this.compareZIndexDesc);
4388
            }
4389
        },
4390
4391
        /**
4392
        * @method _onOverlayElementFocus
4393
        * @description Event handler for the DOM event that is used to focus 
4394
        * the Overlay instance as specified by the "focusevent" 
4395
        * configuration property.
4396
        * @private
4397
        * @param {Event} p_oEvent Object representing the DOM event 
4398
        * object passed back by the event utility (Event).
4399
        */
4400
        _onOverlayElementFocus: function (p_oEvent) {
4401
4402
            var oTarget = Event.getTarget(p_oEvent),
4403
                oClose = this.close;
4404
4405
            if (oClose && (oTarget == oClose || Dom.isAncestor(oClose, oTarget))) {
4406
                this.blur();
4407
            } else {
4408
                this.focus();
4409
            }
4410
        },
4411
4412
        /**
4413
        * @method _onOverlayDestroy
4414
        * @description "destroy" event handler for the Overlay.
4415
        * @private
4416
        * @param {String} p_sType String representing the name of the event  
4417
        * that was fired.
4418
        * @param {Array} p_aArgs Array of arguments sent when the event 
4419
        * was fired.
4420
        * @param {Overlay} p_oOverlay Object representing the overlay that 
4421
        * fired the event.
4422
        */
4423
        _onOverlayDestroy: function (p_sType, p_aArgs, p_oOverlay) {
4424
            this.remove(p_oOverlay);
4425
        },
4426
4427
        /**
4428
        * @method _onOverlayFocusHandler
4429
        *
4430
        * @description focusEvent Handler, used to delegate to _manageFocus with the correct arguments.
4431
        *
4432
        * @private
4433
        * @param {String} p_sType String representing the name of the event  
4434
        * that was fired.
4435
        * @param {Array} p_aArgs Array of arguments sent when the event 
4436
        * was fired.
4437
        * @param {Overlay} p_oOverlay Object representing the overlay that 
4438
        * fired the event.
4439
        */
4440
        _onOverlayFocusHandler: function(p_sType, p_aArgs, p_oOverlay) {
4441
            this._manageFocus(p_oOverlay);
4442
        },
4443
4444
        /**
4445
        * @method _onOverlayBlurHandler
4446
        * @description blurEvent Handler, used to delegate to _manageBlur with the correct arguments.
4447
        *
4448
        * @private
4449
        * @param {String} p_sType String representing the name of the event  
4450
        * that was fired.
4451
        * @param {Array} p_aArgs Array of arguments sent when the event 
4452
        * was fired.
4453
        * @param {Overlay} p_oOverlay Object representing the overlay that 
4454
        * fired the event.
4455
        */
4456
        _onOverlayBlurHandler: function(p_sType, p_aArgs, p_oOverlay) {
4457
            this._manageBlur(p_oOverlay);
4458
        },
4459
4460
        /**
4461
         * Subscribes to the Overlay based instance focusEvent, to allow the OverlayManager to
4462
         * monitor focus state.
4463
         * 
4464
         * If the instance already has a focusEvent (e.g. Menu), OverlayManager will subscribe 
4465
         * to the existing focusEvent, however if a focusEvent or focus method does not exist
4466
         * on the instance, the _bindFocus method will add them, and the focus method will 
4467
         * update the OverlayManager's state directly.
4468
         * 
4469
         * @method _bindFocus
4470
         * @param {Overlay} overlay The overlay for which focus needs to be managed
4471
         * @protected
4472
         */
4473
        _bindFocus : function(overlay) {
4474
            var mgr = this;
4475
4476
            if (!overlay.focusEvent) {
4477
                overlay.focusEvent = overlay.createEvent("focus");
4478
                overlay.focusEvent.signature = CustomEvent.LIST;
4479
                overlay.focusEvent._managed = true;
4480
            } else {
4481
                overlay.focusEvent.subscribe(mgr._onOverlayFocusHandler, overlay, mgr);
4482
            }
4483
4484
            if (!overlay.focus) {
4485
                Event.on(overlay.element, mgr.cfg.getProperty("focusevent"), mgr._onOverlayElementFocus, null, overlay);
4486
                overlay.focus = function () {
4487
                    if (mgr._manageFocus(this)) {
4488
                        // For Panel/Dialog
4489
                        if (this.cfg.getProperty("visible") && this.focusFirst) {
4490
                            this.focusFirst();
4491
                        }
4492
                        this.focusEvent.fire();
4493
                    }
4494
                };
4495
                overlay.focus._managed = true;
4496
            }
4497
        },
4498
4499
        /**
4500
         * Subscribes to the Overlay based instance's blurEvent to allow the OverlayManager to
4501
         * monitor blur state.
4502
         *
4503
         * If the instance already has a blurEvent (e.g. Menu), OverlayManager will subscribe 
4504
         * to the existing blurEvent, however if a blurEvent or blur method does not exist
4505
         * on the instance, the _bindBlur method will add them, and the blur method 
4506
         * update the OverlayManager's state directly.
4507
         *
4508
         * @method _bindBlur
4509
         * @param {Overlay} overlay The overlay for which blur needs to be managed
4510
         * @protected
4511
         */
4512
        _bindBlur : function(overlay) {
4513
            var mgr = this;
4514
4515
            if (!overlay.blurEvent) {
4516
                overlay.blurEvent = overlay.createEvent("blur");
4517
                overlay.blurEvent.signature = CustomEvent.LIST;
4518
                overlay.focusEvent._managed = true;
4519
            } else {
4520
                overlay.blurEvent.subscribe(mgr._onOverlayBlurHandler, overlay, mgr);
4521
            }
4522
4523
            if (!overlay.blur) {
4524
                overlay.blur = function () {
4525
                    if (mgr._manageBlur(this)) {
4526
                        this.blurEvent.fire();
4527
                    }
4528
                };
4529
                overlay.blur._managed = true;
4530
            }
4531
4532
            overlay.hideEvent.subscribe(overlay.blur);
4533
        },
4534
4535
        /**
4536
         * Subscribes to the Overlay based instance's destroyEvent, to allow the Overlay
4537
         * to be removed for the OverlayManager when destroyed.
4538
         * 
4539
         * @method _bindDestroy
4540
         * @param {Overlay} overlay The overlay instance being managed
4541
         * @protected
4542
         */
4543
        _bindDestroy : function(overlay) {
4544
            var mgr = this;
4545
            overlay.destroyEvent.subscribe(mgr._onOverlayDestroy, overlay, mgr);
4546
        },
4547
4548
        /**
4549
         * Ensures the zIndex configuration property on the managed overlay based instance
4550
         * is set to the computed zIndex value from the DOM (with "auto" translating to 0).
4551
         *
4552
         * @method _syncZIndex
4553
         * @param {Overlay} overlay The overlay instance being managed
4554
         * @protected
4555
         */
4556
        _syncZIndex : function(overlay) {
4557
            var zIndex = Dom.getStyle(overlay.element, "zIndex");
4558
            if (!isNaN(zIndex)) {
4559
                overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
4560
            } else {
4561
                overlay.cfg.setProperty("zIndex", 0);
4562
            }
4563
        },
4564
4565
        /**
4566
        * Registers an Overlay or an array of Overlays with the manager. Upon 
4567
        * registration, the Overlay receives functions for focus and blur, 
4568
        * along with CustomEvents for each.
4569
        *
4570
        * @method register
4571
        * @param {Overlay} overlay  An Overlay to register with the manager.
4572
        * @param {Overlay[]} overlay  An array of Overlays to register with 
4573
        * the manager.
4574
        * @return {boolean} true if any Overlays are registered.
4575
        */
4576
        register: function (overlay) {
4577
4578
            var registered = false,
4579
                i,
4580
                n;
4581
4582
            if (overlay instanceof Overlay) {
4583
4584
                overlay.cfg.addProperty("manager", { value: this } );
4585
4586
                this._bindFocus(overlay);
4587
                this._bindBlur(overlay);
4588
                this._bindDestroy(overlay);
4589
                this._syncZIndex(overlay);
4590
4591
                this.overlays.push(overlay);
4592
                this.bringToTop(overlay);
4593
4594
                registered = true;
4595
4596
            } else if (overlay instanceof Array) {
4597
4598
                for (i = 0, n = overlay.length; i < n; i++) {
4599
                    registered = this.register(overlay[i]) || registered;
4600
                }
4601
4602
            }
4603
4604
            return registered;
4605
        },
4606
4607
        /**
4608
        * Places the specified Overlay instance on top of all other 
4609
        * Overlay instances.
4610
        * @method bringToTop
4611
        * @param {YAHOO.widget.Overlay} p_oOverlay Object representing an 
4612
        * Overlay instance.
4613
        * @param {String} p_oOverlay String representing the id of an 
4614
        * Overlay instance.
4615
        */        
4616
        bringToTop: function (p_oOverlay) {
4617
4618
            var oOverlay = this.find(p_oOverlay),
4619
                nTopZIndex,
4620
                oTopOverlay,
4621
                aOverlays;
4622
4623
            if (oOverlay) {
4624
4625
                aOverlays = this.overlays;
4626
                aOverlays.sort(this.compareZIndexDesc);
4627
4628
                oTopOverlay = aOverlays[0];
4629
4630
                if (oTopOverlay) {
4631
                    nTopZIndex = Dom.getStyle(oTopOverlay.element, "zIndex");
4632
4633
                    if (!isNaN(nTopZIndex)) {
4634
4635
                        var bRequiresBump = false;
4636
4637
                        if (oTopOverlay !== oOverlay) {
4638
                            bRequiresBump = true;
4639
                        } else if (aOverlays.length > 1) {
4640
                            var nNextZIndex = Dom.getStyle(aOverlays[1].element, "zIndex");
4641
                            // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
4642
                            if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
4643
                                bRequiresBump = true;
4644
                            }
4645
                        }
4646
4647
                        if (bRequiresBump) {
4648
                            oOverlay.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
4649
                        }
4650
                    }
4651
                    aOverlays.sort(this.compareZIndexDesc);
4652
                }
4653
            }
4654
        },
4655
4656
        /**
4657
        * Attempts to locate an Overlay by instance or ID.
4658
        * @method find
4659
        * @param {Overlay} overlay  An Overlay to locate within the manager
4660
        * @param {String} overlay  An Overlay id to locate within the manager
4661
        * @return {Overlay} The requested Overlay, if found, or null if it 
4662
        * cannot be located.
4663
        */
4664
        find: function (overlay) {
4665
4666
            var isInstance = overlay instanceof Overlay,
4667
                overlays = this.overlays,
4668
                n = overlays.length,
4669
                found = null,
4670
                o,
4671
                i;
4672
4673
            if (isInstance || typeof overlay == "string") {
4674
                for (i = n-1; i >= 0; i--) {
4675
                    o = overlays[i];
4676
                    if ((isInstance && (o === overlay)) || (o.id == overlay)) {
4677
                        found = o;
4678
                        break;
4679
                    }
4680
                }
4681
            }
4682
4683
            return found;
4684
        },
4685
4686
        /**
4687
        * Used for sorting the manager's Overlays by z-index.
4688
        * @method compareZIndexDesc
4689
        * @private
4690
        * @return {Number} 0, 1, or -1, depending on where the Overlay should 
4691
        * fall in the stacking order.
4692
        */
4693
        compareZIndexDesc: function (o1, o2) {
4694
4695
            var zIndex1 = (o1.cfg) ? o1.cfg.getProperty("zIndex") : null, // Sort invalid (destroyed)
4696
                zIndex2 = (o2.cfg) ? o2.cfg.getProperty("zIndex") : null; // objects at bottom.
4697
4698
            if (zIndex1 === null && zIndex2 === null) {
4699
                return 0;
4700
            } else if (zIndex1 === null){
4701
                return 1;
4702
            } else if (zIndex2 === null) {
4703
                return -1;
4704
            } else if (zIndex1 > zIndex2) {
4705
                return -1;
4706
            } else if (zIndex1 < zIndex2) {
4707
                return 1;
4708
            } else {
4709
                return 0;
4710
            }
4711
        },
4712
4713
        /**
4714
        * Shows all Overlays in the manager.
4715
        * @method showAll
4716
        */
4717
        showAll: function () {
4718
            var overlays = this.overlays,
4719
                n = overlays.length,
4720
                i;
4721
4722
            for (i = n - 1; i >= 0; i--) {
4723
                overlays[i].show();
4724
            }
4725
        },
4726
4727
        /**
4728
        * Hides all Overlays in the manager.
4729
        * @method hideAll
4730
        */
4731
        hideAll: function () {
4732
            var overlays = this.overlays,
4733
                n = overlays.length,
4734
                i;
4735
4736
            for (i = n - 1; i >= 0; i--) {
4737
                overlays[i].hide();
4738
            }
4739
        },
4740
4741
        /**
4742
        * Returns a string representation of the object.
4743
        * @method toString
4744
        * @return {String} The string representation of the OverlayManager
4745
        */
4746
        toString: function () {
4747
            return "OverlayManager";
4748
        }
4749
    };
4750
}());
4751
(function () {
4752
4753
    /**
4754
    * Tooltip is an implementation of Overlay that behaves like an OS tooltip, 
4755
    * displaying when the user mouses over a particular element, and 
4756
    * disappearing on mouse out.
4757
    * @namespace YAHOO.widget
4758
    * @class Tooltip
4759
    * @extends YAHOO.widget.Overlay
4760
    * @constructor
4761
    * @param {String} el The element ID representing the Tooltip <em>OR</em>
4762
    * @param {HTMLElement} el The element representing the Tooltip
4763
    * @param {Object} userConfig The configuration object literal containing 
4764
    * the configuration that should be set for this Overlay. See configuration 
4765
    * documentation for more details.
4766
    */
4767
    YAHOO.widget.Tooltip = function (el, userConfig) {
4768
        YAHOO.widget.Tooltip.superclass.constructor.call(this, el, userConfig);
4769
    };
4770
4771
    var Lang = YAHOO.lang,
4772
        Event = YAHOO.util.Event,
4773
        CustomEvent = YAHOO.util.CustomEvent,
4774
        Dom = YAHOO.util.Dom,
4775
        Tooltip = YAHOO.widget.Tooltip,
4776
        UA = YAHOO.env.ua,
4777
        bIEQuirks = (UA.ie && (UA.ie <= 6 || document.compatMode == "BackCompat")),
4778
4779
        m_oShadowTemplate,
4780
4781
        /**
4782
        * Constant representing the Tooltip's configuration properties
4783
        * @property DEFAULT_CONFIG
4784
        * @private
4785
        * @final
4786
        * @type Object
4787
        */
4788
        DEFAULT_CONFIG = {
4789
4790
            "PREVENT_OVERLAP": { 
4791
                key: "preventoverlap", 
4792
                value: true, 
4793
                validator: Lang.isBoolean, 
4794
                supercedes: ["x", "y", "xy"] 
4795
            },
4796
4797
            "SHOW_DELAY": { 
4798
                key: "showdelay", 
4799
                value: 200, 
4800
                validator: Lang.isNumber 
4801
            }, 
4802
4803
            "AUTO_DISMISS_DELAY": { 
4804
                key: "autodismissdelay", 
4805
                value: 5000, 
4806
                validator: Lang.isNumber 
4807
            }, 
4808
4809
            "HIDE_DELAY": { 
4810
                key: "hidedelay", 
4811
                value: 250, 
4812
                validator: Lang.isNumber 
4813
            }, 
4814
4815
            "TEXT": { 
4816
                key: "text", 
4817
                suppressEvent: true 
4818
            }, 
4819
4820
            "CONTAINER": { 
4821
                key: "container"
4822
            },
4823
4824
            "DISABLED": {
4825
                key: "disabled",
4826
                value: false,
4827
                suppressEvent: true
4828
            },
4829
4830
            "XY_OFFSET": {
4831
                key: "xyoffset",
4832
                value: [0, 25],
4833
                suppressEvent: true
4834
            }
4835
        },
4836
4837
        /**
4838
        * Constant representing the name of the Tooltip's events
4839
        * @property EVENT_TYPES
4840
        * @private
4841
        * @final
4842
        * @type Object
4843
        */
4844
        EVENT_TYPES = {
4845
            "CONTEXT_MOUSE_OVER": "contextMouseOver",
4846
            "CONTEXT_MOUSE_OUT": "contextMouseOut",
4847
            "CONTEXT_TRIGGER": "contextTrigger"
4848
        };
4849
4850
    /**
4851
    * Constant representing the Tooltip CSS class
4852
    * @property YAHOO.widget.Tooltip.CSS_TOOLTIP
4853
    * @static
4854
    * @final
4855
    * @type String
4856
    */
4857
    Tooltip.CSS_TOOLTIP = "yui-tt";
4858
4859
    function restoreOriginalWidth(sOriginalWidth, sForcedWidth) {
4860
4861
        var oConfig = this.cfg,
4862
            sCurrentWidth = oConfig.getProperty("width");
4863
4864
        if (sCurrentWidth == sForcedWidth) {
4865
            oConfig.setProperty("width", sOriginalWidth);
4866
        }
4867
    }
4868
4869
    /* 
4870
        changeContent event handler that sets a Tooltip instance's "width"
4871
        configuration property to the value of its root HTML 
4872
        elements's offsetWidth if a specific width has not been set.
4873
    */
4874
4875
    function setWidthToOffsetWidth(p_sType, p_aArgs) {
4876
4877
        if ("_originalWidth" in this) {
4878
            restoreOriginalWidth.call(this, this._originalWidth, this._forcedWidth);
4879
        }
4880
4881
        var oBody = document.body,
4882
            oConfig = this.cfg,
4883
            sOriginalWidth = oConfig.getProperty("width"),
4884
            sNewWidth,
4885
            oClone;
4886
4887
        if ((!sOriginalWidth || sOriginalWidth == "auto") && 
4888
            (oConfig.getProperty("container") != oBody || 
4889
            oConfig.getProperty("x") >= Dom.getViewportWidth() || 
4890
            oConfig.getProperty("y") >= Dom.getViewportHeight())) {
4891
4892
            oClone = this.element.cloneNode(true);
4893
            oClone.style.visibility = "hidden";
4894
            oClone.style.top = "0px";
4895
            oClone.style.left = "0px";
4896
4897
            oBody.appendChild(oClone);
4898
4899
            sNewWidth = (oClone.offsetWidth + "px");
4900
4901
            oBody.removeChild(oClone);
4902
            oClone = null;
4903
4904
            oConfig.setProperty("width", sNewWidth);
4905
            oConfig.refireEvent("xy");
4906
4907
            this._originalWidth = sOriginalWidth || "";
4908
            this._forcedWidth = sNewWidth;
4909
        }
4910
    }
4911
4912
    // "onDOMReady" that renders the ToolTip
4913
4914
    function onDOMReady(p_sType, p_aArgs, p_oObject) {
4915
        this.render(p_oObject);
4916
    }
4917
4918
    //  "init" event handler that automatically renders the Tooltip
4919
4920
    function onInit() {
4921
        Event.onDOMReady(onDOMReady, this.cfg.getProperty("container"), this);
4922
    }
4923
4924
    YAHOO.extend(Tooltip, YAHOO.widget.Overlay, { 
4925
4926
        /**
4927
        * The Tooltip initialization method. This method is automatically 
4928
        * called by the constructor. A Tooltip is automatically rendered by 
4929
        * the init method, and it also is set to be invisible by default, 
4930
        * and constrained to viewport by default as well.
4931
        * @method init
4932
        * @param {String} el The element ID representing the Tooltip <em>OR</em>
4933
        * @param {HTMLElement} el The element representing the Tooltip
4934
        * @param {Object} userConfig The configuration object literal 
4935
        * containing the configuration that should be set for this Tooltip. 
4936
        * See configuration documentation for more details.
4937
        */
4938
        init: function (el, userConfig) {
4939
4940
            this.logger = new YAHOO.widget.LogWriter(this.toString());
4941
4942
            Tooltip.superclass.init.call(this, el);
4943
4944
            this.beforeInitEvent.fire(Tooltip);
4945
4946
            Dom.addClass(this.element, Tooltip.CSS_TOOLTIP);
4947
4948
            if (userConfig) {
4949
                this.cfg.applyConfig(userConfig, true);
4950
            }
4951
4952
            this.cfg.queueProperty("visible", false);
4953
            this.cfg.queueProperty("constraintoviewport", true);
4954
4955
            this.setBody("");
4956
4957
            this.subscribe("changeContent", setWidthToOffsetWidth);
4958
            this.subscribe("init", onInit);
4959
            this.subscribe("render", this.onRender);
4960
4961
            this.initEvent.fire(Tooltip);
4962
        },
4963
4964
        /**
4965
        * Initializes the custom events for Tooltip
4966
        * @method initEvents
4967
        */
4968
        initEvents: function () {
4969
4970
            Tooltip.superclass.initEvents.call(this);
4971
            var SIGNATURE = CustomEvent.LIST;
4972
4973
            /**
4974
            * CustomEvent fired when user mouses over a context element. Returning false from
4975
            * a subscriber to this event will prevent the tooltip from being displayed for
4976
            * the current context element.
4977
            * 
4978
            * @event contextMouseOverEvent
4979
            * @param {HTMLElement} context The context element which the user just moused over
4980
            * @param {DOMEvent} e The DOM event object, associated with the mouse over
4981
            */
4982
            this.contextMouseOverEvent = this.createEvent(EVENT_TYPES.CONTEXT_MOUSE_OVER);
4983
            this.contextMouseOverEvent.signature = SIGNATURE;
4984
4985
            /**
4986
            * CustomEvent fired when the user mouses out of a context element.
4987
            * 
4988
            * @event contextMouseOutEvent
4989
            * @param {HTMLElement} context The context element which the user just moused out of
4990
            * @param {DOMEvent} e The DOM event object, associated with the mouse out
4991
            */
4992
            this.contextMouseOutEvent = this.createEvent(EVENT_TYPES.CONTEXT_MOUSE_OUT);
4993
            this.contextMouseOutEvent.signature = SIGNATURE;
4994
4995
            /**
4996
            * CustomEvent fired just before the tooltip is displayed for the current context.
4997
            * <p>
4998
            *  You can subscribe to this event if you need to set up the text for the 
4999
            *  tooltip based on the context element for which it is about to be displayed.
5000
            * </p>
5001
            * <p>This event differs from the beforeShow event in following respects:</p>
5002
            * <ol>
5003
            *   <li>
5004
            *    When moving from one context element to another, if the tooltip is not
5005
            *    hidden (the <code>hidedelay</code> is not reached), the beforeShow and Show events will not
5006
            *    be fired when the tooltip is displayed for the new context since it is already visible.
5007
            *    However the contextTrigger event is always fired before displaying the tooltip for
5008
            *    a new context.
5009
            *   </li>
5010
            *   <li>
5011
            *    The trigger event provides access to the context element, allowing you to 
5012
            *    set the text of the tooltip based on context element for which the tooltip is
5013
            *    triggered.
5014
            *   </li>
5015
            * </ol>
5016
            * <p>
5017
            *  It is not possible to prevent the tooltip from being displayed
5018
            *  using this event. You can use the contextMouseOverEvent if you need to prevent
5019
            *  the tooltip from being displayed.
5020
            * </p>
5021
            * @event contextTriggerEvent
5022
            * @param {HTMLElement} context The context element for which the tooltip is triggered
5023
            */
5024
            this.contextTriggerEvent = this.createEvent(EVENT_TYPES.CONTEXT_TRIGGER);
5025
            this.contextTriggerEvent.signature = SIGNATURE;
5026
        },
5027
5028
        /**
5029
        * Initializes the class's configurable properties which can be 
5030
        * changed using the Overlay's Config object (cfg).
5031
        * @method initDefaultConfig
5032
        */
5033
        initDefaultConfig: function () {
5034
5035
            Tooltip.superclass.initDefaultConfig.call(this);
5036
5037
            /**
5038
            * Specifies whether the Tooltip should be kept from overlapping 
5039
            * its context element.
5040
            * @config preventoverlap
5041
            * @type Boolean
5042
            * @default true
5043
            */
5044
            this.cfg.addProperty(DEFAULT_CONFIG.PREVENT_OVERLAP.key, {
5045
                value: DEFAULT_CONFIG.PREVENT_OVERLAP.value, 
5046
                validator: DEFAULT_CONFIG.PREVENT_OVERLAP.validator, 
5047
                supercedes: DEFAULT_CONFIG.PREVENT_OVERLAP.supercedes
5048
            });
5049
5050
            /**
5051
            * The number of milliseconds to wait before showing a Tooltip 
5052
            * on mouseover.
5053
            * @config showdelay
5054
            * @type Number
5055
            * @default 200
5056
            */
5057
            this.cfg.addProperty(DEFAULT_CONFIG.SHOW_DELAY.key, {
5058
                handler: this.configShowDelay,
5059
                value: 200, 
5060
                validator: DEFAULT_CONFIG.SHOW_DELAY.validator
5061
            });
5062
5063
            /**
5064
            * The number of milliseconds to wait before automatically 
5065
            * dismissing a Tooltip after the mouse has been resting on the 
5066
            * context element.
5067
            * @config autodismissdelay
5068
            * @type Number
5069
            * @default 5000
5070
            */
5071
            this.cfg.addProperty(DEFAULT_CONFIG.AUTO_DISMISS_DELAY.key, {
5072
                handler: this.configAutoDismissDelay,
5073
                value: DEFAULT_CONFIG.AUTO_DISMISS_DELAY.value,
5074
                validator: DEFAULT_CONFIG.AUTO_DISMISS_DELAY.validator
5075
            });
5076
5077
            /**
5078
            * The number of milliseconds to wait before hiding a Tooltip 
5079
            * after mouseout.
5080
            * @config hidedelay
5081
            * @type Number
5082
            * @default 250
5083
            */
5084
            this.cfg.addProperty(DEFAULT_CONFIG.HIDE_DELAY.key, {
5085
                handler: this.configHideDelay,
5086
                value: DEFAULT_CONFIG.HIDE_DELAY.value, 
5087
                validator: DEFAULT_CONFIG.HIDE_DELAY.validator
5088
            });
5089
5090
            /**
5091
            * Specifies the Tooltip's text. 
5092
            * @config text
5093
            * @type String
5094
            * @default null
5095
            */
5096
            this.cfg.addProperty(DEFAULT_CONFIG.TEXT.key, {
5097
                handler: this.configText,
5098
                suppressEvent: DEFAULT_CONFIG.TEXT.suppressEvent
5099
            });
5100
5101
            /**
5102
            * Specifies the container element that the Tooltip's markup 
5103
            * should be rendered into.
5104
            * @config container
5105
            * @type HTMLElement/String
5106
            * @default document.body
5107
            */
5108
            this.cfg.addProperty(DEFAULT_CONFIG.CONTAINER.key, {
5109
                handler: this.configContainer,
5110
                value: document.body
5111
            });
5112
5113
            /**
5114
            * Specifies whether or not the tooltip is disabled. Disabled tooltips
5115
            * will not be displayed. If the tooltip is driven by the title attribute
5116
            * of the context element, the title attribute will still be removed for 
5117
            * disabled tooltips, to prevent default tooltip behavior.
5118
            * 
5119
            * @config disabled
5120
            * @type Boolean
5121
            * @default false
5122
            */
5123
            this.cfg.addProperty(DEFAULT_CONFIG.DISABLED.key, {
5124
                handler: this.configContainer,
5125
                value: DEFAULT_CONFIG.DISABLED.value,
5126
                supressEvent: DEFAULT_CONFIG.DISABLED.suppressEvent
5127
            });
5128
5129
            /**
5130
            * Specifies the XY offset from the mouse position, where the tooltip should be displayed, specified
5131
            * as a 2 element array (e.g. [10, 20]); 
5132
            *
5133
            * @config xyoffset
5134
            * @type Array
5135
            * @default [0, 25]
5136
            */
5137
            this.cfg.addProperty(DEFAULT_CONFIG.XY_OFFSET.key, {
5138
                value: DEFAULT_CONFIG.XY_OFFSET.value.concat(),
5139
                supressEvent: DEFAULT_CONFIG.XY_OFFSET.suppressEvent 
5140
            });
5141
5142
            /**
5143
            * Specifies the element or elements that the Tooltip should be 
5144
            * anchored to on mouseover.
5145
            * @config context
5146
            * @type HTMLElement[]/String[]
5147
            * @default null
5148
            */ 
5149
5150
            /**
5151
            * String representing the width of the Tooltip.  <em>Please note:
5152
            * </em> As of version 2.3 if either no value or a value of "auto" 
5153
            * is specified, and the Toolip's "container" configuration property
5154
            * is set to something other than <code>document.body</code> or 
5155
            * its "context" element resides outside the immediately visible 
5156
            * portion of the document, the width of the Tooltip will be 
5157
            * calculated based on the offsetWidth of its root HTML and set just 
5158
            * before it is made visible.  The original value will be 
5159
            * restored when the Tooltip is hidden. This ensures the Tooltip is 
5160
            * rendered at a usable width.  For more information see 
5161
            * YUILibrary bug #1685496 and YUILibrary 
5162
            * bug #1735423.
5163
            * @config width
5164
            * @type String
5165
            * @default null
5166
            */
5167
        
5168
        },
5169
        
5170
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
5171
        
5172
        /**
5173
        * The default event handler fired when the "text" property is changed.
5174
        * @method configText
5175
        * @param {String} type The CustomEvent type (usually the property name)
5176
        * @param {Object[]} args The CustomEvent arguments. For configuration 
5177
        * handlers, args[0] will equal the newly applied value for the property.
5178
        * @param {Object} obj The scope object. For configuration handlers, 
5179
        * this will usually equal the owner.
5180
        */
5181
        configText: function (type, args, obj) {
5182
            var text = args[0];
5183
            if (text) {
5184
                this.setBody(text);
5185
            }
5186
        },
5187
        
5188
        /**
5189
        * The default event handler fired when the "container" property 
5190
        * is changed.
5191
        * @method configContainer
5192
        * @param {String} type The CustomEvent type (usually the property name)
5193
        * @param {Object[]} args The CustomEvent arguments. For 
5194
        * configuration handlers, args[0] will equal the newly applied value 
5195
        * for the property.
5196
        * @param {Object} obj The scope object. For configuration handlers,
5197
        * this will usually equal the owner.
5198
        */
5199
        configContainer: function (type, args, obj) {
5200
            var container = args[0];
5201
5202
            if (typeof container == 'string') {
5203
                this.cfg.setProperty("container", document.getElementById(container), true);
5204
            }
5205
        },
5206
        
5207
        /**
5208
        * @method _removeEventListeners
5209
        * @description Removes all of the DOM event handlers from the HTML
5210
        *  element(s) that trigger the display of the tooltip.
5211
        * @protected
5212
        */
5213
        _removeEventListeners: function () {
5214
        
5215
            var aElements = this._context,
5216
                nElements,
5217
                oElement,
5218
                i;
5219
5220
            if (aElements) {
5221
                nElements = aElements.length;
5222
                if (nElements > 0) {
5223
                    i = nElements - 1;
5224
                    do {
5225
                        oElement = aElements[i];
5226
                        Event.removeListener(oElement, "mouseover", this.onContextMouseOver);
5227
                        Event.removeListener(oElement, "mousemove", this.onContextMouseMove);
5228
                        Event.removeListener(oElement, "mouseout", this.onContextMouseOut);
5229
                    }
5230
                    while (i--);
5231
                }
5232
            }
5233
        },
5234
        
5235
        /**
5236
        * The default event handler fired when the "context" property 
5237
        * is changed.
5238
        * @method configContext
5239
        * @param {String} type The CustomEvent type (usually the property name)
5240
        * @param {Object[]} args The CustomEvent arguments. For configuration 
5241
        * handlers, args[0] will equal the newly applied value for the property.
5242
        * @param {Object} obj The scope object. For configuration handlers,
5243
        * this will usually equal the owner.
5244
        */
5245
        configContext: function (type, args, obj) {
5246
5247
            var context = args[0],
5248
                aElements,
5249
                nElements,
5250
                oElement,
5251
                i;
5252
5253
            if (context) {
5254
5255
                // Normalize parameter into an array
5256
                if (! (context instanceof Array)) {
5257
                    if (typeof context == "string") {
5258
                        this.cfg.setProperty("context", [document.getElementById(context)], true);
5259
                    } else { // Assuming this is an element
5260
                        this.cfg.setProperty("context", [context], true);
5261
                    }
5262
                    context = this.cfg.getProperty("context");
5263
                }
5264
5265
                // Remove any existing mouseover/mouseout listeners
5266
                this._removeEventListeners();
5267
5268
                // Add mouseover/mouseout listeners to context elements
5269
                this._context = context;
5270
5271
                aElements = this._context;
5272
5273
                if (aElements) {
5274
                    nElements = aElements.length;
5275
                    if (nElements > 0) {
5276
                        i = nElements - 1;
5277
                        do {
5278
                            oElement = aElements[i];
5279
                            Event.on(oElement, "mouseover", this.onContextMouseOver, this);
5280
                            Event.on(oElement, "mousemove", this.onContextMouseMove, this);
5281
                            Event.on(oElement, "mouseout", this.onContextMouseOut, this);
5282
                        }
5283
                        while (i--);
5284
                    }
5285
                }
5286
            }
5287
        },
5288
5289
        // END BUILT-IN PROPERTY EVENT HANDLERS //
5290
5291
        // BEGIN BUILT-IN DOM EVENT HANDLERS //
5292
5293
        /**
5294
        * The default event handler fired when the user moves the mouse while 
5295
        * over the context element.
5296
        * @method onContextMouseMove
5297
        * @param {DOMEvent} e The current DOM event
5298
        * @param {Object} obj The object argument
5299
        */
5300
        onContextMouseMove: function (e, obj) {
5301
            obj.pageX = Event.getPageX(e);
5302
            obj.pageY = Event.getPageY(e);
5303
        },
5304
5305
        /**
5306
        * The default event handler fired when the user mouses over the 
5307
        * context element.
5308
        * @method onContextMouseOver
5309
        * @param {DOMEvent} e The current DOM event
5310
        * @param {Object} obj The object argument
5311
        */
5312
        onContextMouseOver: function (e, obj) {
5313
            var context = this;
5314
5315
            if (context.title) {
5316
                obj._tempTitle = context.title;
5317
                context.title = "";
5318
            }
5319
5320
            // Fire first, to honor disabled set in the listner
5321
            if (obj.fireEvent("contextMouseOver", context, e) !== false 
5322
                    && !obj.cfg.getProperty("disabled")) {
5323
5324
                // Stop the tooltip from being hidden (set on last mouseout)
5325
                if (obj.hideProcId) {
5326
                    clearTimeout(obj.hideProcId);
5327
                    obj.logger.log("Clearing hide timer: " + obj.hideProcId, "time");
5328
                    obj.hideProcId = null;
5329
                }
5330
5331
                Event.on(context, "mousemove", obj.onContextMouseMove, obj);
5332
5333
                /**
5334
                * The unique process ID associated with the thread responsible 
5335
                * for showing the Tooltip.
5336
                * @type int
5337
                */
5338
                obj.showProcId = obj.doShow(e, context);
5339
                obj.logger.log("Setting show tooltip timeout: " + obj.showProcId, "time");
5340
            }
5341
        },
5342
5343
        /**
5344
        * The default event handler fired when the user mouses out of 
5345
        * the context element.
5346
        * @method onContextMouseOut
5347
        * @param {DOMEvent} e The current DOM event
5348
        * @param {Object} obj The object argument
5349
        */
5350
        onContextMouseOut: function (e, obj) {
5351
            var el = this;
5352
5353
            if (obj._tempTitle) {
5354
                el.title = obj._tempTitle;
5355
                obj._tempTitle = null;
5356
            }
5357
5358
            if (obj.showProcId) {
5359
                clearTimeout(obj.showProcId);
5360
                obj.logger.log("Clearing show timer: " + obj.showProcId, "time");
5361
                obj.showProcId = null;
5362
            }
5363
5364
            if (obj.hideProcId) {
5365
                clearTimeout(obj.hideProcId);
5366
                obj.logger.log("Clearing hide timer: " + obj.hideProcId, "time");
5367
                obj.hideProcId = null;
5368
            }
5369
5370
            obj.fireEvent("contextMouseOut", el, e);
5371
5372
            obj.hideProcId = setTimeout(function () {
5373
                obj.hide();
5374
            }, obj.cfg.getProperty("hidedelay"));
5375
        },
5376
5377
        // END BUILT-IN DOM EVENT HANDLERS //
5378
5379
        /**
5380
        * Processes the showing of the Tooltip by setting the timeout delay 
5381
        * and offset of the Tooltip.
5382
        * @method doShow
5383
        * @param {DOMEvent} e The current DOM event
5384
        * @param {HTMLElement} context The current context element
5385
        * @return {Number} The process ID of the timeout function associated 
5386
        * with doShow
5387
        */
5388
        doShow: function (e, context) {
5389
5390
            var offset = this.cfg.getProperty("xyoffset"),
5391
                xOffset = offset[0],
5392
                yOffset = offset[1],
5393
                me = this;
5394
5395
            if (UA.opera && context.tagName && 
5396
                context.tagName.toUpperCase() == "A") {
5397
                yOffset += 12;
5398
            }
5399
5400
            return setTimeout(function () {
5401
5402
                var txt = me.cfg.getProperty("text");
5403
5404
                // title does not over-ride text
5405
                if (me._tempTitle && (txt === "" || YAHOO.lang.isUndefined(txt) || YAHOO.lang.isNull(txt))) {
5406
                    me.setBody(me._tempTitle);
5407
                } else {
5408
                    me.cfg.refireEvent("text");
5409
                }
5410
5411
                me.logger.log("Show tooltip", "time");
5412
                me.moveTo(me.pageX + xOffset, me.pageY + yOffset);
5413
5414
                if (me.cfg.getProperty("preventoverlap")) {
5415
                    me.preventOverlap(me.pageX, me.pageY);
5416
                }
5417
5418
                Event.removeListener(context, "mousemove", me.onContextMouseMove);
5419
5420
                me.contextTriggerEvent.fire(context);
5421
5422
                me.show();
5423
5424
                me.hideProcId = me.doHide();
5425
                me.logger.log("Hide tooltip time active: " + me.hideProcId, "time");
5426
5427
            }, this.cfg.getProperty("showdelay"));
5428
        },
5429
5430
        /**
5431
        * Sets the timeout for the auto-dismiss delay, which by default is 5 
5432
        * seconds, meaning that a tooltip will automatically dismiss itself 
5433
        * after 5 seconds of being displayed.
5434
        * @method doHide
5435
        */
5436
        doHide: function () {
5437
5438
            var me = this;
5439
5440
            me.logger.log("Setting hide tooltip timeout", "time");
5441
5442
            return setTimeout(function () {
5443
5444
                me.logger.log("Hide tooltip", "time");
5445
                me.hide();
5446
5447
            }, this.cfg.getProperty("autodismissdelay"));
5448
5449
        },
5450
5451
        /**
5452
        * Fired when the Tooltip is moved, this event handler is used to 
5453
        * prevent the Tooltip from overlapping with its context element.
5454
        * @method preventOverlay
5455
        * @param {Number} pageX The x coordinate position of the mouse pointer
5456
        * @param {Number} pageY The y coordinate position of the mouse pointer
5457
        */
5458
        preventOverlap: function (pageX, pageY) {
5459
        
5460
            var height = this.element.offsetHeight,
5461
                mousePoint = new YAHOO.util.Point(pageX, pageY),
5462
                elementRegion = Dom.getRegion(this.element);
5463
        
5464
            elementRegion.top -= 5;
5465
            elementRegion.left -= 5;
5466
            elementRegion.right += 5;
5467
            elementRegion.bottom += 5;
5468
        
5469
            this.logger.log("context " + elementRegion, "ttip");
5470
            this.logger.log("mouse " + mousePoint, "ttip");
5471
        
5472
            if (elementRegion.contains(mousePoint)) {
5473
                this.logger.log("OVERLAP", "warn");
5474
                this.cfg.setProperty("y", (pageY - height - 5));
5475
            }
5476
        },
5477
5478
5479
        /**
5480
        * @method onRender
5481
        * @description "render" event handler for the Tooltip.
5482
        * @param {String} p_sType String representing the name of the event  
5483
        * that was fired.
5484
        * @param {Array} p_aArgs Array of arguments sent when the event 
5485
        * was fired.
5486
        */
5487
        onRender: function (p_sType, p_aArgs) {
5488
    
5489
            function sizeShadow() {
5490
    
5491
                var oElement = this.element,
5492
                    oShadow = this.underlay;
5493
            
5494
                if (oShadow) {
5495
                    oShadow.style.width = (oElement.offsetWidth + 6) + "px";
5496
                    oShadow.style.height = (oElement.offsetHeight + 1) + "px"; 
5497
                }
5498
            
5499
            }
5500
5501
            function addShadowVisibleClass() {
5502
                Dom.addClass(this.underlay, "yui-tt-shadow-visible");
5503
5504
                if (UA.ie) {
5505
                    this.forceUnderlayRedraw();
5506
                }
5507
            }
5508
5509
            function removeShadowVisibleClass() {
5510
                Dom.removeClass(this.underlay, "yui-tt-shadow-visible");
5511
            }
5512
5513
            function createShadow() {
5514
    
5515
                var oShadow = this.underlay,
5516
                    oElement,
5517
                    Module,
5518
                    nIE,
5519
                    me;
5520
    
5521
                if (!oShadow) {
5522
    
5523
                    oElement = this.element;
5524
                    Module = YAHOO.widget.Module;
5525
                    nIE = UA.ie;
5526
                    me = this;
5527
5528
                    if (!m_oShadowTemplate) {
5529
                        m_oShadowTemplate = document.createElement("div");
5530
                        m_oShadowTemplate.className = "yui-tt-shadow";
5531
                    }
5532
5533
                    oShadow = m_oShadowTemplate.cloneNode(false);
5534
5535
                    oElement.appendChild(oShadow);
5536
5537
                    this.underlay = oShadow;
5538
5539
                    // Backward compatibility, even though it's probably 
5540
                    // intended to be "private", it isn't marked as such in the api docs
5541
                    this._shadow = this.underlay;
5542
5543
                    addShadowVisibleClass.call(this);
5544
5545
                    this.subscribe("beforeShow", addShadowVisibleClass);
5546
                    this.subscribe("hide", removeShadowVisibleClass);
5547
5548
                    if (bIEQuirks) {
5549
                        window.setTimeout(function () { 
5550
                            sizeShadow.call(me); 
5551
                        }, 0);
5552
    
5553
                        this.cfg.subscribeToConfigEvent("width", sizeShadow);
5554
                        this.cfg.subscribeToConfigEvent("height", sizeShadow);
5555
                        this.subscribe("changeContent", sizeShadow);
5556
5557
                        Module.textResizeEvent.subscribe(sizeShadow, this, true);
5558
                        this.subscribe("destroy", function () {
5559
                            Module.textResizeEvent.unsubscribe(sizeShadow, this);
5560
                        });
5561
                    }
5562
                }
5563
            }
5564
5565
            function onBeforeShow() {
5566
                createShadow.call(this);
5567
                this.unsubscribe("beforeShow", onBeforeShow);
5568
            }
5569
5570
            if (this.cfg.getProperty("visible")) {
5571
                createShadow.call(this);
5572
            } else {
5573
                this.subscribe("beforeShow", onBeforeShow);
5574
            }
5575
        
5576
        },
5577
5578
        /**
5579
         * Forces the underlay element to be repainted, through the application/removal
5580
         * of a yui-force-redraw class to the underlay element.
5581
         * 
5582
         * @method forceUnderlayRedraw
5583
         */
5584
        forceUnderlayRedraw : function() {
5585
            var tt = this;
5586
            Dom.addClass(tt.underlay, "yui-force-redraw");
5587
            setTimeout(function() {Dom.removeClass(tt.underlay, "yui-force-redraw");}, 0);
5588
        },
5589
5590
        /**
5591
        * Removes the Tooltip element from the DOM and sets all child 
5592
        * elements to null.
5593
        * @method destroy
5594
        */
5595
        destroy: function () {
5596
        
5597
            // Remove any existing mouseover/mouseout listeners
5598
            this._removeEventListeners();
5599
5600
            Tooltip.superclass.destroy.call(this);  
5601
        
5602
        },
5603
        
5604
        /**
5605
        * Returns a string representation of the object.
5606
        * @method toString
5607
        * @return {String} The string representation of the Tooltip
5608
        */
5609
        toString: function () {
5610
            return "Tooltip " + this.id;
5611
        }
5612
    
5613
    });
5614
5615
}());
5616
(function () {
5617
5618
    /**
5619
    * Panel is an implementation of Overlay that behaves like an OS window, 
5620
    * with a draggable header and an optional close icon at the top right.
5621
    * @namespace YAHOO.widget
5622
    * @class Panel
5623
    * @extends YAHOO.widget.Overlay
5624
    * @constructor
5625
    * @param {String} el The element ID representing the Panel <em>OR</em>
5626
    * @param {HTMLElement} el The element representing the Panel
5627
    * @param {Object} userConfig The configuration object literal containing 
5628
    * the configuration that should be set for this Panel. See configuration 
5629
    * documentation for more details.
5630
    */
5631
    YAHOO.widget.Panel = function (el, userConfig) {
5632
        YAHOO.widget.Panel.superclass.constructor.call(this, el, userConfig);
5633
    };
5634
5635
    var _currentModal = null;
5636
5637
    var Lang = YAHOO.lang,
5638
        Util = YAHOO.util,
5639
        Dom = Util.Dom,
5640
        Event = Util.Event,
5641
        CustomEvent = Util.CustomEvent,
5642
        KeyListener = YAHOO.util.KeyListener,
5643
        Config = Util.Config,
5644
        Overlay = YAHOO.widget.Overlay,
5645
        Panel = YAHOO.widget.Panel,
5646
        UA = YAHOO.env.ua,
5647
5648
        bIEQuirks = (UA.ie && (UA.ie <= 6 || document.compatMode == "BackCompat")),
5649
5650
        m_oMaskTemplate,
5651
        m_oUnderlayTemplate,
5652
        m_oCloseIconTemplate,
5653
5654
        /**
5655
        * Constant representing the name of the Panel's events
5656
        * @property EVENT_TYPES
5657
        * @private
5658
        * @final
5659
        * @type Object
5660
        */
5661
        EVENT_TYPES = {
5662
            "SHOW_MASK": "showMask",
5663
            "HIDE_MASK": "hideMask",
5664
            "DRAG": "drag"
5665
        },
5666
5667
        /**
5668
        * Constant representing the Panel's configuration properties
5669
        * @property DEFAULT_CONFIG
5670
        * @private
5671
        * @final
5672
        * @type Object
5673
        */
5674
        DEFAULT_CONFIG = {
5675
5676
            "CLOSE": { 
5677
                key: "close", 
5678
                value: true, 
5679
                validator: Lang.isBoolean, 
5680
                supercedes: ["visible"] 
5681
            },
5682
5683
            "DRAGGABLE": {
5684
                key: "draggable", 
5685
                value: (Util.DD ? true : false), 
5686
                validator: Lang.isBoolean, 
5687
                supercedes: ["visible"]  
5688
            },
5689
5690
            "DRAG_ONLY" : {
5691
                key: "dragonly",
5692
                value: false,
5693
                validator: Lang.isBoolean,
5694
                supercedes: ["draggable"]
5695
            },
5696
5697
            "UNDERLAY": { 
5698
                key: "underlay", 
5699
                value: "shadow", 
5700
                supercedes: ["visible"] 
5701
            },
5702
5703
            "MODAL": { 
5704
                key: "modal", 
5705
                value: false, 
5706
                validator: Lang.isBoolean, 
5707
                supercedes: ["visible", "zindex"]
5708
            },
5709
5710
            "KEY_LISTENERS": {
5711
                key: "keylisteners",
5712
                suppressEvent: true,
5713
                supercedes: ["visible"]
5714
            },
5715
5716
            "STRINGS" : {
5717
                key: "strings",
5718
                supercedes: ["close"],
5719
                validator: Lang.isObject,
5720
                value: {
5721
                    close: "Close"
5722
                }
5723
            }
5724
        };
5725
5726
    /**
5727
    * Constant representing the default CSS class used for a Panel
5728
    * @property YAHOO.widget.Panel.CSS_PANEL
5729
    * @static
5730
    * @final
5731
    * @type String
5732
    */
5733
    Panel.CSS_PANEL = "yui-panel";
5734
    
5735
    /**
5736
    * Constant representing the default CSS class used for a Panel's 
5737
    * wrapping container
5738
    * @property YAHOO.widget.Panel.CSS_PANEL_CONTAINER
5739
    * @static
5740
    * @final
5741
    * @type String
5742
    */
5743
    Panel.CSS_PANEL_CONTAINER = "yui-panel-container";
5744
5745
    /**
5746
     * Constant representing the default set of focusable elements 
5747
     * on the pagewhich Modal Panels will prevent access to, when
5748
     * the modal mask is displayed
5749
     * 
5750
     * @property YAHOO.widget.Panel.FOCUSABLE
5751
     * @static
5752
     * @type Array
5753
     */
5754
    Panel.FOCUSABLE = [
5755
        "a",
5756
        "button",
5757
        "select",
5758
        "textarea",
5759
        "input",
5760
        "iframe"
5761
    ];
5762
5763
    // Private CustomEvent listeners
5764
5765
    /* 
5766
        "beforeRender" event handler that creates an empty header for a Panel 
5767
        instance if its "draggable" configuration property is set to "true" 
5768
        and no header has been created.
5769
    */
5770
5771
    function createHeader(p_sType, p_aArgs) {
5772
        if (!this.header && this.cfg.getProperty("draggable")) {
5773
            this.setHeader("&#160;");
5774
        }
5775
    }
5776
5777
    /* 
5778
        "hide" event handler that sets a Panel instance's "width"
5779
        configuration property back to its original value before 
5780
        "setWidthToOffsetWidth" was called.
5781
    */
5782
    
5783
    function restoreOriginalWidth(p_sType, p_aArgs, p_oObject) {
5784
5785
        var sOriginalWidth = p_oObject[0],
5786
            sNewWidth = p_oObject[1],
5787
            oConfig = this.cfg,
5788
            sCurrentWidth = oConfig.getProperty("width");
5789
5790
        if (sCurrentWidth == sNewWidth) {
5791
            oConfig.setProperty("width", sOriginalWidth);
5792
        }
5793
5794
        this.unsubscribe("hide", restoreOriginalWidth, p_oObject);
5795
    }
5796
5797
    /* 
5798
        "beforeShow" event handler that sets a Panel instance's "width"
5799
        configuration property to the value of its root HTML 
5800
        elements's offsetWidth
5801
    */
5802
5803
    function setWidthToOffsetWidth(p_sType, p_aArgs) {
5804
5805
        var oConfig,
5806
            sOriginalWidth,
5807
            sNewWidth;
5808
5809
        if (bIEQuirks) {
5810
5811
            oConfig = this.cfg;
5812
            sOriginalWidth = oConfig.getProperty("width");
5813
            
5814
            if (!sOriginalWidth || sOriginalWidth == "auto") {
5815
    
5816
                sNewWidth = (this.element.offsetWidth + "px");
5817
    
5818
                oConfig.setProperty("width", sNewWidth);
5819
5820
                this.subscribe("hide", restoreOriginalWidth, 
5821
                    [(sOriginalWidth || ""), sNewWidth]);
5822
            
5823
            }
5824
        }
5825
    }
5826
5827
    YAHOO.extend(Panel, Overlay, {
5828
5829
        /**
5830
        * The Overlay initialization method, which is executed for Overlay and 
5831
        * all of its subclasses. This method is automatically called by the 
5832
        * constructor, and  sets up all DOM references for pre-existing markup, 
5833
        * and creates required markup if it is not already present.
5834
        * @method init
5835
        * @param {String} el The element ID representing the Overlay <em>OR</em>
5836
        * @param {HTMLElement} el The element representing the Overlay
5837
        * @param {Object} userConfig The configuration object literal 
5838
        * containing the configuration that should be set for this Overlay. 
5839
        * See configuration documentation for more details.
5840
        */
5841
        init: function (el, userConfig) {
5842
            /*
5843
                 Note that we don't pass the user config in here yet because 
5844
                 we only want it executed once, at the lowest subclass level
5845
            */
5846
5847
            Panel.superclass.init.call(this, el/*, userConfig*/);
5848
5849
            this.beforeInitEvent.fire(Panel);
5850
5851
            Dom.addClass(this.element, Panel.CSS_PANEL);
5852
5853
            this.buildWrapper();
5854
5855
            if (userConfig) {
5856
                this.cfg.applyConfig(userConfig, true);
5857
            }
5858
5859
            this.subscribe("showMask", this._addFocusHandlers);
5860
            this.subscribe("hideMask", this._removeFocusHandlers);
5861
            this.subscribe("beforeRender", createHeader);
5862
5863
            this.subscribe("render", function() {
5864
                this.setFirstLastFocusable();
5865
                this.subscribe("changeContent", this.setFirstLastFocusable);
5866
            });
5867
5868
            this.subscribe("show", this.focusFirst);
5869
5870
            this.initEvent.fire(Panel);
5871
        },
5872
5873
        /**
5874
         * @method _onElementFocus
5875
         * @private
5876
         *
5877
         * "focus" event handler for a focuable element. Used to automatically
5878
         * blur the element when it receives focus to ensure that a Panel
5879
         * instance's modality is not compromised.
5880
         *
5881
         * @param {Event} e The DOM event object
5882
         */
5883
        _onElementFocus : function(e){
5884
5885
            if(_currentModal === this) {
5886
5887
                var target = Event.getTarget(e),
5888
                    doc = document.documentElement,
5889
                    insideDoc = (target !== doc && target !== window);
5890
5891
                // mask and documentElement checks added for IE, which focuses on the mask when it's clicked on, and focuses on 
5892
                // the documentElement, when the document scrollbars are clicked on
5893
                if (insideDoc && target !== this.element && target !== this.mask && !Dom.isAncestor(this.element, target)) {
5894
                    try {
5895
                        if (this.firstElement) {
5896
                            this.firstElement.focus();
5897
                        } else {
5898
                            if (this._modalFocus) {
5899
                                this._modalFocus.focus();
5900
                            } else {
5901
                                this.innerElement.focus();
5902
                            }
5903
                        }
5904
                    } catch(err){
5905
                        // Just in case we fail to focus
5906
                        try {
5907
                            if (insideDoc && target !== document.body) {
5908
                                target.blur();
5909
                            }
5910
                        } catch(err2) { }
5911
                    }
5912
                }
5913
            }
5914
        },
5915
5916
        /** 
5917
         *  @method _addFocusHandlers
5918
         *  @protected
5919
         *  
5920
         *  "showMask" event handler that adds a "focus" event handler to all
5921
         *  focusable elements in the document to enforce a Panel instance's 
5922
         *  modality from being compromised.
5923
         *
5924
         *  @param p_sType {String} Custom event type
5925
         *  @param p_aArgs {Array} Custom event arguments
5926
         */
5927
        _addFocusHandlers: function(p_sType, p_aArgs) {
5928
            if (!this.firstElement) {
5929
                if (UA.webkit || UA.opera) {
5930
                    if (!this._modalFocus) {
5931
                        this._createHiddenFocusElement();
5932
                    }
5933
                } else {
5934
                    this.innerElement.tabIndex = 0;
5935
                }
5936
            }
5937
            this.setTabLoop(this.firstElement, this.lastElement);
5938
            Event.onFocus(document.documentElement, this._onElementFocus, this, true);
5939
            _currentModal = this;
5940
        },
5941
5942
        /**
5943
         * Creates a hidden focusable element, used to focus on,
5944
         * to enforce modality for browsers in which focus cannot
5945
         * be applied to the container box.
5946
         * 
5947
         * @method _createHiddenFocusElement
5948
         * @private
5949
         */
5950
        _createHiddenFocusElement : function() {
5951
            var e = document.createElement("button");
5952
            e.style.height = "1px";
5953
            e.style.width = "1px";
5954
            e.style.position = "absolute";
5955
            e.style.left = "-10000em";
5956
            e.style.opacity = 0;
5957
            e.tabIndex = -1;
5958
            this.innerElement.appendChild(e);
5959
            this._modalFocus = e;
5960
        },
5961
5962
        /**
5963
         *  @method _removeFocusHandlers
5964
         *  @protected
5965
         *
5966
         *  "hideMask" event handler that removes all "focus" event handlers added 
5967
         *  by the "addFocusEventHandlers" method.
5968
         *
5969
         *  @param p_sType {String} Event type
5970
         *  @param p_aArgs {Array} Event Arguments
5971
         */
5972
        _removeFocusHandlers: function(p_sType, p_aArgs) {
5973
            Event.removeFocusListener(document.documentElement, this._onElementFocus, this);
5974
5975
            if (_currentModal == this) {
5976
                _currentModal = null;
5977
            }
5978
        },
5979
5980
        /**
5981
         * Sets focus to the first element in the Panel.
5982
         *
5983
         * @method focusFirst
5984
         */
5985
        focusFirst: function (type, args, obj) {
5986
            var el = this.firstElement;
5987
5988
            if (args && args[1]) {
5989
                Event.stopEvent(args[1]);
5990
            }
5991
5992
            if (el) {
5993
                try {
5994
                    el.focus();
5995
                } catch(err) {
5996
                    // Ignore
5997
                }
5998
            }
5999
        },
6000
6001
        /**
6002
         * Sets focus to the last element in the Panel.
6003
         *
6004
         * @method focusLast
6005
         */
6006
        focusLast: function (type, args, obj) {
6007
            var el = this.lastElement;
6008
6009
            if (args && args[1]) {
6010
                Event.stopEvent(args[1]);
6011
            }
6012
6013
            if (el) {
6014
                try {
6015
                    el.focus();
6016
                } catch(err) {
6017
                    // Ignore
6018
                }
6019
            }
6020
        },
6021
6022
        /**
6023
         * Sets up a tab, shift-tab loop between the first and last elements
6024
         * provided. NOTE: Sets up the preventBackTab and preventTabOut KeyListener
6025
         * instance properties, which are reset everytime this method is invoked.
6026
         *
6027
         * @method setTabLoop
6028
         * @param {HTMLElement} firstElement
6029
         * @param {HTMLElement} lastElement
6030
         *
6031
         */
6032
        setTabLoop : function(firstElement, lastElement) {
6033
6034
            var backTab = this.preventBackTab, tab = this.preventTabOut,
6035
                showEvent = this.showEvent, hideEvent = this.hideEvent;
6036
6037
            if (backTab) {
6038
                backTab.disable();
6039
                showEvent.unsubscribe(backTab.enable, backTab);
6040
                hideEvent.unsubscribe(backTab.disable, backTab);
6041
                backTab = this.preventBackTab = null;
6042
            }
6043
6044
            if (tab) {
6045
                tab.disable();
6046
                showEvent.unsubscribe(tab.enable, tab);
6047
                hideEvent.unsubscribe(tab.disable,tab);
6048
                tab = this.preventTabOut = null;
6049
            }
6050
6051
            if (firstElement) {
6052
                this.preventBackTab = new KeyListener(firstElement, 
6053
                    {shift:true, keys:9},
6054
                    {fn:this.focusLast, scope:this, correctScope:true}
6055
                );
6056
                backTab = this.preventBackTab;
6057
6058
                showEvent.subscribe(backTab.enable, backTab, true);
6059
                hideEvent.subscribe(backTab.disable,backTab, true);
6060
            }
6061
6062
            if (lastElement) {
6063
                this.preventTabOut = new KeyListener(lastElement, 
6064
                    {shift:false, keys:9}, 
6065
                    {fn:this.focusFirst, scope:this, correctScope:true}
6066
                );
6067
                tab = this.preventTabOut;
6068
6069
                showEvent.subscribe(tab.enable, tab, true);
6070
                hideEvent.subscribe(tab.disable,tab, true);
6071
            }
6072
        },
6073
6074
        /**
6075
         * Returns an array of the currently focusable items which reside within
6076
         * Panel. The set of focusable elements the method looks for are defined
6077
         * in the Panel.FOCUSABLE static property
6078
         *
6079
         * @method getFocusableElements
6080
         * @param {HTMLElement} root element to start from.
6081
         */
6082
        getFocusableElements : function(root) {
6083
6084
            root = root || this.innerElement;
6085
6086
            var focusable = {};
6087
            for (var i = 0; i < Panel.FOCUSABLE.length; i++) {
6088
                focusable[Panel.FOCUSABLE[i]] = true;
6089
            }
6090
6091
            function isFocusable(el) {
6092
                if (el.focus && el.type !== "hidden" && !el.disabled && focusable[el.tagName.toLowerCase()]) {
6093
                    return true;
6094
                }
6095
                return false;
6096
            }
6097
6098
            // Not looking by Tag, since we want elements in DOM order
6099
            return Dom.getElementsBy(isFocusable, null, root);
6100
        },
6101
6102
        /**
6103
         * Sets the firstElement and lastElement instance properties
6104
         * to the first and last focusable elements in the Panel.
6105
         *
6106
         * @method setFirstLastFocusable
6107
         */
6108
        setFirstLastFocusable : function() {
6109
6110
            this.firstElement = null;
6111
            this.lastElement = null;
6112
6113
            var elements = this.getFocusableElements();
6114
            this.focusableElements = elements;
6115
6116
            if (elements.length > 0) {
6117
                this.firstElement = elements[0];
6118
                this.lastElement = elements[elements.length - 1];
6119
            }
6120
6121
            if (this.cfg.getProperty("modal")) {
6122
                this.setTabLoop(this.firstElement, this.lastElement);
6123
            }
6124
        },
6125
6126
        /**
6127
         * Initializes the custom events for Module which are fired 
6128
         * automatically at appropriate times by the Module class.
6129
         */
6130
        initEvents: function () {
6131
            Panel.superclass.initEvents.call(this);
6132
6133
            var SIGNATURE = CustomEvent.LIST;
6134
6135
            /**
6136
            * CustomEvent fired after the modality mask is shown
6137
            * @event showMaskEvent
6138
            */
6139
            this.showMaskEvent = this.createEvent(EVENT_TYPES.SHOW_MASK);
6140
            this.showMaskEvent.signature = SIGNATURE;
6141
6142
            /**
6143
            * CustomEvent fired after the modality mask is hidden
6144
            * @event hideMaskEvent
6145
            */
6146
            this.hideMaskEvent = this.createEvent(EVENT_TYPES.HIDE_MASK);
6147
            this.hideMaskEvent.signature = SIGNATURE;
6148
6149
            /**
6150
            * CustomEvent when the Panel is dragged
6151
            * @event dragEvent
6152
            */
6153
            this.dragEvent = this.createEvent(EVENT_TYPES.DRAG);
6154
            this.dragEvent.signature = SIGNATURE;
6155
        },
6156
6157
        /**
6158
         * Initializes the class's configurable properties which can be changed 
6159
         * using the Panel's Config object (cfg).
6160
         * @method initDefaultConfig
6161
         */
6162
        initDefaultConfig: function () {
6163
            Panel.superclass.initDefaultConfig.call(this);
6164
6165
            // Add panel config properties //
6166
6167
            /**
6168
            * True if the Panel should display a "close" button
6169
            * @config close
6170
            * @type Boolean
6171
            * @default true
6172
            */
6173
            this.cfg.addProperty(DEFAULT_CONFIG.CLOSE.key, { 
6174
                handler: this.configClose, 
6175
                value: DEFAULT_CONFIG.CLOSE.value, 
6176
                validator: DEFAULT_CONFIG.CLOSE.validator, 
6177
                supercedes: DEFAULT_CONFIG.CLOSE.supercedes 
6178
            });
6179
6180
            /**
6181
            * Boolean specifying if the Panel should be draggable.  The default 
6182
            * value is "true" if the Drag and Drop utility is included, 
6183
            * otherwise it is "false." <strong>PLEASE NOTE:</strong> There is a 
6184
            * known issue in IE 6 (Strict Mode and Quirks Mode) and IE 7 
6185
            * (Quirks Mode) where Panels that either don't have a value set for 
6186
            * their "width" configuration property, or their "width" 
6187
            * configuration property is set to "auto" will only be draggable by
6188
            * placing the mouse on the text of the Panel's header element.
6189
            * To fix this bug, draggable Panels missing a value for their 
6190
            * "width" configuration property, or whose "width" configuration 
6191
            * property is set to "auto" will have it set to the value of 
6192
            * their root HTML element's offsetWidth before they are made 
6193
            * visible.  The calculated width is then removed when the Panel is   
6194
            * hidden. <em>This fix is only applied to draggable Panels in IE 6 
6195
            * (Strict Mode and Quirks Mode) and IE 7 (Quirks Mode)</em>. For 
6196
            * more information on this issue see:
6197
            * YUILibrary bugs #1726972 and #1589210.
6198
            * @config draggable
6199
            * @type Boolean
6200
            * @default true
6201
            */
6202
            this.cfg.addProperty(DEFAULT_CONFIG.DRAGGABLE.key, {
6203
                handler: this.configDraggable,
6204
                value: (Util.DD) ? true : false,
6205
                validator: DEFAULT_CONFIG.DRAGGABLE.validator,
6206
                supercedes: DEFAULT_CONFIG.DRAGGABLE.supercedes
6207
            });
6208
6209
            /**
6210
            * Boolean specifying if the draggable Panel should be drag only, not interacting with drop 
6211
            * targets on the page.
6212
            * <p>
6213
            * When set to true, draggable Panels will not check to see if they are over drop targets,
6214
            * or fire the DragDrop events required to support drop target interaction (onDragEnter, 
6215
            * onDragOver, onDragOut, onDragDrop etc.).
6216
            * If the Panel is not designed to be dropped on any target elements on the page, then this 
6217
            * flag can be set to true to improve performance.
6218
            * </p>
6219
            * <p>
6220
            * When set to false, all drop target related events will be fired.
6221
            * </p>
6222
            * <p>
6223
            * The property is set to false by default to maintain backwards compatibility but should be 
6224
            * set to true if drop target interaction is not required for the Panel, to improve performance.</p>
6225
            * 
6226
            * @config dragOnly
6227
            * @type Boolean
6228
            * @default false
6229
            */
6230
            this.cfg.addProperty(DEFAULT_CONFIG.DRAG_ONLY.key, { 
6231
                value: DEFAULT_CONFIG.DRAG_ONLY.value, 
6232
                validator: DEFAULT_CONFIG.DRAG_ONLY.validator, 
6233
                supercedes: DEFAULT_CONFIG.DRAG_ONLY.supercedes 
6234
            });
6235
6236
            /**
6237
            * Sets the type of underlay to display for the Panel. Valid values 
6238
            * are "shadow," "matte," and "none".  <strong>PLEASE NOTE:</strong> 
6239
            * The creation of the underlay element is deferred until the Panel 
6240
            * is initially made visible.  For Gecko-based browsers on Mac
6241
            * OS X the underlay elment is always created as it is used as a 
6242
            * shim to prevent Aqua scrollbars below a Panel instance from poking 
6243
            * through it (See YUILibrary bug #1723530).
6244
            * @config underlay
6245
            * @type String
6246
            * @default shadow
6247
            */
6248
            this.cfg.addProperty(DEFAULT_CONFIG.UNDERLAY.key, { 
6249
                handler: this.configUnderlay, 
6250
                value: DEFAULT_CONFIG.UNDERLAY.value, 
6251
                supercedes: DEFAULT_CONFIG.UNDERLAY.supercedes 
6252
            });
6253
        
6254
            /**
6255
            * True if the Panel should be displayed in a modal fashion, 
6256
            * automatically creating a transparent mask over the document that
6257
            * will not be removed until the Panel is dismissed.
6258
            * @config modal
6259
            * @type Boolean
6260
            * @default false
6261
            */
6262
            this.cfg.addProperty(DEFAULT_CONFIG.MODAL.key, { 
6263
                handler: this.configModal, 
6264
                value: DEFAULT_CONFIG.MODAL.value,
6265
                validator: DEFAULT_CONFIG.MODAL.validator, 
6266
                supercedes: DEFAULT_CONFIG.MODAL.supercedes 
6267
            });
6268
6269
            /**
6270
            * A KeyListener (or array of KeyListeners) that will be enabled 
6271
            * when the Panel is shown, and disabled when the Panel is hidden.
6272
            * @config keylisteners
6273
            * @type YAHOO.util.KeyListener[]
6274
            * @default null
6275
            */
6276
            this.cfg.addProperty(DEFAULT_CONFIG.KEY_LISTENERS.key, { 
6277
                handler: this.configKeyListeners, 
6278
                suppressEvent: DEFAULT_CONFIG.KEY_LISTENERS.suppressEvent, 
6279
                supercedes: DEFAULT_CONFIG.KEY_LISTENERS.supercedes 
6280
            });
6281
6282
            /**
6283
            * UI Strings used by the Panel
6284
            * 
6285
            * @config strings
6286
            * @type Object
6287
            * @default An object literal with the properties shown below:
6288
            *     <dl>
6289
            *         <dt>close</dt><dd><em>String</em> : The string to use for the close icon. Defaults to "Close".</dd>
6290
            *     </dl>
6291
            */
6292
            this.cfg.addProperty(DEFAULT_CONFIG.STRINGS.key, { 
6293
                value:DEFAULT_CONFIG.STRINGS.value,
6294
                handler:this.configStrings,
6295
                validator:DEFAULT_CONFIG.STRINGS.validator,
6296
                supercedes:DEFAULT_CONFIG.STRINGS.supercedes
6297
            });
6298
        },
6299
6300
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
6301
        
6302
        /**
6303
        * The default event handler fired when the "close" property is changed.
6304
        * The method controls the appending or hiding of the close icon at the 
6305
        * top right of the Panel.
6306
        * @method configClose
6307
        * @param {String} type The CustomEvent type (usually the property name)
6308
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6309
        * handlers, args[0] will equal the newly applied value for the property.
6310
        * @param {Object} obj The scope object. For configuration handlers, 
6311
        * this will usually equal the owner.
6312
        */
6313
        configClose: function (type, args, obj) {
6314
6315
            var val = args[0],
6316
                oClose = this.close,
6317
                strings = this.cfg.getProperty("strings");
6318
6319
            if (val) {
6320
                if (!oClose) {
6321
6322
                    if (!m_oCloseIconTemplate) {
6323
                        m_oCloseIconTemplate = document.createElement("a");
6324
                        m_oCloseIconTemplate.className = "container-close";
6325
                        m_oCloseIconTemplate.href = "#";
6326
                    }
6327
6328
                    oClose = m_oCloseIconTemplate.cloneNode(true);
6329
                    this.innerElement.appendChild(oClose);
6330
6331
                    oClose.innerHTML = (strings && strings.close) ? strings.close : "&#160;";
6332
6333
                    Event.on(oClose, "click", this._doClose, this, true);
6334
6335
                    this.close = oClose;
6336
6337
                } else {
6338
                    oClose.style.display = "block";
6339
                }
6340
6341
            } else {
6342
                if (oClose) {
6343
                    oClose.style.display = "none";
6344
                }
6345
            }
6346
6347
        },
6348
6349
        /**
6350
         * Event handler for the close icon
6351
         * 
6352
         * @method _doClose
6353
         * @protected
6354
         * 
6355
         * @param {DOMEvent} e
6356
         */
6357
        _doClose : function (e) {
6358
            Event.preventDefault(e);
6359
            this.hide();
6360
        },
6361
6362
        /**
6363
        * The default event handler fired when the "draggable" property 
6364
        * is changed.
6365
        * @method configDraggable
6366
        * @param {String} type The CustomEvent type (usually the property name)
6367
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6368
        * handlers, args[0] will equal the newly applied value for the property.
6369
        * @param {Object} obj The scope object. For configuration handlers, 
6370
        * this will usually equal the owner.
6371
        */
6372
        configDraggable: function (type, args, obj) {
6373
            var val = args[0];
6374
6375
            if (val) {
6376
                if (!Util.DD) {
6377
                    YAHOO.log("DD dependency not met.", "error");
6378
                    this.cfg.setProperty("draggable", false);
6379
                    return;
6380
                }
6381
6382
                if (this.header) {
6383
                    Dom.setStyle(this.header, "cursor", "move");
6384
                    this.registerDragDrop();
6385
                }
6386
6387
                this.subscribe("beforeShow", setWidthToOffsetWidth);
6388
6389
            } else {
6390
6391
                if (this.dd) {
6392
                    this.dd.unreg();
6393
                }
6394
6395
                if (this.header) {
6396
                    Dom.setStyle(this.header,"cursor","auto");
6397
                }
6398
6399
                this.unsubscribe("beforeShow", setWidthToOffsetWidth);
6400
            }
6401
        },
6402
      
6403
        /**
6404
        * The default event handler fired when the "underlay" property 
6405
        * is changed.
6406
        * @method configUnderlay
6407
        * @param {String} type The CustomEvent type (usually the property name)
6408
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6409
        * handlers, args[0] will equal the newly applied value for the property.
6410
        * @param {Object} obj The scope object. For configuration handlers, 
6411
        * this will usually equal the owner.
6412
        */
6413
        configUnderlay: function (type, args, obj) {
6414
6415
            var bMacGecko = (this.platform == "mac" && UA.gecko),
6416
                sUnderlay = args[0].toLowerCase(),
6417
                oUnderlay = this.underlay,
6418
                oElement = this.element;
6419
6420
            function createUnderlay() {
6421
                var bNew = false;
6422
                if (!oUnderlay) { // create if not already in DOM
6423
6424
                    if (!m_oUnderlayTemplate) {
6425
                        m_oUnderlayTemplate = document.createElement("div");
6426
                        m_oUnderlayTemplate.className = "underlay";
6427
                    }
6428
6429
                    oUnderlay = m_oUnderlayTemplate.cloneNode(false);
6430
                    this.element.appendChild(oUnderlay);
6431
6432
                    this.underlay = oUnderlay;
6433
6434
                    if (bIEQuirks) {
6435
                        this.sizeUnderlay();
6436
                        this.cfg.subscribeToConfigEvent("width", this.sizeUnderlay);
6437
                        this.cfg.subscribeToConfigEvent("height", this.sizeUnderlay);
6438
6439
                        this.changeContentEvent.subscribe(this.sizeUnderlay);
6440
                        YAHOO.widget.Module.textResizeEvent.subscribe(this.sizeUnderlay, this, true);
6441
                    }
6442
6443
                    if (UA.webkit && UA.webkit < 420) {
6444
                        this.changeContentEvent.subscribe(this.forceUnderlayRedraw);
6445
                    }
6446
6447
                    bNew = true;
6448
                }
6449
            }
6450
6451
            function onBeforeShow() {
6452
                var bNew = createUnderlay.call(this);
6453
                if (!bNew && bIEQuirks) {
6454
                    this.sizeUnderlay();
6455
                }
6456
                this._underlayDeferred = false;
6457
                this.beforeShowEvent.unsubscribe(onBeforeShow);
6458
            }
6459
6460
            function destroyUnderlay() {
6461
                if (this._underlayDeferred) {
6462
                    this.beforeShowEvent.unsubscribe(onBeforeShow);
6463
                    this._underlayDeferred = false;
6464
                }
6465
6466
                if (oUnderlay) {
6467
                    this.cfg.unsubscribeFromConfigEvent("width", this.sizeUnderlay);
6468
                    this.cfg.unsubscribeFromConfigEvent("height",this.sizeUnderlay);
6469
                    this.changeContentEvent.unsubscribe(this.sizeUnderlay);
6470
                    this.changeContentEvent.unsubscribe(this.forceUnderlayRedraw);
6471
                    YAHOO.widget.Module.textResizeEvent.unsubscribe(this.sizeUnderlay, this, true);
6472
6473
                    this.element.removeChild(oUnderlay);
6474
6475
                    this.underlay = null;
6476
                }
6477
            }
6478
6479
            switch (sUnderlay) {
6480
                case "shadow":
6481
                    Dom.removeClass(oElement, "matte");
6482
                    Dom.addClass(oElement, "shadow");
6483
                    break;
6484
                case "matte":
6485
                    if (!bMacGecko) {
6486
                        destroyUnderlay.call(this);
6487
                    }
6488
                    Dom.removeClass(oElement, "shadow");
6489
                    Dom.addClass(oElement, "matte");
6490
                    break;
6491
                default:
6492
                    if (!bMacGecko) {
6493
                        destroyUnderlay.call(this);
6494
                    }
6495
                    Dom.removeClass(oElement, "shadow");
6496
                    Dom.removeClass(oElement, "matte");
6497
                    break;
6498
            }
6499
6500
            if ((sUnderlay == "shadow") || (bMacGecko && !oUnderlay)) {
6501
                if (this.cfg.getProperty("visible")) {
6502
                    var bNew = createUnderlay.call(this);
6503
                    if (!bNew && bIEQuirks) {
6504
                        this.sizeUnderlay();
6505
                    }
6506
                } else {
6507
                    if (!this._underlayDeferred) {
6508
                        this.beforeShowEvent.subscribe(onBeforeShow);
6509
                        this._underlayDeferred = true;
6510
                    }
6511
                }
6512
            }
6513
        },
6514
        
6515
        /**
6516
        * The default event handler fired when the "modal" property is 
6517
        * changed. This handler subscribes or unsubscribes to the show and hide
6518
        * events to handle the display or hide of the modality mask.
6519
        * @method configModal
6520
        * @param {String} type The CustomEvent type (usually the property name)
6521
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6522
        * handlers, args[0] will equal the newly applied value for the property.
6523
        * @param {Object} obj The scope object. For configuration handlers, 
6524
        * this will usually equal the owner.
6525
        */
6526
        configModal: function (type, args, obj) {
6527
6528
            var modal = args[0];
6529
            if (modal) {
6530
                if (!this._hasModalityEventListeners) {
6531
6532
                    this.subscribe("beforeShow", this.buildMask);
6533
                    this.subscribe("beforeShow", this.bringToTop);
6534
                    this.subscribe("beforeShow", this.showMask);
6535
                    this.subscribe("hide", this.hideMask);
6536
6537
                    Overlay.windowResizeEvent.subscribe(this.sizeMask, 
6538
                        this, true);
6539
6540
                    this._hasModalityEventListeners = true;
6541
                }
6542
            } else {
6543
                if (this._hasModalityEventListeners) {
6544
6545
                    if (this.cfg.getProperty("visible")) {
6546
                        this.hideMask();
6547
                        this.removeMask();
6548
                    }
6549
6550
                    this.unsubscribe("beforeShow", this.buildMask);
6551
                    this.unsubscribe("beforeShow", this.bringToTop);
6552
                    this.unsubscribe("beforeShow", this.showMask);
6553
                    this.unsubscribe("hide", this.hideMask);
6554
6555
                    Overlay.windowResizeEvent.unsubscribe(this.sizeMask, this);
6556
6557
                    this._hasModalityEventListeners = false;
6558
                }
6559
            }
6560
        },
6561
6562
        /**
6563
        * Removes the modality mask.
6564
        * @method removeMask
6565
        */
6566
        removeMask: function () {
6567
6568
            var oMask = this.mask,
6569
                oParentNode;
6570
6571
            if (oMask) {
6572
                /*
6573
                    Hide the mask before destroying it to ensure that DOM
6574
                    event handlers on focusable elements get removed.
6575
                */
6576
                this.hideMask();
6577
6578
                oParentNode = oMask.parentNode;
6579
                if (oParentNode) {
6580
                    oParentNode.removeChild(oMask);
6581
                }
6582
6583
                this.mask = null;
6584
            }
6585
        },
6586
        
6587
        /**
6588
        * The default event handler fired when the "keylisteners" property 
6589
        * is changed.
6590
        * @method configKeyListeners
6591
        * @param {String} type The CustomEvent type (usually the property name)
6592
        * @param {Object[]} args The CustomEvent arguments. For configuration
6593
        * handlers, args[0] will equal the newly applied value for the property.
6594
        * @param {Object} obj The scope object. For configuration handlers, 
6595
        * this will usually equal the owner.
6596
        */
6597
        configKeyListeners: function (type, args, obj) {
6598
6599
            var listeners = args[0],
6600
                listener,
6601
                nListeners,
6602
                i;
6603
        
6604
            if (listeners) {
6605
6606
                if (listeners instanceof Array) {
6607
6608
                    nListeners = listeners.length;
6609
6610
                    for (i = 0; i < nListeners; i++) {
6611
6612
                        listener = listeners[i];
6613
        
6614
                        if (!Config.alreadySubscribed(this.showEvent, 
6615
                            listener.enable, listener)) {
6616
6617
                            this.showEvent.subscribe(listener.enable, 
6618
                                listener, true);
6619
6620
                        }
6621
6622
                        if (!Config.alreadySubscribed(this.hideEvent, 
6623
                            listener.disable, listener)) {
6624
6625
                            this.hideEvent.subscribe(listener.disable, 
6626
                                listener, true);
6627
6628
                            this.destroyEvent.subscribe(listener.disable, 
6629
                                listener, true);
6630
                        }
6631
                    }
6632
6633
                } else {
6634
6635
                    if (!Config.alreadySubscribed(this.showEvent, 
6636
                        listeners.enable, listeners)) {
6637
6638
                        this.showEvent.subscribe(listeners.enable, 
6639
                            listeners, true);
6640
                    }
6641
6642
                    if (!Config.alreadySubscribed(this.hideEvent, 
6643
                        listeners.disable, listeners)) {
6644
6645
                        this.hideEvent.subscribe(listeners.disable, 
6646
                            listeners, true);
6647
6648
                        this.destroyEvent.subscribe(listeners.disable, 
6649
                            listeners, true);
6650
6651
                    }
6652
6653
                }
6654
6655
            }
6656
6657
        },
6658
6659
        /**
6660
        * The default handler for the "strings" property
6661
        * @method configStrings
6662
        */
6663
        configStrings : function(type, args, obj) {
6664
            var val = Lang.merge(DEFAULT_CONFIG.STRINGS.value, args[0]);
6665
            this.cfg.setProperty(DEFAULT_CONFIG.STRINGS.key, val, true);
6666
        },
6667
6668
        /**
6669
        * The default event handler fired when the "height" property is changed.
6670
        * @method configHeight
6671
        * @param {String} type The CustomEvent type (usually the property name)
6672
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6673
        * handlers, args[0] will equal the newly applied value for the property.
6674
        * @param {Object} obj The scope object. For configuration handlers, 
6675
        * this will usually equal the owner.
6676
        */
6677
        configHeight: function (type, args, obj) {
6678
            var height = args[0],
6679
                el = this.innerElement;
6680
6681
            Dom.setStyle(el, "height", height);
6682
            this.cfg.refireEvent("iframe");
6683
        },
6684
6685
        /**
6686
         * The default custom event handler executed when the Panel's height is changed, 
6687
         * if the autofillheight property has been set.
6688
         *
6689
         * @method _autoFillOnHeightChange
6690
         * @protected
6691
         * @param {String} type The event type
6692
         * @param {Array} args The array of arguments passed to event subscribers
6693
         * @param {HTMLElement} el The header, body or footer element which is to be resized to fill
6694
         * out the containers height
6695
         */
6696
        _autoFillOnHeightChange : function(type, args, el) {
6697
            Panel.superclass._autoFillOnHeightChange.apply(this, arguments);
6698
            if (bIEQuirks) {
6699
                var panel = this;
6700
                setTimeout(function() {
6701
                    panel.sizeUnderlay();
6702
                },0);
6703
            }
6704
        },
6705
6706
        /**
6707
        * The default event handler fired when the "width" property is changed.
6708
        * @method configWidth
6709
        * @param {String} type The CustomEvent type (usually the property name)
6710
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6711
        * handlers, args[0] will equal the newly applied value for the property.
6712
        * @param {Object} obj The scope object. For configuration handlers, 
6713
        * this will usually equal the owner.
6714
        */
6715
        configWidth: function (type, args, obj) {
6716
    
6717
            var width = args[0],
6718
                el = this.innerElement;
6719
    
6720
            Dom.setStyle(el, "width", width);
6721
            this.cfg.refireEvent("iframe");
6722
    
6723
        },
6724
        
6725
        /**
6726
        * The default event handler fired when the "zIndex" property is changed.
6727
        * @method configzIndex
6728
        * @param {String} type The CustomEvent type (usually the property name)
6729
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6730
        * handlers, args[0] will equal the newly applied value for the property.
6731
        * @param {Object} obj The scope object. For configuration handlers, 
6732
        * this will usually equal the owner.
6733
        */
6734
        configzIndex: function (type, args, obj) {
6735
            Panel.superclass.configzIndex.call(this, type, args, obj);
6736
6737
            if (this.mask || this.cfg.getProperty("modal") === true) {
6738
                var panelZ = Dom.getStyle(this.element, "zIndex");
6739
                if (!panelZ || isNaN(panelZ)) {
6740
                    panelZ = 0;
6741
                }
6742
6743
                if (panelZ === 0) {
6744
                    // Recursive call to configzindex (which should be stopped
6745
                    // from going further because panelZ should no longer === 0)
6746
                    this.cfg.setProperty("zIndex", 1);
6747
                } else {
6748
                    this.stackMask();
6749
                }
6750
            }
6751
        },
6752
6753
        // END BUILT-IN PROPERTY EVENT HANDLERS //
6754
        /**
6755
        * Builds the wrapping container around the Panel that is used for 
6756
        * positioning the shadow and matte underlays. The container element is 
6757
        * assigned to a  local instance variable called container, and the 
6758
        * element is reinserted inside of it.
6759
        * @method buildWrapper
6760
        */
6761
        buildWrapper: function () {
6762
6763
            var elementParent = this.element.parentNode,
6764
                originalElement = this.element,
6765
                wrapper = document.createElement("div");
6766
6767
            wrapper.className = Panel.CSS_PANEL_CONTAINER;
6768
            wrapper.id = originalElement.id + "_c";
6769
6770
            if (elementParent) {
6771
                elementParent.insertBefore(wrapper, originalElement);
6772
            }
6773
6774
            wrapper.appendChild(originalElement);
6775
6776
            this.element = wrapper;
6777
            this.innerElement = originalElement;
6778
6779
            Dom.setStyle(this.innerElement, "visibility", "inherit");
6780
        },
6781
6782
        /**
6783
        * Adjusts the size of the shadow based on the size of the element.
6784
        * @method sizeUnderlay
6785
        */
6786
        sizeUnderlay: function () {
6787
            var oUnderlay = this.underlay,
6788
                oElement;
6789
6790
            if (oUnderlay) {
6791
                oElement = this.element;
6792
                oUnderlay.style.width = oElement.offsetWidth + "px";
6793
                oUnderlay.style.height = oElement.offsetHeight + "px";
6794
            }
6795
        },
6796
6797
        /**
6798
        * Registers the Panel's header for drag & drop capability.
6799
        * @method registerDragDrop
6800
        */
6801
        registerDragDrop: function () {
6802
6803
            var me = this;
6804
6805
            if (this.header) {
6806
6807
                if (!Util.DD) {
6808
                    YAHOO.log("DD dependency not met.", "error");
6809
                    return;
6810
                }
6811
6812
                var bDragOnly = (this.cfg.getProperty("dragonly") === true);
6813
6814
                /**
6815
                 * The YAHOO.util.DD instance, used to implement the draggable header for the panel if draggable is enabled
6816
                 *
6817
                 * @property dd
6818
                 * @type YAHOO.util.DD
6819
                 */
6820
                this.dd = new Util.DD(this.element.id, this.id, {dragOnly: bDragOnly});
6821
6822
                if (!this.header.id) {
6823
                    this.header.id = this.id + "_h";
6824
                }
6825
6826
                this.dd.startDrag = function () {
6827
6828
                    var offsetHeight,
6829
                        offsetWidth,
6830
                        viewPortWidth,
6831
                        viewPortHeight,
6832
                        scrollX,
6833
                        scrollY;
6834
6835
                    if (YAHOO.env.ua.ie == 6) {
6836
                        Dom.addClass(me.element,"drag");
6837
                    }
6838
6839
                    if (me.cfg.getProperty("constraintoviewport")) {
6840
6841
                        var nViewportOffset = Overlay.VIEWPORT_OFFSET;
6842
6843
                        offsetHeight = me.element.offsetHeight;
6844
                        offsetWidth = me.element.offsetWidth;
6845
6846
                        viewPortWidth = Dom.getViewportWidth();
6847
                        viewPortHeight = Dom.getViewportHeight();
6848
6849
                        scrollX = Dom.getDocumentScrollLeft();
6850
                        scrollY = Dom.getDocumentScrollTop();
6851
6852
                        if (offsetHeight + nViewportOffset < viewPortHeight) {
6853
                            this.minY = scrollY + nViewportOffset;
6854
                            this.maxY = scrollY + viewPortHeight - offsetHeight - nViewportOffset;
6855
                        } else {
6856
                            this.minY = scrollY + nViewportOffset;
6857
                            this.maxY = scrollY + nViewportOffset;
6858
                        }
6859
6860
                        if (offsetWidth + nViewportOffset < viewPortWidth) {
6861
                            this.minX = scrollX + nViewportOffset;
6862
                            this.maxX = scrollX + viewPortWidth - offsetWidth - nViewportOffset;
6863
                        } else {
6864
                            this.minX = scrollX + nViewportOffset;
6865
                            this.maxX = scrollX + nViewportOffset;
6866
                        }
6867
6868
                        this.constrainX = true;
6869
                        this.constrainY = true;
6870
                    } else {
6871
                        this.constrainX = false;
6872
                        this.constrainY = false;
6873
                    }
6874
6875
                    me.dragEvent.fire("startDrag", arguments);
6876
                };
6877
6878
                this.dd.onDrag = function () {
6879
                    me.syncPosition();
6880
                    me.cfg.refireEvent("iframe");
6881
                    if (this.platform == "mac" && YAHOO.env.ua.gecko) {
6882
                        this.showMacGeckoScrollbars();
6883
                    }
6884
6885
                    me.dragEvent.fire("onDrag", arguments);
6886
                };
6887
6888
                this.dd.endDrag = function () {
6889
6890
                    if (YAHOO.env.ua.ie == 6) {
6891
                        Dom.removeClass(me.element,"drag");
6892
                    }
6893
6894
                    me.dragEvent.fire("endDrag", arguments);
6895
                    me.moveEvent.fire(me.cfg.getProperty("xy"));
6896
6897
                };
6898
6899
                this.dd.setHandleElId(this.header.id);
6900
                this.dd.addInvalidHandleType("INPUT");
6901
                this.dd.addInvalidHandleType("SELECT");
6902
                this.dd.addInvalidHandleType("TEXTAREA");
6903
            }
6904
        },
6905
        
6906
        /**
6907
        * Builds the mask that is laid over the document when the Panel is 
6908
        * configured to be modal.
6909
        * @method buildMask
6910
        */
6911
        buildMask: function () {
6912
            var oMask = this.mask;
6913
            if (!oMask) {
6914
                if (!m_oMaskTemplate) {
6915
                    m_oMaskTemplate = document.createElement("div");
6916
                    m_oMaskTemplate.className = "mask";
6917
                    m_oMaskTemplate.innerHTML = "&#160;";
6918
                }
6919
                oMask = m_oMaskTemplate.cloneNode(true);
6920
                oMask.id = this.id + "_mask";
6921
6922
                document.body.insertBefore(oMask, document.body.firstChild);
6923
6924
                this.mask = oMask;
6925
6926
                if (YAHOO.env.ua.gecko && this.platform == "mac") {
6927
                    Dom.addClass(this.mask, "block-scrollbars");
6928
                }
6929
6930
                // Stack mask based on the element zindex
6931
                this.stackMask();
6932
            }
6933
        },
6934
6935
        /**
6936
        * Hides the modality mask.
6937
        * @method hideMask
6938
        */
6939
        hideMask: function () {
6940
            if (this.cfg.getProperty("modal") && this.mask) {
6941
                this.mask.style.display = "none";
6942
                Dom.removeClass(document.body, "masked");
6943
                this.hideMaskEvent.fire();
6944
            }
6945
        },
6946
6947
        /**
6948
        * Shows the modality mask.
6949
        * @method showMask
6950
        */
6951
        showMask: function () {
6952
            if (this.cfg.getProperty("modal") && this.mask) {
6953
                Dom.addClass(document.body, "masked");
6954
                this.sizeMask();
6955
                this.mask.style.display = "block";
6956
                this.showMaskEvent.fire();
6957
            }
6958
        },
6959
6960
        /**
6961
        * Sets the size of the modality mask to cover the entire scrollable 
6962
        * area of the document
6963
        * @method sizeMask
6964
        */
6965
        sizeMask: function () {
6966
            if (this.mask) {
6967
6968
                // Shrink mask first, so it doesn't affect the document size.
6969
                var mask = this.mask,
6970
                    viewWidth = Dom.getViewportWidth(),
6971
                    viewHeight = Dom.getViewportHeight();
6972
6973
                if (mask.offsetHeight > viewHeight) {
6974
                    mask.style.height = viewHeight + "px";
6975
                }
6976
6977
                if (mask.offsetWidth > viewWidth) {
6978
                    mask.style.width = viewWidth + "px";
6979
                }
6980
6981
                // Then size it to the document
6982
                mask.style.height = Dom.getDocumentHeight() + "px";
6983
                mask.style.width = Dom.getDocumentWidth() + "px";
6984
            }
6985
        },
6986
6987
        /**
6988
         * Sets the zindex of the mask, if it exists, based on the zindex of 
6989
         * the Panel element. The zindex of the mask is set to be one less 
6990
         * than the Panel element's zindex.
6991
         * 
6992
         * <p>NOTE: This method will not bump up the zindex of the Panel
6993
         * to ensure that the mask has a non-negative zindex. If you require the
6994
         * mask zindex to be 0 or higher, the zindex of the Panel 
6995
         * should be set to a value higher than 0, before this method is called.
6996
         * </p>
6997
         * @method stackMask
6998
         */
6999
        stackMask: function() {
7000
            if (this.mask) {
7001
                var panelZ = Dom.getStyle(this.element, "zIndex");
7002
                if (!YAHOO.lang.isUndefined(panelZ) && !isNaN(panelZ)) {
7003
                    Dom.setStyle(this.mask, "zIndex", panelZ - 1);
7004
                }
7005
            }
7006
        },
7007
7008
        /**
7009
        * Renders the Panel by inserting the elements that are not already in 
7010
        * the main Panel into their correct places. Optionally appends the 
7011
        * Panel to the specified node prior to the render's execution. NOTE: 
7012
        * For Panels without existing markup, the appendToNode argument is 
7013
        * REQUIRED. If this argument is ommitted and the current element is 
7014
        * not present in the document, the function will return false, 
7015
        * indicating that the render was a failure.
7016
        * @method render
7017
        * @param {String} appendToNode The element id to which the Module 
7018
        * should be appended to prior to rendering <em>OR</em>
7019
        * @param {HTMLElement} appendToNode The element to which the Module 
7020
        * should be appended to prior to rendering
7021
        * @return {boolean} Success or failure of the render
7022
        */
7023
        render: function (appendToNode) {
7024
            return Panel.superclass.render.call(this, appendToNode, this.innerElement);
7025
        },
7026
7027
        /**
7028
         * Renders the currently set header into it's proper position under the 
7029
         * module element. If the module element is not provided, "this.innerElement" 
7030
         * is used.
7031
         *
7032
         * @method _renderHeader
7033
         * @protected
7034
         * @param {HTMLElement} moduleElement Optional. A reference to the module element
7035
         */
7036
        _renderHeader: function(moduleElement){
7037
            moduleElement = moduleElement || this.innerElement;
7038
			Panel.superclass._renderHeader.call(this, moduleElement);
7039
        },
7040
7041
        /**
7042
         * Renders the currently set body into it's proper position under the 
7043
         * module element. If the module element is not provided, "this.innerElement" 
7044
         * is used.
7045
         * 
7046
         * @method _renderBody
7047
         * @protected
7048
         * @param {HTMLElement} moduleElement Optional. A reference to the module element.
7049
         */
7050
        _renderBody: function(moduleElement){
7051
            moduleElement = moduleElement || this.innerElement;
7052
            Panel.superclass._renderBody.call(this, moduleElement);
7053
        },
7054
7055
        /**
7056
         * Renders the currently set footer into it's proper position under the 
7057
         * module element. If the module element is not provided, "this.innerElement" 
7058
         * is used.
7059
         *
7060
         * @method _renderFooter
7061
         * @protected
7062
         * @param {HTMLElement} moduleElement Optional. A reference to the module element
7063
         */
7064
        _renderFooter: function(moduleElement){
7065
            moduleElement = moduleElement || this.innerElement;
7066
            Panel.superclass._renderFooter.call(this, moduleElement);
7067
        },
7068
        
7069
        /**
7070
        * Removes the Panel element from the DOM and sets all child elements
7071
        * to null.
7072
        * @method destroy
7073
        */
7074
        destroy: function () {
7075
            Overlay.windowResizeEvent.unsubscribe(this.sizeMask, this);
7076
            this.removeMask();
7077
            if (this.close) {
7078
                Event.purgeElement(this.close);
7079
            }
7080
            Panel.superclass.destroy.call(this);  
7081
        },
7082
7083
        /**
7084
         * Forces the underlay element to be repainted through the application/removal 
7085
         * of a yui-force-redraw class to the underlay element.
7086
         *
7087
         * @method forceUnderlayRedraw
7088
         */
7089
        forceUnderlayRedraw : function () {
7090
            var u = this.underlay;
7091
            Dom.addClass(u, "yui-force-redraw");
7092
            setTimeout(function(){Dom.removeClass(u, "yui-force-redraw");}, 0);
7093
        },
7094
7095
        /**
7096
        * Returns a String representation of the object.
7097
        * @method toString
7098
        * @return {String} The string representation of the Panel.
7099
        */
7100
        toString: function () {
7101
            return "Panel " + this.id;
7102
        }
7103
    
7104
    });
7105
7106
}());
7107
(function () {
7108
7109
    /**
7110
    * <p>
7111
    * Dialog is an implementation of Panel that can be used to submit form 
7112
    * data.
7113
    * </p>
7114
    * <p>
7115
    * Built-in functionality for buttons with event handlers is included. 
7116
    * If the optional YUI Button dependancy is included on the page, the buttons
7117
    * created will be instances of YAHOO.widget.Button, otherwise regular HTML buttons
7118
    * will be created.
7119
    * </p>
7120
    * <p>
7121
    * Forms can be processed in 3 ways -- via an asynchronous Connection utility call, 
7122
    * a simple form POST or GET, or manually. The YUI Connection utility should be
7123
    * included if you're using the default "async" postmethod, but is not required if
7124
    * you're using any of the other postmethod values.
7125
    * </p>
7126
    * @namespace YAHOO.widget
7127
    * @class Dialog
7128
    * @extends YAHOO.widget.Panel
7129
    * @constructor
7130
    * @param {String} el The element ID representing the Dialog <em>OR</em>
7131
    * @param {HTMLElement} el The element representing the Dialog
7132
    * @param {Object} userConfig The configuration object literal containing 
7133
    * the configuration that should be set for this Dialog. See configuration 
7134
    * documentation for more details.
7135
    */
7136
    YAHOO.widget.Dialog = function (el, userConfig) {
7137
        YAHOO.widget.Dialog.superclass.constructor.call(this, el, userConfig);
7138
    };
7139
7140
    var Event = YAHOO.util.Event,
7141
        CustomEvent = YAHOO.util.CustomEvent,
7142
        Dom = YAHOO.util.Dom,
7143
        Dialog = YAHOO.widget.Dialog,
7144
        Lang = YAHOO.lang,
7145
7146
        /**
7147
         * Constant representing the name of the Dialog's events
7148
         * @property EVENT_TYPES
7149
         * @private
7150
         * @final
7151
         * @type Object
7152
         */
7153
        EVENT_TYPES = {
7154
            "BEFORE_SUBMIT": "beforeSubmit",
7155
            "SUBMIT": "submit",
7156
            "MANUAL_SUBMIT": "manualSubmit",
7157
            "ASYNC_SUBMIT": "asyncSubmit",
7158
            "FORM_SUBMIT": "formSubmit",
7159
            "CANCEL": "cancel"
7160
        },
7161
7162
        /**
7163
        * Constant representing the Dialog's configuration properties
7164
        * @property DEFAULT_CONFIG
7165
        * @private
7166
        * @final
7167
        * @type Object
7168
        */
7169
        DEFAULT_CONFIG = {
7170
7171
            "POST_METHOD": { 
7172
                key: "postmethod", 
7173
                value: "async"
7174
            },
7175
7176
            "POST_DATA" : {
7177
                key: "postdata",
7178
                value: null
7179
            },
7180
7181
            "BUTTONS": {
7182
                key: "buttons",
7183
                value: "none",
7184
                supercedes: ["visible"]
7185
            },
7186
7187
            "HIDEAFTERSUBMIT" : {
7188
                key: "hideaftersubmit",
7189
                value: true
7190
            }
7191
7192
        };
7193
7194
    /**
7195
    * Constant representing the default CSS class used for a Dialog
7196
    * @property YAHOO.widget.Dialog.CSS_DIALOG
7197
    * @static
7198
    * @final
7199
    * @type String
7200
    */
7201
    Dialog.CSS_DIALOG = "yui-dialog";
7202
7203
    function removeButtonEventHandlers() {
7204
7205
        var aButtons = this._aButtons,
7206
            nButtons,
7207
            oButton,
7208
            i;
7209
7210
        if (Lang.isArray(aButtons)) {
7211
            nButtons = aButtons.length;
7212
7213
            if (nButtons > 0) {
7214
                i = nButtons - 1;
7215
                do {
7216
                    oButton = aButtons[i];
7217
7218
                    if (YAHOO.widget.Button && oButton instanceof YAHOO.widget.Button) {
7219
                        oButton.destroy();
7220
                    }
7221
                    else if (oButton.tagName.toUpperCase() == "BUTTON") {
7222
                        Event.purgeElement(oButton);
7223
                        Event.purgeElement(oButton, false);
7224
                    }
7225
                }
7226
                while (i--);
7227
            }
7228
        }
7229
    }
7230
7231
    YAHOO.extend(Dialog, YAHOO.widget.Panel, { 
7232
7233
        /**
7234
        * @property form
7235
        * @description Object reference to the Dialog's 
7236
        * <code>&#60;form&#62;</code> element.
7237
        * @default null 
7238
        * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
7239
        * level-one-html.html#ID-40002357">HTMLFormElement</a>
7240
        */
7241
        form: null,
7242
    
7243
        /**
7244
        * Initializes the class's configurable properties which can be changed 
7245
        * using the Dialog's Config object (cfg).
7246
        * @method initDefaultConfig
7247
        */
7248
        initDefaultConfig: function () {
7249
            Dialog.superclass.initDefaultConfig.call(this);
7250
7251
            /**
7252
            * The internally maintained callback object for use with the 
7253
            * Connection utility. The format of the callback object is 
7254
            * similar to Connection Manager's callback object and is 
7255
            * simply passed through to Connection Manager when the async 
7256
            * request is made.
7257
            * @property callback
7258
            * @type Object
7259
            */
7260
            this.callback = {
7261
7262
                /**
7263
                * The function to execute upon success of the 
7264
                * Connection submission (when the form does not
7265
                * contain a file input element).
7266
                * 
7267
                * @property callback.success
7268
                * @type Function
7269
                */
7270
                success: null,
7271
7272
                /**
7273
                * The function to execute upon failure of the 
7274
                * Connection submission
7275
                * @property callback.failure
7276
                * @type Function
7277
                */
7278
                failure: null,
7279
7280
                /**
7281
                *<p>
7282
                * The function to execute upon success of the 
7283
                * Connection submission, when the form contains
7284
                * a file input element.
7285
                * </p>
7286
                * <p>
7287
                * <em>NOTE:</em> Connection manager will not
7288
                * invoke the success or failure handlers for the file
7289
                * upload use case. This will be the only callback
7290
                * handler invoked.
7291
                * </p>
7292
                * <p>
7293
                * For more information, see the <a href="http://developer.yahoo.com/yui/connection/#file">
7294
                * Connection Manager documenation on file uploads</a>.
7295
                * </p>
7296
                * @property callback.upload
7297
                * @type Function
7298
                */
7299
7300
                /**
7301
                * The arbitraty argument or arguments to pass to the Connection 
7302
                * callback functions
7303
                * @property callback.argument
7304
                * @type Object
7305
                */
7306
                argument: null
7307
7308
            };
7309
7310
            // Add form dialog config properties //
7311
            /**
7312
            * The method to use for posting the Dialog's form. Possible values 
7313
            * are "async", "form", and "manual".
7314
            * @config postmethod
7315
            * @type String
7316
            * @default async
7317
            */
7318
            this.cfg.addProperty(DEFAULT_CONFIG.POST_METHOD.key, {
7319
                handler: this.configPostMethod, 
7320
                value: DEFAULT_CONFIG.POST_METHOD.value, 
7321
                validator: function (val) {
7322
                    if (val != "form" && val != "async" && val != "none" && 
7323
                        val != "manual") {
7324
                        return false;
7325
                    } else {
7326
                        return true;
7327
                    }
7328
                }
7329
            });
7330
7331
            /**
7332
            * Any additional post data which needs to be sent when using the 
7333
            * <a href="#config_postmethod">async</a> postmethod for dialog POST submissions.
7334
            * The format for the post data string is defined by Connection Manager's 
7335
            * <a href="YAHOO.util.Connect.html#method_asyncRequest">asyncRequest</a> 
7336
            * method.
7337
            * @config postdata
7338
            * @type String
7339
            * @default null
7340
            */
7341
            this.cfg.addProperty(DEFAULT_CONFIG.POST_DATA.key, {
7342
                value: DEFAULT_CONFIG.POST_DATA.value
7343
            });
7344
7345
            /**
7346
            * This property is used to configure whether or not the 
7347
            * dialog should be automatically hidden after submit.
7348
            * 
7349
            * @config hideaftersubmit
7350
            * @type Boolean
7351
            * @default true
7352
            */
7353
            this.cfg.addProperty(DEFAULT_CONFIG.HIDEAFTERSUBMIT.key, {
7354
                value: DEFAULT_CONFIG.HIDEAFTERSUBMIT.value
7355
            });
7356
7357
            /**
7358
            * Array of object literals, each containing a set of properties 
7359
            * defining a button to be appended into the Dialog's footer.
7360
            *
7361
            * <p>Each button object in the buttons array can have three properties:</p>
7362
            * <dl>
7363
            *    <dt>text:</dt>
7364
            *    <dd>
7365
            *       The text that will display on the face of the button. The text can 
7366
            *       include HTML, as long as it is compliant with HTML Button specifications.
7367
            *    </dd>
7368
            *    <dt>handler:</dt>
7369
            *    <dd>Can be either:
7370
            *    <ol>
7371
            *       <li>A reference to a function that should fire when the 
7372
            *       button is clicked.  (In this case scope of this function is 
7373
            *       always its Dialog instance.)</li>
7374
            *
7375
            *       <li>An object literal representing the code to be 
7376
            *       executed when the button is clicked.
7377
            *       
7378
            *       <p>Format:</p>
7379
            *
7380
            *       <p>
7381
            *       <code>{
7382
            *       <br>
7383
            *       <strong>fn:</strong> Function, &#47;&#47;
7384
            *       The handler to call when  the event fires.
7385
            *       <br>
7386
            *       <strong>obj:</strong> Object, &#47;&#47; 
7387
            *       An  object to pass back to the handler.
7388
            *       <br>
7389
            *       <strong>scope:</strong> Object &#47;&#47; 
7390
            *       The object to use for the scope of the handler.
7391
            *       <br>
7392
            *       }</code>
7393
            *       </p>
7394
            *       </li>
7395
            *     </ol>
7396
            *     </dd>
7397
            *     <dt>isDefault:</dt>
7398
            *     <dd>
7399
            *        An optional boolean value that specifies that a button 
7400
            *        should be highlighted and focused by default.
7401
            *     </dd>
7402
            * </dl>
7403
            *
7404
            * <em>NOTE:</em>If the YUI Button Widget is included on the page, 
7405
            * the buttons created will be instances of YAHOO.widget.Button. 
7406
            * Otherwise, HTML Buttons (<code>&#60;BUTTON&#62;</code>) will be 
7407
            * created.
7408
            *
7409
            * @config buttons
7410
            * @type {Array|String}
7411
            * @default "none"
7412
            */
7413
            this.cfg.addProperty(DEFAULT_CONFIG.BUTTONS.key, {
7414
                handler: this.configButtons,
7415
                value: DEFAULT_CONFIG.BUTTONS.value,
7416
                supercedes : DEFAULT_CONFIG.BUTTONS.supercedes
7417
            }); 
7418
7419
        },
7420
7421
        /**
7422
        * Initializes the custom events for Dialog which are fired 
7423
        * automatically at appropriate times by the Dialog class.
7424
        * @method initEvents
7425
        */
7426
        initEvents: function () {
7427
            Dialog.superclass.initEvents.call(this);
7428
7429
            var SIGNATURE = CustomEvent.LIST;
7430
7431
            /**
7432
            * CustomEvent fired prior to submission
7433
            * @event beforeSubmitEvent
7434
            */ 
7435
            this.beforeSubmitEvent = 
7436
                this.createEvent(EVENT_TYPES.BEFORE_SUBMIT);
7437
            this.beforeSubmitEvent.signature = SIGNATURE;
7438
            
7439
            /**
7440
            * CustomEvent fired after submission
7441
            * @event submitEvent
7442
            */
7443
            this.submitEvent = this.createEvent(EVENT_TYPES.SUBMIT);
7444
            this.submitEvent.signature = SIGNATURE;
7445
        
7446
            /**
7447
            * CustomEvent fired for manual submission, before the generic submit event is fired
7448
            * @event manualSubmitEvent
7449
            */
7450
            this.manualSubmitEvent = 
7451
                this.createEvent(EVENT_TYPES.MANUAL_SUBMIT);
7452
            this.manualSubmitEvent.signature = SIGNATURE;
7453
7454
            /**
7455
            * CustomEvent fired after asynchronous submission, before the generic submit event is fired
7456
            *
7457
            * @event asyncSubmitEvent
7458
            * @param {Object} conn The connection object, returned by YAHOO.util.Connect.asyncRequest
7459
            */
7460
            this.asyncSubmitEvent = this.createEvent(EVENT_TYPES.ASYNC_SUBMIT);
7461
            this.asyncSubmitEvent.signature = SIGNATURE;
7462
7463
            /**
7464
            * CustomEvent fired after form-based submission, before the generic submit event is fired
7465
            * @event formSubmitEvent
7466
            */
7467
            this.formSubmitEvent = this.createEvent(EVENT_TYPES.FORM_SUBMIT);
7468
            this.formSubmitEvent.signature = SIGNATURE;
7469
7470
            /**
7471
            * CustomEvent fired after cancel
7472
            * @event cancelEvent
7473
            */
7474
            this.cancelEvent = this.createEvent(EVENT_TYPES.CANCEL);
7475
            this.cancelEvent.signature = SIGNATURE;
7476
        
7477
        },
7478
        
7479
        /**
7480
        * The Dialog initialization method, which is executed for Dialog and 
7481
        * all of its subclasses. This method is automatically called by the 
7482
        * constructor, and  sets up all DOM references for pre-existing markup, 
7483
        * and creates required markup if it is not already present.
7484
        * 
7485
        * @method init
7486
        * @param {String} el The element ID representing the Dialog <em>OR</em>
7487
        * @param {HTMLElement} el The element representing the Dialog
7488
        * @param {Object} userConfig The configuration object literal 
7489
        * containing the configuration that should be set for this Dialog. 
7490
        * See configuration documentation for more details.
7491
        */
7492
        init: function (el, userConfig) {
7493
7494
            /*
7495
                 Note that we don't pass the user config in here yet because 
7496
                 we only want it executed once, at the lowest subclass level
7497
            */
7498
7499
            Dialog.superclass.init.call(this, el/*, userConfig*/); 
7500
7501
            this.beforeInitEvent.fire(Dialog);
7502
7503
            Dom.addClass(this.element, Dialog.CSS_DIALOG);
7504
7505
            this.cfg.setProperty("visible", false);
7506
7507
            if (userConfig) {
7508
                this.cfg.applyConfig(userConfig, true);
7509
            }
7510
7511
            this.showEvent.subscribe(this.focusFirst, this, true);
7512
            this.beforeHideEvent.subscribe(this.blurButtons, this, true);
7513
7514
            this.subscribe("changeBody", this.registerForm);
7515
7516
            this.initEvent.fire(Dialog);
7517
        },
7518
7519
        /**
7520
        * Submits the Dialog's form depending on the value of the 
7521
        * "postmethod" configuration property.  <strong>Please note:
7522
        * </strong> As of version 2.3 this method will automatically handle 
7523
        * asyncronous file uploads should the Dialog instance's form contain 
7524
        * <code>&#60;input type="file"&#62;</code> elements.  If a Dialog 
7525
        * instance will be handling asyncronous file uploads, its 
7526
        * <code>callback</code> property will need to be setup with a 
7527
        * <code>upload</code> handler rather than the standard 
7528
        * <code>success</code> and, or <code>failure</code> handlers.  For more 
7529
        * information, see the <a href="http://developer.yahoo.com/yui/
7530
        * connection/#file">Connection Manager documenation on file uploads</a>.
7531
        * @method doSubmit
7532
        */
7533
        doSubmit: function () {
7534
7535
            var Connect = YAHOO.util.Connect,
7536
                oForm = this.form,
7537
                bUseFileUpload = false,
7538
                bUseSecureFileUpload = false,
7539
                aElements,
7540
                nElements,
7541
                i,
7542
                formAttrs;
7543
7544
            switch (this.cfg.getProperty("postmethod")) {
7545
7546
                case "async":
7547
                    aElements = oForm.elements;
7548
                    nElements = aElements.length;
7549
7550
                    if (nElements > 0) {
7551
                        i = nElements - 1;
7552
                        do {
7553
                            if (aElements[i].type == "file") {
7554
                                bUseFileUpload = true;
7555
                                break;
7556
                            }
7557
                        }
7558
                        while(i--);
7559
                    }
7560
7561
                    if (bUseFileUpload && YAHOO.env.ua.ie && this.isSecure) {
7562
                        bUseSecureFileUpload = true;
7563
                    }
7564
7565
                    formAttrs = this._getFormAttributes(oForm);
7566
7567
                    Connect.setForm(oForm, bUseFileUpload, bUseSecureFileUpload);
7568
7569
                    var postData = this.cfg.getProperty("postdata");
7570
                    var c = Connect.asyncRequest(formAttrs.method, formAttrs.action, this.callback, postData);
7571
7572
                    this.asyncSubmitEvent.fire(c);
7573
7574
                    break;
7575
7576
                case "form":
7577
                    oForm.submit();
7578
                    this.formSubmitEvent.fire();
7579
                    break;
7580
7581
                case "none":
7582
                case "manual":
7583
                    this.manualSubmitEvent.fire();
7584
                    break;
7585
            }
7586
        },
7587
7588
        /**
7589
         * Retrieves important attributes (currently method and action) from
7590
         * the form element, accounting for any elements which may have the same name 
7591
         * as the attributes. Defaults to "POST" and "" for method and action respectively
7592
         * if the attribute cannot be retrieved.
7593
         *
7594
         * @method _getFormAttributes
7595
         * @protected
7596
         * @param {HTMLFormElement} oForm The HTML Form element from which to retrieve the attributes
7597
         * @return {Object} Object literal, with method and action String properties.
7598
         */
7599
        _getFormAttributes : function(oForm){
7600
            var attrs = {
7601
                method : null,
7602
                action : null
7603
            };
7604
7605
            if (oForm) {
7606
                if (oForm.getAttributeNode) {
7607
                    var action = oForm.getAttributeNode("action");
7608
                    var method = oForm.getAttributeNode("method");
7609
7610
                    if (action) {
7611
                        attrs.action = action.value;
7612
                    }
7613
7614
                    if (method) {
7615
                        attrs.method = method.value;
7616
                    }
7617
7618
                } else {
7619
                    attrs.action = oForm.getAttribute("action");
7620
                    attrs.method = oForm.getAttribute("method");
7621
                }
7622
            }
7623
7624
            attrs.method = (Lang.isString(attrs.method) ? attrs.method : "POST").toUpperCase();
7625
            attrs.action = Lang.isString(attrs.action) ? attrs.action : "";
7626
7627
            return attrs;
7628
        },
7629
7630
        /**
7631
        * Prepares the Dialog's internal FORM object, creating one if one is
7632
        * not currently present.
7633
        * @method registerForm
7634
        */
7635
        registerForm: function() {
7636
7637
            var form = this.element.getElementsByTagName("form")[0];
7638
7639
            if (this.form) {
7640
                if (this.form == form && Dom.isAncestor(this.element, this.form)) {
7641
                    return;
7642
                } else {
7643
                    Event.purgeElement(this.form);
7644
                    this.form = null;
7645
                }
7646
            }
7647
7648
            if (!form) {
7649
                form = document.createElement("form");
7650
                form.name = "frm_" + this.id;
7651
                this.body.appendChild(form);
7652
            }
7653
7654
            if (form) {
7655
                this.form = form;
7656
                Event.on(form, "submit", this._submitHandler, this, true);
7657
            }
7658
        },
7659
7660
        /**
7661
         * Internal handler for the form submit event
7662
         *
7663
         * @method _submitHandler
7664
         * @protected
7665
         * @param {DOMEvent} e The DOM Event object
7666
         */
7667
        _submitHandler : function(e) {
7668
            Event.stopEvent(e);
7669
            this.submit();
7670
            this.form.blur();
7671
        },
7672
7673
        /**
7674
         * Sets up a tab, shift-tab loop between the first and last elements
7675
         * provided. NOTE: Sets up the preventBackTab and preventTabOut KeyListener
7676
         * instance properties, which are reset everytime this method is invoked.
7677
         *
7678
         * @method setTabLoop
7679
         * @param {HTMLElement} firstElement
7680
         * @param {HTMLElement} lastElement
7681
         *
7682
         */
7683
        setTabLoop : function(firstElement, lastElement) {
7684
7685
            firstElement = firstElement || this.firstButton;
7686
            lastElement = this.lastButton || lastElement;
7687
7688
            Dialog.superclass.setTabLoop.call(this, firstElement, lastElement);
7689
        },
7690
7691
        /**
7692
         * Configures instance properties, pointing to the 
7693
         * first and last focusable elements in the Dialog's form.
7694
         *
7695
         * @method setFirstLastFocusable
7696
         */
7697
        setFirstLastFocusable : function() {
7698
7699
            Dialog.superclass.setFirstLastFocusable.call(this);
7700
7701
            var i, l, el, elements = this.focusableElements;
7702
7703
            this.firstFormElement = null;
7704
            this.lastFormElement = null;
7705
7706
            if (this.form && elements && elements.length > 0) {
7707
                l = elements.length;
7708
7709
                for (i = 0; i < l; ++i) {
7710
                    el = elements[i];
7711
                    if (this.form === el.form) {
7712
                        this.firstFormElement = el;
7713
                        break;
7714
                    }
7715
                }
7716
7717
                for (i = l-1; i >= 0; --i) {
7718
                    el = elements[i];
7719
                    if (this.form === el.form) {
7720
                        this.lastFormElement = el;
7721
                        break;
7722
                    }
7723
                }
7724
            }
7725
        },
7726
7727
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
7728
        /**
7729
        * The default event handler fired when the "close" property is 
7730
        * changed. The method controls the appending or hiding of the close
7731
        * icon at the top right of the Dialog.
7732
        * @method configClose
7733
        * @param {String} type The CustomEvent type (usually the property name)
7734
        * @param {Object[]} args The CustomEvent arguments. For 
7735
        * configuration handlers, args[0] will equal the newly applied value 
7736
        * for the property.
7737
        * @param {Object} obj The scope object. For configuration handlers, 
7738
        * this will usually equal the owner.
7739
        */
7740
        configClose: function (type, args, obj) {
7741
            Dialog.superclass.configClose.apply(this, arguments);
7742
        },
7743
7744
        /**
7745
         * Event handler for the close icon
7746
         * 
7747
         * @method _doClose
7748
         * @protected
7749
         * 
7750
         * @param {DOMEvent} e
7751
         */
7752
         _doClose : function(e) {
7753
            Event.preventDefault(e);
7754
            this.cancel();
7755
        },
7756
7757
        /**
7758
        * The default event handler for the "buttons" configuration property
7759
        * @method configButtons
7760
        * @param {String} type The CustomEvent type (usually the property name)
7761
        * @param {Object[]} args The CustomEvent arguments. For configuration 
7762
        * handlers, args[0] will equal the newly applied value for the property.
7763
        * @param {Object} obj The scope object. For configuration handlers, 
7764
        * this will usually equal the owner.
7765
        */
7766
        configButtons: function (type, args, obj) {
7767
7768
            var Button = YAHOO.widget.Button,
7769
                aButtons = args[0],
7770
                oInnerElement = this.innerElement,
7771
                oButton,
7772
                oButtonEl,
7773
                oYUIButton,
7774
                nButtons,
7775
                oSpan,
7776
                oFooter,
7777
                i;
7778
7779
            removeButtonEventHandlers.call(this);
7780
7781
            this._aButtons = null;
7782
7783
            if (Lang.isArray(aButtons)) {
7784
7785
                oSpan = document.createElement("span");
7786
                oSpan.className = "button-group";
7787
                nButtons = aButtons.length;
7788
7789
                this._aButtons = [];
7790
                this.defaultHtmlButton = null;
7791
7792
                for (i = 0; i < nButtons; i++) {
7793
                    oButton = aButtons[i];
7794
7795
                    if (Button) {
7796
                        oYUIButton = new Button({ label: oButton.text});
7797
                        oYUIButton.appendTo(oSpan);
7798
7799
                        oButtonEl = oYUIButton.get("element");
7800
7801
                        if (oButton.isDefault) {
7802
                            oYUIButton.addClass("default");
7803
                            this.defaultHtmlButton = oButtonEl;
7804
                        }
7805
7806
                        if (Lang.isFunction(oButton.handler)) {
7807
7808
                            oYUIButton.set("onclick", { 
7809
                                fn: oButton.handler, 
7810
                                obj: this, 
7811
                                scope: this 
7812
                            });
7813
7814
                        } else if (Lang.isObject(oButton.handler) && Lang.isFunction(oButton.handler.fn)) {
7815
7816
                            oYUIButton.set("onclick", { 
7817
                                fn: oButton.handler.fn, 
7818
                                obj: ((!Lang.isUndefined(oButton.handler.obj)) ? oButton.handler.obj : this), 
7819
                                scope: (oButton.handler.scope || this) 
7820
                            });
7821
7822
                        }
7823
7824
                        this._aButtons[this._aButtons.length] = oYUIButton;
7825
7826
                    } else {
7827
7828
                        oButtonEl = document.createElement("button");
7829
                        oButtonEl.setAttribute("type", "button");
7830
7831
                        if (oButton.isDefault) {
7832
                            oButtonEl.className = "default";
7833
                            this.defaultHtmlButton = oButtonEl;
7834
                        }
7835
7836
                        oButtonEl.innerHTML = oButton.text;
7837
7838
                        if (Lang.isFunction(oButton.handler)) {
7839
                            Event.on(oButtonEl, "click", oButton.handler, this, true);
7840
                        } else if (Lang.isObject(oButton.handler) && 
7841
                            Lang.isFunction(oButton.handler.fn)) {
7842
    
7843
                            Event.on(oButtonEl, "click", 
7844
                                oButton.handler.fn, 
7845
                                ((!Lang.isUndefined(oButton.handler.obj)) ? oButton.handler.obj : this), 
7846
                                (oButton.handler.scope || this));
7847
                        }
7848
7849
                        oSpan.appendChild(oButtonEl);
7850
                        this._aButtons[this._aButtons.length] = oButtonEl;
7851
                    }
7852
7853
                    oButton.htmlButton = oButtonEl;
7854
7855
                    if (i === 0) {
7856
                        this.firstButton = oButtonEl;
7857
                    }
7858
7859
                    if (i == (nButtons - 1)) {
7860
                        this.lastButton = oButtonEl;
7861
                    }
7862
                }
7863
7864
                this.setFooter(oSpan);
7865
7866
                oFooter = this.footer;
7867
7868
                if (Dom.inDocument(this.element) && !Dom.isAncestor(oInnerElement, oFooter)) {
7869
                    oInnerElement.appendChild(oFooter);
7870
                }
7871
7872
                this.buttonSpan = oSpan;
7873
7874
            } else { // Do cleanup
7875
                oSpan = this.buttonSpan;
7876
                oFooter = this.footer;
7877
                if (oSpan && oFooter) {
7878
                    oFooter.removeChild(oSpan);
7879
                    this.buttonSpan = null;
7880
                    this.firstButton = null;
7881
                    this.lastButton = null;
7882
                    this.defaultHtmlButton = null;
7883
                }
7884
            }
7885
7886
            this.changeContentEvent.fire();
7887
        },
7888
7889
        /**
7890
        * @method getButtons
7891
        * @description Returns an array containing each of the Dialog's 
7892
        * buttons, by default an array of HTML <code>&#60;BUTTON&#62;</code> 
7893
        * elements.  If the Dialog's buttons were created using the 
7894
        * YAHOO.widget.Button class (via the inclusion of the optional Button 
7895
        * dependancy on the page), an array of YAHOO.widget.Button instances 
7896
        * is returned.
7897
        * @return {Array}
7898
        */
7899
        getButtons: function () {
7900
            return this._aButtons || null;
7901
        },
7902
7903
        /**
7904
         * <p>
7905
         * Sets focus to the first focusable element in the Dialog's form if found, 
7906
         * else, the default button if found, else the first button defined via the 
7907
         * "buttons" configuration property.
7908
         * </p>
7909
         * <p>
7910
         * This method is invoked when the Dialog is made visible.
7911
         * </p>
7912
         * @method focusFirst
7913
         */
7914
        focusFirst: function (type, args, obj) {
7915
7916
            var el = this.firstFormElement;
7917
7918
            if (args && args[1]) {
7919
                Event.stopEvent(args[1]);
7920
            }
7921
7922
            if (el) {
7923
                try {
7924
                    el.focus();
7925
                } catch(oException) {
7926
                    // Ignore
7927
                }
7928
            } else {
7929
                if (this.defaultHtmlButton) {
7930
                    this.focusDefaultButton();
7931
                } else {
7932
                    this.focusFirstButton();
7933
                }
7934
            }
7935
        },
7936
7937
        /**
7938
        * Sets focus to the last element in the Dialog's form or the last 
7939
        * button defined via the "buttons" configuration property.
7940
        * @method focusLast
7941
        */
7942
        focusLast: function (type, args, obj) {
7943
7944
            var aButtons = this.cfg.getProperty("buttons"),
7945
                el = this.lastFormElement;
7946
7947
            if (args && args[1]) {
7948
                Event.stopEvent(args[1]);
7949
            }
7950
7951
            if (aButtons && Lang.isArray(aButtons)) {
7952
                this.focusLastButton();
7953
            } else {
7954
                if (el) {
7955
                    try {
7956
                        el.focus();
7957
                    } catch(oException) {
7958
                        // Ignore
7959
                    }
7960
                }
7961
            }
7962
        },
7963
7964
        /**
7965
         * Helper method to normalize button references. It either returns the 
7966
         * YUI Button instance for the given element if found,
7967
         * or the passes back the HTMLElement reference if a corresponding YUI Button
7968
         * reference is not found or YAHOO.widget.Button does not exist on the page.
7969
         *
7970
         * @method _getButton
7971
         * @private
7972
         * @param {HTMLElement} button
7973
         * @return {YAHOO.widget.Button|HTMLElement}
7974
         */
7975
        _getButton : function(button) {
7976
            var Button = YAHOO.widget.Button;
7977
7978
            // If we have an HTML button and YUI Button is on the page, 
7979
            // get the YUI Button reference if available.
7980
            if (Button && button && button.nodeName && button.id) {
7981
                button = Button.getButton(button.id) || button;
7982
            }
7983
7984
            return button;
7985
        },
7986
7987
        /**
7988
        * Sets the focus to the button that is designated as the default via 
7989
        * the "buttons" configuration property. By default, this method is 
7990
        * called when the Dialog is made visible.
7991
        * @method focusDefaultButton
7992
        */
7993
        focusDefaultButton: function () {
7994
            var button = this._getButton(this.defaultHtmlButton);
7995
            if (button) {
7996
                /*
7997
                    Place the call to the "focus" method inside a try/catch
7998
                    block to prevent IE from throwing JavaScript errors if
7999
                    the element is disabled or hidden.
8000
                */
8001
                try {
8002
                    button.focus();
8003
                } catch(oException) {
8004
                }
8005
            }
8006
        },
8007
8008
        /**
8009
        * Blurs all the buttons defined via the "buttons" 
8010
        * configuration property.
8011
        * @method blurButtons
8012
        */
8013
        blurButtons: function () {
8014
            
8015
            var aButtons = this.cfg.getProperty("buttons"),
8016
                nButtons,
8017
                oButton,
8018
                oElement,
8019
                i;
8020
8021
            if (aButtons && Lang.isArray(aButtons)) {
8022
                nButtons = aButtons.length;
8023
                if (nButtons > 0) {
8024
                    i = (nButtons - 1);
8025
                    do {
8026
                        oButton = aButtons[i];
8027
                        if (oButton) {
8028
                            oElement = this._getButton(oButton.htmlButton);
8029
                            if (oElement) {
8030
                                /*
8031
                                    Place the call to the "blur" method inside  
8032
                                    a try/catch block to prevent IE from  
8033
                                    throwing JavaScript errors if the element 
8034
                                    is disabled or hidden.
8035
                                */
8036
                                try {
8037
                                    oElement.blur();
8038
                                } catch(oException) {
8039
                                    // ignore
8040
                                }
8041
                            }
8042
                        }
8043
                    } while(i--);
8044
                }
8045
            }
8046
        },
8047
8048
        /**
8049
        * Sets the focus to the first button created via the "buttons"
8050
        * configuration property.
8051
        * @method focusFirstButton
8052
        */
8053
        focusFirstButton: function () {
8054
8055
            var aButtons = this.cfg.getProperty("buttons"),
8056
                oButton,
8057
                oElement;
8058
8059
            if (aButtons && Lang.isArray(aButtons)) {
8060
                oButton = aButtons[0];
8061
                if (oButton) {
8062
                    oElement = this._getButton(oButton.htmlButton);
8063
                    if (oElement) {
8064
                        /*
8065
                            Place the call to the "focus" method inside a 
8066
                            try/catch block to prevent IE from throwing 
8067
                            JavaScript errors if the element is disabled 
8068
                            or hidden.
8069
                        */
8070
                        try {
8071
                            oElement.focus();
8072
                        } catch(oException) {
8073
                            // ignore
8074
                        }
8075
                    }
8076
                }
8077
            }
8078
        },
8079
8080
        /**
8081
        * Sets the focus to the last button created via the "buttons" 
8082
        * configuration property.
8083
        * @method focusLastButton
8084
        */
8085
        focusLastButton: function () {
8086
8087
            var aButtons = this.cfg.getProperty("buttons"),
8088
                nButtons,
8089
                oButton,
8090
                oElement;
8091
8092
            if (aButtons && Lang.isArray(aButtons)) {
8093
                nButtons = aButtons.length;
8094
                if (nButtons > 0) {
8095
                    oButton = aButtons[(nButtons - 1)];
8096
8097
                    if (oButton) {
8098
                        oElement = this._getButton(oButton.htmlButton);
8099
                        if (oElement) {
8100
                            /*
8101
                                Place the call to the "focus" method inside a 
8102
                                try/catch block to prevent IE from throwing 
8103
                                JavaScript errors if the element is disabled
8104
                                or hidden.
8105
                            */
8106
        
8107
                            try {
8108
                                oElement.focus();
8109
                            } catch(oException) {
8110
                                // Ignore
8111
                            }
8112
                        }
8113
                    }
8114
                }
8115
            }
8116
        },
8117
8118
        /**
8119
        * The default event handler for the "postmethod" configuration property
8120
        * @method configPostMethod
8121
        * @param {String} type The CustomEvent type (usually the property name)
8122
        * @param {Object[]} args The CustomEvent arguments. For 
8123
        * configuration handlers, args[0] will equal the newly applied value 
8124
        * for the property.
8125
        * @param {Object} obj The scope object. For configuration handlers, 
8126
        * this will usually equal the owner.
8127
        */
8128
        configPostMethod: function (type, args, obj) {
8129
            this.registerForm();
8130
        },
8131
8132
        // END BUILT-IN PROPERTY EVENT HANDLERS //
8133
        
8134
        /**
8135
        * Built-in function hook for writing a validation function that will 
8136
        * be checked for a "true" value prior to a submit. This function, as 
8137
        * implemented by default, always returns true, so it should be 
8138
        * overridden if validation is necessary.
8139
        * @method validate
8140
        */
8141
        validate: function () {
8142
            return true;
8143
        },
8144
8145
        /**
8146
        * Executes a submit of the Dialog if validation 
8147
        * is successful. By default the Dialog is hidden
8148
        * after submission, but you can set the "hideaftersubmit"
8149
        * configuration property to false, to prevent the Dialog
8150
        * from being hidden.
8151
        * 
8152
        * @method submit
8153
        */
8154
        submit: function () {
8155
            if (this.validate()) {
8156
                if (this.beforeSubmitEvent.fire()) {
8157
                    this.doSubmit();
8158
                    this.submitEvent.fire();
8159
    
8160
                    if (this.cfg.getProperty("hideaftersubmit")) {
8161
                        this.hide();
8162
                    }
8163
    
8164
                    return true;
8165
                } else {
8166
                    return false;
8167
                }
8168
            } else {
8169
                return false;
8170
            }
8171
        },
8172
8173
        /**
8174
        * Executes the cancel of the Dialog followed by a hide.
8175
        * @method cancel
8176
        */
8177
        cancel: function () {
8178
            this.cancelEvent.fire();
8179
            this.hide();
8180
        },
8181
        
8182
        /**
8183
        * Returns a JSON-compatible data structure representing the data 
8184
        * currently contained in the form.
8185
        * @method getData
8186
        * @return {Object} A JSON object reprsenting the data of the 
8187
        * current form.
8188
        */
8189
        getData: function () {
8190
8191
            var oForm = this.form,
8192
                aElements,
8193
                nTotalElements,
8194
                oData,
8195
                sName,
8196
                oElement,
8197
                nElements,
8198
                sType,
8199
                sTagName,
8200
                aOptions,
8201
                nOptions,
8202
                aValues,
8203
                oOption,
8204
                oRadio,
8205
                oCheckbox,
8206
                valueAttr,
8207
                i,
8208
                n;    
8209
    
8210
            function isFormElement(p_oElement) {
8211
                var sTag = p_oElement.tagName.toUpperCase();
8212
                return ((sTag == "INPUT" || sTag == "TEXTAREA" || 
8213
                        sTag == "SELECT") && p_oElement.name == sName);
8214
            }
8215
8216
            if (oForm) {
8217
8218
                aElements = oForm.elements;
8219
                nTotalElements = aElements.length;
8220
                oData = {};
8221
8222
                for (i = 0; i < nTotalElements; i++) {
8223
                    sName = aElements[i].name;
8224
8225
                    /*
8226
                        Using "Dom.getElementsBy" to safeguard user from JS 
8227
                        errors that result from giving a form field (or set of 
8228
                        fields) the same name as a native method of a form 
8229
                        (like "submit") or a DOM collection (such as the "item"
8230
                        method). Originally tried accessing fields via the 
8231
                        "namedItem" method of the "element" collection, but 
8232
                        discovered that it won't return a collection of fields 
8233
                        in Gecko.
8234
                    */
8235
8236
                    oElement = Dom.getElementsBy(isFormElement, "*", oForm);
8237
                    nElements = oElement.length;
8238
8239
                    if (nElements > 0) {
8240
                        if (nElements == 1) {
8241
                            oElement = oElement[0];
8242
8243
                            sType = oElement.type;
8244
                            sTagName = oElement.tagName.toUpperCase();
8245
8246
                            switch (sTagName) {
8247
                                case "INPUT":
8248
                                    if (sType == "checkbox") {
8249
                                        oData[sName] = oElement.checked;
8250
                                    } else if (sType != "radio") {
8251
                                        oData[sName] = oElement.value;
8252
                                    }
8253
                                    break;
8254
8255
                                case "TEXTAREA":
8256
                                    oData[sName] = oElement.value;
8257
                                    break;
8258
    
8259
                                case "SELECT":
8260
                                    aOptions = oElement.options;
8261
                                    nOptions = aOptions.length;
8262
                                    aValues = [];
8263
    
8264
                                    for (n = 0; n < nOptions; n++) {
8265
                                        oOption = aOptions[n];
8266
                                        if (oOption.selected) {
8267
                                            valueAttr = oOption.attributes.value;
8268
                                            aValues[aValues.length] = (valueAttr && valueAttr.specified) ? oOption.value : oOption.text;
8269
                                        }
8270
                                    }
8271
                                    oData[sName] = aValues;
8272
                                    break;
8273
                            }
8274
        
8275
                        } else {
8276
                            sType = oElement[0].type;
8277
                            switch (sType) {
8278
                                case "radio":
8279
                                    for (n = 0; n < nElements; n++) {
8280
                                        oRadio = oElement[n];
8281
                                        if (oRadio.checked) {
8282
                                            oData[sName] = oRadio.value;
8283
                                            break;
8284
                                        }
8285
                                    }
8286
                                    break;
8287
        
8288
                                case "checkbox":
8289
                                    aValues = [];
8290
                                    for (n = 0; n < nElements; n++) {
8291
                                        oCheckbox = oElement[n];
8292
                                        if (oCheckbox.checked) {
8293
                                            aValues[aValues.length] =  oCheckbox.value;
8294
                                        }
8295
                                    }
8296
                                    oData[sName] = aValues;
8297
                                    break;
8298
                            }
8299
                        }
8300
                    }
8301
                }
8302
            }
8303
8304
            return oData;
8305
        },
8306
8307
        /**
8308
        * Removes the Panel element from the DOM and sets all child elements 
8309
        * to null.
8310
        * @method destroy
8311
        */
8312
        destroy: function () {
8313
            removeButtonEventHandlers.call(this);
8314
8315
            this._aButtons = null;
8316
8317
            var aForms = this.element.getElementsByTagName("form"),
8318
                oForm;
8319
8320
            if (aForms.length > 0) {
8321
                oForm = aForms[0];
8322
8323
                if (oForm) {
8324
                    Event.purgeElement(oForm);
8325
                    if (oForm.parentNode) {
8326
                        oForm.parentNode.removeChild(oForm);
8327
                    }
8328
                    this.form = null;
8329
                }
8330
            }
8331
            Dialog.superclass.destroy.call(this);
8332
        },
8333
8334
        /**
8335
        * Returns a string representation of the object.
8336
        * @method toString
8337
        * @return {String} The string representation of the Dialog
8338
        */
8339
        toString: function () {
8340
            return "Dialog " + this.id;
8341
        }
8342
    
8343
    });
8344
8345
}());
8346
(function () {
8347
8348
    /**
8349
    * SimpleDialog is a simple implementation of Dialog that can be used to 
8350
    * submit a single value. Forms can be processed in 3 ways -- via an 
8351
    * asynchronous Connection utility call, a simple form POST or GET, 
8352
    * or manually.
8353
    * @namespace YAHOO.widget
8354
    * @class SimpleDialog
8355
    * @extends YAHOO.widget.Dialog
8356
    * @constructor
8357
    * @param {String} el The element ID representing the SimpleDialog 
8358
    * <em>OR</em>
8359
    * @param {HTMLElement} el The element representing the SimpleDialog
8360
    * @param {Object} userConfig The configuration object literal containing 
8361
    * the configuration that should be set for this SimpleDialog. See 
8362
    * configuration documentation for more details.
8363
    */
8364
    YAHOO.widget.SimpleDialog = function (el, userConfig) {
8365
    
8366
        YAHOO.widget.SimpleDialog.superclass.constructor.call(this, 
8367
            el, userConfig);
8368
    
8369
    };
8370
8371
    var Dom = YAHOO.util.Dom,
8372
        SimpleDialog = YAHOO.widget.SimpleDialog,
8373
    
8374
        /**
8375
        * Constant representing the SimpleDialog's configuration properties
8376
        * @property DEFAULT_CONFIG
8377
        * @private
8378
        * @final
8379
        * @type Object
8380
        */
8381
        DEFAULT_CONFIG = {
8382
        
8383
            "ICON": { 
8384
                key: "icon", 
8385
                value: "none", 
8386
                suppressEvent: true  
8387
            },
8388
        
8389
            "TEXT": { 
8390
                key: "text", 
8391
                value: "", 
8392
                suppressEvent: true, 
8393
                supercedes: ["icon"] 
8394
            }
8395
        
8396
        };
8397
8398
    /**
8399
    * Constant for the standard network icon for a blocking action
8400
    * @property YAHOO.widget.SimpleDialog.ICON_BLOCK
8401
    * @static
8402
    * @final
8403
    * @type String
8404
    */
8405
    SimpleDialog.ICON_BLOCK = "blckicon";
8406
    
8407
    /**
8408
    * Constant for the standard network icon for alarm
8409
    * @property YAHOO.widget.SimpleDialog.ICON_ALARM
8410
    * @static
8411
    * @final
8412
    * @type String
8413
    */
8414
    SimpleDialog.ICON_ALARM = "alrticon";
8415
    
8416
    /**
8417
    * Constant for the standard network icon for help
8418
    * @property YAHOO.widget.SimpleDialog.ICON_HELP
8419
    * @static
8420
    * @final
8421
    * @type String
8422
    */
8423
    SimpleDialog.ICON_HELP  = "hlpicon";
8424
    
8425
    /**
8426
    * Constant for the standard network icon for info
8427
    * @property YAHOO.widget.SimpleDialog.ICON_INFO
8428
    * @static
8429
    * @final
8430
    * @type String
8431
    */
8432
    SimpleDialog.ICON_INFO  = "infoicon";
8433
    
8434
    /**
8435
    * Constant for the standard network icon for warn
8436
    * @property YAHOO.widget.SimpleDialog.ICON_WARN
8437
    * @static
8438
    * @final
8439
    * @type String
8440
    */
8441
    SimpleDialog.ICON_WARN  = "warnicon";
8442
    
8443
    /**
8444
    * Constant for the standard network icon for a tip
8445
    * @property YAHOO.widget.SimpleDialog.ICON_TIP
8446
    * @static
8447
    * @final
8448
    * @type String
8449
    */
8450
    SimpleDialog.ICON_TIP   = "tipicon";
8451
8452
    /**
8453
    * Constant representing the name of the CSS class applied to the element 
8454
    * created by the "icon" configuration property.
8455
    * @property YAHOO.widget.SimpleDialog.ICON_CSS_CLASSNAME
8456
    * @static
8457
    * @final
8458
    * @type String
8459
    */
8460
    SimpleDialog.ICON_CSS_CLASSNAME = "yui-icon";
8461
    
8462
    /**
8463
    * Constant representing the default CSS class used for a SimpleDialog
8464
    * @property YAHOO.widget.SimpleDialog.CSS_SIMPLEDIALOG
8465
    * @static
8466
    * @final
8467
    * @type String
8468
    */
8469
    SimpleDialog.CSS_SIMPLEDIALOG = "yui-simple-dialog";
8470
8471
    
8472
    YAHOO.extend(SimpleDialog, YAHOO.widget.Dialog, {
8473
    
8474
        /**
8475
        * Initializes the class's configurable properties which can be changed 
8476
        * using the SimpleDialog's Config object (cfg).
8477
        * @method initDefaultConfig
8478
        */
8479
        initDefaultConfig: function () {
8480
        
8481
            SimpleDialog.superclass.initDefaultConfig.call(this);
8482
        
8483
            // Add dialog config properties //
8484
        
8485
            /**
8486
            * Sets the informational icon for the SimpleDialog
8487
            * @config icon
8488
            * @type String
8489
            * @default "none"
8490
            */
8491
            this.cfg.addProperty(DEFAULT_CONFIG.ICON.key, {
8492
                handler: this.configIcon,
8493
                value: DEFAULT_CONFIG.ICON.value,
8494
                suppressEvent: DEFAULT_CONFIG.ICON.suppressEvent
8495
            });
8496
        
8497
            /**
8498
            * Sets the text for the SimpleDialog
8499
            * @config text
8500
            * @type String
8501
            * @default ""
8502
            */
8503
            this.cfg.addProperty(DEFAULT_CONFIG.TEXT.key, { 
8504
                handler: this.configText, 
8505
                value: DEFAULT_CONFIG.TEXT.value, 
8506
                suppressEvent: DEFAULT_CONFIG.TEXT.suppressEvent, 
8507
                supercedes: DEFAULT_CONFIG.TEXT.supercedes 
8508
            });
8509
        
8510
        },
8511
        
8512
        
8513
        /**
8514
        * The SimpleDialog initialization method, which is executed for 
8515
        * SimpleDialog and all of its subclasses. This method is automatically 
8516
        * called by the constructor, and  sets up all DOM references for 
8517
        * pre-existing markup, and creates required markup if it is not 
8518
        * already present.
8519
        * @method init
8520
        * @param {String} el The element ID representing the SimpleDialog 
8521
        * <em>OR</em>
8522
        * @param {HTMLElement} el The element representing the SimpleDialog
8523
        * @param {Object} userConfig The configuration object literal 
8524
        * containing the configuration that should be set for this 
8525
        * SimpleDialog. See configuration documentation for more details.
8526
        */
8527
        init: function (el, userConfig) {
8528
8529
            /*
8530
                Note that we don't pass the user config in here yet because we 
8531
                only want it executed once, at the lowest subclass level
8532
            */
8533
8534
            SimpleDialog.superclass.init.call(this, el/*, userConfig*/);
8535
        
8536
            this.beforeInitEvent.fire(SimpleDialog);
8537
        
8538
            Dom.addClass(this.element, SimpleDialog.CSS_SIMPLEDIALOG);
8539
        
8540
            this.cfg.queueProperty("postmethod", "manual");
8541
        
8542
            if (userConfig) {
8543
                this.cfg.applyConfig(userConfig, true);
8544
            }
8545
        
8546
            this.beforeRenderEvent.subscribe(function () {
8547
                if (! this.body) {
8548
                    this.setBody("");
8549
                }
8550
            }, this, true);
8551
        
8552
            this.initEvent.fire(SimpleDialog);
8553
        
8554
        },
8555
        
8556
        /**
8557
        * Prepares the SimpleDialog's internal FORM object, creating one if one 
8558
        * is not currently present, and adding the value hidden field.
8559
        * @method registerForm
8560
        */
8561
        registerForm: function () {
8562
8563
            SimpleDialog.superclass.registerForm.call(this);
8564
8565
            this.form.innerHTML += "<input type=\"hidden\" name=\"" + 
8566
                this.id + "\" value=\"\"/>";
8567
8568
        },
8569
        
8570
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
8571
        
8572
        /**
8573
        * Fired when the "icon" property is set.
8574
        * @method configIcon
8575
        * @param {String} type The CustomEvent type (usually the property name)
8576
        * @param {Object[]} args The CustomEvent arguments. For configuration 
8577
        * handlers, args[0] will equal the newly applied value for the property.
8578
        * @param {Object} obj The scope object. For configuration handlers, 
8579
        * this will usually equal the owner.
8580
        */
8581
        configIcon: function (type,args,obj) {
8582
        
8583
            var sIcon = args[0],
8584
                oBody = this.body,
8585
                sCSSClass = SimpleDialog.ICON_CSS_CLASSNAME,
8586
				aElements,
8587
                oIcon,
8588
                oIconParent;
8589
        
8590
            if (sIcon && sIcon != "none") {
8591
8592
                aElements = Dom.getElementsByClassName(sCSSClass, "*" , oBody);
8593
8594
				if (aElements.length === 1) {
8595
8596
					oIcon = aElements[0];
8597
                    oIconParent = oIcon.parentNode;
8598
8599
                    if (oIconParent) {
8600
8601
                        oIconParent.removeChild(oIcon);
8602
8603
                        oIcon = null;
8604
8605
                    }
8606
8607
				}
8608
8609
8610
                if (sIcon.indexOf(".") == -1) {
8611
8612
                    oIcon = document.createElement("span");
8613
                    oIcon.className = (sCSSClass + " " + sIcon);
8614
                    oIcon.innerHTML = "&#160;";
8615
8616
                } else {
8617
8618
                    oIcon = document.createElement("img");
8619
                    oIcon.src = (this.imageRoot + sIcon);
8620
                    oIcon.className = sCSSClass;
8621
8622
                }
8623
                
8624
8625
                if (oIcon) {
8626
                
8627
                    oBody.insertBefore(oIcon, oBody.firstChild);
8628
                
8629
                }
8630
8631
            }
8632
8633
        },
8634
8635
        /**
8636
        * Fired when the "text" property is set.
8637
        * @method configText
8638
        * @param {String} type The CustomEvent type (usually the property name)
8639
        * @param {Object[]} args The CustomEvent arguments. For configuration 
8640
        * handlers, args[0] will equal the newly applied value for the property.
8641
        * @param {Object} obj The scope object. For configuration handlers, 
8642
        * this will usually equal the owner.
8643
        */
8644
        configText: function (type,args,obj) {
8645
            var text = args[0];
8646
            if (text) {
8647
                this.setBody(text);
8648
                this.cfg.refireEvent("icon");
8649
            }
8650
        },
8651
        
8652
        // END BUILT-IN PROPERTY EVENT HANDLERS //
8653
        
8654
        /**
8655
        * Returns a string representation of the object.
8656
        * @method toString
8657
        * @return {String} The string representation of the SimpleDialog
8658
        */
8659
        toString: function () {
8660
            return "SimpleDialog " + this.id;
8661
        }
8662
8663
        /**
8664
        * <p>
8665
        * Sets the SimpleDialog's body content to the HTML specified. 
8666
        * If no body is present, one will be automatically created. 
8667
        * An empty string can be passed to the method to clear the contents of the body.
8668
        * </p>
8669
        * <p><strong>NOTE:</strong> SimpleDialog provides the <a href="#config_text">text</a>
8670
        * and <a href="#config_icon">icon</a> configuration properties to set the contents
8671
        * of it's body element in accordance with the UI design for a SimpleDialog (an 
8672
        * icon and message text). Calling setBody on the SimpleDialog will not enforce this 
8673
        * UI design constraint and will replace the entire contents of the SimpleDialog body. 
8674
        * It should only be used if you wish the replace the default icon/text body structure 
8675
        * of a SimpleDialog with your own custom markup.</p>
8676
        * 
8677
        * @method setBody
8678
        * @param {String} bodyContent The HTML used to set the body. 
8679
        * As a convenience, non HTMLElement objects can also be passed into 
8680
        * the method, and will be treated as strings, with the body innerHTML
8681
        * set to their default toString implementations.
8682
        * <em>OR</em>
8683
        * @param {HTMLElement} bodyContent The HTMLElement to add as the first and only child of the body element.
8684
        * <em>OR</em>
8685
        * @param {DocumentFragment} bodyContent The document fragment 
8686
        * containing elements which are to be added to the body
8687
        */
8688
    });
8689
8690
}());
8691
(function () {
8692
8693
    /**
8694
    * ContainerEffect encapsulates animation transitions that are executed when 
8695
    * an Overlay is shown or hidden.
8696
    * @namespace YAHOO.widget
8697
    * @class ContainerEffect
8698
    * @constructor
8699
    * @param {YAHOO.widget.Overlay} overlay The Overlay that the animation 
8700
    * should be associated with
8701
    * @param {Object} attrIn The object literal representing the animation 
8702
    * arguments to be used for the animate-in transition. The arguments for 
8703
    * this literal are: attributes(object, see YAHOO.util.Anim for description), 
8704
    * duration(Number), and method(i.e. Easing.easeIn).
8705
    * @param {Object} attrOut The object literal representing the animation 
8706
    * arguments to be used for the animate-out transition. The arguments for  
8707
    * this literal are: attributes(object, see YAHOO.util.Anim for description), 
8708
    * duration(Number), and method(i.e. Easing.easeIn).
8709
    * @param {HTMLElement} targetElement Optional. The target element that  
8710
    * should be animated during the transition. Defaults to overlay.element.
8711
    * @param {class} Optional. The animation class to instantiate. Defaults to 
8712
    * YAHOO.util.Anim. Other options include YAHOO.util.Motion.
8713
    */
8714
    YAHOO.widget.ContainerEffect = function (overlay, attrIn, attrOut, targetElement, animClass) {
8715
8716
        if (!animClass) {
8717
            animClass = YAHOO.util.Anim;
8718
        }
8719
8720
        /**
8721
        * The overlay to animate
8722
        * @property overlay
8723
        * @type YAHOO.widget.Overlay
8724
        */
8725
        this.overlay = overlay;
8726
    
8727
        /**
8728
        * The animation attributes to use when transitioning into view
8729
        * @property attrIn
8730
        * @type Object
8731
        */
8732
        this.attrIn = attrIn;
8733
    
8734
        /**
8735
        * The animation attributes to use when transitioning out of view
8736
        * @property attrOut
8737
        * @type Object
8738
        */
8739
        this.attrOut = attrOut;
8740
    
8741
        /**
8742
        * The target element to be animated
8743
        * @property targetElement
8744
        * @type HTMLElement
8745
        */
8746
        this.targetElement = targetElement || overlay.element;
8747
    
8748
        /**
8749
        * The animation class to use for animating the overlay
8750
        * @property animClass
8751
        * @type class
8752
        */
8753
        this.animClass = animClass;
8754
    
8755
    };
8756
8757
8758
    var Dom = YAHOO.util.Dom,
8759
        CustomEvent = YAHOO.util.CustomEvent,
8760
        ContainerEffect = YAHOO.widget.ContainerEffect;
8761
8762
8763
    /**
8764
    * A pre-configured ContainerEffect instance that can be used for fading 
8765
    * an overlay in and out.
8766
    * @method FADE
8767
    * @static
8768
    * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
8769
    * @param {Number} dur The duration of the animation
8770
    * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
8771
    */
8772
    ContainerEffect.FADE = function (overlay, dur) {
8773
8774
        var Easing = YAHOO.util.Easing,
8775
            fin = {
8776
                attributes: {opacity:{from:0, to:1}},
8777
                duration: dur,
8778
                method: Easing.easeIn
8779
            },
8780
            fout = {
8781
                attributes: {opacity:{to:0}},
8782
                duration: dur,
8783
                method: Easing.easeOut
8784
            },
8785
            fade = new ContainerEffect(overlay, fin, fout, overlay.element);
8786
8787
        fade.handleUnderlayStart = function() {
8788
            var underlay = this.overlay.underlay;
8789
            if (underlay && YAHOO.env.ua.ie) {
8790
                var hasFilters = (underlay.filters && underlay.filters.length > 0);
8791
                if(hasFilters) {
8792
                    Dom.addClass(overlay.element, "yui-effect-fade");
8793
                }
8794
            }
8795
        };
8796
8797
        fade.handleUnderlayComplete = function() {
8798
            var underlay = this.overlay.underlay;
8799
            if (underlay && YAHOO.env.ua.ie) {
8800
                Dom.removeClass(overlay.element, "yui-effect-fade");
8801
            }
8802
        };
8803
8804
        fade.handleStartAnimateIn = function (type, args, obj) {
8805
            Dom.addClass(obj.overlay.element, "hide-select");
8806
8807
            if (!obj.overlay.underlay) {
8808
                obj.overlay.cfg.refireEvent("underlay");
8809
            }
8810
8811
            obj.handleUnderlayStart();
8812
8813
            obj.overlay._setDomVisibility(true);
8814
            Dom.setStyle(obj.overlay.element, "opacity", 0);
8815
        };
8816
8817
        fade.handleCompleteAnimateIn = function (type,args,obj) {
8818
            Dom.removeClass(obj.overlay.element, "hide-select");
8819
8820
            if (obj.overlay.element.style.filter) {
8821
                obj.overlay.element.style.filter = null;
8822
            }
8823
8824
            obj.handleUnderlayComplete();
8825
8826
            obj.overlay.cfg.refireEvent("iframe");
8827
            obj.animateInCompleteEvent.fire();
8828
        };
8829
8830
        fade.handleStartAnimateOut = function (type, args, obj) {
8831
            Dom.addClass(obj.overlay.element, "hide-select");
8832
            obj.handleUnderlayStart();
8833
        };
8834
8835
        fade.handleCompleteAnimateOut =  function (type, args, obj) {
8836
            Dom.removeClass(obj.overlay.element, "hide-select");
8837
            if (obj.overlay.element.style.filter) {
8838
                obj.overlay.element.style.filter = null;
8839
            }
8840
            obj.overlay._setDomVisibility(false);
8841
            Dom.setStyle(obj.overlay.element, "opacity", 1);
8842
8843
            obj.handleUnderlayComplete();
8844
8845
            obj.overlay.cfg.refireEvent("iframe");
8846
            obj.animateOutCompleteEvent.fire();
8847
        };
8848
8849
        fade.init();
8850
        return fade;
8851
    };
8852
    
8853
    
8854
    /**
8855
    * A pre-configured ContainerEffect instance that can be used for sliding an 
8856
    * overlay in and out.
8857
    * @method SLIDE
8858
    * @static
8859
    * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
8860
    * @param {Number} dur The duration of the animation
8861
    * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
8862
    */
8863
    ContainerEffect.SLIDE = function (overlay, dur) {
8864
        var Easing = YAHOO.util.Easing,
8865
8866
            x = overlay.cfg.getProperty("x") || Dom.getX(overlay.element),
8867
            y = overlay.cfg.getProperty("y") || Dom.getY(overlay.element),
8868
            clientWidth = Dom.getClientWidth(),
8869
            offsetWidth = overlay.element.offsetWidth,
8870
8871
            sin =  { 
8872
                attributes: { points: { to: [x, y] } },
8873
                duration: dur,
8874
                method: Easing.easeIn 
8875
            },
8876
8877
            sout = {
8878
                attributes: { points: { to: [(clientWidth + 25), y] } },
8879
                duration: dur,
8880
                method: Easing.easeOut 
8881
            },
8882
8883
            slide = new ContainerEffect(overlay, sin, sout, overlay.element, YAHOO.util.Motion);
8884
8885
        slide.handleStartAnimateIn = function (type,args,obj) {
8886
            obj.overlay.element.style.left = ((-25) - offsetWidth) + "px";
8887
            obj.overlay.element.style.top  = y + "px";
8888
        };
8889
8890
        slide.handleTweenAnimateIn = function (type, args, obj) {
8891
        
8892
            var pos = Dom.getXY(obj.overlay.element),
8893
                currentX = pos[0],
8894
                currentY = pos[1];
8895
        
8896
            if (Dom.getStyle(obj.overlay.element, "visibility") == 
8897
                "hidden" && currentX < x) {
8898
8899
                obj.overlay._setDomVisibility(true);
8900
8901
            }
8902
        
8903
            obj.overlay.cfg.setProperty("xy", [currentX, currentY], true);
8904
            obj.overlay.cfg.refireEvent("iframe");
8905
        };
8906
        
8907
        slide.handleCompleteAnimateIn = function (type, args, obj) {
8908
            obj.overlay.cfg.setProperty("xy", [x, y], true);
8909
            obj.startX = x;
8910
            obj.startY = y;
8911
            obj.overlay.cfg.refireEvent("iframe");
8912
            obj.animateInCompleteEvent.fire();
8913
        };
8914
        
8915
        slide.handleStartAnimateOut = function (type, args, obj) {
8916
    
8917
            var vw = Dom.getViewportWidth(),
8918
                pos = Dom.getXY(obj.overlay.element),
8919
                yso = pos[1];
8920
    
8921
            obj.animOut.attributes.points.to = [(vw + 25), yso];
8922
        };
8923
        
8924
        slide.handleTweenAnimateOut = function (type, args, obj) {
8925
    
8926
            var pos = Dom.getXY(obj.overlay.element),
8927
                xto = pos[0],
8928
                yto = pos[1];
8929
        
8930
            obj.overlay.cfg.setProperty("xy", [xto, yto], true);
8931
            obj.overlay.cfg.refireEvent("iframe");
8932
        };
8933
        
8934
        slide.handleCompleteAnimateOut = function (type, args, obj) {
8935
            obj.overlay._setDomVisibility(false);
8936
8937
            obj.overlay.cfg.setProperty("xy", [x, y]);
8938
            obj.animateOutCompleteEvent.fire();
8939
        };
8940
8941
        slide.init();
8942
        return slide;
8943
    };
8944
8945
    ContainerEffect.prototype = {
8946
8947
        /**
8948
        * Initializes the animation classes and events.
8949
        * @method init
8950
        */
8951
        init: function () {
8952
8953
            this.beforeAnimateInEvent = this.createEvent("beforeAnimateIn");
8954
            this.beforeAnimateInEvent.signature = CustomEvent.LIST;
8955
            
8956
            this.beforeAnimateOutEvent = this.createEvent("beforeAnimateOut");
8957
            this.beforeAnimateOutEvent.signature = CustomEvent.LIST;
8958
        
8959
            this.animateInCompleteEvent = this.createEvent("animateInComplete");
8960
            this.animateInCompleteEvent.signature = CustomEvent.LIST;
8961
        
8962
            this.animateOutCompleteEvent = 
8963
                this.createEvent("animateOutComplete");
8964
            this.animateOutCompleteEvent.signature = CustomEvent.LIST;
8965
        
8966
            this.animIn = new this.animClass(this.targetElement, 
8967
                this.attrIn.attributes, this.attrIn.duration, 
8968
                this.attrIn.method);
8969
8970
            this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
8971
            this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
8972
8973
            this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn, 
8974
                this);
8975
        
8976
            this.animOut = new this.animClass(this.targetElement, 
8977
                this.attrOut.attributes, this.attrOut.duration, 
8978
                this.attrOut.method);
8979
8980
            this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
8981
            this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
8982
            this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut, 
8983
                this);
8984
8985
        },
8986
        
8987
        /**
8988
        * Triggers the in-animation.
8989
        * @method animateIn
8990
        */
8991
        animateIn: function () {
8992
            this.beforeAnimateInEvent.fire();
8993
            this.animIn.animate();
8994
        },
8995
8996
        /**
8997
        * Triggers the out-animation.
8998
        * @method animateOut
8999
        */
9000
        animateOut: function () {
9001
            this.beforeAnimateOutEvent.fire();
9002
            this.animOut.animate();
9003
        },
9004
9005
        /**
9006
        * The default onStart handler for the in-animation.
9007
        * @method handleStartAnimateIn
9008
        * @param {String} type The CustomEvent type
9009
        * @param {Object[]} args The CustomEvent arguments
9010
        * @param {Object} obj The scope object
9011
        */
9012
        handleStartAnimateIn: function (type, args, obj) { },
9013
9014
        /**
9015
        * The default onTween handler for the in-animation.
9016
        * @method handleTweenAnimateIn
9017
        * @param {String} type The CustomEvent type
9018
        * @param {Object[]} args The CustomEvent arguments
9019
        * @param {Object} obj The scope object
9020
        */
9021
        handleTweenAnimateIn: function (type, args, obj) { },
9022
9023
        /**
9024
        * The default onComplete handler for the in-animation.
9025
        * @method handleCompleteAnimateIn
9026
        * @param {String} type The CustomEvent type
9027
        * @param {Object[]} args The CustomEvent arguments
9028
        * @param {Object} obj The scope object
9029
        */
9030
        handleCompleteAnimateIn: function (type, args, obj) { },
9031
9032
        /**
9033
        * The default onStart handler for the out-animation.
9034
        * @method handleStartAnimateOut
9035
        * @param {String} type The CustomEvent type
9036
        * @param {Object[]} args The CustomEvent arguments
9037
        * @param {Object} obj The scope object
9038
        */
9039
        handleStartAnimateOut: function (type, args, obj) { },
9040
9041
        /**
9042
        * The default onTween handler for the out-animation.
9043
        * @method handleTweenAnimateOut
9044
        * @param {String} type The CustomEvent type
9045
        * @param {Object[]} args The CustomEvent arguments
9046
        * @param {Object} obj The scope object
9047
        */
9048
        handleTweenAnimateOut: function (type, args, obj) { },
9049
9050
        /**
9051
        * The default onComplete handler for the out-animation.
9052
        * @method handleCompleteAnimateOut
9053
        * @param {String} type The CustomEvent type
9054
        * @param {Object[]} args The CustomEvent arguments
9055
        * @param {Object} obj The scope object
9056
        */
9057
        handleCompleteAnimateOut: function (type, args, obj) { },
9058
        
9059
        /**
9060
        * Returns a string representation of the object.
9061
        * @method toString
9062
        * @return {String} The string representation of the ContainerEffect
9063
        */
9064
        toString: function () {
9065
            var output = "ContainerEffect";
9066
            if (this.overlay) {
9067
                output += " [" + this.overlay.toString() + "]";
9068
            }
9069
            return output;
9070
        }
9071
    };
9072
9073
    YAHOO.lang.augmentProto(ContainerEffect, YAHOO.util.EventProvider);
9074
9075
})();
9076
YAHOO.register("container", YAHOO.widget.Module, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/container/container-min.js (-19 lines)
Lines 1-19 Link Here
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.8.0r4
6
*/
7
(function(){YAHOO.util.Config=function(D){if(D){this.init(D);}};var B=YAHOO.lang,C=YAHOO.util.CustomEvent,A=YAHOO.util.Config;A.CONFIG_CHANGED_EVENT="configChanged";A.BOOLEAN_TYPE="boolean";A.prototype={owner:null,queueInProgress:false,config:null,initialConfig:null,eventQueue:null,configChangedEvent:null,init:function(D){this.owner=D;this.configChangedEvent=this.createEvent(A.CONFIG_CHANGED_EVENT);this.configChangedEvent.signature=C.LIST;this.queueInProgress=false;this.config={};this.initialConfig={};this.eventQueue=[];},checkBoolean:function(D){return(typeof D==A.BOOLEAN_TYPE);},checkNumber:function(D){return(!isNaN(D));},fireEvent:function(D,F){var E=this.config[D];if(E&&E.event){E.event.fire(F);}},addProperty:function(E,D){E=E.toLowerCase();this.config[E]=D;D.event=this.createEvent(E,{scope:this.owner});D.event.signature=C.LIST;D.key=E;if(D.handler){D.event.subscribe(D.handler,this.owner);}this.setProperty(E,D.value,true);if(!D.suppressEvent){this.queueProperty(E,D.value);}},getConfig:function(){var D={},F=this.config,G,E;for(G in F){if(B.hasOwnProperty(F,G)){E=F[G];if(E&&E.event){D[G]=E.value;}}}return D;},getProperty:function(D){var E=this.config[D.toLowerCase()];if(E&&E.event){return E.value;}else{return undefined;}},resetProperty:function(D){D=D.toLowerCase();var E=this.config[D];if(E&&E.event){if(this.initialConfig[D]&&!B.isUndefined(this.initialConfig[D])){this.setProperty(D,this.initialConfig[D]);return true;}}else{return false;}},setProperty:function(E,G,D){var F;E=E.toLowerCase();if(this.queueInProgress&&!D){this.queueProperty(E,G);return true;}else{F=this.config[E];if(F&&F.event){if(F.validator&&!F.validator(G)){return false;}else{F.value=G;if(!D){this.fireEvent(E,G);this.configChangedEvent.fire([E,G]);}return true;}}else{return false;}}},queueProperty:function(S,P){S=S.toLowerCase();var R=this.config[S],K=false,J,G,H,I,O,Q,F,M,N,D,L,T,E;if(R&&R.event){if(!B.isUndefined(P)&&R.validator&&!R.validator(P)){return false;}else{if(!B.isUndefined(P)){R.value=P;}else{P=R.value;}K=false;J=this.eventQueue.length;for(L=0;L<J;L++){G=this.eventQueue[L];if(G){H=G[0];I=G[1];if(H==S){this.eventQueue[L]=null;this.eventQueue.push([S,(!B.isUndefined(P)?P:I)]);K=true;break;}}}if(!K&&!B.isUndefined(P)){this.eventQueue.push([S,P]);}}if(R.supercedes){O=R.supercedes.length;for(T=0;T<O;T++){Q=R.supercedes[T];F=this.eventQueue.length;for(E=0;E<F;E++){M=this.eventQueue[E];if(M){N=M[0];D=M[1];if(N==Q.toLowerCase()){this.eventQueue.push([N,D]);this.eventQueue[E]=null;break;}}}}}return true;}else{return false;}},refireEvent:function(D){D=D.toLowerCase();var E=this.config[D];if(E&&E.event&&!B.isUndefined(E.value)){if(this.queueInProgress){this.queueProperty(D);}else{this.fireEvent(D,E.value);}}},applyConfig:function(D,G){var F,E;if(G){E={};for(F in D){if(B.hasOwnProperty(D,F)){E[F.toLowerCase()]=D[F];}}this.initialConfig=E;}for(F in D){if(B.hasOwnProperty(D,F)){this.queueProperty(F,D[F]);}}},refresh:function(){var D;for(D in this.config){if(B.hasOwnProperty(this.config,D)){this.refireEvent(D);}}},fireQueue:function(){var E,H,D,G,F;this.queueInProgress=true;for(E=0;E<this.eventQueue.length;E++){H=this.eventQueue[E];if(H){D=H[0];G=H[1];F=this.config[D];F.value=G;this.eventQueue[E]=null;this.fireEvent(D,G);}}this.queueInProgress=false;this.eventQueue=[];},subscribeToConfigEvent:function(D,E,G,H){var F=this.config[D.toLowerCase()];if(F&&F.event){if(!A.alreadySubscribed(F.event,E,G)){F.event.subscribe(E,G,H);}return true;}else{return false;}},unsubscribeFromConfigEvent:function(D,E,G){var F=this.config[D.toLowerCase()];if(F&&F.event){return F.event.unsubscribe(E,G);}else{return false;}},toString:function(){var D="Config";if(this.owner){D+=" ["+this.owner.toString()+"]";}return D;},outputEventQueue:function(){var D="",G,E,F=this.eventQueue.length;for(E=0;E<F;E++){G=this.eventQueue[E];if(G){D+=G[0]+"="+G[1]+", ";}}return D;},destroy:function(){var E=this.config,D,F;for(D in E){if(B.hasOwnProperty(E,D)){F=E[D];F.event.unsubscribeAll();F.event=null;}}this.configChangedEvent.unsubscribeAll();this.configChangedEvent=null;this.owner=null;this.config=null;this.initialConfig=null;this.eventQueue=null;}};A.alreadySubscribed=function(E,H,I){var F=E.subscribers.length,D,G;if(F>0){G=F-1;do{D=E.subscribers[G];if(D&&D.obj==I&&D.fn==H){return true;}}while(G--);}return false;};YAHOO.lang.augmentProto(A,YAHOO.util.EventProvider);}());(function(){YAHOO.widget.Module=function(R,Q){if(R){this.init(R,Q);}else{}};var F=YAHOO.util.Dom,D=YAHOO.util.Config,N=YAHOO.util.Event,M=YAHOO.util.CustomEvent,G=YAHOO.widget.Module,I=YAHOO.env.ua,H,P,O,E,A={"BEFORE_INIT":"beforeInit","INIT":"init","APPEND":"append","BEFORE_RENDER":"beforeRender","RENDER":"render","CHANGE_HEADER":"changeHeader","CHANGE_BODY":"changeBody","CHANGE_FOOTER":"changeFooter","CHANGE_CONTENT":"changeContent","DESTROY":"destroy","BEFORE_SHOW":"beforeShow","SHOW":"show","BEFORE_HIDE":"beforeHide","HIDE":"hide"},J={"VISIBLE":{key:"visible",value:true,validator:YAHOO.lang.isBoolean},"EFFECT":{key:"effect",suppressEvent:true,supercedes:["visible"]},"MONITOR_RESIZE":{key:"monitorresize",value:true},"APPEND_TO_DOCUMENT_BODY":{key:"appendtodocumentbody",value:false}};G.IMG_ROOT=null;G.IMG_ROOT_SSL=null;G.CSS_MODULE="yui-module";G.CSS_HEADER="hd";G.CSS_BODY="bd";G.CSS_FOOTER="ft";G.RESIZE_MONITOR_SECURE_URL="javascript:false;";G.RESIZE_MONITOR_BUFFER=1;G.textResizeEvent=new M("textResize");G.forceDocumentRedraw=function(){var Q=document.documentElement;if(Q){Q.className+=" ";Q.className=YAHOO.lang.trim(Q.className);}};function L(){if(!H){H=document.createElement("div");H.innerHTML=('<div class="'+G.CSS_HEADER+'"></div>'+'<div class="'+G.CSS_BODY+'"></div><div class="'+G.CSS_FOOTER+'"></div>');P=H.firstChild;O=P.nextSibling;E=O.nextSibling;}return H;}function K(){if(!P){L();}return(P.cloneNode(false));}function B(){if(!O){L();}return(O.cloneNode(false));}function C(){if(!E){L();}return(E.cloneNode(false));}G.prototype={constructor:G,element:null,header:null,body:null,footer:null,id:null,imageRoot:G.IMG_ROOT,initEvents:function(){var Q=M.LIST;
8
this.beforeInitEvent=this.createEvent(A.BEFORE_INIT);this.beforeInitEvent.signature=Q;this.initEvent=this.createEvent(A.INIT);this.initEvent.signature=Q;this.appendEvent=this.createEvent(A.APPEND);this.appendEvent.signature=Q;this.beforeRenderEvent=this.createEvent(A.BEFORE_RENDER);this.beforeRenderEvent.signature=Q;this.renderEvent=this.createEvent(A.RENDER);this.renderEvent.signature=Q;this.changeHeaderEvent=this.createEvent(A.CHANGE_HEADER);this.changeHeaderEvent.signature=Q;this.changeBodyEvent=this.createEvent(A.CHANGE_BODY);this.changeBodyEvent.signature=Q;this.changeFooterEvent=this.createEvent(A.CHANGE_FOOTER);this.changeFooterEvent.signature=Q;this.changeContentEvent=this.createEvent(A.CHANGE_CONTENT);this.changeContentEvent.signature=Q;this.destroyEvent=this.createEvent(A.DESTROY);this.destroyEvent.signature=Q;this.beforeShowEvent=this.createEvent(A.BEFORE_SHOW);this.beforeShowEvent.signature=Q;this.showEvent=this.createEvent(A.SHOW);this.showEvent.signature=Q;this.beforeHideEvent=this.createEvent(A.BEFORE_HIDE);this.beforeHideEvent.signature=Q;this.hideEvent=this.createEvent(A.HIDE);this.hideEvent.signature=Q;},platform:function(){var Q=navigator.userAgent.toLowerCase();if(Q.indexOf("windows")!=-1||Q.indexOf("win32")!=-1){return"windows";}else{if(Q.indexOf("macintosh")!=-1){return"mac";}else{return false;}}}(),browser:function(){var Q=navigator.userAgent.toLowerCase();if(Q.indexOf("opera")!=-1){return"opera";}else{if(Q.indexOf("msie 7")!=-1){return"ie7";}else{if(Q.indexOf("msie")!=-1){return"ie";}else{if(Q.indexOf("safari")!=-1){return"safari";}else{if(Q.indexOf("gecko")!=-1){return"gecko";}else{return false;}}}}}}(),isSecure:function(){if(window.location.href.toLowerCase().indexOf("https")===0){return true;}else{return false;}}(),initDefaultConfig:function(){this.cfg.addProperty(J.VISIBLE.key,{handler:this.configVisible,value:J.VISIBLE.value,validator:J.VISIBLE.validator});this.cfg.addProperty(J.EFFECT.key,{suppressEvent:J.EFFECT.suppressEvent,supercedes:J.EFFECT.supercedes});this.cfg.addProperty(J.MONITOR_RESIZE.key,{handler:this.configMonitorResize,value:J.MONITOR_RESIZE.value});this.cfg.addProperty(J.APPEND_TO_DOCUMENT_BODY.key,{value:J.APPEND_TO_DOCUMENT_BODY.value});},init:function(V,U){var S,W;this.initEvents();this.beforeInitEvent.fire(G);this.cfg=new D(this);if(this.isSecure){this.imageRoot=G.IMG_ROOT_SSL;}if(typeof V=="string"){S=V;V=document.getElementById(V);if(!V){V=(L()).cloneNode(false);V.id=S;}}this.id=F.generateId(V);this.element=V;W=this.element.firstChild;if(W){var R=false,Q=false,T=false;do{if(1==W.nodeType){if(!R&&F.hasClass(W,G.CSS_HEADER)){this.header=W;R=true;}else{if(!Q&&F.hasClass(W,G.CSS_BODY)){this.body=W;Q=true;}else{if(!T&&F.hasClass(W,G.CSS_FOOTER)){this.footer=W;T=true;}}}}}while((W=W.nextSibling));}this.initDefaultConfig();F.addClass(this.element,G.CSS_MODULE);if(U){this.cfg.applyConfig(U,true);}if(!D.alreadySubscribed(this.renderEvent,this.cfg.fireQueue,this.cfg)){this.renderEvent.subscribe(this.cfg.fireQueue,this.cfg,true);}this.initEvent.fire(G);},initResizeMonitor:function(){var R=(I.gecko&&this.platform=="windows");if(R){var Q=this;setTimeout(function(){Q._initResizeMonitor();},0);}else{this._initResizeMonitor();}},_initResizeMonitor:function(){var Q,S,U;function W(){G.textResizeEvent.fire();}if(!I.opera){S=F.get("_yuiResizeMonitor");var V=this._supportsCWResize();if(!S){S=document.createElement("iframe");if(this.isSecure&&G.RESIZE_MONITOR_SECURE_URL&&I.ie){S.src=G.RESIZE_MONITOR_SECURE_URL;}if(!V){U=["<html><head><script ",'type="text/javascript">',"window.onresize=function(){window.parent.","YAHOO.widget.Module.textResizeEvent.","fire();};<","/script></head>","<body></body></html>"].join("");S.src="data:text/html;charset=utf-8,"+encodeURIComponent(U);}S.id="_yuiResizeMonitor";S.title="Text Resize Monitor";S.style.position="absolute";S.style.visibility="hidden";var R=document.body,T=R.firstChild;if(T){R.insertBefore(S,T);}else{R.appendChild(S);}S.style.backgroundColor="transparent";S.style.borderWidth="0";S.style.width="2em";S.style.height="2em";S.style.left="0";S.style.top=(-1*(S.offsetHeight+G.RESIZE_MONITOR_BUFFER))+"px";S.style.visibility="visible";if(I.webkit){Q=S.contentWindow.document;Q.open();Q.close();}}if(S&&S.contentWindow){G.textResizeEvent.subscribe(this.onDomResize,this,true);if(!G.textResizeInitialized){if(V){if(!N.on(S.contentWindow,"resize",W)){N.on(S,"resize",W);}}G.textResizeInitialized=true;}this.resizeMonitor=S;}}},_supportsCWResize:function(){var Q=true;if(I.gecko&&I.gecko<=1.8){Q=false;}return Q;},onDomResize:function(S,R){var Q=-1*(this.resizeMonitor.offsetHeight+G.RESIZE_MONITOR_BUFFER);this.resizeMonitor.style.top=Q+"px";this.resizeMonitor.style.left="0";},setHeader:function(R){var Q=this.header||(this.header=K());if(R.nodeName){Q.innerHTML="";Q.appendChild(R);}else{Q.innerHTML=R;}if(this._rendered){this._renderHeader();}this.changeHeaderEvent.fire(R);this.changeContentEvent.fire();},appendToHeader:function(R){var Q=this.header||(this.header=K());Q.appendChild(R);this.changeHeaderEvent.fire(R);this.changeContentEvent.fire();},setBody:function(R){var Q=this.body||(this.body=B());if(R.nodeName){Q.innerHTML="";Q.appendChild(R);}else{Q.innerHTML=R;}if(this._rendered){this._renderBody();}this.changeBodyEvent.fire(R);this.changeContentEvent.fire();},appendToBody:function(R){var Q=this.body||(this.body=B());Q.appendChild(R);this.changeBodyEvent.fire(R);this.changeContentEvent.fire();},setFooter:function(R){var Q=this.footer||(this.footer=C());if(R.nodeName){Q.innerHTML="";Q.appendChild(R);}else{Q.innerHTML=R;}if(this._rendered){this._renderFooter();}this.changeFooterEvent.fire(R);this.changeContentEvent.fire();},appendToFooter:function(R){var Q=this.footer||(this.footer=C());Q.appendChild(R);this.changeFooterEvent.fire(R);this.changeContentEvent.fire();},render:function(S,Q){var T=this;function R(U){if(typeof U=="string"){U=document.getElementById(U);}if(U){T._addToParent(U,T.element);T.appendEvent.fire();}}this.beforeRenderEvent.fire();
9
if(!Q){Q=this.element;}if(S){R(S);}else{if(!F.inDocument(this.element)){return false;}}this._renderHeader(Q);this._renderBody(Q);this._renderFooter(Q);this._rendered=true;this.renderEvent.fire();return true;},_renderHeader:function(Q){Q=Q||this.element;if(this.header&&!F.inDocument(this.header)){var R=Q.firstChild;if(R){Q.insertBefore(this.header,R);}else{Q.appendChild(this.header);}}},_renderBody:function(Q){Q=Q||this.element;if(this.body&&!F.inDocument(this.body)){if(this.footer&&F.isAncestor(Q,this.footer)){Q.insertBefore(this.body,this.footer);}else{Q.appendChild(this.body);}}},_renderFooter:function(Q){Q=Q||this.element;if(this.footer&&!F.inDocument(this.footer)){Q.appendChild(this.footer);}},destroy:function(){var Q;if(this.element){N.purgeElement(this.element,true);Q=this.element.parentNode;}if(Q){Q.removeChild(this.element);}this.element=null;this.header=null;this.body=null;this.footer=null;G.textResizeEvent.unsubscribe(this.onDomResize,this);this.cfg.destroy();this.cfg=null;this.destroyEvent.fire();},show:function(){this.cfg.setProperty("visible",true);},hide:function(){this.cfg.setProperty("visible",false);},configVisible:function(R,Q,S){var T=Q[0];if(T){this.beforeShowEvent.fire();F.setStyle(this.element,"display","block");this.showEvent.fire();}else{this.beforeHideEvent.fire();F.setStyle(this.element,"display","none");this.hideEvent.fire();}},configMonitorResize:function(S,R,T){var Q=R[0];if(Q){this.initResizeMonitor();}else{G.textResizeEvent.unsubscribe(this.onDomResize,this,true);this.resizeMonitor=null;}},_addToParent:function(Q,R){if(!this.cfg.getProperty("appendtodocumentbody")&&Q===document.body&&Q.firstChild){Q.insertBefore(R,Q.firstChild);}else{Q.appendChild(R);}},toString:function(){return"Module "+this.id;}};YAHOO.lang.augmentProto(G,YAHOO.util.EventProvider);}());(function(){YAHOO.widget.Overlay=function(P,O){YAHOO.widget.Overlay.superclass.constructor.call(this,P,O);};var I=YAHOO.lang,M=YAHOO.util.CustomEvent,G=YAHOO.widget.Module,N=YAHOO.util.Event,F=YAHOO.util.Dom,D=YAHOO.util.Config,K=YAHOO.env.ua,B=YAHOO.widget.Overlay,H="subscribe",E="unsubscribe",C="contained",J,A={"BEFORE_MOVE":"beforeMove","MOVE":"move"},L={"X":{key:"x",validator:I.isNumber,suppressEvent:true,supercedes:["iframe"]},"Y":{key:"y",validator:I.isNumber,suppressEvent:true,supercedes:["iframe"]},"XY":{key:"xy",suppressEvent:true,supercedes:["iframe"]},"CONTEXT":{key:"context",suppressEvent:true,supercedes:["iframe"]},"FIXED_CENTER":{key:"fixedcenter",value:false,supercedes:["iframe","visible"]},"WIDTH":{key:"width",suppressEvent:true,supercedes:["context","fixedcenter","iframe"]},"HEIGHT":{key:"height",suppressEvent:true,supercedes:["context","fixedcenter","iframe"]},"AUTO_FILL_HEIGHT":{key:"autofillheight",supercedes:["height"],value:"body"},"ZINDEX":{key:"zindex",value:null},"CONSTRAIN_TO_VIEWPORT":{key:"constraintoviewport",value:false,validator:I.isBoolean,supercedes:["iframe","x","y","xy"]},"IFRAME":{key:"iframe",value:(K.ie==6?true:false),validator:I.isBoolean,supercedes:["zindex"]},"PREVENT_CONTEXT_OVERLAP":{key:"preventcontextoverlap",value:false,validator:I.isBoolean,supercedes:["constraintoviewport"]}};B.IFRAME_SRC="javascript:false;";B.IFRAME_OFFSET=3;B.VIEWPORT_OFFSET=10;B.TOP_LEFT="tl";B.TOP_RIGHT="tr";B.BOTTOM_LEFT="bl";B.BOTTOM_RIGHT="br";B.PREVENT_OVERLAP_X={"tltr":true,"blbr":true,"brbl":true,"trtl":true};B.PREVENT_OVERLAP_Y={"trbr":true,"tlbl":true,"bltl":true,"brtr":true};B.CSS_OVERLAY="yui-overlay";B.CSS_HIDDEN="yui-overlay-hidden";B.CSS_IFRAME="yui-overlay-iframe";B.STD_MOD_RE=/^\s*?(body|footer|header)\s*?$/i;B.windowScrollEvent=new M("windowScroll");B.windowResizeEvent=new M("windowResize");B.windowScrollHandler=function(P){var O=N.getTarget(P);if(!O||O===window||O===window.document){if(K.ie){if(!window.scrollEnd){window.scrollEnd=-1;}clearTimeout(window.scrollEnd);window.scrollEnd=setTimeout(function(){B.windowScrollEvent.fire();},1);}else{B.windowScrollEvent.fire();}}};B.windowResizeHandler=function(O){if(K.ie){if(!window.resizeEnd){window.resizeEnd=-1;}clearTimeout(window.resizeEnd);window.resizeEnd=setTimeout(function(){B.windowResizeEvent.fire();},100);}else{B.windowResizeEvent.fire();}};B._initialized=null;if(B._initialized===null){N.on(window,"scroll",B.windowScrollHandler);N.on(window,"resize",B.windowResizeHandler);B._initialized=true;}B._TRIGGER_MAP={"windowScroll":B.windowScrollEvent,"windowResize":B.windowResizeEvent,"textResize":G.textResizeEvent};YAHOO.extend(B,G,{CONTEXT_TRIGGERS:[],init:function(P,O){B.superclass.init.call(this,P);this.beforeInitEvent.fire(B);F.addClass(this.element,B.CSS_OVERLAY);if(O){this.cfg.applyConfig(O,true);}if(this.platform=="mac"&&K.gecko){if(!D.alreadySubscribed(this.showEvent,this.showMacGeckoScrollbars,this)){this.showEvent.subscribe(this.showMacGeckoScrollbars,this,true);}if(!D.alreadySubscribed(this.hideEvent,this.hideMacGeckoScrollbars,this)){this.hideEvent.subscribe(this.hideMacGeckoScrollbars,this,true);}}this.initEvent.fire(B);},initEvents:function(){B.superclass.initEvents.call(this);var O=M.LIST;this.beforeMoveEvent=this.createEvent(A.BEFORE_MOVE);this.beforeMoveEvent.signature=O;this.moveEvent=this.createEvent(A.MOVE);this.moveEvent.signature=O;},initDefaultConfig:function(){B.superclass.initDefaultConfig.call(this);var O=this.cfg;O.addProperty(L.X.key,{handler:this.configX,validator:L.X.validator,suppressEvent:L.X.suppressEvent,supercedes:L.X.supercedes});O.addProperty(L.Y.key,{handler:this.configY,validator:L.Y.validator,suppressEvent:L.Y.suppressEvent,supercedes:L.Y.supercedes});O.addProperty(L.XY.key,{handler:this.configXY,suppressEvent:L.XY.suppressEvent,supercedes:L.XY.supercedes});O.addProperty(L.CONTEXT.key,{handler:this.configContext,suppressEvent:L.CONTEXT.suppressEvent,supercedes:L.CONTEXT.supercedes});O.addProperty(L.FIXED_CENTER.key,{handler:this.configFixedCenter,value:L.FIXED_CENTER.value,validator:L.FIXED_CENTER.validator,supercedes:L.FIXED_CENTER.supercedes});O.addProperty(L.WIDTH.key,{handler:this.configWidth,suppressEvent:L.WIDTH.suppressEvent,supercedes:L.WIDTH.supercedes});
10
O.addProperty(L.HEIGHT.key,{handler:this.configHeight,suppressEvent:L.HEIGHT.suppressEvent,supercedes:L.HEIGHT.supercedes});O.addProperty(L.AUTO_FILL_HEIGHT.key,{handler:this.configAutoFillHeight,value:L.AUTO_FILL_HEIGHT.value,validator:this._validateAutoFill,supercedes:L.AUTO_FILL_HEIGHT.supercedes});O.addProperty(L.ZINDEX.key,{handler:this.configzIndex,value:L.ZINDEX.value});O.addProperty(L.CONSTRAIN_TO_VIEWPORT.key,{handler:this.configConstrainToViewport,value:L.CONSTRAIN_TO_VIEWPORT.value,validator:L.CONSTRAIN_TO_VIEWPORT.validator,supercedes:L.CONSTRAIN_TO_VIEWPORT.supercedes});O.addProperty(L.IFRAME.key,{handler:this.configIframe,value:L.IFRAME.value,validator:L.IFRAME.validator,supercedes:L.IFRAME.supercedes});O.addProperty(L.PREVENT_CONTEXT_OVERLAP.key,{value:L.PREVENT_CONTEXT_OVERLAP.value,validator:L.PREVENT_CONTEXT_OVERLAP.validator,supercedes:L.PREVENT_CONTEXT_OVERLAP.supercedes});},moveTo:function(O,P){this.cfg.setProperty("xy",[O,P]);},hideMacGeckoScrollbars:function(){F.replaceClass(this.element,"show-scrollbars","hide-scrollbars");},showMacGeckoScrollbars:function(){F.replaceClass(this.element,"hide-scrollbars","show-scrollbars");},_setDomVisibility:function(O){F.setStyle(this.element,"visibility",(O)?"visible":"hidden");var P=B.CSS_HIDDEN;if(O){F.removeClass(this.element,P);}else{F.addClass(this.element,P);}},configVisible:function(R,O,X){var Q=O[0],S=F.getStyle(this.element,"visibility"),Y=this.cfg.getProperty("effect"),V=[],U=(this.platform=="mac"&&K.gecko),g=D.alreadySubscribed,W,P,f,c,b,a,d,Z,T;if(S=="inherit"){f=this.element.parentNode;while(f.nodeType!=9&&f.nodeType!=11){S=F.getStyle(f,"visibility");if(S!="inherit"){break;}f=f.parentNode;}if(S=="inherit"){S="visible";}}if(Y){if(Y instanceof Array){Z=Y.length;for(c=0;c<Z;c++){W=Y[c];V[V.length]=W.effect(this,W.duration);}}else{V[V.length]=Y.effect(this,Y.duration);}}if(Q){if(U){this.showMacGeckoScrollbars();}if(Y){if(Q){if(S!="visible"||S===""){this.beforeShowEvent.fire();T=V.length;for(b=0;b<T;b++){P=V[b];if(b===0&&!g(P.animateInCompleteEvent,this.showEvent.fire,this.showEvent)){P.animateInCompleteEvent.subscribe(this.showEvent.fire,this.showEvent,true);}P.animateIn();}}}}else{if(S!="visible"||S===""){this.beforeShowEvent.fire();this._setDomVisibility(true);this.cfg.refireEvent("iframe");this.showEvent.fire();}else{this._setDomVisibility(true);}}}else{if(U){this.hideMacGeckoScrollbars();}if(Y){if(S=="visible"){this.beforeHideEvent.fire();T=V.length;for(a=0;a<T;a++){d=V[a];if(a===0&&!g(d.animateOutCompleteEvent,this.hideEvent.fire,this.hideEvent)){d.animateOutCompleteEvent.subscribe(this.hideEvent.fire,this.hideEvent,true);}d.animateOut();}}else{if(S===""){this._setDomVisibility(false);}}}else{if(S=="visible"||S===""){this.beforeHideEvent.fire();this._setDomVisibility(false);this.hideEvent.fire();}else{this._setDomVisibility(false);}}}},doCenterOnDOMEvent:function(){var O=this.cfg,P=O.getProperty("fixedcenter");if(O.getProperty("visible")){if(P&&(P!==C||this.fitsInViewport())){this.center();}}},fitsInViewport:function(){var S=B.VIEWPORT_OFFSET,Q=this.element,T=Q.offsetWidth,R=Q.offsetHeight,O=F.getViewportWidth(),P=F.getViewportHeight();return((T+S<O)&&(R+S<P));},configFixedCenter:function(S,Q,T){var U=Q[0],P=D.alreadySubscribed,R=B.windowResizeEvent,O=B.windowScrollEvent;if(U){this.center();if(!P(this.beforeShowEvent,this.center)){this.beforeShowEvent.subscribe(this.center);}if(!P(R,this.doCenterOnDOMEvent,this)){R.subscribe(this.doCenterOnDOMEvent,this,true);}if(!P(O,this.doCenterOnDOMEvent,this)){O.subscribe(this.doCenterOnDOMEvent,this,true);}}else{this.beforeShowEvent.unsubscribe(this.center);R.unsubscribe(this.doCenterOnDOMEvent,this);O.unsubscribe(this.doCenterOnDOMEvent,this);}},configHeight:function(R,P,S){var O=P[0],Q=this.element;F.setStyle(Q,"height",O);this.cfg.refireEvent("iframe");},configAutoFillHeight:function(T,S,P){var V=S[0],Q=this.cfg,U="autofillheight",W="height",R=Q.getProperty(U),O=this._autoFillOnHeightChange;Q.unsubscribeFromConfigEvent(W,O);G.textResizeEvent.unsubscribe(O);this.changeContentEvent.unsubscribe(O);if(R&&V!==R&&this[R]){F.setStyle(this[R],W,"");}if(V){V=I.trim(V.toLowerCase());Q.subscribeToConfigEvent(W,O,this[V],this);G.textResizeEvent.subscribe(O,this[V],this);this.changeContentEvent.subscribe(O,this[V],this);Q.setProperty(U,V,true);}},configWidth:function(R,O,S){var Q=O[0],P=this.element;F.setStyle(P,"width",Q);this.cfg.refireEvent("iframe");},configzIndex:function(Q,O,R){var S=O[0],P=this.element;if(!S){S=F.getStyle(P,"zIndex");if(!S||isNaN(S)){S=0;}}if(this.iframe||this.cfg.getProperty("iframe")===true){if(S<=0){S=1;}}F.setStyle(P,"zIndex",S);this.cfg.setProperty("zIndex",S,true);if(this.iframe){this.stackIframe();}},configXY:function(Q,P,R){var T=P[0],O=T[0],S=T[1];this.cfg.setProperty("x",O);this.cfg.setProperty("y",S);this.beforeMoveEvent.fire([O,S]);O=this.cfg.getProperty("x");S=this.cfg.getProperty("y");this.cfg.refireEvent("iframe");this.moveEvent.fire([O,S]);},configX:function(Q,P,R){var O=P[0],S=this.cfg.getProperty("y");this.cfg.setProperty("x",O,true);this.cfg.setProperty("y",S,true);this.beforeMoveEvent.fire([O,S]);O=this.cfg.getProperty("x");S=this.cfg.getProperty("y");F.setX(this.element,O,true);this.cfg.setProperty("xy",[O,S],true);this.cfg.refireEvent("iframe");this.moveEvent.fire([O,S]);},configY:function(Q,P,R){var O=this.cfg.getProperty("x"),S=P[0];this.cfg.setProperty("x",O,true);this.cfg.setProperty("y",S,true);this.beforeMoveEvent.fire([O,S]);O=this.cfg.getProperty("x");S=this.cfg.getProperty("y");F.setY(this.element,S,true);this.cfg.setProperty("xy",[O,S],true);this.cfg.refireEvent("iframe");this.moveEvent.fire([O,S]);},showIframe:function(){var P=this.iframe,O;if(P){O=this.element.parentNode;if(O!=P.parentNode){this._addToParent(O,P);}P.style.display="block";}},hideIframe:function(){if(this.iframe){this.iframe.style.display="none";}},syncIframe:function(){var O=this.iframe,Q=this.element,S=B.IFRAME_OFFSET,P=(S*2),R;if(O){O.style.width=(Q.offsetWidth+P+"px");
11
O.style.height=(Q.offsetHeight+P+"px");R=this.cfg.getProperty("xy");if(!I.isArray(R)||(isNaN(R[0])||isNaN(R[1]))){this.syncPosition();R=this.cfg.getProperty("xy");}F.setXY(O,[(R[0]-S),(R[1]-S)]);}},stackIframe:function(){if(this.iframe){var O=F.getStyle(this.element,"zIndex");if(!YAHOO.lang.isUndefined(O)&&!isNaN(O)){F.setStyle(this.iframe,"zIndex",(O-1));}}},configIframe:function(R,Q,S){var O=Q[0];function T(){var V=this.iframe,W=this.element,X;if(!V){if(!J){J=document.createElement("iframe");if(this.isSecure){J.src=B.IFRAME_SRC;}if(K.ie){J.style.filter="alpha(opacity=0)";J.frameBorder=0;}else{J.style.opacity="0";}J.style.position="absolute";J.style.border="none";J.style.margin="0";J.style.padding="0";J.style.display="none";J.tabIndex=-1;J.className=B.CSS_IFRAME;}V=J.cloneNode(false);V.id=this.id+"_f";X=W.parentNode;var U=X||document.body;this._addToParent(U,V);this.iframe=V;}this.showIframe();this.syncIframe();this.stackIframe();if(!this._hasIframeEventListeners){this.showEvent.subscribe(this.showIframe);this.hideEvent.subscribe(this.hideIframe);this.changeContentEvent.subscribe(this.syncIframe);this._hasIframeEventListeners=true;}}function P(){T.call(this);this.beforeShowEvent.unsubscribe(P);this._iframeDeferred=false;}if(O){if(this.cfg.getProperty("visible")){T.call(this);}else{if(!this._iframeDeferred){this.beforeShowEvent.subscribe(P);this._iframeDeferred=true;}}}else{this.hideIframe();if(this._hasIframeEventListeners){this.showEvent.unsubscribe(this.showIframe);this.hideEvent.unsubscribe(this.hideIframe);this.changeContentEvent.unsubscribe(this.syncIframe);this._hasIframeEventListeners=false;}}},_primeXYFromDOM:function(){if(YAHOO.lang.isUndefined(this.cfg.getProperty("xy"))){this.syncPosition();this.cfg.refireEvent("xy");this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);}},configConstrainToViewport:function(P,O,Q){var R=O[0];if(R){if(!D.alreadySubscribed(this.beforeMoveEvent,this.enforceConstraints,this)){this.beforeMoveEvent.subscribe(this.enforceConstraints,this,true);}if(!D.alreadySubscribed(this.beforeShowEvent,this._primeXYFromDOM)){this.beforeShowEvent.subscribe(this._primeXYFromDOM);}}else{this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);this.beforeMoveEvent.unsubscribe(this.enforceConstraints,this);}},configContext:function(U,T,Q){var X=T[0],R,O,V,S,P,W=this.CONTEXT_TRIGGERS;if(X){R=X[0];O=X[1];V=X[2];S=X[3];P=X[4];if(W&&W.length>0){S=(S||[]).concat(W);}if(R){if(typeof R=="string"){this.cfg.setProperty("context",[document.getElementById(R),O,V,S,P],true);}if(O&&V){this.align(O,V,P);}if(this._contextTriggers){this._processTriggers(this._contextTriggers,E,this._alignOnTrigger);}if(S){this._processTriggers(S,H,this._alignOnTrigger);this._contextTriggers=S;}}}},_alignOnTrigger:function(P,O){this.align();},_findTriggerCE:function(O){var P=null;if(O instanceof M){P=O;}else{if(B._TRIGGER_MAP[O]){P=B._TRIGGER_MAP[O];}}return P;},_processTriggers:function(S,U,R){var Q,T;for(var P=0,O=S.length;P<O;++P){Q=S[P];T=this._findTriggerCE(Q);if(T){T[U](R,this,true);}else{this[U](Q,R);}}},align:function(P,W,S){var V=this.cfg.getProperty("context"),T=this,O,Q,U;function R(Z,a){var Y=null,X=null;switch(P){case B.TOP_LEFT:Y=a;X=Z;break;case B.TOP_RIGHT:Y=a-Q.offsetWidth;X=Z;break;case B.BOTTOM_LEFT:Y=a;X=Z-Q.offsetHeight;break;case B.BOTTOM_RIGHT:Y=a-Q.offsetWidth;X=Z-Q.offsetHeight;break;}if(Y!==null&&X!==null){if(S){Y+=S[0];X+=S[1];}T.moveTo(Y,X);}}if(V){O=V[0];Q=this.element;T=this;if(!P){P=V[1];}if(!W){W=V[2];}if(!S&&V[4]){S=V[4];}if(Q&&O){U=F.getRegion(O);switch(W){case B.TOP_LEFT:R(U.top,U.left);break;case B.TOP_RIGHT:R(U.top,U.right);break;case B.BOTTOM_LEFT:R(U.bottom,U.left);break;case B.BOTTOM_RIGHT:R(U.bottom,U.right);break;}}}},enforceConstraints:function(P,O,Q){var S=O[0];var R=this.getConstrainedXY(S[0],S[1]);this.cfg.setProperty("x",R[0],true);this.cfg.setProperty("y",R[1],true);this.cfg.setProperty("xy",R,true);},_getConstrainedPos:function(X,P){var T=this.element,R=B.VIEWPORT_OFFSET,Z=(X=="x"),Y=(Z)?T.offsetWidth:T.offsetHeight,S=(Z)?F.getViewportWidth():F.getViewportHeight(),c=(Z)?F.getDocumentScrollLeft():F.getDocumentScrollTop(),b=(Z)?B.PREVENT_OVERLAP_X:B.PREVENT_OVERLAP_Y,O=this.cfg.getProperty("context"),U=(Y+R<S),W=this.cfg.getProperty("preventcontextoverlap")&&O&&b[(O[1]+O[2])],V=c+R,a=c+S-Y-R,Q=P;if(P<V||P>a){if(W){Q=this._preventOverlap(X,O[0],Y,S,c);}else{if(U){if(P<V){Q=V;}else{if(P>a){Q=a;}}}else{Q=V;}}}return Q;},_preventOverlap:function(X,W,Y,U,b){var Z=(X=="x"),T=B.VIEWPORT_OFFSET,S=this,Q=((Z)?F.getX(W):F.getY(W))-b,O=(Z)?W.offsetWidth:W.offsetHeight,P=Q-T,R=(U-(Q+O))-T,c=false,V=function(){var d;if((S.cfg.getProperty(X)-b)>Q){d=(Q-Y);}else{d=(Q+O);}S.cfg.setProperty(X,(d+b),true);return d;},a=function(){var e=((S.cfg.getProperty(X)-b)>Q)?R:P,d;if(Y>e){if(c){V();}else{V();c=true;d=a();}}return d;};a();return this.cfg.getProperty(X);},getConstrainedX:function(O){return this._getConstrainedPos("x",O);},getConstrainedY:function(O){return this._getConstrainedPos("y",O);},getConstrainedXY:function(O,P){return[this.getConstrainedX(O),this.getConstrainedY(P)];},center:function(){var R=B.VIEWPORT_OFFSET,S=this.element.offsetWidth,Q=this.element.offsetHeight,P=F.getViewportWidth(),T=F.getViewportHeight(),O,U;if(S<P){O=(P/2)-(S/2)+F.getDocumentScrollLeft();}else{O=R+F.getDocumentScrollLeft();}if(Q<T){U=(T/2)-(Q/2)+F.getDocumentScrollTop();}else{U=R+F.getDocumentScrollTop();}this.cfg.setProperty("xy",[parseInt(O,10),parseInt(U,10)]);this.cfg.refireEvent("iframe");if(K.webkit){this.forceContainerRedraw();}},syncPosition:function(){var O=F.getXY(this.element);this.cfg.setProperty("x",O[0],true);this.cfg.setProperty("y",O[1],true);this.cfg.setProperty("xy",O,true);},onDomResize:function(Q,P){var O=this;B.superclass.onDomResize.call(this,Q,P);setTimeout(function(){O.syncPosition();O.cfg.refireEvent("iframe");O.cfg.refireEvent("context");},0);},_getComputedHeight:(function(){if(document.defaultView&&document.defaultView.getComputedStyle){return function(P){var O=null;
12
if(P.ownerDocument&&P.ownerDocument.defaultView){var Q=P.ownerDocument.defaultView.getComputedStyle(P,"");if(Q){O=parseInt(Q.height,10);}}return(I.isNumber(O))?O:null;};}else{return function(P){var O=null;if(P.style.pixelHeight){O=P.style.pixelHeight;}return(I.isNumber(O))?O:null;};}})(),_validateAutoFillHeight:function(O){return(!O)||(I.isString(O)&&B.STD_MOD_RE.test(O));},_autoFillOnHeightChange:function(R,P,Q){var O=this.cfg.getProperty("height");if((O&&O!=="auto")||(O===0)){this.fillHeight(Q);}},_getPreciseHeight:function(P){var O=P.offsetHeight;if(P.getBoundingClientRect){var Q=P.getBoundingClientRect();O=Q.bottom-Q.top;}return O;},fillHeight:function(R){if(R){var P=this.innerElement||this.element,O=[this.header,this.body,this.footer],V,W=0,X=0,T=0,Q=false;for(var U=0,S=O.length;U<S;U++){V=O[U];if(V){if(R!==V){X+=this._getPreciseHeight(V);}else{Q=true;}}}if(Q){if(K.ie||K.opera){F.setStyle(R,"height",0+"px");}W=this._getComputedHeight(P);if(W===null){F.addClass(P,"yui-override-padding");W=P.clientHeight;F.removeClass(P,"yui-override-padding");}T=Math.max(W-X,0);F.setStyle(R,"height",T+"px");if(R.offsetHeight!=T){T=Math.max(T-(R.offsetHeight-T),0);}F.setStyle(R,"height",T+"px");}}},bringToTop:function(){var S=[],R=this.element;function V(Z,Y){var b=F.getStyle(Z,"zIndex"),a=F.getStyle(Y,"zIndex"),X=(!b||isNaN(b))?0:parseInt(b,10),W=(!a||isNaN(a))?0:parseInt(a,10);if(X>W){return -1;}else{if(X<W){return 1;}else{return 0;}}}function Q(Y){var X=F.hasClass(Y,B.CSS_OVERLAY),W=YAHOO.widget.Panel;if(X&&!F.isAncestor(R,Y)){if(W&&F.hasClass(Y,W.CSS_PANEL)){S[S.length]=Y.parentNode;}else{S[S.length]=Y;}}}F.getElementsBy(Q,"DIV",document.body);S.sort(V);var O=S[0],U;if(O){U=F.getStyle(O,"zIndex");if(!isNaN(U)){var T=false;if(O!=R){T=true;}else{if(S.length>1){var P=F.getStyle(S[1],"zIndex");if(!isNaN(P)&&(U==P)){T=true;}}}if(T){this.cfg.setProperty("zindex",(parseInt(U,10)+2));}}}},destroy:function(){if(this.iframe){this.iframe.parentNode.removeChild(this.iframe);}this.iframe=null;B.windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent,this);B.windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent,this);G.textResizeEvent.unsubscribe(this._autoFillOnHeightChange);if(this._contextTriggers){this._processTriggers(this._contextTriggers,E,this._alignOnTrigger);}B.superclass.destroy.call(this);},forceContainerRedraw:function(){var O=this;F.addClass(O.element,"yui-force-redraw");setTimeout(function(){F.removeClass(O.element,"yui-force-redraw");},0);},toString:function(){return"Overlay "+this.id;}});}());(function(){YAHOO.widget.OverlayManager=function(G){this.init(G);};var D=YAHOO.widget.Overlay,C=YAHOO.util.Event,E=YAHOO.util.Dom,B=YAHOO.util.Config,F=YAHOO.util.CustomEvent,A=YAHOO.widget.OverlayManager;A.CSS_FOCUSED="focused";A.prototype={constructor:A,overlays:null,initDefaultConfig:function(){this.cfg.addProperty("overlays",{suppressEvent:true});this.cfg.addProperty("focusevent",{value:"mousedown"});},init:function(I){this.cfg=new B(this);this.initDefaultConfig();if(I){this.cfg.applyConfig(I,true);}this.cfg.fireQueue();var H=null;this.getActive=function(){return H;};this.focus=function(J){var K=this.find(J);if(K){K.focus();}};this.remove=function(K){var M=this.find(K),J;if(M){if(H==M){H=null;}var L=(M.element===null&&M.cfg===null)?true:false;if(!L){J=E.getStyle(M.element,"zIndex");M.cfg.setProperty("zIndex",-1000,true);}this.overlays.sort(this.compareZIndexDesc);this.overlays=this.overlays.slice(0,(this.overlays.length-1));M.hideEvent.unsubscribe(M.blur);M.destroyEvent.unsubscribe(this._onOverlayDestroy,M);M.focusEvent.unsubscribe(this._onOverlayFocusHandler,M);M.blurEvent.unsubscribe(this._onOverlayBlurHandler,M);if(!L){C.removeListener(M.element,this.cfg.getProperty("focusevent"),this._onOverlayElementFocus);M.cfg.setProperty("zIndex",J,true);M.cfg.setProperty("manager",null);}if(M.focusEvent._managed){M.focusEvent=null;}if(M.blurEvent._managed){M.blurEvent=null;}if(M.focus._managed){M.focus=null;}if(M.blur._managed){M.blur=null;}}};this.blurAll=function(){var K=this.overlays.length,J;if(K>0){J=K-1;do{this.overlays[J].blur();}while(J--);}};this._manageBlur=function(J){var K=false;if(H==J){E.removeClass(H.element,A.CSS_FOCUSED);H=null;K=true;}return K;};this._manageFocus=function(J){var K=false;if(H!=J){if(H){H.blur();}H=J;this.bringToTop(H);E.addClass(H.element,A.CSS_FOCUSED);K=true;}return K;};var G=this.cfg.getProperty("overlays");if(!this.overlays){this.overlays=[];}if(G){this.register(G);this.overlays.sort(this.compareZIndexDesc);}},_onOverlayElementFocus:function(I){var G=C.getTarget(I),H=this.close;if(H&&(G==H||E.isAncestor(H,G))){this.blur();}else{this.focus();}},_onOverlayDestroy:function(H,G,I){this.remove(I);},_onOverlayFocusHandler:function(H,G,I){this._manageFocus(I);},_onOverlayBlurHandler:function(H,G,I){this._manageBlur(I);},_bindFocus:function(G){var H=this;if(!G.focusEvent){G.focusEvent=G.createEvent("focus");G.focusEvent.signature=F.LIST;G.focusEvent._managed=true;}else{G.focusEvent.subscribe(H._onOverlayFocusHandler,G,H);}if(!G.focus){C.on(G.element,H.cfg.getProperty("focusevent"),H._onOverlayElementFocus,null,G);G.focus=function(){if(H._manageFocus(this)){if(this.cfg.getProperty("visible")&&this.focusFirst){this.focusFirst();}this.focusEvent.fire();}};G.focus._managed=true;}},_bindBlur:function(G){var H=this;if(!G.blurEvent){G.blurEvent=G.createEvent("blur");G.blurEvent.signature=F.LIST;G.focusEvent._managed=true;}else{G.blurEvent.subscribe(H._onOverlayBlurHandler,G,H);}if(!G.blur){G.blur=function(){if(H._manageBlur(this)){this.blurEvent.fire();}};G.blur._managed=true;}G.hideEvent.subscribe(G.blur);},_bindDestroy:function(G){var H=this;G.destroyEvent.subscribe(H._onOverlayDestroy,G,H);},_syncZIndex:function(G){var H=E.getStyle(G.element,"zIndex");if(!isNaN(H)){G.cfg.setProperty("zIndex",parseInt(H,10));}else{G.cfg.setProperty("zIndex",0);}},register:function(G){var J=false,H,I;if(G instanceof D){G.cfg.addProperty("manager",{value:this});this._bindFocus(G);this._bindBlur(G);this._bindDestroy(G);
13
this._syncZIndex(G);this.overlays.push(G);this.bringToTop(G);J=true;}else{if(G instanceof Array){for(H=0,I=G.length;H<I;H++){J=this.register(G[H])||J;}}}return J;},bringToTop:function(M){var I=this.find(M),L,G,J;if(I){J=this.overlays;J.sort(this.compareZIndexDesc);G=J[0];if(G){L=E.getStyle(G.element,"zIndex");if(!isNaN(L)){var K=false;if(G!==I){K=true;}else{if(J.length>1){var H=E.getStyle(J[1].element,"zIndex");if(!isNaN(H)&&(L==H)){K=true;}}}if(K){I.cfg.setProperty("zindex",(parseInt(L,10)+2));}}J.sort(this.compareZIndexDesc);}}},find:function(G){var K=G instanceof D,I=this.overlays,M=I.length,J=null,L,H;if(K||typeof G=="string"){for(H=M-1;H>=0;H--){L=I[H];if((K&&(L===G))||(L.id==G)){J=L;break;}}}return J;},compareZIndexDesc:function(J,I){var H=(J.cfg)?J.cfg.getProperty("zIndex"):null,G=(I.cfg)?I.cfg.getProperty("zIndex"):null;if(H===null&&G===null){return 0;}else{if(H===null){return 1;}else{if(G===null){return -1;}else{if(H>G){return -1;}else{if(H<G){return 1;}else{return 0;}}}}}},showAll:function(){var H=this.overlays,I=H.length,G;for(G=I-1;G>=0;G--){H[G].show();}},hideAll:function(){var H=this.overlays,I=H.length,G;for(G=I-1;G>=0;G--){H[G].hide();}},toString:function(){return"OverlayManager";}};}());(function(){YAHOO.widget.Tooltip=function(P,O){YAHOO.widget.Tooltip.superclass.constructor.call(this,P,O);};var E=YAHOO.lang,N=YAHOO.util.Event,M=YAHOO.util.CustomEvent,C=YAHOO.util.Dom,J=YAHOO.widget.Tooltip,H=YAHOO.env.ua,G=(H.ie&&(H.ie<=6||document.compatMode=="BackCompat")),F,I={"PREVENT_OVERLAP":{key:"preventoverlap",value:true,validator:E.isBoolean,supercedes:["x","y","xy"]},"SHOW_DELAY":{key:"showdelay",value:200,validator:E.isNumber},"AUTO_DISMISS_DELAY":{key:"autodismissdelay",value:5000,validator:E.isNumber},"HIDE_DELAY":{key:"hidedelay",value:250,validator:E.isNumber},"TEXT":{key:"text",suppressEvent:true},"CONTAINER":{key:"container"},"DISABLED":{key:"disabled",value:false,suppressEvent:true},"XY_OFFSET":{key:"xyoffset",value:[0,25],suppressEvent:true}},A={"CONTEXT_MOUSE_OVER":"contextMouseOver","CONTEXT_MOUSE_OUT":"contextMouseOut","CONTEXT_TRIGGER":"contextTrigger"};J.CSS_TOOLTIP="yui-tt";function K(Q,O){var P=this.cfg,R=P.getProperty("width");if(R==O){P.setProperty("width",Q);}}function D(P,O){if("_originalWidth" in this){K.call(this,this._originalWidth,this._forcedWidth);}var Q=document.body,U=this.cfg,T=U.getProperty("width"),R,S;if((!T||T=="auto")&&(U.getProperty("container")!=Q||U.getProperty("x")>=C.getViewportWidth()||U.getProperty("y")>=C.getViewportHeight())){S=this.element.cloneNode(true);S.style.visibility="hidden";S.style.top="0px";S.style.left="0px";Q.appendChild(S);R=(S.offsetWidth+"px");Q.removeChild(S);S=null;U.setProperty("width",R);U.refireEvent("xy");this._originalWidth=T||"";this._forcedWidth=R;}}function B(P,O,Q){this.render(Q);}function L(){N.onDOMReady(B,this.cfg.getProperty("container"),this);}YAHOO.extend(J,YAHOO.widget.Overlay,{init:function(P,O){J.superclass.init.call(this,P);this.beforeInitEvent.fire(J);C.addClass(this.element,J.CSS_TOOLTIP);if(O){this.cfg.applyConfig(O,true);}this.cfg.queueProperty("visible",false);this.cfg.queueProperty("constraintoviewport",true);this.setBody("");this.subscribe("changeContent",D);this.subscribe("init",L);this.subscribe("render",this.onRender);this.initEvent.fire(J);},initEvents:function(){J.superclass.initEvents.call(this);var O=M.LIST;this.contextMouseOverEvent=this.createEvent(A.CONTEXT_MOUSE_OVER);this.contextMouseOverEvent.signature=O;this.contextMouseOutEvent=this.createEvent(A.CONTEXT_MOUSE_OUT);this.contextMouseOutEvent.signature=O;this.contextTriggerEvent=this.createEvent(A.CONTEXT_TRIGGER);this.contextTriggerEvent.signature=O;},initDefaultConfig:function(){J.superclass.initDefaultConfig.call(this);this.cfg.addProperty(I.PREVENT_OVERLAP.key,{value:I.PREVENT_OVERLAP.value,validator:I.PREVENT_OVERLAP.validator,supercedes:I.PREVENT_OVERLAP.supercedes});this.cfg.addProperty(I.SHOW_DELAY.key,{handler:this.configShowDelay,value:200,validator:I.SHOW_DELAY.validator});this.cfg.addProperty(I.AUTO_DISMISS_DELAY.key,{handler:this.configAutoDismissDelay,value:I.AUTO_DISMISS_DELAY.value,validator:I.AUTO_DISMISS_DELAY.validator});this.cfg.addProperty(I.HIDE_DELAY.key,{handler:this.configHideDelay,value:I.HIDE_DELAY.value,validator:I.HIDE_DELAY.validator});this.cfg.addProperty(I.TEXT.key,{handler:this.configText,suppressEvent:I.TEXT.suppressEvent});this.cfg.addProperty(I.CONTAINER.key,{handler:this.configContainer,value:document.body});this.cfg.addProperty(I.DISABLED.key,{handler:this.configContainer,value:I.DISABLED.value,supressEvent:I.DISABLED.suppressEvent});this.cfg.addProperty(I.XY_OFFSET.key,{value:I.XY_OFFSET.value.concat(),supressEvent:I.XY_OFFSET.suppressEvent});},configText:function(P,O,Q){var R=O[0];if(R){this.setBody(R);}},configContainer:function(Q,P,R){var O=P[0];if(typeof O=="string"){this.cfg.setProperty("container",document.getElementById(O),true);}},_removeEventListeners:function(){var R=this._context,O,Q,P;if(R){O=R.length;if(O>0){P=O-1;do{Q=R[P];N.removeListener(Q,"mouseover",this.onContextMouseOver);N.removeListener(Q,"mousemove",this.onContextMouseMove);N.removeListener(Q,"mouseout",this.onContextMouseOut);}while(P--);}}},configContext:function(T,P,U){var S=P[0],V,O,R,Q;if(S){if(!(S instanceof Array)){if(typeof S=="string"){this.cfg.setProperty("context",[document.getElementById(S)],true);}else{this.cfg.setProperty("context",[S],true);}S=this.cfg.getProperty("context");}this._removeEventListeners();this._context=S;V=this._context;if(V){O=V.length;if(O>0){Q=O-1;do{R=V[Q];N.on(R,"mouseover",this.onContextMouseOver,this);N.on(R,"mousemove",this.onContextMouseMove,this);N.on(R,"mouseout",this.onContextMouseOut,this);}while(Q--);}}}},onContextMouseMove:function(P,O){O.pageX=N.getPageX(P);O.pageY=N.getPageY(P);},onContextMouseOver:function(Q,P){var O=this;if(O.title){P._tempTitle=O.title;O.title="";}if(P.fireEvent("contextMouseOver",O,Q)!==false&&!P.cfg.getProperty("disabled")){if(P.hideProcId){clearTimeout(P.hideProcId);
14
P.hideProcId=null;}N.on(O,"mousemove",P.onContextMouseMove,P);P.showProcId=P.doShow(Q,O);}},onContextMouseOut:function(Q,P){var O=this;if(P._tempTitle){O.title=P._tempTitle;P._tempTitle=null;}if(P.showProcId){clearTimeout(P.showProcId);P.showProcId=null;}if(P.hideProcId){clearTimeout(P.hideProcId);P.hideProcId=null;}P.fireEvent("contextMouseOut",O,Q);P.hideProcId=setTimeout(function(){P.hide();},P.cfg.getProperty("hidedelay"));},doShow:function(R,O){var T=this.cfg.getProperty("xyoffset"),P=T[0],S=T[1],Q=this;if(H.opera&&O.tagName&&O.tagName.toUpperCase()=="A"){S+=12;}return setTimeout(function(){var U=Q.cfg.getProperty("text");if(Q._tempTitle&&(U===""||YAHOO.lang.isUndefined(U)||YAHOO.lang.isNull(U))){Q.setBody(Q._tempTitle);}else{Q.cfg.refireEvent("text");}Q.moveTo(Q.pageX+P,Q.pageY+S);if(Q.cfg.getProperty("preventoverlap")){Q.preventOverlap(Q.pageX,Q.pageY);}N.removeListener(O,"mousemove",Q.onContextMouseMove);Q.contextTriggerEvent.fire(O);Q.show();Q.hideProcId=Q.doHide();},this.cfg.getProperty("showdelay"));},doHide:function(){var O=this;return setTimeout(function(){O.hide();},this.cfg.getProperty("autodismissdelay"));},preventOverlap:function(S,R){var O=this.element.offsetHeight,Q=new YAHOO.util.Point(S,R),P=C.getRegion(this.element);P.top-=5;P.left-=5;P.right+=5;P.bottom+=5;if(P.contains(Q)){this.cfg.setProperty("y",(R-O-5));}},onRender:function(S,R){function T(){var W=this.element,V=this.underlay;if(V){V.style.width=(W.offsetWidth+6)+"px";V.style.height=(W.offsetHeight+1)+"px";}}function P(){C.addClass(this.underlay,"yui-tt-shadow-visible");if(H.ie){this.forceUnderlayRedraw();}}function O(){C.removeClass(this.underlay,"yui-tt-shadow-visible");}function U(){var X=this.underlay,W,V,Z,Y;if(!X){W=this.element;V=YAHOO.widget.Module;Z=H.ie;Y=this;if(!F){F=document.createElement("div");F.className="yui-tt-shadow";}X=F.cloneNode(false);W.appendChild(X);this.underlay=X;this._shadow=this.underlay;P.call(this);this.subscribe("beforeShow",P);this.subscribe("hide",O);if(G){window.setTimeout(function(){T.call(Y);},0);this.cfg.subscribeToConfigEvent("width",T);this.cfg.subscribeToConfigEvent("height",T);this.subscribe("changeContent",T);V.textResizeEvent.subscribe(T,this,true);this.subscribe("destroy",function(){V.textResizeEvent.unsubscribe(T,this);});}}}function Q(){U.call(this);this.unsubscribe("beforeShow",Q);}if(this.cfg.getProperty("visible")){U.call(this);}else{this.subscribe("beforeShow",Q);}},forceUnderlayRedraw:function(){var O=this;C.addClass(O.underlay,"yui-force-redraw");setTimeout(function(){C.removeClass(O.underlay,"yui-force-redraw");},0);},destroy:function(){this._removeEventListeners();J.superclass.destroy.call(this);},toString:function(){return"Tooltip "+this.id;}});}());(function(){YAHOO.widget.Panel=function(V,U){YAHOO.widget.Panel.superclass.constructor.call(this,V,U);};var S=null;var E=YAHOO.lang,F=YAHOO.util,A=F.Dom,T=F.Event,M=F.CustomEvent,K=YAHOO.util.KeyListener,I=F.Config,H=YAHOO.widget.Overlay,O=YAHOO.widget.Panel,L=YAHOO.env.ua,P=(L.ie&&(L.ie<=6||document.compatMode=="BackCompat")),G,Q,C,D={"SHOW_MASK":"showMask","HIDE_MASK":"hideMask","DRAG":"drag"},N={"CLOSE":{key:"close",value:true,validator:E.isBoolean,supercedes:["visible"]},"DRAGGABLE":{key:"draggable",value:(F.DD?true:false),validator:E.isBoolean,supercedes:["visible"]},"DRAG_ONLY":{key:"dragonly",value:false,validator:E.isBoolean,supercedes:["draggable"]},"UNDERLAY":{key:"underlay",value:"shadow",supercedes:["visible"]},"MODAL":{key:"modal",value:false,validator:E.isBoolean,supercedes:["visible","zindex"]},"KEY_LISTENERS":{key:"keylisteners",suppressEvent:true,supercedes:["visible"]},"STRINGS":{key:"strings",supercedes:["close"],validator:E.isObject,value:{close:"Close"}}};O.CSS_PANEL="yui-panel";O.CSS_PANEL_CONTAINER="yui-panel-container";O.FOCUSABLE=["a","button","select","textarea","input","iframe"];function J(V,U){if(!this.header&&this.cfg.getProperty("draggable")){this.setHeader("&#160;");}}function R(V,U,W){var Z=W[0],X=W[1],Y=this.cfg,a=Y.getProperty("width");if(a==X){Y.setProperty("width",Z);}this.unsubscribe("hide",R,W);}function B(V,U){var Y,X,W;if(P){Y=this.cfg;X=Y.getProperty("width");if(!X||X=="auto"){W=(this.element.offsetWidth+"px");Y.setProperty("width",W);this.subscribe("hide",R,[(X||""),W]);}}}YAHOO.extend(O,H,{init:function(V,U){O.superclass.init.call(this,V);this.beforeInitEvent.fire(O);A.addClass(this.element,O.CSS_PANEL);this.buildWrapper();if(U){this.cfg.applyConfig(U,true);}this.subscribe("showMask",this._addFocusHandlers);this.subscribe("hideMask",this._removeFocusHandlers);this.subscribe("beforeRender",J);this.subscribe("render",function(){this.setFirstLastFocusable();this.subscribe("changeContent",this.setFirstLastFocusable);});this.subscribe("show",this.focusFirst);this.initEvent.fire(O);},_onElementFocus:function(Z){if(S===this){var Y=T.getTarget(Z),X=document.documentElement,V=(Y!==X&&Y!==window);if(V&&Y!==this.element&&Y!==this.mask&&!A.isAncestor(this.element,Y)){try{if(this.firstElement){this.firstElement.focus();}else{if(this._modalFocus){this._modalFocus.focus();}else{this.innerElement.focus();}}}catch(W){try{if(V&&Y!==document.body){Y.blur();}}catch(U){}}}}},_addFocusHandlers:function(V,U){if(!this.firstElement){if(L.webkit||L.opera){if(!this._modalFocus){this._createHiddenFocusElement();}}else{this.innerElement.tabIndex=0;}}this.setTabLoop(this.firstElement,this.lastElement);T.onFocus(document.documentElement,this._onElementFocus,this,true);S=this;},_createHiddenFocusElement:function(){var U=document.createElement("button");U.style.height="1px";U.style.width="1px";U.style.position="absolute";U.style.left="-10000em";U.style.opacity=0;U.tabIndex=-1;this.innerElement.appendChild(U);this._modalFocus=U;},_removeFocusHandlers:function(V,U){T.removeFocusListener(document.documentElement,this._onElementFocus,this);if(S==this){S=null;}},focusFirst:function(W,U,Y){var V=this.firstElement;if(U&&U[1]){T.stopEvent(U[1]);}if(V){try{V.focus();}catch(X){}}},focusLast:function(W,U,Y){var V=this.lastElement;
15
if(U&&U[1]){T.stopEvent(U[1]);}if(V){try{V.focus();}catch(X){}}},setTabLoop:function(X,Z){var V=this.preventBackTab,W=this.preventTabOut,U=this.showEvent,Y=this.hideEvent;if(V){V.disable();U.unsubscribe(V.enable,V);Y.unsubscribe(V.disable,V);V=this.preventBackTab=null;}if(W){W.disable();U.unsubscribe(W.enable,W);Y.unsubscribe(W.disable,W);W=this.preventTabOut=null;}if(X){this.preventBackTab=new K(X,{shift:true,keys:9},{fn:this.focusLast,scope:this,correctScope:true});V=this.preventBackTab;U.subscribe(V.enable,V,true);Y.subscribe(V.disable,V,true);}if(Z){this.preventTabOut=new K(Z,{shift:false,keys:9},{fn:this.focusFirst,scope:this,correctScope:true});W=this.preventTabOut;U.subscribe(W.enable,W,true);Y.subscribe(W.disable,W,true);}},getFocusableElements:function(U){U=U||this.innerElement;var X={};for(var W=0;W<O.FOCUSABLE.length;W++){X[O.FOCUSABLE[W]]=true;}function V(Y){if(Y.focus&&Y.type!=="hidden"&&!Y.disabled&&X[Y.tagName.toLowerCase()]){return true;}return false;}return A.getElementsBy(V,null,U);},setFirstLastFocusable:function(){this.firstElement=null;this.lastElement=null;var U=this.getFocusableElements();this.focusableElements=U;if(U.length>0){this.firstElement=U[0];this.lastElement=U[U.length-1];}if(this.cfg.getProperty("modal")){this.setTabLoop(this.firstElement,this.lastElement);}},initEvents:function(){O.superclass.initEvents.call(this);var U=M.LIST;this.showMaskEvent=this.createEvent(D.SHOW_MASK);this.showMaskEvent.signature=U;this.hideMaskEvent=this.createEvent(D.HIDE_MASK);this.hideMaskEvent.signature=U;this.dragEvent=this.createEvent(D.DRAG);this.dragEvent.signature=U;},initDefaultConfig:function(){O.superclass.initDefaultConfig.call(this);this.cfg.addProperty(N.CLOSE.key,{handler:this.configClose,value:N.CLOSE.value,validator:N.CLOSE.validator,supercedes:N.CLOSE.supercedes});this.cfg.addProperty(N.DRAGGABLE.key,{handler:this.configDraggable,value:(F.DD)?true:false,validator:N.DRAGGABLE.validator,supercedes:N.DRAGGABLE.supercedes});this.cfg.addProperty(N.DRAG_ONLY.key,{value:N.DRAG_ONLY.value,validator:N.DRAG_ONLY.validator,supercedes:N.DRAG_ONLY.supercedes});this.cfg.addProperty(N.UNDERLAY.key,{handler:this.configUnderlay,value:N.UNDERLAY.value,supercedes:N.UNDERLAY.supercedes});this.cfg.addProperty(N.MODAL.key,{handler:this.configModal,value:N.MODAL.value,validator:N.MODAL.validator,supercedes:N.MODAL.supercedes});this.cfg.addProperty(N.KEY_LISTENERS.key,{handler:this.configKeyListeners,suppressEvent:N.KEY_LISTENERS.suppressEvent,supercedes:N.KEY_LISTENERS.supercedes});this.cfg.addProperty(N.STRINGS.key,{value:N.STRINGS.value,handler:this.configStrings,validator:N.STRINGS.validator,supercedes:N.STRINGS.supercedes});},configClose:function(X,V,Y){var Z=V[0],W=this.close,U=this.cfg.getProperty("strings");if(Z){if(!W){if(!C){C=document.createElement("a");C.className="container-close";C.href="#";}W=C.cloneNode(true);this.innerElement.appendChild(W);W.innerHTML=(U&&U.close)?U.close:"&#160;";T.on(W,"click",this._doClose,this,true);this.close=W;}else{W.style.display="block";}}else{if(W){W.style.display="none";}}},_doClose:function(U){T.preventDefault(U);this.hide();},configDraggable:function(V,U,W){var X=U[0];if(X){if(!F.DD){this.cfg.setProperty("draggable",false);return;}if(this.header){A.setStyle(this.header,"cursor","move");this.registerDragDrop();}this.subscribe("beforeShow",B);}else{if(this.dd){this.dd.unreg();}if(this.header){A.setStyle(this.header,"cursor","auto");}this.unsubscribe("beforeShow",B);}},configUnderlay:function(d,c,Z){var b=(this.platform=="mac"&&L.gecko),e=c[0].toLowerCase(),V=this.underlay,W=this.element;function X(){var f=false;if(!V){if(!Q){Q=document.createElement("div");Q.className="underlay";}V=Q.cloneNode(false);this.element.appendChild(V);this.underlay=V;if(P){this.sizeUnderlay();this.cfg.subscribeToConfigEvent("width",this.sizeUnderlay);this.cfg.subscribeToConfigEvent("height",this.sizeUnderlay);this.changeContentEvent.subscribe(this.sizeUnderlay);YAHOO.widget.Module.textResizeEvent.subscribe(this.sizeUnderlay,this,true);}if(L.webkit&&L.webkit<420){this.changeContentEvent.subscribe(this.forceUnderlayRedraw);}f=true;}}function a(){var f=X.call(this);if(!f&&P){this.sizeUnderlay();}this._underlayDeferred=false;this.beforeShowEvent.unsubscribe(a);}function Y(){if(this._underlayDeferred){this.beforeShowEvent.unsubscribe(a);this._underlayDeferred=false;}if(V){this.cfg.unsubscribeFromConfigEvent("width",this.sizeUnderlay);this.cfg.unsubscribeFromConfigEvent("height",this.sizeUnderlay);this.changeContentEvent.unsubscribe(this.sizeUnderlay);this.changeContentEvent.unsubscribe(this.forceUnderlayRedraw);YAHOO.widget.Module.textResizeEvent.unsubscribe(this.sizeUnderlay,this,true);this.element.removeChild(V);this.underlay=null;}}switch(e){case"shadow":A.removeClass(W,"matte");A.addClass(W,"shadow");break;case"matte":if(!b){Y.call(this);}A.removeClass(W,"shadow");A.addClass(W,"matte");break;default:if(!b){Y.call(this);}A.removeClass(W,"shadow");A.removeClass(W,"matte");break;}if((e=="shadow")||(b&&!V)){if(this.cfg.getProperty("visible")){var U=X.call(this);if(!U&&P){this.sizeUnderlay();}}else{if(!this._underlayDeferred){this.beforeShowEvent.subscribe(a);this._underlayDeferred=true;}}}},configModal:function(V,U,X){var W=U[0];if(W){if(!this._hasModalityEventListeners){this.subscribe("beforeShow",this.buildMask);this.subscribe("beforeShow",this.bringToTop);this.subscribe("beforeShow",this.showMask);this.subscribe("hide",this.hideMask);H.windowResizeEvent.subscribe(this.sizeMask,this,true);this._hasModalityEventListeners=true;}}else{if(this._hasModalityEventListeners){if(this.cfg.getProperty("visible")){this.hideMask();this.removeMask();}this.unsubscribe("beforeShow",this.buildMask);this.unsubscribe("beforeShow",this.bringToTop);this.unsubscribe("beforeShow",this.showMask);this.unsubscribe("hide",this.hideMask);H.windowResizeEvent.unsubscribe(this.sizeMask,this);this._hasModalityEventListeners=false;}}},removeMask:function(){var V=this.mask,U;if(V){this.hideMask();U=V.parentNode;
16
if(U){U.removeChild(V);}this.mask=null;}},configKeyListeners:function(X,U,a){var W=U[0],Z,Y,V;if(W){if(W instanceof Array){Y=W.length;for(V=0;V<Y;V++){Z=W[V];if(!I.alreadySubscribed(this.showEvent,Z.enable,Z)){this.showEvent.subscribe(Z.enable,Z,true);}if(!I.alreadySubscribed(this.hideEvent,Z.disable,Z)){this.hideEvent.subscribe(Z.disable,Z,true);this.destroyEvent.subscribe(Z.disable,Z,true);}}}else{if(!I.alreadySubscribed(this.showEvent,W.enable,W)){this.showEvent.subscribe(W.enable,W,true);}if(!I.alreadySubscribed(this.hideEvent,W.disable,W)){this.hideEvent.subscribe(W.disable,W,true);this.destroyEvent.subscribe(W.disable,W,true);}}}},configStrings:function(V,U,W){var X=E.merge(N.STRINGS.value,U[0]);this.cfg.setProperty(N.STRINGS.key,X,true);},configHeight:function(X,V,Y){var U=V[0],W=this.innerElement;A.setStyle(W,"height",U);this.cfg.refireEvent("iframe");},_autoFillOnHeightChange:function(X,V,W){O.superclass._autoFillOnHeightChange.apply(this,arguments);if(P){var U=this;setTimeout(function(){U.sizeUnderlay();},0);}},configWidth:function(X,U,Y){var W=U[0],V=this.innerElement;A.setStyle(V,"width",W);this.cfg.refireEvent("iframe");},configzIndex:function(V,U,X){O.superclass.configzIndex.call(this,V,U,X);if(this.mask||this.cfg.getProperty("modal")===true){var W=A.getStyle(this.element,"zIndex");if(!W||isNaN(W)){W=0;}if(W===0){this.cfg.setProperty("zIndex",1);}else{this.stackMask();}}},buildWrapper:function(){var W=this.element.parentNode,U=this.element,V=document.createElement("div");V.className=O.CSS_PANEL_CONTAINER;V.id=U.id+"_c";if(W){W.insertBefore(V,U);}V.appendChild(U);this.element=V;this.innerElement=U;A.setStyle(this.innerElement,"visibility","inherit");},sizeUnderlay:function(){var V=this.underlay,U;if(V){U=this.element;V.style.width=U.offsetWidth+"px";V.style.height=U.offsetHeight+"px";}},registerDragDrop:function(){var V=this;if(this.header){if(!F.DD){return;}var U=(this.cfg.getProperty("dragonly")===true);this.dd=new F.DD(this.element.id,this.id,{dragOnly:U});if(!this.header.id){this.header.id=this.id+"_h";}this.dd.startDrag=function(){var X,Z,W,c,b,a;if(YAHOO.env.ua.ie==6){A.addClass(V.element,"drag");}if(V.cfg.getProperty("constraintoviewport")){var Y=H.VIEWPORT_OFFSET;X=V.element.offsetHeight;Z=V.element.offsetWidth;W=A.getViewportWidth();c=A.getViewportHeight();b=A.getDocumentScrollLeft();a=A.getDocumentScrollTop();if(X+Y<c){this.minY=a+Y;this.maxY=a+c-X-Y;}else{this.minY=a+Y;this.maxY=a+Y;}if(Z+Y<W){this.minX=b+Y;this.maxX=b+W-Z-Y;}else{this.minX=b+Y;this.maxX=b+Y;}this.constrainX=true;this.constrainY=true;}else{this.constrainX=false;this.constrainY=false;}V.dragEvent.fire("startDrag",arguments);};this.dd.onDrag=function(){V.syncPosition();V.cfg.refireEvent("iframe");if(this.platform=="mac"&&YAHOO.env.ua.gecko){this.showMacGeckoScrollbars();}V.dragEvent.fire("onDrag",arguments);};this.dd.endDrag=function(){if(YAHOO.env.ua.ie==6){A.removeClass(V.element,"drag");}V.dragEvent.fire("endDrag",arguments);V.moveEvent.fire(V.cfg.getProperty("xy"));};this.dd.setHandleElId(this.header.id);this.dd.addInvalidHandleType("INPUT");this.dd.addInvalidHandleType("SELECT");this.dd.addInvalidHandleType("TEXTAREA");}},buildMask:function(){var U=this.mask;if(!U){if(!G){G=document.createElement("div");G.className="mask";G.innerHTML="&#160;";}U=G.cloneNode(true);U.id=this.id+"_mask";document.body.insertBefore(U,document.body.firstChild);this.mask=U;if(YAHOO.env.ua.gecko&&this.platform=="mac"){A.addClass(this.mask,"block-scrollbars");}this.stackMask();}},hideMask:function(){if(this.cfg.getProperty("modal")&&this.mask){this.mask.style.display="none";A.removeClass(document.body,"masked");this.hideMaskEvent.fire();}},showMask:function(){if(this.cfg.getProperty("modal")&&this.mask){A.addClass(document.body,"masked");this.sizeMask();this.mask.style.display="block";this.showMaskEvent.fire();}},sizeMask:function(){if(this.mask){var V=this.mask,W=A.getViewportWidth(),U=A.getViewportHeight();if(V.offsetHeight>U){V.style.height=U+"px";}if(V.offsetWidth>W){V.style.width=W+"px";}V.style.height=A.getDocumentHeight()+"px";V.style.width=A.getDocumentWidth()+"px";}},stackMask:function(){if(this.mask){var U=A.getStyle(this.element,"zIndex");if(!YAHOO.lang.isUndefined(U)&&!isNaN(U)){A.setStyle(this.mask,"zIndex",U-1);}}},render:function(U){return O.superclass.render.call(this,U,this.innerElement);},_renderHeader:function(U){U=U||this.innerElement;O.superclass._renderHeader.call(this,U);},_renderBody:function(U){U=U||this.innerElement;O.superclass._renderBody.call(this,U);},_renderFooter:function(U){U=U||this.innerElement;O.superclass._renderFooter.call(this,U);},destroy:function(){H.windowResizeEvent.unsubscribe(this.sizeMask,this);this.removeMask();if(this.close){T.purgeElement(this.close);}O.superclass.destroy.call(this);},forceUnderlayRedraw:function(){var U=this.underlay;A.addClass(U,"yui-force-redraw");setTimeout(function(){A.removeClass(U,"yui-force-redraw");},0);},toString:function(){return"Panel "+this.id;}});}());(function(){YAHOO.widget.Dialog=function(J,I){YAHOO.widget.Dialog.superclass.constructor.call(this,J,I);};var B=YAHOO.util.Event,G=YAHOO.util.CustomEvent,E=YAHOO.util.Dom,A=YAHOO.widget.Dialog,F=YAHOO.lang,H={"BEFORE_SUBMIT":"beforeSubmit","SUBMIT":"submit","MANUAL_SUBMIT":"manualSubmit","ASYNC_SUBMIT":"asyncSubmit","FORM_SUBMIT":"formSubmit","CANCEL":"cancel"},C={"POST_METHOD":{key:"postmethod",value:"async"},"POST_DATA":{key:"postdata",value:null},"BUTTONS":{key:"buttons",value:"none",supercedes:["visible"]},"HIDEAFTERSUBMIT":{key:"hideaftersubmit",value:true}};A.CSS_DIALOG="yui-dialog";function D(){var L=this._aButtons,J,K,I;if(F.isArray(L)){J=L.length;if(J>0){I=J-1;do{K=L[I];if(YAHOO.widget.Button&&K instanceof YAHOO.widget.Button){K.destroy();}else{if(K.tagName.toUpperCase()=="BUTTON"){B.purgeElement(K);B.purgeElement(K,false);}}}while(I--);}}}YAHOO.extend(A,YAHOO.widget.Panel,{form:null,initDefaultConfig:function(){A.superclass.initDefaultConfig.call(this);this.callback={success:null,failure:null,argument:null};
17
this.cfg.addProperty(C.POST_METHOD.key,{handler:this.configPostMethod,value:C.POST_METHOD.value,validator:function(I){if(I!="form"&&I!="async"&&I!="none"&&I!="manual"){return false;}else{return true;}}});this.cfg.addProperty(C.POST_DATA.key,{value:C.POST_DATA.value});this.cfg.addProperty(C.HIDEAFTERSUBMIT.key,{value:C.HIDEAFTERSUBMIT.value});this.cfg.addProperty(C.BUTTONS.key,{handler:this.configButtons,value:C.BUTTONS.value,supercedes:C.BUTTONS.supercedes});},initEvents:function(){A.superclass.initEvents.call(this);var I=G.LIST;this.beforeSubmitEvent=this.createEvent(H.BEFORE_SUBMIT);this.beforeSubmitEvent.signature=I;this.submitEvent=this.createEvent(H.SUBMIT);this.submitEvent.signature=I;this.manualSubmitEvent=this.createEvent(H.MANUAL_SUBMIT);this.manualSubmitEvent.signature=I;this.asyncSubmitEvent=this.createEvent(H.ASYNC_SUBMIT);this.asyncSubmitEvent.signature=I;this.formSubmitEvent=this.createEvent(H.FORM_SUBMIT);this.formSubmitEvent.signature=I;this.cancelEvent=this.createEvent(H.CANCEL);this.cancelEvent.signature=I;},init:function(J,I){A.superclass.init.call(this,J);this.beforeInitEvent.fire(A);E.addClass(this.element,A.CSS_DIALOG);this.cfg.setProperty("visible",false);if(I){this.cfg.applyConfig(I,true);}this.showEvent.subscribe(this.focusFirst,this,true);this.beforeHideEvent.subscribe(this.blurButtons,this,true);this.subscribe("changeBody",this.registerForm);this.initEvent.fire(A);},doSubmit:function(){var P=YAHOO.util.Connect,Q=this.form,K=false,N=false,R,M,L,I;switch(this.cfg.getProperty("postmethod")){case"async":R=Q.elements;M=R.length;if(M>0){L=M-1;do{if(R[L].type=="file"){K=true;break;}}while(L--);}if(K&&YAHOO.env.ua.ie&&this.isSecure){N=true;}I=this._getFormAttributes(Q);P.setForm(Q,K,N);var J=this.cfg.getProperty("postdata");var O=P.asyncRequest(I.method,I.action,this.callback,J);this.asyncSubmitEvent.fire(O);break;case"form":Q.submit();this.formSubmitEvent.fire();break;case"none":case"manual":this.manualSubmitEvent.fire();break;}},_getFormAttributes:function(K){var I={method:null,action:null};if(K){if(K.getAttributeNode){var J=K.getAttributeNode("action");var L=K.getAttributeNode("method");if(J){I.action=J.value;}if(L){I.method=L.value;}}else{I.action=K.getAttribute("action");I.method=K.getAttribute("method");}}I.method=(F.isString(I.method)?I.method:"POST").toUpperCase();I.action=F.isString(I.action)?I.action:"";return I;},registerForm:function(){var I=this.element.getElementsByTagName("form")[0];if(this.form){if(this.form==I&&E.isAncestor(this.element,this.form)){return;}else{B.purgeElement(this.form);this.form=null;}}if(!I){I=document.createElement("form");I.name="frm_"+this.id;this.body.appendChild(I);}if(I){this.form=I;B.on(I,"submit",this._submitHandler,this,true);}},_submitHandler:function(I){B.stopEvent(I);this.submit();this.form.blur();},setTabLoop:function(I,J){I=I||this.firstButton;J=this.lastButton||J;A.superclass.setTabLoop.call(this,I,J);},setFirstLastFocusable:function(){A.superclass.setFirstLastFocusable.call(this);var J,I,K,L=this.focusableElements;this.firstFormElement=null;this.lastFormElement=null;if(this.form&&L&&L.length>0){I=L.length;for(J=0;J<I;++J){K=L[J];if(this.form===K.form){this.firstFormElement=K;break;}}for(J=I-1;J>=0;--J){K=L[J];if(this.form===K.form){this.lastFormElement=K;break;}}}},configClose:function(J,I,K){A.superclass.configClose.apply(this,arguments);},_doClose:function(I){B.preventDefault(I);this.cancel();},configButtons:function(S,R,M){var N=YAHOO.widget.Button,U=R[0],K=this.innerElement,T,P,J,Q,O,I,L;D.call(this);this._aButtons=null;if(F.isArray(U)){O=document.createElement("span");O.className="button-group";Q=U.length;this._aButtons=[];this.defaultHtmlButton=null;for(L=0;L<Q;L++){T=U[L];if(N){J=new N({label:T.text});J.appendTo(O);P=J.get("element");if(T.isDefault){J.addClass("default");this.defaultHtmlButton=P;}if(F.isFunction(T.handler)){J.set("onclick",{fn:T.handler,obj:this,scope:this});}else{if(F.isObject(T.handler)&&F.isFunction(T.handler.fn)){J.set("onclick",{fn:T.handler.fn,obj:((!F.isUndefined(T.handler.obj))?T.handler.obj:this),scope:(T.handler.scope||this)});}}this._aButtons[this._aButtons.length]=J;}else{P=document.createElement("button");P.setAttribute("type","button");if(T.isDefault){P.className="default";this.defaultHtmlButton=P;}P.innerHTML=T.text;if(F.isFunction(T.handler)){B.on(P,"click",T.handler,this,true);}else{if(F.isObject(T.handler)&&F.isFunction(T.handler.fn)){B.on(P,"click",T.handler.fn,((!F.isUndefined(T.handler.obj))?T.handler.obj:this),(T.handler.scope||this));}}O.appendChild(P);this._aButtons[this._aButtons.length]=P;}T.htmlButton=P;if(L===0){this.firstButton=P;}if(L==(Q-1)){this.lastButton=P;}}this.setFooter(O);I=this.footer;if(E.inDocument(this.element)&&!E.isAncestor(K,I)){K.appendChild(I);}this.buttonSpan=O;}else{O=this.buttonSpan;I=this.footer;if(O&&I){I.removeChild(O);this.buttonSpan=null;this.firstButton=null;this.lastButton=null;this.defaultHtmlButton=null;}}this.changeContentEvent.fire();},getButtons:function(){return this._aButtons||null;},focusFirst:function(K,I,M){var J=this.firstFormElement;if(I&&I[1]){B.stopEvent(I[1]);}if(J){try{J.focus();}catch(L){}}else{if(this.defaultHtmlButton){this.focusDefaultButton();}else{this.focusFirstButton();}}},focusLast:function(K,I,M){var N=this.cfg.getProperty("buttons"),J=this.lastFormElement;if(I&&I[1]){B.stopEvent(I[1]);}if(N&&F.isArray(N)){this.focusLastButton();}else{if(J){try{J.focus();}catch(L){}}}},_getButton:function(J){var I=YAHOO.widget.Button;if(I&&J&&J.nodeName&&J.id){J=I.getButton(J.id)||J;}return J;},focusDefaultButton:function(){var I=this._getButton(this.defaultHtmlButton);if(I){try{I.focus();}catch(J){}}},blurButtons:function(){var N=this.cfg.getProperty("buttons"),K,M,J,I;if(N&&F.isArray(N)){K=N.length;if(K>0){I=(K-1);do{M=N[I];if(M){J=this._getButton(M.htmlButton);if(J){try{J.blur();}catch(L){}}}}while(I--);}}},focusFirstButton:function(){var L=this.cfg.getProperty("buttons"),K,I;if(L&&F.isArray(L)){K=L[0];if(K){I=this._getButton(K.htmlButton);
18
if(I){try{I.focus();}catch(J){}}}}},focusLastButton:function(){var M=this.cfg.getProperty("buttons"),J,L,I;if(M&&F.isArray(M)){J=M.length;if(J>0){L=M[(J-1)];if(L){I=this._getButton(L.htmlButton);if(I){try{I.focus();}catch(K){}}}}}},configPostMethod:function(J,I,K){this.registerForm();},validate:function(){return true;},submit:function(){if(this.validate()){if(this.beforeSubmitEvent.fire()){this.doSubmit();this.submitEvent.fire();if(this.cfg.getProperty("hideaftersubmit")){this.hide();}return true;}else{return false;}}else{return false;}},cancel:function(){this.cancelEvent.fire();this.hide();},getData:function(){var Y=this.form,J,R,U,L,S,P,O,I,V,K,W,Z,N,a,M,X,T;function Q(c){var b=c.tagName.toUpperCase();return((b=="INPUT"||b=="TEXTAREA"||b=="SELECT")&&c.name==L);}if(Y){J=Y.elements;R=J.length;U={};for(X=0;X<R;X++){L=J[X].name;S=E.getElementsBy(Q,"*",Y);P=S.length;if(P>0){if(P==1){S=S[0];O=S.type;I=S.tagName.toUpperCase();switch(I){case"INPUT":if(O=="checkbox"){U[L]=S.checked;}else{if(O!="radio"){U[L]=S.value;}}break;case"TEXTAREA":U[L]=S.value;break;case"SELECT":V=S.options;K=V.length;W=[];for(T=0;T<K;T++){Z=V[T];if(Z.selected){M=Z.attributes.value;W[W.length]=(M&&M.specified)?Z.value:Z.text;}}U[L]=W;break;}}else{O=S[0].type;switch(O){case"radio":for(T=0;T<P;T++){N=S[T];if(N.checked){U[L]=N.value;break;}}break;case"checkbox":W=[];for(T=0;T<P;T++){a=S[T];if(a.checked){W[W.length]=a.value;}}U[L]=W;break;}}}}}return U;},destroy:function(){D.call(this);this._aButtons=null;var I=this.element.getElementsByTagName("form"),J;if(I.length>0){J=I[0];if(J){B.purgeElement(J);if(J.parentNode){J.parentNode.removeChild(J);}this.form=null;}}A.superclass.destroy.call(this);},toString:function(){return"Dialog "+this.id;}});}());(function(){YAHOO.widget.SimpleDialog=function(E,D){YAHOO.widget.SimpleDialog.superclass.constructor.call(this,E,D);};var C=YAHOO.util.Dom,B=YAHOO.widget.SimpleDialog,A={"ICON":{key:"icon",value:"none",suppressEvent:true},"TEXT":{key:"text",value:"",suppressEvent:true,supercedes:["icon"]}};B.ICON_BLOCK="blckicon";B.ICON_ALARM="alrticon";B.ICON_HELP="hlpicon";B.ICON_INFO="infoicon";B.ICON_WARN="warnicon";B.ICON_TIP="tipicon";B.ICON_CSS_CLASSNAME="yui-icon";B.CSS_SIMPLEDIALOG="yui-simple-dialog";YAHOO.extend(B,YAHOO.widget.Dialog,{initDefaultConfig:function(){B.superclass.initDefaultConfig.call(this);this.cfg.addProperty(A.ICON.key,{handler:this.configIcon,value:A.ICON.value,suppressEvent:A.ICON.suppressEvent});this.cfg.addProperty(A.TEXT.key,{handler:this.configText,value:A.TEXT.value,suppressEvent:A.TEXT.suppressEvent,supercedes:A.TEXT.supercedes});},init:function(E,D){B.superclass.init.call(this,E);this.beforeInitEvent.fire(B);C.addClass(this.element,B.CSS_SIMPLEDIALOG);this.cfg.queueProperty("postmethod","manual");if(D){this.cfg.applyConfig(D,true);}this.beforeRenderEvent.subscribe(function(){if(!this.body){this.setBody("");}},this,true);this.initEvent.fire(B);},registerForm:function(){B.superclass.registerForm.call(this);this.form.innerHTML+='<input type="hidden" name="'+this.id+'" value=""/>';},configIcon:function(K,J,H){var D=J[0],E=this.body,F=B.ICON_CSS_CLASSNAME,L,I,G;if(D&&D!="none"){L=C.getElementsByClassName(F,"*",E);if(L.length===1){I=L[0];G=I.parentNode;if(G){G.removeChild(I);I=null;}}if(D.indexOf(".")==-1){I=document.createElement("span");I.className=(F+" "+D);I.innerHTML="&#160;";}else{I=document.createElement("img");I.src=(this.imageRoot+D);I.className=F;}if(I){E.insertBefore(I,E.firstChild);}}},configText:function(E,D,F){var G=D[0];if(G){this.setBody(G);this.cfg.refireEvent("icon");}},toString:function(){return"SimpleDialog "+this.id;}});}());(function(){YAHOO.widget.ContainerEffect=function(E,H,G,D,F){if(!F){F=YAHOO.util.Anim;}this.overlay=E;this.attrIn=H;this.attrOut=G;this.targetElement=D||E.element;this.animClass=F;};var B=YAHOO.util.Dom,C=YAHOO.util.CustomEvent,A=YAHOO.widget.ContainerEffect;A.FADE=function(D,F){var G=YAHOO.util.Easing,I={attributes:{opacity:{from:0,to:1}},duration:F,method:G.easeIn},E={attributes:{opacity:{to:0}},duration:F,method:G.easeOut},H=new A(D,I,E,D.element);H.handleUnderlayStart=function(){var K=this.overlay.underlay;if(K&&YAHOO.env.ua.ie){var J=(K.filters&&K.filters.length>0);if(J){B.addClass(D.element,"yui-effect-fade");}}};H.handleUnderlayComplete=function(){var J=this.overlay.underlay;if(J&&YAHOO.env.ua.ie){B.removeClass(D.element,"yui-effect-fade");}};H.handleStartAnimateIn=function(K,J,L){B.addClass(L.overlay.element,"hide-select");if(!L.overlay.underlay){L.overlay.cfg.refireEvent("underlay");}L.handleUnderlayStart();L.overlay._setDomVisibility(true);B.setStyle(L.overlay.element,"opacity",0);};H.handleCompleteAnimateIn=function(K,J,L){B.removeClass(L.overlay.element,"hide-select");if(L.overlay.element.style.filter){L.overlay.element.style.filter=null;}L.handleUnderlayComplete();L.overlay.cfg.refireEvent("iframe");L.animateInCompleteEvent.fire();};H.handleStartAnimateOut=function(K,J,L){B.addClass(L.overlay.element,"hide-select");L.handleUnderlayStart();};H.handleCompleteAnimateOut=function(K,J,L){B.removeClass(L.overlay.element,"hide-select");if(L.overlay.element.style.filter){L.overlay.element.style.filter=null;}L.overlay._setDomVisibility(false);B.setStyle(L.overlay.element,"opacity",1);L.handleUnderlayComplete();L.overlay.cfg.refireEvent("iframe");L.animateOutCompleteEvent.fire();};H.init();return H;};A.SLIDE=function(F,D){var I=YAHOO.util.Easing,L=F.cfg.getProperty("x")||B.getX(F.element),K=F.cfg.getProperty("y")||B.getY(F.element),M=B.getClientWidth(),H=F.element.offsetWidth,J={attributes:{points:{to:[L,K]}},duration:D,method:I.easeIn},E={attributes:{points:{to:[(M+25),K]}},duration:D,method:I.easeOut},G=new A(F,J,E,F.element,YAHOO.util.Motion);G.handleStartAnimateIn=function(O,N,P){P.overlay.element.style.left=((-25)-H)+"px";P.overlay.element.style.top=K+"px";};G.handleTweenAnimateIn=function(Q,P,R){var S=B.getXY(R.overlay.element),O=S[0],N=S[1];if(B.getStyle(R.overlay.element,"visibility")=="hidden"&&O<L){R.overlay._setDomVisibility(true);
19
}R.overlay.cfg.setProperty("xy",[O,N],true);R.overlay.cfg.refireEvent("iframe");};G.handleCompleteAnimateIn=function(O,N,P){P.overlay.cfg.setProperty("xy",[L,K],true);P.startX=L;P.startY=K;P.overlay.cfg.refireEvent("iframe");P.animateInCompleteEvent.fire();};G.handleStartAnimateOut=function(O,N,R){var P=B.getViewportWidth(),S=B.getXY(R.overlay.element),Q=S[1];R.animOut.attributes.points.to=[(P+25),Q];};G.handleTweenAnimateOut=function(P,O,Q){var S=B.getXY(Q.overlay.element),N=S[0],R=S[1];Q.overlay.cfg.setProperty("xy",[N,R],true);Q.overlay.cfg.refireEvent("iframe");};G.handleCompleteAnimateOut=function(O,N,P){P.overlay._setDomVisibility(false);P.overlay.cfg.setProperty("xy",[L,K]);P.animateOutCompleteEvent.fire();};G.init();return G;};A.prototype={init:function(){this.beforeAnimateInEvent=this.createEvent("beforeAnimateIn");this.beforeAnimateInEvent.signature=C.LIST;this.beforeAnimateOutEvent=this.createEvent("beforeAnimateOut");this.beforeAnimateOutEvent.signature=C.LIST;this.animateInCompleteEvent=this.createEvent("animateInComplete");this.animateInCompleteEvent.signature=C.LIST;this.animateOutCompleteEvent=this.createEvent("animateOutComplete");this.animateOutCompleteEvent.signature=C.LIST;this.animIn=new this.animClass(this.targetElement,this.attrIn.attributes,this.attrIn.duration,this.attrIn.method);this.animIn.onStart.subscribe(this.handleStartAnimateIn,this);this.animIn.onTween.subscribe(this.handleTweenAnimateIn,this);this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn,this);this.animOut=new this.animClass(this.targetElement,this.attrOut.attributes,this.attrOut.duration,this.attrOut.method);this.animOut.onStart.subscribe(this.handleStartAnimateOut,this);this.animOut.onTween.subscribe(this.handleTweenAnimateOut,this);this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut,this);},animateIn:function(){this.beforeAnimateInEvent.fire();this.animIn.animate();},animateOut:function(){this.beforeAnimateOutEvent.fire();this.animOut.animate();},handleStartAnimateIn:function(E,D,F){},handleTweenAnimateIn:function(E,D,F){},handleCompleteAnimateIn:function(E,D,F){},handleStartAnimateOut:function(E,D,F){},handleTweenAnimateOut:function(E,D,F){},handleCompleteAnimateOut:function(E,D,F){},toString:function(){var D="ContainerEffect";if(this.overlay){D+=" ["+this.overlay.toString()+"]";}return D;}};YAHOO.lang.augmentProto(A,YAHOO.util.EventProvider);})();YAHOO.register("container",YAHOO.widget.Module,{version:"2.8.0r4",build:"2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/container/container.js (-9052 lines)
Lines 1-9052 Link Here
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.8.0r4
6
*/
7
(function () {
8
9
    /**
10
    * Config is a utility used within an Object to allow the implementer to
11
    * maintain a list of local configuration properties and listen for changes 
12
    * to those properties dynamically using CustomEvent. The initial values are 
13
    * also maintained so that the configuration can be reset at any given point 
14
    * to its initial state.
15
    * @namespace YAHOO.util
16
    * @class Config
17
    * @constructor
18
    * @param {Object} owner The owner Object to which this Config Object belongs
19
    */
20
    YAHOO.util.Config = function (owner) {
21
22
        if (owner) {
23
            this.init(owner);
24
        }
25
26
27
    };
28
29
30
    var Lang = YAHOO.lang,
31
        CustomEvent = YAHOO.util.CustomEvent,
32
        Config = YAHOO.util.Config;
33
34
35
    /**
36
     * Constant representing the CustomEvent type for the config changed event.
37
     * @property YAHOO.util.Config.CONFIG_CHANGED_EVENT
38
     * @private
39
     * @static
40
     * @final
41
     */
42
    Config.CONFIG_CHANGED_EVENT = "configChanged";
43
    
44
    /**
45
     * Constant representing the boolean type string
46
     * @property YAHOO.util.Config.BOOLEAN_TYPE
47
     * @private
48
     * @static
49
     * @final
50
     */
51
    Config.BOOLEAN_TYPE = "boolean";
52
    
53
    Config.prototype = {
54
     
55
        /**
56
        * Object reference to the owner of this Config Object
57
        * @property owner
58
        * @type Object
59
        */
60
        owner: null,
61
        
62
        /**
63
        * Boolean flag that specifies whether a queue is currently 
64
        * being executed
65
        * @property queueInProgress
66
        * @type Boolean
67
        */
68
        queueInProgress: false,
69
        
70
        /**
71
        * Maintains the local collection of configuration property objects and 
72
        * their specified values
73
        * @property config
74
        * @private
75
        * @type Object
76
        */ 
77
        config: null,
78
        
79
        /**
80
        * Maintains the local collection of configuration property objects as 
81
        * they were initially applied.
82
        * This object is used when resetting a property.
83
        * @property initialConfig
84
        * @private
85
        * @type Object
86
        */ 
87
        initialConfig: null,
88
        
89
        /**
90
        * Maintains the local, normalized CustomEvent queue
91
        * @property eventQueue
92
        * @private
93
        * @type Object
94
        */ 
95
        eventQueue: null,
96
        
97
        /**
98
        * Custom Event, notifying subscribers when Config properties are set 
99
        * (setProperty is called without the silent flag
100
        * @event configChangedEvent
101
        */
102
        configChangedEvent: null,
103
    
104
        /**
105
        * Initializes the configuration Object and all of its local members.
106
        * @method init
107
        * @param {Object} owner The owner Object to which this Config 
108
        * Object belongs
109
        */
110
        init: function (owner) {
111
    
112
            this.owner = owner;
113
    
114
            this.configChangedEvent = 
115
                this.createEvent(Config.CONFIG_CHANGED_EVENT);
116
    
117
            this.configChangedEvent.signature = CustomEvent.LIST;
118
            this.queueInProgress = false;
119
            this.config = {};
120
            this.initialConfig = {};
121
            this.eventQueue = [];
122
        
123
        },
124
        
125
        /**
126
        * Validates that the value passed in is a Boolean.
127
        * @method checkBoolean
128
        * @param {Object} val The value to validate
129
        * @return {Boolean} true, if the value is valid
130
        */ 
131
        checkBoolean: function (val) {
132
            return (typeof val == Config.BOOLEAN_TYPE);
133
        },
134
        
135
        /**
136
        * Validates that the value passed in is a number.
137
        * @method checkNumber
138
        * @param {Object} val The value to validate
139
        * @return {Boolean} true, if the value is valid
140
        */
141
        checkNumber: function (val) {
142
            return (!isNaN(val));
143
        },
144
        
145
        /**
146
        * Fires a configuration property event using the specified value. 
147
        * @method fireEvent
148
        * @private
149
        * @param {String} key The configuration property's name
150
        * @param {value} Object The value of the correct type for the property
151
        */ 
152
        fireEvent: function ( key, value ) {
153
            var property = this.config[key];
154
        
155
            if (property && property.event) {
156
                property.event.fire(value);
157
            } 
158
        },
159
        
160
        /**
161
        * Adds a property to the Config Object's private config hash.
162
        * @method addProperty
163
        * @param {String} key The configuration property's name
164
        * @param {Object} propertyObject The Object containing all of this 
165
        * property's arguments
166
        */
167
        addProperty: function ( key, propertyObject ) {
168
            key = key.toLowerCase();
169
        
170
            this.config[key] = propertyObject;
171
        
172
            propertyObject.event = this.createEvent(key, { scope: this.owner });
173
            propertyObject.event.signature = CustomEvent.LIST;
174
            
175
            
176
            propertyObject.key = key;
177
        
178
            if (propertyObject.handler) {
179
                propertyObject.event.subscribe(propertyObject.handler, 
180
                    this.owner);
181
            }
182
        
183
            this.setProperty(key, propertyObject.value, true);
184
            
185
            if (! propertyObject.suppressEvent) {
186
                this.queueProperty(key, propertyObject.value);
187
            }
188
            
189
        },
190
        
191
        /**
192
        * Returns a key-value configuration map of the values currently set in  
193
        * the Config Object.
194
        * @method getConfig
195
        * @return {Object} The current config, represented in a key-value map
196
        */
197
        getConfig: function () {
198
        
199
            var cfg = {},
200
                currCfg = this.config,
201
                prop,
202
                property;
203
                
204
            for (prop in currCfg) {
205
                if (Lang.hasOwnProperty(currCfg, prop)) {
206
                    property = currCfg[prop];
207
                    if (property && property.event) {
208
                        cfg[prop] = property.value;
209
                    }
210
                }
211
            }
212
213
            return cfg;
214
        },
215
        
216
        /**
217
        * Returns the value of specified property.
218
        * @method getProperty
219
        * @param {String} key The name of the property
220
        * @return {Object}  The value of the specified property
221
        */
222
        getProperty: function (key) {
223
            var property = this.config[key.toLowerCase()];
224
            if (property && property.event) {
225
                return property.value;
226
            } else {
227
                return undefined;
228
            }
229
        },
230
        
231
        /**
232
        * Resets the specified property's value to its initial value.
233
        * @method resetProperty
234
        * @param {String} key The name of the property
235
        * @return {Boolean} True is the property was reset, false if not
236
        */
237
        resetProperty: function (key) {
238
    
239
            key = key.toLowerCase();
240
        
241
            var property = this.config[key];
242
    
243
            if (property && property.event) {
244
    
245
                if (this.initialConfig[key] && 
246
                    !Lang.isUndefined(this.initialConfig[key])) {
247
    
248
                    this.setProperty(key, this.initialConfig[key]);
249
250
                    return true;
251
    
252
                }
253
    
254
            } else {
255
    
256
                return false;
257
            }
258
    
259
        },
260
        
261
        /**
262
        * Sets the value of a property. If the silent property is passed as 
263
        * true, the property's event will not be fired.
264
        * @method setProperty
265
        * @param {String} key The name of the property
266
        * @param {String} value The value to set the property to
267
        * @param {Boolean} silent Whether the value should be set silently, 
268
        * without firing the property event.
269
        * @return {Boolean} True, if the set was successful, false if it failed.
270
        */
271
        setProperty: function (key, value, silent) {
272
        
273
            var property;
274
        
275
            key = key.toLowerCase();
276
        
277
            if (this.queueInProgress && ! silent) {
278
                // Currently running through a queue... 
279
                this.queueProperty(key,value);
280
                return true;
281
    
282
            } else {
283
                property = this.config[key];
284
                if (property && property.event) {
285
                    if (property.validator && !property.validator(value)) {
286
                        return false;
287
                    } else {
288
                        property.value = value;
289
                        if (! silent) {
290
                            this.fireEvent(key, value);
291
                            this.configChangedEvent.fire([key, value]);
292
                        }
293
                        return true;
294
                    }
295
                } else {
296
                    return false;
297
                }
298
            }
299
        },
300
        
301
        /**
302
        * Sets the value of a property and queues its event to execute. If the 
303
        * event is already scheduled to execute, it is
304
        * moved from its current position to the end of the queue.
305
        * @method queueProperty
306
        * @param {String} key The name of the property
307
        * @param {String} value The value to set the property to
308
        * @return {Boolean}  true, if the set was successful, false if 
309
        * it failed.
310
        */ 
311
        queueProperty: function (key, value) {
312
        
313
            key = key.toLowerCase();
314
        
315
            var property = this.config[key],
316
                foundDuplicate = false,
317
                iLen,
318
                queueItem,
319
                queueItemKey,
320
                queueItemValue,
321
                sLen,
322
                supercedesCheck,
323
                qLen,
324
                queueItemCheck,
325
                queueItemCheckKey,
326
                queueItemCheckValue,
327
                i,
328
                s,
329
                q;
330
                                
331
            if (property && property.event) {
332
    
333
                if (!Lang.isUndefined(value) && property.validator && 
334
                    !property.validator(value)) { // validator
335
                    return false;
336
                } else {
337
        
338
                    if (!Lang.isUndefined(value)) {
339
                        property.value = value;
340
                    } else {
341
                        value = property.value;
342
                    }
343
        
344
                    foundDuplicate = false;
345
                    iLen = this.eventQueue.length;
346
        
347
                    for (i = 0; i < iLen; i++) {
348
                        queueItem = this.eventQueue[i];
349
        
350
                        if (queueItem) {
351
                            queueItemKey = queueItem[0];
352
                            queueItemValue = queueItem[1];
353
354
                            if (queueItemKey == key) {
355
    
356
                                /*
357
                                    found a dupe... push to end of queue, null 
358
                                    current item, and break
359
                                */
360
    
361
                                this.eventQueue[i] = null;
362
    
363
                                this.eventQueue.push(
364
                                    [key, (!Lang.isUndefined(value) ? 
365
                                    value : queueItemValue)]);
366
    
367
                                foundDuplicate = true;
368
                                break;
369
                            }
370
                        }
371
                    }
372
                    
373
                    // this is a refire, or a new property in the queue
374
    
375
                    if (! foundDuplicate && !Lang.isUndefined(value)) { 
376
                        this.eventQueue.push([key, value]);
377
                    }
378
                }
379
        
380
                if (property.supercedes) {
381
382
                    sLen = property.supercedes.length;
383
384
                    for (s = 0; s < sLen; s++) {
385
386
                        supercedesCheck = property.supercedes[s];
387
                        qLen = this.eventQueue.length;
388
389
                        for (q = 0; q < qLen; q++) {
390
                            queueItemCheck = this.eventQueue[q];
391
392
                            if (queueItemCheck) {
393
                                queueItemCheckKey = queueItemCheck[0];
394
                                queueItemCheckValue = queueItemCheck[1];
395
396
                                if (queueItemCheckKey == 
397
                                    supercedesCheck.toLowerCase() ) {
398
399
                                    this.eventQueue.push([queueItemCheckKey, 
400
                                        queueItemCheckValue]);
401
402
                                    this.eventQueue[q] = null;
403
                                    break;
404
405
                                }
406
                            }
407
                        }
408
                    }
409
                }
410
411
412
                return true;
413
            } else {
414
                return false;
415
            }
416
        },
417
        
418
        /**
419
        * Fires the event for a property using the property's current value.
420
        * @method refireEvent
421
        * @param {String} key The name of the property
422
        */
423
        refireEvent: function (key) {
424
    
425
            key = key.toLowerCase();
426
        
427
            var property = this.config[key];
428
    
429
            if (property && property.event && 
430
    
431
                !Lang.isUndefined(property.value)) {
432
    
433
                if (this.queueInProgress) {
434
    
435
                    this.queueProperty(key);
436
    
437
                } else {
438
    
439
                    this.fireEvent(key, property.value);
440
    
441
                }
442
    
443
            }
444
        },
445
        
446
        /**
447
        * Applies a key-value Object literal to the configuration, replacing  
448
        * any existing values, and queueing the property events.
449
        * Although the values will be set, fireQueue() must be called for their 
450
        * associated events to execute.
451
        * @method applyConfig
452
        * @param {Object} userConfig The configuration Object literal
453
        * @param {Boolean} init  When set to true, the initialConfig will 
454
        * be set to the userConfig passed in, so that calling a reset will 
455
        * reset the properties to the passed values.
456
        */
457
        applyConfig: function (userConfig, init) {
458
        
459
            var sKey,
460
                oConfig;
461
462
            if (init) {
463
                oConfig = {};
464
                for (sKey in userConfig) {
465
                    if (Lang.hasOwnProperty(userConfig, sKey)) {
466
                        oConfig[sKey.toLowerCase()] = userConfig[sKey];
467
                    }
468
                }
469
                this.initialConfig = oConfig;
470
            }
471
472
            for (sKey in userConfig) {
473
                if (Lang.hasOwnProperty(userConfig, sKey)) {
474
                    this.queueProperty(sKey, userConfig[sKey]);
475
                }
476
            }
477
        },
478
        
479
        /**
480
        * Refires the events for all configuration properties using their 
481
        * current values.
482
        * @method refresh
483
        */
484
        refresh: function () {
485
486
            var prop;
487
488
            for (prop in this.config) {
489
                if (Lang.hasOwnProperty(this.config, prop)) {
490
                    this.refireEvent(prop);
491
                }
492
            }
493
        },
494
        
495
        /**
496
        * Fires the normalized list of queued property change events
497
        * @method fireQueue
498
        */
499
        fireQueue: function () {
500
        
501
            var i, 
502
                queueItem,
503
                key,
504
                value,
505
                property;
506
        
507
            this.queueInProgress = true;
508
            for (i = 0;i < this.eventQueue.length; i++) {
509
                queueItem = this.eventQueue[i];
510
                if (queueItem) {
511
        
512
                    key = queueItem[0];
513
                    value = queueItem[1];
514
                    property = this.config[key];
515
516
                    property.value = value;
517
518
                    // Clear out queue entry, to avoid it being 
519
                    // re-added to the queue by any queueProperty/supercedes
520
                    // calls which are invoked during fireEvent
521
                    this.eventQueue[i] = null;
522
523
                    this.fireEvent(key,value);
524
                }
525
            }
526
            
527
            this.queueInProgress = false;
528
            this.eventQueue = [];
529
        },
530
        
531
        /**
532
        * Subscribes an external handler to the change event for any 
533
        * given property. 
534
        * @method subscribeToConfigEvent
535
        * @param {String} key The property name
536
        * @param {Function} handler The handler function to use subscribe to 
537
        * the property's event
538
        * @param {Object} obj The Object to use for scoping the event handler 
539
        * (see CustomEvent documentation)
540
        * @param {Boolean} overrideContext Optional. If true, will override
541
        * "this" within the handler to map to the scope Object passed into the
542
        * method.
543
        * @return {Boolean} True, if the subscription was successful, 
544
        * otherwise false.
545
        */ 
546
        subscribeToConfigEvent: function (key, handler, obj, overrideContext) {
547
    
548
            var property = this.config[key.toLowerCase()];
549
    
550
            if (property && property.event) {
551
                if (!Config.alreadySubscribed(property.event, handler, obj)) {
552
                    property.event.subscribe(handler, obj, overrideContext);
553
                }
554
                return true;
555
            } else {
556
                return false;
557
            }
558
    
559
        },
560
        
561
        /**
562
        * Unsubscribes an external handler from the change event for any 
563
        * given property. 
564
        * @method unsubscribeFromConfigEvent
565
        * @param {String} key The property name
566
        * @param {Function} handler The handler function to use subscribe to 
567
        * the property's event
568
        * @param {Object} obj The Object to use for scoping the event 
569
        * handler (see CustomEvent documentation)
570
        * @return {Boolean} True, if the unsubscription was successful, 
571
        * otherwise false.
572
        */
573
        unsubscribeFromConfigEvent: function (key, handler, obj) {
574
            var property = this.config[key.toLowerCase()];
575
            if (property && property.event) {
576
                return property.event.unsubscribe(handler, obj);
577
            } else {
578
                return false;
579
            }
580
        },
581
        
582
        /**
583
        * Returns a string representation of the Config object
584
        * @method toString
585
        * @return {String} The Config object in string format.
586
        */
587
        toString: function () {
588
            var output = "Config";
589
            if (this.owner) {
590
                output += " [" + this.owner.toString() + "]";
591
            }
592
            return output;
593
        },
594
        
595
        /**
596
        * Returns a string representation of the Config object's current 
597
        * CustomEvent queue
598
        * @method outputEventQueue
599
        * @return {String} The string list of CustomEvents currently queued 
600
        * for execution
601
        */
602
        outputEventQueue: function () {
603
604
            var output = "",
605
                queueItem,
606
                q,
607
                nQueue = this.eventQueue.length;
608
              
609
            for (q = 0; q < nQueue; q++) {
610
                queueItem = this.eventQueue[q];
611
                if (queueItem) {
612
                    output += queueItem[0] + "=" + queueItem[1] + ", ";
613
                }
614
            }
615
            return output;
616
        },
617
618
        /**
619
        * Sets all properties to null, unsubscribes all listeners from each 
620
        * property's change event and all listeners from the configChangedEvent.
621
        * @method destroy
622
        */
623
        destroy: function () {
624
625
            var oConfig = this.config,
626
                sProperty,
627
                oProperty;
628
629
630
            for (sProperty in oConfig) {
631
            
632
                if (Lang.hasOwnProperty(oConfig, sProperty)) {
633
634
                    oProperty = oConfig[sProperty];
635
636
                    oProperty.event.unsubscribeAll();
637
                    oProperty.event = null;
638
639
                }
640
            
641
            }
642
            
643
            this.configChangedEvent.unsubscribeAll();
644
            
645
            this.configChangedEvent = null;
646
            this.owner = null;
647
            this.config = null;
648
            this.initialConfig = null;
649
            this.eventQueue = null;
650
        
651
        }
652
653
    };
654
    
655
    
656
    
657
    /**
658
    * Checks to determine if a particular function/Object pair are already 
659
    * subscribed to the specified CustomEvent
660
    * @method YAHOO.util.Config.alreadySubscribed
661
    * @static
662
    * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check 
663
    * the subscriptions
664
    * @param {Function} fn The function to look for in the subscribers list
665
    * @param {Object} obj The execution scope Object for the subscription
666
    * @return {Boolean} true, if the function/Object pair is already subscribed 
667
    * to the CustomEvent passed in
668
    */
669
    Config.alreadySubscribed = function (evt, fn, obj) {
670
    
671
        var nSubscribers = evt.subscribers.length,
672
            subsc,
673
            i;
674
675
        if (nSubscribers > 0) {
676
            i = nSubscribers - 1;
677
            do {
678
                subsc = evt.subscribers[i];
679
                if (subsc && subsc.obj == obj && subsc.fn == fn) {
680
                    return true;
681
                }
682
            }
683
            while (i--);
684
        }
685
686
        return false;
687
688
    };
689
690
    YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
691
692
}());
693
(function () {
694
695
    /**
696
    * The Container family of components is designed to enable developers to 
697
    * create different kinds of content-containing modules on the web. Module 
698
    * and Overlay are the most basic containers, and they can be used directly 
699
    * or extended to build custom containers. Also part of the Container family 
700
    * are four UI controls that extend Module and Overlay: Tooltip, Panel, 
701
    * Dialog, and SimpleDialog.
702
    * @module container
703
    * @title Container
704
    * @requires yahoo, dom, event 
705
    * @optional dragdrop, animation, button
706
    */
707
    
708
    /**
709
    * Module is a JavaScript representation of the Standard Module Format. 
710
    * Standard Module Format is a simple standard for markup containers where 
711
    * child nodes representing the header, body, and footer of the content are 
712
    * denoted using the CSS classes "hd", "bd", and "ft" respectively. 
713
    * Module is the base class for all other classes in the YUI 
714
    * Container package.
715
    * @namespace YAHOO.widget
716
    * @class Module
717
    * @constructor
718
    * @param {String} el The element ID representing the Module <em>OR</em>
719
    * @param {HTMLElement} el The element representing the Module
720
    * @param {Object} userConfig The configuration Object literal containing 
721
    * the configuration that should be set for this module. See configuration 
722
    * documentation for more details.
723
    */
724
    YAHOO.widget.Module = function (el, userConfig) {
725
        if (el) {
726
            this.init(el, userConfig);
727
        } else {
728
        }
729
    };
730
731
    var Dom = YAHOO.util.Dom,
732
        Config = YAHOO.util.Config,
733
        Event = YAHOO.util.Event,
734
        CustomEvent = YAHOO.util.CustomEvent,
735
        Module = YAHOO.widget.Module,
736
        UA = YAHOO.env.ua,
737
738
        m_oModuleTemplate,
739
        m_oHeaderTemplate,
740
        m_oBodyTemplate,
741
        m_oFooterTemplate,
742
743
        /**
744
        * Constant representing the name of the Module's events
745
        * @property EVENT_TYPES
746
        * @private
747
        * @final
748
        * @type Object
749
        */
750
        EVENT_TYPES = {
751
            "BEFORE_INIT": "beforeInit",
752
            "INIT": "init",
753
            "APPEND": "append",
754
            "BEFORE_RENDER": "beforeRender",
755
            "RENDER": "render",
756
            "CHANGE_HEADER": "changeHeader",
757
            "CHANGE_BODY": "changeBody",
758
            "CHANGE_FOOTER": "changeFooter",
759
            "CHANGE_CONTENT": "changeContent",
760
            "DESTROY": "destroy",
761
            "BEFORE_SHOW": "beforeShow",
762
            "SHOW": "show",
763
            "BEFORE_HIDE": "beforeHide",
764
            "HIDE": "hide"
765
        },
766
            
767
        /**
768
        * Constant representing the Module's configuration properties
769
        * @property DEFAULT_CONFIG
770
        * @private
771
        * @final
772
        * @type Object
773
        */
774
        DEFAULT_CONFIG = {
775
        
776
            "VISIBLE": { 
777
                key: "visible", 
778
                value: true, 
779
                validator: YAHOO.lang.isBoolean 
780
            },
781
782
            "EFFECT": {
783
                key: "effect",
784
                suppressEvent: true,
785
                supercedes: ["visible"]
786
            },
787
788
            "MONITOR_RESIZE": {
789
                key: "monitorresize",
790
                value: true
791
            },
792
793
            "APPEND_TO_DOCUMENT_BODY": {
794
                key: "appendtodocumentbody",
795
                value: false
796
            }
797
        };
798
799
    /**
800
    * Constant representing the prefix path to use for non-secure images
801
    * @property YAHOO.widget.Module.IMG_ROOT
802
    * @static
803
    * @final
804
    * @type String
805
    */
806
    Module.IMG_ROOT = null;
807
    
808
    /**
809
    * Constant representing the prefix path to use for securely served images
810
    * @property YAHOO.widget.Module.IMG_ROOT_SSL
811
    * @static
812
    * @final
813
    * @type String
814
    */
815
    Module.IMG_ROOT_SSL = null;
816
    
817
    /**
818
    * Constant for the default CSS class name that represents a Module
819
    * @property YAHOO.widget.Module.CSS_MODULE
820
    * @static
821
    * @final
822
    * @type String
823
    */
824
    Module.CSS_MODULE = "yui-module";
825
    
826
    /**
827
    * Constant representing the module header
828
    * @property YAHOO.widget.Module.CSS_HEADER
829
    * @static
830
    * @final
831
    * @type String
832
    */
833
    Module.CSS_HEADER = "hd";
834
835
    /**
836
    * Constant representing the module body
837
    * @property YAHOO.widget.Module.CSS_BODY
838
    * @static
839
    * @final
840
    * @type String
841
    */
842
    Module.CSS_BODY = "bd";
843
    
844
    /**
845
    * Constant representing the module footer
846
    * @property YAHOO.widget.Module.CSS_FOOTER
847
    * @static
848
    * @final
849
    * @type String
850
    */
851
    Module.CSS_FOOTER = "ft";
852
    
853
    /**
854
    * Constant representing the url for the "src" attribute of the iframe 
855
    * used to monitor changes to the browser's base font size
856
    * @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL
857
    * @static
858
    * @final
859
    * @type String
860
    */
861
    Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;";
862
863
    /**
864
    * Constant representing the buffer amount (in pixels) to use when positioning
865
    * the text resize monitor offscreen. The resize monitor is positioned
866
    * offscreen by an amount eqaul to its offsetHeight + the buffer value.
867
    * 
868
    * @property YAHOO.widget.Module.RESIZE_MONITOR_BUFFER
869
    * @static
870
    * @type Number
871
    */
872
    // Set to 1, to work around pixel offset in IE8, which increases when zoom is used
873
    Module.RESIZE_MONITOR_BUFFER = 1;
874
875
    /**
876
    * Singleton CustomEvent fired when the font size is changed in the browser.
877
    * Opera's "zoom" functionality currently does not support text 
878
    * size detection.
879
    * @event YAHOO.widget.Module.textResizeEvent
880
    */
881
    Module.textResizeEvent = new CustomEvent("textResize");
882
883
    /**
884
     * Helper utility method, which forces a document level 
885
     * redraw for Opera, which can help remove repaint
886
     * irregularities after applying DOM changes.
887
     *
888
     * @method YAHOO.widget.Module.forceDocumentRedraw
889
     * @static
890
     */
891
    Module.forceDocumentRedraw = function() {
892
        var docEl = document.documentElement;
893
        if (docEl) {
894
            docEl.className += " ";
895
            docEl.className = YAHOO.lang.trim(docEl.className);
896
        }
897
    };
898
899
    function createModuleTemplate() {
900
901
        if (!m_oModuleTemplate) {
902
            m_oModuleTemplate = document.createElement("div");
903
            
904
            m_oModuleTemplate.innerHTML = ("<div class=\"" + 
905
                Module.CSS_HEADER + "\"></div>" + "<div class=\"" + 
906
                Module.CSS_BODY + "\"></div><div class=\"" + 
907
                Module.CSS_FOOTER + "\"></div>");
908
909
            m_oHeaderTemplate = m_oModuleTemplate.firstChild;
910
            m_oBodyTemplate = m_oHeaderTemplate.nextSibling;
911
            m_oFooterTemplate = m_oBodyTemplate.nextSibling;
912
        }
913
914
        return m_oModuleTemplate;
915
    }
916
917
    function createHeader() {
918
        if (!m_oHeaderTemplate) {
919
            createModuleTemplate();
920
        }
921
        return (m_oHeaderTemplate.cloneNode(false));
922
    }
923
924
    function createBody() {
925
        if (!m_oBodyTemplate) {
926
            createModuleTemplate();
927
        }
928
        return (m_oBodyTemplate.cloneNode(false));
929
    }
930
931
    function createFooter() {
932
        if (!m_oFooterTemplate) {
933
            createModuleTemplate();
934
        }
935
        return (m_oFooterTemplate.cloneNode(false));
936
    }
937
938
    Module.prototype = {
939
940
        /**
941
        * The class's constructor function
942
        * @property contructor
943
        * @type Function
944
        */
945
        constructor: Module,
946
        
947
        /**
948
        * The main module element that contains the header, body, and footer
949
        * @property element
950
        * @type HTMLElement
951
        */
952
        element: null,
953
954
        /**
955
        * The header element, denoted with CSS class "hd"
956
        * @property header
957
        * @type HTMLElement
958
        */
959
        header: null,
960
961
        /**
962
        * The body element, denoted with CSS class "bd"
963
        * @property body
964
        * @type HTMLElement
965
        */
966
        body: null,
967
968
        /**
969
        * The footer element, denoted with CSS class "ft"
970
        * @property footer
971
        * @type HTMLElement
972
        */
973
        footer: null,
974
975
        /**
976
        * The id of the element
977
        * @property id
978
        * @type String
979
        */
980
        id: null,
981
982
        /**
983
        * A string representing the root path for all images created by
984
        * a Module instance.
985
        * @deprecated It is recommend that any images for a Module be applied
986
        * via CSS using the "background-image" property.
987
        * @property imageRoot
988
        * @type String
989
        */
990
        imageRoot: Module.IMG_ROOT,
991
992
        /**
993
        * Initializes the custom events for Module which are fired 
994
        * automatically at appropriate times by the Module class.
995
        * @method initEvents
996
        */
997
        initEvents: function () {
998
999
            var SIGNATURE = CustomEvent.LIST;
1000
1001
            /**
1002
            * CustomEvent fired prior to class initalization.
1003
            * @event beforeInitEvent
1004
            * @param {class} classRef class reference of the initializing 
1005
            * class, such as this.beforeInitEvent.fire(Module)
1006
            */
1007
            this.beforeInitEvent = this.createEvent(EVENT_TYPES.BEFORE_INIT);
1008
            this.beforeInitEvent.signature = SIGNATURE;
1009
1010
            /**
1011
            * CustomEvent fired after class initalization.
1012
            * @event initEvent
1013
            * @param {class} classRef class reference of the initializing 
1014
            * class, such as this.beforeInitEvent.fire(Module)
1015
            */  
1016
            this.initEvent = this.createEvent(EVENT_TYPES.INIT);
1017
            this.initEvent.signature = SIGNATURE;
1018
1019
            /**
1020
            * CustomEvent fired when the Module is appended to the DOM
1021
            * @event appendEvent
1022
            */
1023
            this.appendEvent = this.createEvent(EVENT_TYPES.APPEND);
1024
            this.appendEvent.signature = SIGNATURE;
1025
1026
            /**
1027
            * CustomEvent fired before the Module is rendered
1028
            * @event beforeRenderEvent
1029
            */
1030
            this.beforeRenderEvent = this.createEvent(EVENT_TYPES.BEFORE_RENDER);
1031
            this.beforeRenderEvent.signature = SIGNATURE;
1032
        
1033
            /**
1034
            * CustomEvent fired after the Module is rendered
1035
            * @event renderEvent
1036
            */
1037
            this.renderEvent = this.createEvent(EVENT_TYPES.RENDER);
1038
            this.renderEvent.signature = SIGNATURE;
1039
        
1040
            /**
1041
            * CustomEvent fired when the header content of the Module 
1042
            * is modified
1043
            * @event changeHeaderEvent
1044
            * @param {String/HTMLElement} content String/element representing 
1045
            * the new header content
1046
            */
1047
            this.changeHeaderEvent = this.createEvent(EVENT_TYPES.CHANGE_HEADER);
1048
            this.changeHeaderEvent.signature = SIGNATURE;
1049
            
1050
            /**
1051
            * CustomEvent fired when the body content of the Module is modified
1052
            * @event changeBodyEvent
1053
            * @param {String/HTMLElement} content String/element representing 
1054
            * the new body content
1055
            */  
1056
            this.changeBodyEvent = this.createEvent(EVENT_TYPES.CHANGE_BODY);
1057
            this.changeBodyEvent.signature = SIGNATURE;
1058
            
1059
            /**
1060
            * CustomEvent fired when the footer content of the Module 
1061
            * is modified
1062
            * @event changeFooterEvent
1063
            * @param {String/HTMLElement} content String/element representing 
1064
            * the new footer content
1065
            */
1066
            this.changeFooterEvent = this.createEvent(EVENT_TYPES.CHANGE_FOOTER);
1067
            this.changeFooterEvent.signature = SIGNATURE;
1068
        
1069
            /**
1070
            * CustomEvent fired when the content of the Module is modified
1071
            * @event changeContentEvent
1072
            */
1073
            this.changeContentEvent = this.createEvent(EVENT_TYPES.CHANGE_CONTENT);
1074
            this.changeContentEvent.signature = SIGNATURE;
1075
1076
            /**
1077
            * CustomEvent fired when the Module is destroyed
1078
            * @event destroyEvent
1079
            */
1080
            this.destroyEvent = this.createEvent(EVENT_TYPES.DESTROY);
1081
            this.destroyEvent.signature = SIGNATURE;
1082
1083
            /**
1084
            * CustomEvent fired before the Module is shown
1085
            * @event beforeShowEvent
1086
            */
1087
            this.beforeShowEvent = this.createEvent(EVENT_TYPES.BEFORE_SHOW);
1088
            this.beforeShowEvent.signature = SIGNATURE;
1089
1090
            /**
1091
            * CustomEvent fired after the Module is shown
1092
            * @event showEvent
1093
            */
1094
            this.showEvent = this.createEvent(EVENT_TYPES.SHOW);
1095
            this.showEvent.signature = SIGNATURE;
1096
1097
            /**
1098
            * CustomEvent fired before the Module is hidden
1099
            * @event beforeHideEvent
1100
            */
1101
            this.beforeHideEvent = this.createEvent(EVENT_TYPES.BEFORE_HIDE);
1102
            this.beforeHideEvent.signature = SIGNATURE;
1103
1104
            /**
1105
            * CustomEvent fired after the Module is hidden
1106
            * @event hideEvent
1107
            */
1108
            this.hideEvent = this.createEvent(EVENT_TYPES.HIDE);
1109
            this.hideEvent.signature = SIGNATURE;
1110
        }, 
1111
1112
        /**
1113
        * String representing the current user-agent platform
1114
        * @property platform
1115
        * @type String
1116
        */
1117
        platform: function () {
1118
            var ua = navigator.userAgent.toLowerCase();
1119
1120
            if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
1121
                return "windows";
1122
            } else if (ua.indexOf("macintosh") != -1) {
1123
                return "mac";
1124
            } else {
1125
                return false;
1126
            }
1127
        }(),
1128
        
1129
        /**
1130
        * String representing the user-agent of the browser
1131
        * @deprecated Use YAHOO.env.ua
1132
        * @property browser
1133
        * @type String
1134
        */
1135
        browser: function () {
1136
            var ua = navigator.userAgent.toLowerCase();
1137
            /*
1138
                 Check Opera first in case of spoof and check Safari before
1139
                 Gecko since Safari's user agent string includes "like Gecko"
1140
            */
1141
            if (ua.indexOf('opera') != -1) { 
1142
                return 'opera';
1143
            } else if (ua.indexOf('msie 7') != -1) {
1144
                return 'ie7';
1145
            } else if (ua.indexOf('msie') != -1) {
1146
                return 'ie';
1147
            } else if (ua.indexOf('safari') != -1) { 
1148
                return 'safari';
1149
            } else if (ua.indexOf('gecko') != -1) {
1150
                return 'gecko';
1151
            } else {
1152
                return false;
1153
            }
1154
        }(),
1155
        
1156
        /**
1157
        * Boolean representing whether or not the current browsing context is 
1158
        * secure (https)
1159
        * @property isSecure
1160
        * @type Boolean
1161
        */
1162
        isSecure: function () {
1163
            if (window.location.href.toLowerCase().indexOf("https") === 0) {
1164
                return true;
1165
            } else {
1166
                return false;
1167
            }
1168
        }(),
1169
        
1170
        /**
1171
        * Initializes the custom events for Module which are fired 
1172
        * automatically at appropriate times by the Module class.
1173
        */
1174
        initDefaultConfig: function () {
1175
            // Add properties //
1176
            /**
1177
            * Specifies whether the Module is visible on the page.
1178
            * @config visible
1179
            * @type Boolean
1180
            * @default true
1181
            */
1182
            this.cfg.addProperty(DEFAULT_CONFIG.VISIBLE.key, {
1183
                handler: this.configVisible, 
1184
                value: DEFAULT_CONFIG.VISIBLE.value, 
1185
                validator: DEFAULT_CONFIG.VISIBLE.validator
1186
            });
1187
1188
            /**
1189
            * <p>
1190
            * Object or array of objects representing the ContainerEffect 
1191
            * classes that are active for animating the container.
1192
            * </p>
1193
            * <p>
1194
            * <strong>NOTE:</strong> Although this configuration 
1195
            * property is introduced at the Module level, an out of the box
1196
            * implementation is not shipped for the Module class so setting
1197
            * the proroperty on the Module class has no effect. The Overlay 
1198
            * class is the first class to provide out of the box ContainerEffect 
1199
            * support.
1200
            * </p>
1201
            * @config effect
1202
            * @type Object
1203
            * @default null
1204
            */
1205
            this.cfg.addProperty(DEFAULT_CONFIG.EFFECT.key, {
1206
                suppressEvent: DEFAULT_CONFIG.EFFECT.suppressEvent, 
1207
                supercedes: DEFAULT_CONFIG.EFFECT.supercedes
1208
            });
1209
1210
            /**
1211
            * Specifies whether to create a special proxy iframe to monitor 
1212
            * for user font resizing in the document
1213
            * @config monitorresize
1214
            * @type Boolean
1215
            * @default true
1216
            */
1217
            this.cfg.addProperty(DEFAULT_CONFIG.MONITOR_RESIZE.key, {
1218
                handler: this.configMonitorResize,
1219
                value: DEFAULT_CONFIG.MONITOR_RESIZE.value
1220
            });
1221
1222
            /**
1223
            * Specifies if the module should be rendered as the first child 
1224
            * of document.body or appended as the last child when render is called
1225
            * with document.body as the "appendToNode".
1226
            * <p>
1227
            * Appending to the body while the DOM is still being constructed can 
1228
            * lead to Operation Aborted errors in IE hence this flag is set to 
1229
            * false by default.
1230
            * </p>
1231
            * 
1232
            * @config appendtodocumentbody
1233
            * @type Boolean
1234
            * @default false
1235
            */
1236
            this.cfg.addProperty(DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.key, {
1237
                value: DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.value
1238
            });
1239
        },
1240
1241
        /**
1242
        * The Module class's initialization method, which is executed for
1243
        * Module and all of its subclasses. This method is automatically 
1244
        * called by the constructor, and  sets up all DOM references for 
1245
        * pre-existing markup, and creates required markup if it is not 
1246
        * already present.
1247
        * <p>
1248
        * If the element passed in does not have an id, one will be generated
1249
        * for it.
1250
        * </p>
1251
        * @method init
1252
        * @param {String} el The element ID representing the Module <em>OR</em>
1253
        * @param {HTMLElement} el The element representing the Module
1254
        * @param {Object} userConfig The configuration Object literal 
1255
        * containing the configuration that should be set for this module. 
1256
        * See configuration documentation for more details.
1257
        */
1258
        init: function (el, userConfig) {
1259
1260
            var elId, child;
1261
1262
            this.initEvents();
1263
            this.beforeInitEvent.fire(Module);
1264
1265
            /**
1266
            * The Module's Config object used for monitoring 
1267
            * configuration properties.
1268
            * @property cfg
1269
            * @type YAHOO.util.Config
1270
            */
1271
            this.cfg = new Config(this);
1272
1273
            if (this.isSecure) {
1274
                this.imageRoot = Module.IMG_ROOT_SSL;
1275
            }
1276
1277
            if (typeof el == "string") {
1278
                elId = el;
1279
                el = document.getElementById(el);
1280
                if (! el) {
1281
                    el = (createModuleTemplate()).cloneNode(false);
1282
                    el.id = elId;
1283
                }
1284
            }
1285
1286
            this.id = Dom.generateId(el);
1287
            this.element = el;
1288
1289
            child = this.element.firstChild;
1290
1291
            if (child) {
1292
                var fndHd = false, fndBd = false, fndFt = false;
1293
                do {
1294
                    // We're looking for elements
1295
                    if (1 == child.nodeType) {
1296
                        if (!fndHd && Dom.hasClass(child, Module.CSS_HEADER)) {
1297
                            this.header = child;
1298
                            fndHd = true;
1299
                        } else if (!fndBd && Dom.hasClass(child, Module.CSS_BODY)) {
1300
                            this.body = child;
1301
                            fndBd = true;
1302
                        } else if (!fndFt && Dom.hasClass(child, Module.CSS_FOOTER)){
1303
                            this.footer = child;
1304
                            fndFt = true;
1305
                        }
1306
                    }
1307
                } while ((child = child.nextSibling));
1308
            }
1309
1310
            this.initDefaultConfig();
1311
1312
            Dom.addClass(this.element, Module.CSS_MODULE);
1313
1314
            if (userConfig) {
1315
                this.cfg.applyConfig(userConfig, true);
1316
            }
1317
1318
            /*
1319
                Subscribe to the fireQueue() method of Config so that any 
1320
                queued configuration changes are excecuted upon render of 
1321
                the Module
1322
            */ 
1323
1324
            if (!Config.alreadySubscribed(this.renderEvent, this.cfg.fireQueue, this.cfg)) {
1325
                this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
1326
            }
1327
1328
            this.initEvent.fire(Module);
1329
        },
1330
1331
        /**
1332
        * Initialize an empty IFRAME that is placed out of the visible area 
1333
        * that can be used to detect text resize.
1334
        * @method initResizeMonitor
1335
        */
1336
        initResizeMonitor: function () {
1337
1338
            var isGeckoWin = (UA.gecko && this.platform == "windows");
1339
            if (isGeckoWin) {
1340
                // Help prevent spinning loading icon which 
1341
                // started with FireFox 2.0.0.8/Win
1342
                var self = this;
1343
                setTimeout(function(){self._initResizeMonitor();}, 0);
1344
            } else {
1345
                this._initResizeMonitor();
1346
            }
1347
        },
1348
1349
        /**
1350
         * Create and initialize the text resize monitoring iframe.
1351
         * 
1352
         * @protected
1353
         * @method _initResizeMonitor
1354
         */
1355
        _initResizeMonitor : function() {
1356
1357
            var oDoc, 
1358
                oIFrame, 
1359
                sHTML;
1360
1361
            function fireTextResize() {
1362
                Module.textResizeEvent.fire();
1363
            }
1364
1365
            if (!UA.opera) {
1366
                oIFrame = Dom.get("_yuiResizeMonitor");
1367
1368
                var supportsCWResize = this._supportsCWResize();
1369
1370
                if (!oIFrame) {
1371
                    oIFrame = document.createElement("iframe");
1372
1373
                    if (this.isSecure && Module.RESIZE_MONITOR_SECURE_URL && UA.ie) {
1374
                        oIFrame.src = Module.RESIZE_MONITOR_SECURE_URL;
1375
                    }
1376
1377
                    if (!supportsCWResize) {
1378
                        // Can't monitor on contentWindow, so fire from inside iframe
1379
                        sHTML = ["<html><head><script ",
1380
                                 "type=\"text/javascript\">",
1381
                                 "window.onresize=function(){window.parent.",
1382
                                 "YAHOO.widget.Module.textResizeEvent.",
1383
                                 "fire();};<",
1384
                                 "\/script></head>",
1385
                                 "<body></body></html>"].join('');
1386
1387
                        oIFrame.src = "data:text/html;charset=utf-8," + encodeURIComponent(sHTML);
1388
                    }
1389
1390
                    oIFrame.id = "_yuiResizeMonitor";
1391
                    oIFrame.title = "Text Resize Monitor";
1392
                    /*
1393
                        Need to set "position" property before inserting the 
1394
                        iframe into the document or Safari's status bar will 
1395
                        forever indicate the iframe is loading 
1396
                        (See YUILibrary bug #1723064)
1397
                    */
1398
                    oIFrame.style.position = "absolute";
1399
                    oIFrame.style.visibility = "hidden";
1400
1401
                    var db = document.body,
1402
                        fc = db.firstChild;
1403
                    if (fc) {
1404
                        db.insertBefore(oIFrame, fc);
1405
                    } else {
1406
                        db.appendChild(oIFrame);
1407
                    }
1408
1409
                    // Setting the background color fixes an issue with IE6/IE7, where
1410
                    // elements in the DOM, with -ve margin-top which positioned them 
1411
                    // offscreen (so they would be overlapped by the iframe and its -ve top
1412
                    // setting), would have their -ve margin-top ignored, when the iframe 
1413
                    // was added.
1414
                    oIFrame.style.backgroundColor = "transparent";
1415
1416
                    oIFrame.style.borderWidth = "0";
1417
                    oIFrame.style.width = "2em";
1418
                    oIFrame.style.height = "2em";
1419
                    oIFrame.style.left = "0";
1420
                    oIFrame.style.top = (-1 * (oIFrame.offsetHeight + Module.RESIZE_MONITOR_BUFFER)) + "px";
1421
                    oIFrame.style.visibility = "visible";
1422
1423
                    /*
1424
                       Don't open/close the document for Gecko like we used to, since it
1425
                       leads to duplicate cookies. (See YUILibrary bug #1721755)
1426
                    */
1427
                    if (UA.webkit) {
1428
                        oDoc = oIFrame.contentWindow.document;
1429
                        oDoc.open();
1430
                        oDoc.close();
1431
                    }
1432
                }
1433
1434
                if (oIFrame && oIFrame.contentWindow) {
1435
                    Module.textResizeEvent.subscribe(this.onDomResize, this, true);
1436
1437
                    if (!Module.textResizeInitialized) {
1438
                        if (supportsCWResize) {
1439
                            if (!Event.on(oIFrame.contentWindow, "resize", fireTextResize)) {
1440
                                /*
1441
                                     This will fail in IE if document.domain has 
1442
                                     changed, so we must change the listener to 
1443
                                     use the oIFrame element instead
1444
                                */
1445
                                Event.on(oIFrame, "resize", fireTextResize);
1446
                            }
1447
                        }
1448
                        Module.textResizeInitialized = true;
1449
                    }
1450
                    this.resizeMonitor = oIFrame;
1451
                }
1452
            }
1453
        },
1454
1455
        /**
1456
         * Text resize monitor helper method.
1457
         * Determines if the browser supports resize events on iframe content windows.
1458
         * 
1459
         * @private
1460
         * @method _supportsCWResize
1461
         */
1462
        _supportsCWResize : function() {
1463
            /*
1464
                Gecko 1.8.0 (FF1.5), 1.8.1.0-5 (FF2) won't fire resize on contentWindow.
1465
                Gecko 1.8.1.6+ (FF2.0.0.6+) and all other browsers will fire resize on contentWindow.
1466
1467
                We don't want to start sniffing for patch versions, so fire textResize the same
1468
                way on all FF2 flavors
1469
             */
1470
            var bSupported = true;
1471
            if (UA.gecko && UA.gecko <= 1.8) {
1472
                bSupported = false;
1473
            }
1474
            return bSupported;
1475
        },
1476
1477
        /**
1478
        * Event handler fired when the resize monitor element is resized.
1479
        * @method onDomResize
1480
        * @param {DOMEvent} e The DOM resize event
1481
        * @param {Object} obj The scope object passed to the handler
1482
        */
1483
        onDomResize: function (e, obj) {
1484
1485
            var nTop = -1 * (this.resizeMonitor.offsetHeight + Module.RESIZE_MONITOR_BUFFER);
1486
1487
            this.resizeMonitor.style.top = nTop + "px";
1488
            this.resizeMonitor.style.left = "0";
1489
        },
1490
1491
        /**
1492
        * Sets the Module's header content to the string specified, or appends 
1493
        * the passed element to the header. If no header is present, one will 
1494
        * be automatically created. An empty string can be passed to the method
1495
        * to clear the contents of the header.
1496
        * 
1497
        * @method setHeader
1498
        * @param {String} headerContent The string used to set the header.
1499
        * As a convenience, non HTMLElement objects can also be passed into 
1500
        * the method, and will be treated as strings, with the header innerHTML
1501
        * set to their default toString implementations.
1502
        * <em>OR</em>
1503
        * @param {HTMLElement} headerContent The HTMLElement to append to 
1504
        * <em>OR</em>
1505
        * @param {DocumentFragment} headerContent The document fragment 
1506
        * containing elements which are to be added to the header
1507
        */
1508
        setHeader: function (headerContent) {
1509
            var oHeader = this.header || (this.header = createHeader());
1510
1511
            if (headerContent.nodeName) {
1512
                oHeader.innerHTML = "";
1513
                oHeader.appendChild(headerContent);
1514
            } else {
1515
                oHeader.innerHTML = headerContent;
1516
            }
1517
1518
            if (this._rendered) {
1519
                this._renderHeader();
1520
            }
1521
1522
            this.changeHeaderEvent.fire(headerContent);
1523
            this.changeContentEvent.fire();
1524
1525
        },
1526
1527
        /**
1528
        * Appends the passed element to the header. If no header is present, 
1529
        * one will be automatically created.
1530
        * @method appendToHeader
1531
        * @param {HTMLElement | DocumentFragment} element The element to 
1532
        * append to the header. In the case of a document fragment, the
1533
        * children of the fragment will be appended to the header.
1534
        */
1535
        appendToHeader: function (element) {
1536
            var oHeader = this.header || (this.header = createHeader());
1537
1538
            oHeader.appendChild(element);
1539
1540
            this.changeHeaderEvent.fire(element);
1541
            this.changeContentEvent.fire();
1542
1543
        },
1544
1545
        /**
1546
        * Sets the Module's body content to the HTML specified. 
1547
        * 
1548
        * If no body is present, one will be automatically created. 
1549
        * 
1550
        * An empty string can be passed to the method to clear the contents of the body.
1551
        * @method setBody
1552
        * @param {String} bodyContent The HTML used to set the body. 
1553
        * As a convenience, non HTMLElement objects can also be passed into 
1554
        * the method, and will be treated as strings, with the body innerHTML
1555
        * set to their default toString implementations.
1556
        * <em>OR</em>
1557
        * @param {HTMLElement} bodyContent The HTMLElement to add as the first and only
1558
        * child of the body element.
1559
        * <em>OR</em>
1560
        * @param {DocumentFragment} bodyContent The document fragment 
1561
        * containing elements which are to be added to the body
1562
        */
1563
        setBody: function (bodyContent) {
1564
            var oBody = this.body || (this.body = createBody());
1565
1566
            if (bodyContent.nodeName) {
1567
                oBody.innerHTML = "";
1568
                oBody.appendChild(bodyContent);
1569
            } else {
1570
                oBody.innerHTML = bodyContent;
1571
            }
1572
1573
            if (this._rendered) {
1574
                this._renderBody();
1575
            }
1576
1577
            this.changeBodyEvent.fire(bodyContent);
1578
            this.changeContentEvent.fire();
1579
        },
1580
1581
        /**
1582
        * Appends the passed element to the body. If no body is present, one 
1583
        * will be automatically created.
1584
        * @method appendToBody
1585
        * @param {HTMLElement | DocumentFragment} element The element to 
1586
        * append to the body. In the case of a document fragment, the
1587
        * children of the fragment will be appended to the body.
1588
        * 
1589
        */
1590
        appendToBody: function (element) {
1591
            var oBody = this.body || (this.body = createBody());
1592
        
1593
            oBody.appendChild(element);
1594
1595
            this.changeBodyEvent.fire(element);
1596
            this.changeContentEvent.fire();
1597
1598
        },
1599
        
1600
        /**
1601
        * Sets the Module's footer content to the HTML specified, or appends 
1602
        * the passed element to the footer. If no footer is present, one will 
1603
        * be automatically created. An empty string can be passed to the method
1604
        * to clear the contents of the footer.
1605
        * @method setFooter
1606
        * @param {String} footerContent The HTML used to set the footer 
1607
        * As a convenience, non HTMLElement objects can also be passed into 
1608
        * the method, and will be treated as strings, with the footer innerHTML
1609
        * set to their default toString implementations.
1610
        * <em>OR</em>
1611
        * @param {HTMLElement} footerContent The HTMLElement to append to 
1612
        * the footer
1613
        * <em>OR</em>
1614
        * @param {DocumentFragment} footerContent The document fragment containing 
1615
        * elements which are to be added to the footer
1616
        */
1617
        setFooter: function (footerContent) {
1618
1619
            var oFooter = this.footer || (this.footer = createFooter());
1620
1621
            if (footerContent.nodeName) {
1622
                oFooter.innerHTML = "";
1623
                oFooter.appendChild(footerContent);
1624
            } else {
1625
                oFooter.innerHTML = footerContent;
1626
            }
1627
1628
            if (this._rendered) {
1629
                this._renderFooter();
1630
            }
1631
1632
            this.changeFooterEvent.fire(footerContent);
1633
            this.changeContentEvent.fire();
1634
        },
1635
1636
        /**
1637
        * Appends the passed element to the footer. If no footer is present, 
1638
        * one will be automatically created.
1639
        * @method appendToFooter
1640
        * @param {HTMLElement | DocumentFragment} element The element to 
1641
        * append to the footer. In the case of a document fragment, the
1642
        * children of the fragment will be appended to the footer
1643
        */
1644
        appendToFooter: function (element) {
1645
1646
            var oFooter = this.footer || (this.footer = createFooter());
1647
1648
            oFooter.appendChild(element);
1649
1650
            this.changeFooterEvent.fire(element);
1651
            this.changeContentEvent.fire();
1652
1653
        },
1654
1655
        /**
1656
        * Renders the Module by inserting the elements that are not already 
1657
        * in the main Module into their correct places. Optionally appends 
1658
        * the Module to the specified node prior to the render's execution. 
1659
        * <p>
1660
        * For Modules without existing markup, the appendToNode argument 
1661
        * is REQUIRED. If this argument is ommitted and the current element is 
1662
        * not present in the document, the function will return false, 
1663
        * indicating that the render was a failure.
1664
        * </p>
1665
        * <p>
1666
        * NOTE: As of 2.3.1, if the appendToNode is the document's body element
1667
        * then the module is rendered as the first child of the body element, 
1668
        * and not appended to it, to avoid Operation Aborted errors in IE when 
1669
        * rendering the module before window's load event is fired. You can 
1670
        * use the appendtodocumentbody configuration property to change this 
1671
        * to append to document.body if required.
1672
        * </p>
1673
        * @method render
1674
        * @param {String} appendToNode The element id to which the Module 
1675
        * should be appended to prior to rendering <em>OR</em>
1676
        * @param {HTMLElement} appendToNode The element to which the Module 
1677
        * should be appended to prior to rendering
1678
        * @param {HTMLElement} moduleElement OPTIONAL. The element that 
1679
        * represents the actual Standard Module container.
1680
        * @return {Boolean} Success or failure of the render
1681
        */
1682
        render: function (appendToNode, moduleElement) {
1683
1684
            var me = this;
1685
1686
            function appendTo(parentNode) {
1687
                if (typeof parentNode == "string") {
1688
                    parentNode = document.getElementById(parentNode);
1689
                }
1690
1691
                if (parentNode) {
1692
                    me._addToParent(parentNode, me.element);
1693
                    me.appendEvent.fire();
1694
                }
1695
            }
1696
1697
            this.beforeRenderEvent.fire();
1698
1699
            if (! moduleElement) {
1700
                moduleElement = this.element;
1701
            }
1702
1703
            if (appendToNode) {
1704
                appendTo(appendToNode);
1705
            } else { 
1706
                // No node was passed in. If the element is not already in the Dom, this fails
1707
                if (! Dom.inDocument(this.element)) {
1708
                    return false;
1709
                }
1710
            }
1711
1712
            this._renderHeader(moduleElement);
1713
            this._renderBody(moduleElement);
1714
            this._renderFooter(moduleElement);
1715
1716
            this._rendered = true;
1717
1718
            this.renderEvent.fire();
1719
            return true;
1720
        },
1721
1722
        /**
1723
         * Renders the currently set header into it's proper position under the 
1724
         * module element. If the module element is not provided, "this.element" 
1725
         * is used.
1726
         * 
1727
         * @method _renderHeader
1728
         * @protected
1729
         * @param {HTMLElement} moduleElement Optional. A reference to the module element
1730
         */
1731
        _renderHeader: function(moduleElement){
1732
            moduleElement = moduleElement || this.element;
1733
1734
            // Need to get everything into the DOM if it isn't already
1735
            if (this.header && !Dom.inDocument(this.header)) {
1736
                // There is a header, but it's not in the DOM yet. Need to add it.
1737
                var firstChild = moduleElement.firstChild;
1738
                if (firstChild) {
1739
                    moduleElement.insertBefore(this.header, firstChild);
1740
                } else {
1741
                    moduleElement.appendChild(this.header);
1742
                }
1743
            }
1744
        },
1745
1746
        /**
1747
         * Renders the currently set body into it's proper position under the 
1748
         * module element. If the module element is not provided, "this.element" 
1749
         * is used.
1750
         * 
1751
         * @method _renderBody
1752
         * @protected
1753
         * @param {HTMLElement} moduleElement Optional. A reference to the module element.
1754
         */
1755
        _renderBody: function(moduleElement){
1756
            moduleElement = moduleElement || this.element;
1757
1758
            if (this.body && !Dom.inDocument(this.body)) {
1759
                // There is a body, but it's not in the DOM yet. Need to add it.
1760
                if (this.footer && Dom.isAncestor(moduleElement, this.footer)) {
1761
                    moduleElement.insertBefore(this.body, this.footer);
1762
                } else {
1763
                    moduleElement.appendChild(this.body);
1764
                }
1765
            }
1766
        },
1767
1768
        /**
1769
         * Renders the currently set footer into it's proper position under the 
1770
         * module element. If the module element is not provided, "this.element" 
1771
         * is used.
1772
         * 
1773
         * @method _renderFooter
1774
         * @protected
1775
         * @param {HTMLElement} moduleElement Optional. A reference to the module element
1776
         */
1777
        _renderFooter: function(moduleElement){
1778
            moduleElement = moduleElement || this.element;
1779
1780
            if (this.footer && !Dom.inDocument(this.footer)) {
1781
                // There is a footer, but it's not in the DOM yet. Need to add it.
1782
                moduleElement.appendChild(this.footer);
1783
            }
1784
        },
1785
1786
        /**
1787
        * Removes the Module element from the DOM and sets all child elements 
1788
        * to null.
1789
        * @method destroy
1790
        */
1791
        destroy: function () {
1792
1793
            var parent;
1794
1795
            if (this.element) {
1796
                Event.purgeElement(this.element, true);
1797
                parent = this.element.parentNode;
1798
            }
1799
1800
            if (parent) {
1801
                parent.removeChild(this.element);
1802
            }
1803
        
1804
            this.element = null;
1805
            this.header = null;
1806
            this.body = null;
1807
            this.footer = null;
1808
1809
            Module.textResizeEvent.unsubscribe(this.onDomResize, this);
1810
1811
            this.cfg.destroy();
1812
            this.cfg = null;
1813
1814
            this.destroyEvent.fire();
1815
        },
1816
1817
        /**
1818
        * Shows the Module element by setting the visible configuration 
1819
        * property to true. Also fires two events: beforeShowEvent prior to 
1820
        * the visibility change, and showEvent after.
1821
        * @method show
1822
        */
1823
        show: function () {
1824
            this.cfg.setProperty("visible", true);
1825
        },
1826
1827
        /**
1828
        * Hides the Module element by setting the visible configuration 
1829
        * property to false. Also fires two events: beforeHideEvent prior to 
1830
        * the visibility change, and hideEvent after.
1831
        * @method hide
1832
        */
1833
        hide: function () {
1834
            this.cfg.setProperty("visible", false);
1835
        },
1836
        
1837
        // BUILT-IN EVENT HANDLERS FOR MODULE //
1838
        /**
1839
        * Default event handler for changing the visibility property of a 
1840
        * Module. By default, this is achieved by switching the "display" style 
1841
        * between "block" and "none".
1842
        * This method is responsible for firing showEvent and hideEvent.
1843
        * @param {String} type The CustomEvent type (usually the property name)
1844
        * @param {Object[]} args The CustomEvent arguments. For configuration 
1845
        * handlers, args[0] will equal the newly applied value for the property.
1846
        * @param {Object} obj The scope object. For configuration handlers, 
1847
        * this will usually equal the owner.
1848
        * @method configVisible
1849
        */
1850
        configVisible: function (type, args, obj) {
1851
            var visible = args[0];
1852
            if (visible) {
1853
                this.beforeShowEvent.fire();
1854
                Dom.setStyle(this.element, "display", "block");
1855
                this.showEvent.fire();
1856
            } else {
1857
                this.beforeHideEvent.fire();
1858
                Dom.setStyle(this.element, "display", "none");
1859
                this.hideEvent.fire();
1860
            }
1861
        },
1862
1863
        /**
1864
        * Default event handler for the "monitorresize" configuration property
1865
        * @param {String} type The CustomEvent type (usually the property name)
1866
        * @param {Object[]} args The CustomEvent arguments. For configuration 
1867
        * handlers, args[0] will equal the newly applied value for the property.
1868
        * @param {Object} obj The scope object. For configuration handlers, 
1869
        * this will usually equal the owner.
1870
        * @method configMonitorResize
1871
        */
1872
        configMonitorResize: function (type, args, obj) {
1873
            var monitor = args[0];
1874
            if (monitor) {
1875
                this.initResizeMonitor();
1876
            } else {
1877
                Module.textResizeEvent.unsubscribe(this.onDomResize, this, true);
1878
                this.resizeMonitor = null;
1879
            }
1880
        },
1881
1882
        /**
1883
         * This method is a protected helper, used when constructing the DOM structure for the module 
1884
         * to account for situations which may cause Operation Aborted errors in IE. It should not 
1885
         * be used for general DOM construction.
1886
         * <p>
1887
         * If the parentNode is not document.body, the element is appended as the last element.
1888
         * </p>
1889
         * <p>
1890
         * If the parentNode is document.body the element is added as the first child to help
1891
         * prevent Operation Aborted errors in IE.
1892
         * </p>
1893
         *
1894
         * @param {parentNode} The HTML element to which the element will be added
1895
         * @param {element} The HTML element to be added to parentNode's children
1896
         * @method _addToParent
1897
         * @protected
1898
         */
1899
        _addToParent: function(parentNode, element) {
1900
            if (!this.cfg.getProperty("appendtodocumentbody") && parentNode === document.body && parentNode.firstChild) {
1901
                parentNode.insertBefore(element, parentNode.firstChild);
1902
            } else {
1903
                parentNode.appendChild(element);
1904
            }
1905
        },
1906
1907
        /**
1908
        * Returns a String representation of the Object.
1909
        * @method toString
1910
        * @return {String} The string representation of the Module
1911
        */
1912
        toString: function () {
1913
            return "Module " + this.id;
1914
        }
1915
    };
1916
1917
    YAHOO.lang.augmentProto(Module, YAHOO.util.EventProvider);
1918
1919
}());
1920
(function () {
1921
1922
    /**
1923
    * Overlay is a Module that is absolutely positioned above the page flow. It 
1924
    * has convenience methods for positioning and sizing, as well as options for 
1925
    * controlling zIndex and constraining the Overlay's position to the current 
1926
    * visible viewport. Overlay also contains a dynamicly generated IFRAME which 
1927
    * is placed beneath it for Internet Explorer 6 and 5.x so that it will be 
1928
    * properly rendered above SELECT elements.
1929
    * @namespace YAHOO.widget
1930
    * @class Overlay
1931
    * @extends YAHOO.widget.Module
1932
    * @param {String} el The element ID representing the Overlay <em>OR</em>
1933
    * @param {HTMLElement} el The element representing the Overlay
1934
    * @param {Object} userConfig The configuration object literal containing 
1935
    * the configuration that should be set for this Overlay. See configuration 
1936
    * documentation for more details.
1937
    * @constructor
1938
    */
1939
    YAHOO.widget.Overlay = function (el, userConfig) {
1940
        YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
1941
    };
1942
1943
    var Lang = YAHOO.lang,
1944
        CustomEvent = YAHOO.util.CustomEvent,
1945
        Module = YAHOO.widget.Module,
1946
        Event = YAHOO.util.Event,
1947
        Dom = YAHOO.util.Dom,
1948
        Config = YAHOO.util.Config,
1949
        UA = YAHOO.env.ua,
1950
        Overlay = YAHOO.widget.Overlay,
1951
1952
        _SUBSCRIBE = "subscribe",
1953
        _UNSUBSCRIBE = "unsubscribe",
1954
        _CONTAINED = "contained",
1955
1956
        m_oIFrameTemplate,
1957
1958
        /**
1959
        * Constant representing the name of the Overlay's events
1960
        * @property EVENT_TYPES
1961
        * @private
1962
        * @final
1963
        * @type Object
1964
        */
1965
        EVENT_TYPES = {
1966
            "BEFORE_MOVE": "beforeMove",
1967
            "MOVE": "move"
1968
        },
1969
1970
        /**
1971
        * Constant representing the Overlay's configuration properties
1972
        * @property DEFAULT_CONFIG
1973
        * @private
1974
        * @final
1975
        * @type Object
1976
        */
1977
        DEFAULT_CONFIG = {
1978
1979
            "X": { 
1980
                key: "x", 
1981
                validator: Lang.isNumber, 
1982
                suppressEvent: true, 
1983
                supercedes: ["iframe"]
1984
            },
1985
1986
            "Y": { 
1987
                key: "y", 
1988
                validator: Lang.isNumber, 
1989
                suppressEvent: true, 
1990
                supercedes: ["iframe"]
1991
            },
1992
1993
            "XY": { 
1994
                key: "xy", 
1995
                suppressEvent: true, 
1996
                supercedes: ["iframe"] 
1997
            },
1998
1999
            "CONTEXT": { 
2000
                key: "context", 
2001
                suppressEvent: true, 
2002
                supercedes: ["iframe"] 
2003
            },
2004
2005
            "FIXED_CENTER": { 
2006
                key: "fixedcenter", 
2007
                value: false, 
2008
                supercedes: ["iframe", "visible"] 
2009
            },
2010
2011
            "WIDTH": { 
2012
                key: "width",
2013
                suppressEvent: true,
2014
                supercedes: ["context", "fixedcenter", "iframe"]
2015
            }, 
2016
2017
            "HEIGHT": { 
2018
                key: "height", 
2019
                suppressEvent: true, 
2020
                supercedes: ["context", "fixedcenter", "iframe"] 
2021
            },
2022
2023
            "AUTO_FILL_HEIGHT" : {
2024
                key: "autofillheight",
2025
                supercedes: ["height"],
2026
                value:"body"
2027
            },
2028
2029
            "ZINDEX": { 
2030
                key: "zindex", 
2031
                value: null 
2032
            },
2033
2034
            "CONSTRAIN_TO_VIEWPORT": { 
2035
                key: "constraintoviewport", 
2036
                value: false, 
2037
                validator: Lang.isBoolean, 
2038
                supercedes: ["iframe", "x", "y", "xy"]
2039
            }, 
2040
2041
            "IFRAME": { 
2042
                key: "iframe", 
2043
                value: (UA.ie == 6 ? true : false), 
2044
                validator: Lang.isBoolean, 
2045
                supercedes: ["zindex"] 
2046
            },
2047
2048
            "PREVENT_CONTEXT_OVERLAP": {
2049
                key: "preventcontextoverlap",
2050
                value: false,
2051
                validator: Lang.isBoolean,  
2052
                supercedes: ["constraintoviewport"]
2053
            }
2054
2055
        };
2056
2057
    /**
2058
    * The URL that will be placed in the iframe
2059
    * @property YAHOO.widget.Overlay.IFRAME_SRC
2060
    * @static
2061
    * @final
2062
    * @type String
2063
    */
2064
    Overlay.IFRAME_SRC = "javascript:false;";
2065
2066
    /**
2067
    * Number representing how much the iframe shim should be offset from each 
2068
    * side of an Overlay instance, in pixels.
2069
    * @property YAHOO.widget.Overlay.IFRAME_SRC
2070
    * @default 3
2071
    * @static
2072
    * @final
2073
    * @type Number
2074
    */
2075
    Overlay.IFRAME_OFFSET = 3;
2076
2077
    /**
2078
    * Number representing the minimum distance an Overlay instance should be 
2079
    * positioned relative to the boundaries of the browser's viewport, in pixels.
2080
    * @property YAHOO.widget.Overlay.VIEWPORT_OFFSET
2081
    * @default 10
2082
    * @static
2083
    * @final
2084
    * @type Number
2085
    */
2086
    Overlay.VIEWPORT_OFFSET = 10;
2087
2088
    /**
2089
    * Constant representing the top left corner of an element, used for 
2090
    * configuring the context element alignment
2091
    * @property YAHOO.widget.Overlay.TOP_LEFT
2092
    * @static
2093
    * @final
2094
    * @type String
2095
    */
2096
    Overlay.TOP_LEFT = "tl";
2097
2098
    /**
2099
    * Constant representing the top right corner of an element, used for 
2100
    * configuring the context element alignment
2101
    * @property YAHOO.widget.Overlay.TOP_RIGHT
2102
    * @static
2103
    * @final
2104
    * @type String
2105
    */
2106
    Overlay.TOP_RIGHT = "tr";
2107
2108
    /**
2109
    * Constant representing the top bottom left corner of an element, used for 
2110
    * configuring the context element alignment
2111
    * @property YAHOO.widget.Overlay.BOTTOM_LEFT
2112
    * @static
2113
    * @final
2114
    * @type String
2115
    */
2116
    Overlay.BOTTOM_LEFT = "bl";
2117
2118
    /**
2119
    * Constant representing the bottom right corner of an element, used for 
2120
    * configuring the context element alignment
2121
    * @property YAHOO.widget.Overlay.BOTTOM_RIGHT
2122
    * @static
2123
    * @final
2124
    * @type String
2125
    */
2126
    Overlay.BOTTOM_RIGHT = "br";
2127
2128
    Overlay.PREVENT_OVERLAP_X = {
2129
        "tltr": true,
2130
        "blbr": true,
2131
        "brbl": true,
2132
        "trtl": true
2133
    };
2134
            
2135
    Overlay.PREVENT_OVERLAP_Y = {
2136
        "trbr": true,
2137
        "tlbl": true,
2138
        "bltl": true,
2139
        "brtr": true
2140
    };
2141
2142
    /**
2143
    * Constant representing the default CSS class used for an Overlay
2144
    * @property YAHOO.widget.Overlay.CSS_OVERLAY
2145
    * @static
2146
    * @final
2147
    * @type String
2148
    */
2149
    Overlay.CSS_OVERLAY = "yui-overlay";
2150
2151
    /**
2152
    * Constant representing the default hidden CSS class used for an Overlay. This class is 
2153
    * applied to the overlay's outer DIV whenever it's hidden.
2154
    *
2155
    * @property YAHOO.widget.Overlay.CSS_HIDDEN
2156
    * @static
2157
    * @final
2158
    * @type String
2159
    */
2160
    Overlay.CSS_HIDDEN = "yui-overlay-hidden";
2161
2162
    /**
2163
    * Constant representing the default CSS class used for an Overlay iframe shim.
2164
    * 
2165
    * @property YAHOO.widget.Overlay.CSS_IFRAME
2166
    * @static
2167
    * @final
2168
    * @type String
2169
    */
2170
    Overlay.CSS_IFRAME = "yui-overlay-iframe";
2171
2172
    /**
2173
     * Constant representing the names of the standard module elements
2174
     * used in the overlay.
2175
     * @property YAHOO.widget.Overlay.STD_MOD_RE
2176
     * @static
2177
     * @final
2178
     * @type RegExp
2179
     */
2180
    Overlay.STD_MOD_RE = /^\s*?(body|footer|header)\s*?$/i;
2181
2182
    /**
2183
    * A singleton CustomEvent used for reacting to the DOM event for 
2184
    * window scroll
2185
    * @event YAHOO.widget.Overlay.windowScrollEvent
2186
    */
2187
    Overlay.windowScrollEvent = new CustomEvent("windowScroll");
2188
2189
    /**
2190
    * A singleton CustomEvent used for reacting to the DOM event for
2191
    * window resize
2192
    * @event YAHOO.widget.Overlay.windowResizeEvent
2193
    */
2194
    Overlay.windowResizeEvent = new CustomEvent("windowResize");
2195
2196
    /**
2197
    * The DOM event handler used to fire the CustomEvent for window scroll
2198
    * @method YAHOO.widget.Overlay.windowScrollHandler
2199
    * @static
2200
    * @param {DOMEvent} e The DOM scroll event
2201
    */
2202
    Overlay.windowScrollHandler = function (e) {
2203
        var t = Event.getTarget(e);
2204
2205
        // - Webkit (Safari 2/3) and Opera 9.2x bubble scroll events from elements to window
2206
        // - FF2/3 and IE6/7, Opera 9.5x don't bubble scroll events from elements to window
2207
        // - IE doesn't recognize scroll registered on the document.
2208
        //
2209
        // Also, when document view is scrolled, IE doesn't provide a target, 
2210
        // rest of the browsers set target to window.document, apart from opera 
2211
        // which sets target to window.
2212
        if (!t || t === window || t === window.document) {
2213
            if (UA.ie) {
2214
2215
                if (! window.scrollEnd) {
2216
                    window.scrollEnd = -1;
2217
                }
2218
2219
                clearTimeout(window.scrollEnd);
2220
        
2221
                window.scrollEnd = setTimeout(function () { 
2222
                    Overlay.windowScrollEvent.fire(); 
2223
                }, 1);
2224
        
2225
            } else {
2226
                Overlay.windowScrollEvent.fire();
2227
            }
2228
        }
2229
    };
2230
2231
    /**
2232
    * The DOM event handler used to fire the CustomEvent for window resize
2233
    * @method YAHOO.widget.Overlay.windowResizeHandler
2234
    * @static
2235
    * @param {DOMEvent} e The DOM resize event
2236
    */
2237
    Overlay.windowResizeHandler = function (e) {
2238
2239
        if (UA.ie) {
2240
            if (! window.resizeEnd) {
2241
                window.resizeEnd = -1;
2242
            }
2243
2244
            clearTimeout(window.resizeEnd);
2245
2246
            window.resizeEnd = setTimeout(function () {
2247
                Overlay.windowResizeEvent.fire(); 
2248
            }, 100);
2249
        } else {
2250
            Overlay.windowResizeEvent.fire();
2251
        }
2252
    };
2253
2254
    /**
2255
    * A boolean that indicated whether the window resize and scroll events have 
2256
    * already been subscribed to.
2257
    * @property YAHOO.widget.Overlay._initialized
2258
    * @private
2259
    * @type Boolean
2260
    */
2261
    Overlay._initialized = null;
2262
2263
    if (Overlay._initialized === null) {
2264
        Event.on(window, "scroll", Overlay.windowScrollHandler);
2265
        Event.on(window, "resize", Overlay.windowResizeHandler);
2266
        Overlay._initialized = true;
2267
    }
2268
2269
    /**
2270
     * Internal map of special event types, which are provided
2271
     * by the instance. It maps the event type to the custom event 
2272
     * instance. Contains entries for the "windowScroll", "windowResize" and
2273
     * "textResize" static container events.
2274
     *
2275
     * @property YAHOO.widget.Overlay._TRIGGER_MAP
2276
     * @type Object
2277
     * @static
2278
     * @private
2279
     */
2280
    Overlay._TRIGGER_MAP = {
2281
        "windowScroll" : Overlay.windowScrollEvent,
2282
        "windowResize" : Overlay.windowResizeEvent,
2283
        "textResize"   : Module.textResizeEvent
2284
    };
2285
2286
    YAHOO.extend(Overlay, Module, {
2287
2288
        /**
2289
         * <p>
2290
         * Array of default event types which will trigger
2291
         * context alignment for the Overlay class.
2292
         * </p>
2293
         * <p>The array is empty by default for Overlay,
2294
         * but maybe populated in future releases, so classes extending
2295
         * Overlay which need to define their own set of CONTEXT_TRIGGERS
2296
         * should concatenate their super class's prototype.CONTEXT_TRIGGERS 
2297
         * value with their own array of values.
2298
         * </p>
2299
         * <p>
2300
         * E.g.:
2301
         * <code>CustomOverlay.prototype.CONTEXT_TRIGGERS = YAHOO.widget.Overlay.prototype.CONTEXT_TRIGGERS.concat(["windowScroll"]);</code>
2302
         * </p>
2303
         * 
2304
         * @property CONTEXT_TRIGGERS
2305
         * @type Array
2306
         * @final
2307
         */
2308
        CONTEXT_TRIGGERS : [],
2309
2310
        /**
2311
        * The Overlay initialization method, which is executed for Overlay and  
2312
        * all of its subclasses. This method is automatically called by the 
2313
        * constructor, and  sets up all DOM references for pre-existing markup, 
2314
        * and creates required markup if it is not already present.
2315
        * @method init
2316
        * @param {String} el The element ID representing the Overlay <em>OR</em>
2317
        * @param {HTMLElement} el The element representing the Overlay
2318
        * @param {Object} userConfig The configuration object literal 
2319
        * containing the configuration that should be set for this Overlay. 
2320
        * See configuration documentation for more details.
2321
        */
2322
        init: function (el, userConfig) {
2323
2324
            /*
2325
                 Note that we don't pass the user config in here yet because we
2326
                 only want it executed once, at the lowest subclass level
2327
            */
2328
2329
            Overlay.superclass.init.call(this, el/*, userConfig*/);
2330
2331
            this.beforeInitEvent.fire(Overlay);
2332
2333
            Dom.addClass(this.element, Overlay.CSS_OVERLAY);
2334
2335
            if (userConfig) {
2336
                this.cfg.applyConfig(userConfig, true);
2337
            }
2338
2339
            if (this.platform == "mac" && UA.gecko) {
2340
2341
                if (! Config.alreadySubscribed(this.showEvent,
2342
                    this.showMacGeckoScrollbars, this)) {
2343
2344
                    this.showEvent.subscribe(this.showMacGeckoScrollbars, 
2345
                        this, true);
2346
2347
                }
2348
2349
                if (! Config.alreadySubscribed(this.hideEvent, 
2350
                    this.hideMacGeckoScrollbars, this)) {
2351
2352
                    this.hideEvent.subscribe(this.hideMacGeckoScrollbars, 
2353
                        this, true);
2354
2355
                }
2356
            }
2357
2358
            this.initEvent.fire(Overlay);
2359
        },
2360
        
2361
        /**
2362
        * Initializes the custom events for Overlay which are fired  
2363
        * automatically at appropriate times by the Overlay class.
2364
        * @method initEvents
2365
        */
2366
        initEvents: function () {
2367
2368
            Overlay.superclass.initEvents.call(this);
2369
2370
            var SIGNATURE = CustomEvent.LIST;
2371
2372
            /**
2373
            * CustomEvent fired before the Overlay is moved.
2374
            * @event beforeMoveEvent
2375
            * @param {Number} x x coordinate
2376
            * @param {Number} y y coordinate
2377
            */
2378
            this.beforeMoveEvent = this.createEvent(EVENT_TYPES.BEFORE_MOVE);
2379
            this.beforeMoveEvent.signature = SIGNATURE;
2380
2381
            /**
2382
            * CustomEvent fired after the Overlay is moved.
2383
            * @event moveEvent
2384
            * @param {Number} x x coordinate
2385
            * @param {Number} y y coordinate
2386
            */
2387
            this.moveEvent = this.createEvent(EVENT_TYPES.MOVE);
2388
            this.moveEvent.signature = SIGNATURE;
2389
2390
        },
2391
        
2392
        /**
2393
        * Initializes the class's configurable properties which can be changed 
2394
        * using the Overlay's Config object (cfg).
2395
        * @method initDefaultConfig
2396
        */
2397
        initDefaultConfig: function () {
2398
    
2399
            Overlay.superclass.initDefaultConfig.call(this);
2400
2401
            var cfg = this.cfg;
2402
2403
            // Add overlay config properties //
2404
            
2405
            /**
2406
            * The absolute x-coordinate position of the Overlay
2407
            * @config x
2408
            * @type Number
2409
            * @default null
2410
            */
2411
            cfg.addProperty(DEFAULT_CONFIG.X.key, { 
2412
    
2413
                handler: this.configX, 
2414
                validator: DEFAULT_CONFIG.X.validator, 
2415
                suppressEvent: DEFAULT_CONFIG.X.suppressEvent, 
2416
                supercedes: DEFAULT_CONFIG.X.supercedes
2417
    
2418
            });
2419
2420
            /**
2421
            * The absolute y-coordinate position of the Overlay
2422
            * @config y
2423
            * @type Number
2424
            * @default null
2425
            */
2426
            cfg.addProperty(DEFAULT_CONFIG.Y.key, {
2427
2428
                handler: this.configY, 
2429
                validator: DEFAULT_CONFIG.Y.validator, 
2430
                suppressEvent: DEFAULT_CONFIG.Y.suppressEvent, 
2431
                supercedes: DEFAULT_CONFIG.Y.supercedes
2432
2433
            });
2434
2435
            /**
2436
            * An array with the absolute x and y positions of the Overlay
2437
            * @config xy
2438
            * @type Number[]
2439
            * @default null
2440
            */
2441
            cfg.addProperty(DEFAULT_CONFIG.XY.key, {
2442
                handler: this.configXY, 
2443
                suppressEvent: DEFAULT_CONFIG.XY.suppressEvent, 
2444
                supercedes: DEFAULT_CONFIG.XY.supercedes
2445
            });
2446
2447
            /**
2448
            * <p>
2449
            * The array of context arguments for context-sensitive positioning. 
2450
            * </p>
2451
            *
2452
            * <p>
2453
            * The format of the array is: <code>[contextElementOrId, overlayCorner, contextCorner, arrayOfTriggerEvents (optional), xyOffset (optional)]</code>, the
2454
            * the 5 array elements described in detail below:
2455
            * </p>
2456
            *
2457
            * <dl>
2458
            * <dt>contextElementOrId &#60;String|HTMLElement&#62;</dt>
2459
            * <dd>A reference to the context element to which the overlay should be aligned (or it's id).</dd>
2460
            * <dt>overlayCorner &#60;String&#62;</dt>
2461
            * <dd>The corner of the overlay which is to be used for alignment. This corner will be aligned to the 
2462
            * corner of the context element defined by the "contextCorner" entry which follows. Supported string values are: 
2463
            * "tr" (top right), "tl" (top left), "br" (bottom right), or "bl" (bottom left).</dd>
2464
            * <dt>contextCorner &#60;String&#62;</dt>
2465
            * <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>
2466
            * <dt>arrayOfTriggerEvents (optional) &#60;Array[String|CustomEvent]&#62;</dt>
2467
            * <dd>
2468
            * <p>
2469
            * 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> 
2470
            * 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. 
2471
            * This is useful in situations where the layout of the document may change, resulting in the context element's position being modified.
2472
            * </p>
2473
            * <p>
2474
            * The array can contain either event type strings for events the instance publishes (e.g. "beforeShow") or CustomEvent instances. Additionally the following
2475
            * 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).
2476
            * </p>
2477
            * </dd>
2478
            * <dt>xyOffset &#60;Number[]&#62;</dt>
2479
            * <dd>
2480
            * A 2 element Array specifying the X and Y pixel amounts by which the Overlay should be offset from the aligned corner. e.g. [5,0] offsets the Overlay 5 pixels to the left, <em>after</em> aligning the given context corners.
2481
            * NOTE: If using this property and no triggers need to be defined, the arrayOfTriggerEvents property should be set to null to maintain correct array positions for the arguments. 
2482
            * </dd>
2483
            * </dl>
2484
            *
2485
            * <p>
2486
            * For example, setting this property to <code>["img1", "tl", "bl"]</code> will 
2487
            * align the Overlay's top left corner to the bottom left corner of the
2488
            * context element with id "img1".
2489
            * </p>
2490
            * <p>
2491
            * Setting this property to <code>["img1", "tl", "bl", null, [0,5]</code> will 
2492
            * align the Overlay's top left corner to the bottom left corner of the
2493
            * context element with id "img1", and then offset it by 5 pixels on the Y axis (providing a 5 pixel gap between the bottom of the context element and top of the overlay).
2494
            * </p>
2495
            * <p>
2496
            * Adding the optional trigger values: <code>["img1", "tl", "bl", ["beforeShow", "windowResize"], [0,5]]</code>,
2497
            * will re-align the overlay position, whenever the "beforeShow" or "windowResize" events are fired.
2498
            * </p>
2499
            *
2500
            * @config context
2501
            * @type Array
2502
            * @default null
2503
            */
2504
            cfg.addProperty(DEFAULT_CONFIG.CONTEXT.key, {
2505
                handler: this.configContext, 
2506
                suppressEvent: DEFAULT_CONFIG.CONTEXT.suppressEvent, 
2507
                supercedes: DEFAULT_CONFIG.CONTEXT.supercedes
2508
            });
2509
2510
            /**
2511
            * Determines whether or not the Overlay should be anchored 
2512
            * to the center of the viewport.
2513
            * 
2514
            * <p>This property can be set to:</p>
2515
            * 
2516
            * <dl>
2517
            * <dt>true</dt>
2518
            * <dd>
2519
            * To enable fixed center positioning
2520
            * <p>
2521
            * When enabled, the overlay will 
2522
            * be positioned in the center of viewport when initially displayed, and 
2523
            * will remain in the center of the viewport whenever the window is 
2524
            * scrolled or resized.
2525
            * </p>
2526
            * <p>
2527
            * If the overlay is too big for the viewport, 
2528
            * it's top left corner will be aligned with the top left corner of the viewport.
2529
            * </p>
2530
            * </dd>
2531
            * <dt>false</dt>
2532
            * <dd>
2533
            * To disable fixed center positioning.
2534
            * <p>In this case the overlay can still be 
2535
            * centered as a one-off operation, by invoking the <code>center()</code> method,
2536
            * however it will not remain centered when the window is scrolled/resized.
2537
            * </dd>
2538
            * <dt>"contained"<dt>
2539
            * <dd>To enable fixed center positioning, as with the <code>true</code> option.
2540
            * <p>However, unlike setting the property to <code>true</code>, 
2541
            * when the property is set to <code>"contained"</code>, if the overlay is 
2542
            * too big for the viewport, it will not get automatically centered when the 
2543
            * user scrolls or resizes the window (until the window is large enough to contain the 
2544
            * overlay). This is useful in cases where the Overlay has both header and footer 
2545
            * UI controls which the user may need to access.
2546
            * </p>
2547
            * </dd>
2548
            * </dl>
2549
            *
2550
            * @config fixedcenter
2551
            * @type Boolean | String
2552
            * @default false
2553
            */
2554
            cfg.addProperty(DEFAULT_CONFIG.FIXED_CENTER.key, {
2555
                handler: this.configFixedCenter,
2556
                value: DEFAULT_CONFIG.FIXED_CENTER.value, 
2557
                validator: DEFAULT_CONFIG.FIXED_CENTER.validator, 
2558
                supercedes: DEFAULT_CONFIG.FIXED_CENTER.supercedes
2559
            });
2560
    
2561
            /**
2562
            * CSS width of the Overlay.
2563
            * @config width
2564
            * @type String
2565
            * @default null
2566
            */
2567
            cfg.addProperty(DEFAULT_CONFIG.WIDTH.key, {
2568
                handler: this.configWidth, 
2569
                suppressEvent: DEFAULT_CONFIG.WIDTH.suppressEvent, 
2570
                supercedes: DEFAULT_CONFIG.WIDTH.supercedes
2571
            });
2572
2573
            /**
2574
            * CSS height of the Overlay.
2575
            * @config height
2576
            * @type String
2577
            * @default null
2578
            */
2579
            cfg.addProperty(DEFAULT_CONFIG.HEIGHT.key, {
2580
                handler: this.configHeight, 
2581
                suppressEvent: DEFAULT_CONFIG.HEIGHT.suppressEvent, 
2582
                supercedes: DEFAULT_CONFIG.HEIGHT.supercedes
2583
            });
2584
2585
            /**
2586
            * Standard module element which should auto fill out the height of the Overlay if the height config property is set.
2587
            * Supported values are "header", "body", "footer".
2588
            *
2589
            * @config autofillheight
2590
            * @type String
2591
            * @default null
2592
            */
2593
            cfg.addProperty(DEFAULT_CONFIG.AUTO_FILL_HEIGHT.key, {
2594
                handler: this.configAutoFillHeight, 
2595
                value : DEFAULT_CONFIG.AUTO_FILL_HEIGHT.value,
2596
                validator : this._validateAutoFill,
2597
                supercedes: DEFAULT_CONFIG.AUTO_FILL_HEIGHT.supercedes
2598
            });
2599
2600
            /**
2601
            * CSS z-index of the Overlay.
2602
            * @config zIndex
2603
            * @type Number
2604
            * @default null
2605
            */
2606
            cfg.addProperty(DEFAULT_CONFIG.ZINDEX.key, {
2607
                handler: this.configzIndex,
2608
                value: DEFAULT_CONFIG.ZINDEX.value
2609
            });
2610
2611
            /**
2612
            * True if the Overlay should be prevented from being positioned 
2613
            * out of the viewport.
2614
            * @config constraintoviewport
2615
            * @type Boolean
2616
            * @default false
2617
            */
2618
            cfg.addProperty(DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.key, {
2619
2620
                handler: this.configConstrainToViewport, 
2621
                value: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.value, 
2622
                validator: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.validator, 
2623
                supercedes: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.supercedes
2624
2625
            });
2626
2627
            /**
2628
            * @config iframe
2629
            * @description Boolean indicating whether or not the Overlay should 
2630
            * have an IFRAME shim; used to prevent SELECT elements from 
2631
            * poking through an Overlay instance in IE6.  When set to "true", 
2632
            * the iframe shim is created when the Overlay instance is intially
2633
            * made visible.
2634
            * @type Boolean
2635
            * @default true for IE6 and below, false for all other browsers.
2636
            */
2637
            cfg.addProperty(DEFAULT_CONFIG.IFRAME.key, {
2638
2639
                handler: this.configIframe, 
2640
                value: DEFAULT_CONFIG.IFRAME.value, 
2641
                validator: DEFAULT_CONFIG.IFRAME.validator, 
2642
                supercedes: DEFAULT_CONFIG.IFRAME.supercedes
2643
2644
            });
2645
2646
            /**
2647
            * @config preventcontextoverlap
2648
            * @description Boolean indicating whether or not the Overlay should overlap its 
2649
            * context element (defined using the "context" configuration property) when the 
2650
            * "constraintoviewport" configuration property is set to "true".
2651
            * @type Boolean
2652
            * @default false
2653
            */
2654
            cfg.addProperty(DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.key, {
2655
                value: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.value, 
2656
                validator: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.validator, 
2657
                supercedes: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.supercedes
2658
            });
2659
        },
2660
2661
        /**
2662
        * Moves the Overlay to the specified position. This function is  
2663
        * identical to calling this.cfg.setProperty("xy", [x,y]);
2664
        * @method moveTo
2665
        * @param {Number} x The Overlay's new x position
2666
        * @param {Number} y The Overlay's new y position
2667
        */
2668
        moveTo: function (x, y) {
2669
            this.cfg.setProperty("xy", [x, y]);
2670
        },
2671
2672
        /**
2673
        * Adds a CSS class ("hide-scrollbars") and removes a CSS class 
2674
        * ("show-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
2675
        * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2676
        * @method hideMacGeckoScrollbars
2677
        */
2678
        hideMacGeckoScrollbars: function () {
2679
            Dom.replaceClass(this.element, "show-scrollbars", "hide-scrollbars");
2680
        },
2681
2682
        /**
2683
        * Adds a CSS class ("show-scrollbars") and removes a CSS class 
2684
        * ("hide-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
2685
        * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2686
        * @method showMacGeckoScrollbars
2687
        */
2688
        showMacGeckoScrollbars: function () {
2689
            Dom.replaceClass(this.element, "hide-scrollbars", "show-scrollbars");
2690
        },
2691
2692
        /**
2693
         * Internal implementation to set the visibility of the overlay in the DOM.
2694
         *
2695
         * @method _setDomVisibility
2696
         * @param {boolean} visible Whether to show or hide the Overlay's outer element
2697
         * @protected
2698
         */
2699
        _setDomVisibility : function(show) {
2700
            Dom.setStyle(this.element, "visibility", (show) ? "visible" : "hidden");
2701
            var hiddenClass = Overlay.CSS_HIDDEN;
2702
2703
            if (show) {
2704
                Dom.removeClass(this.element, hiddenClass);
2705
            } else {
2706
                Dom.addClass(this.element, hiddenClass);
2707
            }
2708
        },
2709
2710
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
2711
        /**
2712
        * The default event handler fired when the "visible" property is 
2713
        * changed.  This method is responsible for firing showEvent
2714
        * and hideEvent.
2715
        * @method configVisible
2716
        * @param {String} type The CustomEvent type (usually the property name)
2717
        * @param {Object[]} args The CustomEvent arguments. For configuration
2718
        * handlers, args[0] will equal the newly applied value for the property.
2719
        * @param {Object} obj The scope object. For configuration handlers, 
2720
        * this will usually equal the owner.
2721
        */
2722
        configVisible: function (type, args, obj) {
2723
2724
            var visible = args[0],
2725
                currentVis = Dom.getStyle(this.element, "visibility"),
2726
                effect = this.cfg.getProperty("effect"),
2727
                effectInstances = [],
2728
                isMacGecko = (this.platform == "mac" && UA.gecko),
2729
                alreadySubscribed = Config.alreadySubscribed,
2730
                eff, ei, e, i, j, k, h,
2731
                nEffects,
2732
                nEffectInstances;
2733
2734
            if (currentVis == "inherit") {
2735
                e = this.element.parentNode;
2736
2737
                while (e.nodeType != 9 && e.nodeType != 11) {
2738
                    currentVis = Dom.getStyle(e, "visibility");
2739
2740
                    if (currentVis != "inherit") {
2741
                        break;
2742
                    }
2743
2744
                    e = e.parentNode;
2745
                }
2746
2747
                if (currentVis == "inherit") {
2748
                    currentVis = "visible";
2749
                }
2750
            }
2751
2752
            if (effect) {
2753
                if (effect instanceof Array) {
2754
                    nEffects = effect.length;
2755
2756
                    for (i = 0; i < nEffects; i++) {
2757
                        eff = effect[i];
2758
                        effectInstances[effectInstances.length] = 
2759
                            eff.effect(this, eff.duration);
2760
2761
                    }
2762
                } else {
2763
                    effectInstances[effectInstances.length] = 
2764
                        effect.effect(this, effect.duration);
2765
                }
2766
            }
2767
2768
            if (visible) { // Show
2769
                if (isMacGecko) {
2770
                    this.showMacGeckoScrollbars();
2771
                }
2772
2773
                if (effect) { // Animate in
2774
                    if (visible) { // Animate in if not showing
2775
                        if (currentVis != "visible" || currentVis === "") {
2776
                            this.beforeShowEvent.fire();
2777
                            nEffectInstances = effectInstances.length;
2778
2779
                            for (j = 0; j < nEffectInstances; j++) {
2780
                                ei = effectInstances[j];
2781
                                if (j === 0 && !alreadySubscribed(
2782
                                        ei.animateInCompleteEvent, 
2783
                                        this.showEvent.fire, this.showEvent)) {
2784
2785
                                    /*
2786
                                         Delegate showEvent until end 
2787
                                         of animateInComplete
2788
                                    */
2789
2790
                                    ei.animateInCompleteEvent.subscribe(
2791
                                     this.showEvent.fire, this.showEvent, true);
2792
                                }
2793
                                ei.animateIn();
2794
                            }
2795
                        }
2796
                    }
2797
                } else { // Show
2798
                    if (currentVis != "visible" || currentVis === "") {
2799
                        this.beforeShowEvent.fire();
2800
2801
                        this._setDomVisibility(true);
2802
2803
                        this.cfg.refireEvent("iframe");
2804
                        this.showEvent.fire();
2805
                    } else {
2806
                        this._setDomVisibility(true);
2807
                    }
2808
                }
2809
            } else { // Hide
2810
2811
                if (isMacGecko) {
2812
                    this.hideMacGeckoScrollbars();
2813
                }
2814
2815
                if (effect) { // Animate out if showing
2816
                    if (currentVis == "visible") {
2817
                        this.beforeHideEvent.fire();
2818
2819
                        nEffectInstances = effectInstances.length;
2820
                        for (k = 0; k < nEffectInstances; k++) {
2821
                            h = effectInstances[k];
2822
    
2823
                            if (k === 0 && !alreadySubscribed(
2824
                                h.animateOutCompleteEvent, this.hideEvent.fire, 
2825
                                this.hideEvent)) {
2826
    
2827
                                /*
2828
                                     Delegate hideEvent until end 
2829
                                     of animateOutComplete
2830
                                */
2831
    
2832
                                h.animateOutCompleteEvent.subscribe(
2833
                                    this.hideEvent.fire, this.hideEvent, true);
2834
    
2835
                            }
2836
                            h.animateOut();
2837
                        }
2838
2839
                    } else if (currentVis === "") {
2840
                        this._setDomVisibility(false);
2841
                    }
2842
2843
                } else { // Simple hide
2844
2845
                    if (currentVis == "visible" || currentVis === "") {
2846
                        this.beforeHideEvent.fire();
2847
                        this._setDomVisibility(false);
2848
                        this.hideEvent.fire();
2849
                    } else {
2850
                        this._setDomVisibility(false);
2851
                    }
2852
                }
2853
            }
2854
        },
2855
2856
        /**
2857
        * Fixed center event handler used for centering on scroll/resize, but only if 
2858
        * the overlay is visible and, if "fixedcenter" is set to "contained", only if 
2859
        * the overlay fits within the viewport.
2860
        *
2861
        * @method doCenterOnDOMEvent
2862
        */
2863
        doCenterOnDOMEvent: function () {
2864
            var cfg = this.cfg,
2865
                fc = cfg.getProperty("fixedcenter");
2866
2867
            if (cfg.getProperty("visible")) {
2868
                if (fc && (fc !== _CONTAINED || this.fitsInViewport())) {
2869
                    this.center();
2870
                }
2871
            }
2872
        },
2873
2874
        /**
2875
         * Determines if the Overlay (including the offset value defined by Overlay.VIEWPORT_OFFSET) 
2876
         * will fit entirely inside the viewport, in both dimensions - width and height.
2877
         * 
2878
         * @method fitsInViewport
2879
         * @return boolean true if the Overlay will fit, false if not
2880
         */
2881
        fitsInViewport : function() {
2882
            var nViewportOffset = Overlay.VIEWPORT_OFFSET,
2883
                element = this.element,
2884
                elementWidth = element.offsetWidth,
2885
                elementHeight = element.offsetHeight,
2886
                viewportWidth = Dom.getViewportWidth(),
2887
                viewportHeight = Dom.getViewportHeight();
2888
2889
            return ((elementWidth + nViewportOffset < viewportWidth) && (elementHeight + nViewportOffset < viewportHeight));
2890
        },
2891
2892
        /**
2893
        * The default event handler fired when the "fixedcenter" property 
2894
        * is changed.
2895
        * @method configFixedCenter
2896
        * @param {String} type The CustomEvent type (usually the property name)
2897
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2898
        * handlers, args[0] will equal the newly applied value for the property.
2899
        * @param {Object} obj The scope object. For configuration handlers, 
2900
        * this will usually equal the owner.
2901
        */
2902
        configFixedCenter: function (type, args, obj) {
2903
2904
            var val = args[0],
2905
                alreadySubscribed = Config.alreadySubscribed,
2906
                windowResizeEvent = Overlay.windowResizeEvent,
2907
                windowScrollEvent = Overlay.windowScrollEvent;
2908
2909
            if (val) {
2910
                this.center();
2911
2912
                if (!alreadySubscribed(this.beforeShowEvent, this.center)) {
2913
                    this.beforeShowEvent.subscribe(this.center);
2914
                }
2915
2916
                if (!alreadySubscribed(windowResizeEvent, this.doCenterOnDOMEvent, this)) {
2917
                    windowResizeEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2918
                }
2919
2920
                if (!alreadySubscribed(windowScrollEvent, this.doCenterOnDOMEvent, this)) {
2921
                    windowScrollEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2922
                }
2923
2924
            } else {
2925
                this.beforeShowEvent.unsubscribe(this.center);
2926
2927
                windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2928
                windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2929
            }
2930
        },
2931
2932
        /**
2933
        * The default event handler fired when the "height" property is changed.
2934
        * @method configHeight
2935
        * @param {String} type The CustomEvent type (usually the property name)
2936
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2937
        * handlers, args[0] will equal the newly applied value for the property.
2938
        * @param {Object} obj The scope object. For configuration handlers, 
2939
        * this will usually equal the owner.
2940
        */
2941
        configHeight: function (type, args, obj) {
2942
2943
            var height = args[0],
2944
                el = this.element;
2945
2946
            Dom.setStyle(el, "height", height);
2947
            this.cfg.refireEvent("iframe");
2948
        },
2949
2950
        /**
2951
         * The default event handler fired when the "autofillheight" property is changed.
2952
         * @method configAutoFillHeight
2953
         *
2954
         * @param {String} type The CustomEvent type (usually the property name)
2955
         * @param {Object[]} args The CustomEvent arguments. For configuration 
2956
         * handlers, args[0] will equal the newly applied value for the property.
2957
         * @param {Object} obj The scope object. For configuration handlers, 
2958
         * this will usually equal the owner.
2959
         */
2960
        configAutoFillHeight: function (type, args, obj) {
2961
            var fillEl = args[0],
2962
                cfg = this.cfg,
2963
                autoFillHeight = "autofillheight",
2964
                height = "height",
2965
                currEl = cfg.getProperty(autoFillHeight),
2966
                autoFill = this._autoFillOnHeightChange;
2967
2968
            cfg.unsubscribeFromConfigEvent(height, autoFill);
2969
            Module.textResizeEvent.unsubscribe(autoFill);
2970
            this.changeContentEvent.unsubscribe(autoFill);
2971
2972
            if (currEl && fillEl !== currEl && this[currEl]) {
2973
                Dom.setStyle(this[currEl], height, "");
2974
            }
2975
2976
            if (fillEl) {
2977
                fillEl = Lang.trim(fillEl.toLowerCase());
2978
2979
                cfg.subscribeToConfigEvent(height, autoFill, this[fillEl], this);
2980
                Module.textResizeEvent.subscribe(autoFill, this[fillEl], this);
2981
                this.changeContentEvent.subscribe(autoFill, this[fillEl], this);
2982
2983
                cfg.setProperty(autoFillHeight, fillEl, true);
2984
            }
2985
        },
2986
2987
        /**
2988
        * The default event handler fired when the "width" property is changed.
2989
        * @method configWidth
2990
        * @param {String} type The CustomEvent type (usually the property name)
2991
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2992
        * handlers, args[0] will equal the newly applied value for the property.
2993
        * @param {Object} obj The scope object. For configuration handlers, 
2994
        * this will usually equal the owner.
2995
        */
2996
        configWidth: function (type, args, obj) {
2997
2998
            var width = args[0],
2999
                el = this.element;
3000
3001
            Dom.setStyle(el, "width", width);
3002
            this.cfg.refireEvent("iframe");
3003
        },
3004
3005
        /**
3006
        * The default event handler fired when the "zIndex" property is changed.
3007
        * @method configzIndex
3008
        * @param {String} type The CustomEvent type (usually the property name)
3009
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3010
        * handlers, args[0] will equal the newly applied value for the property.
3011
        * @param {Object} obj The scope object. For configuration handlers, 
3012
        * this will usually equal the owner.
3013
        */
3014
        configzIndex: function (type, args, obj) {
3015
3016
            var zIndex = args[0],
3017
                el = this.element;
3018
3019
            if (! zIndex) {
3020
                zIndex = Dom.getStyle(el, "zIndex");
3021
                if (! zIndex || isNaN(zIndex)) {
3022
                    zIndex = 0;
3023
                }
3024
            }
3025
3026
            if (this.iframe || this.cfg.getProperty("iframe") === true) {
3027
                if (zIndex <= 0) {
3028
                    zIndex = 1;
3029
                }
3030
            }
3031
3032
            Dom.setStyle(el, "zIndex", zIndex);
3033
            this.cfg.setProperty("zIndex", zIndex, true);
3034
3035
            if (this.iframe) {
3036
                this.stackIframe();
3037
            }
3038
        },
3039
3040
        /**
3041
        * The default event handler fired when the "xy" property is changed.
3042
        * @method configXY
3043
        * @param {String} type The CustomEvent type (usually the property name)
3044
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3045
        * handlers, args[0] will equal the newly applied value for the property.
3046
        * @param {Object} obj The scope object. For configuration handlers, 
3047
        * this will usually equal the owner.
3048
        */
3049
        configXY: function (type, args, obj) {
3050
3051
            var pos = args[0],
3052
                x = pos[0],
3053
                y = pos[1];
3054
3055
            this.cfg.setProperty("x", x);
3056
            this.cfg.setProperty("y", y);
3057
3058
            this.beforeMoveEvent.fire([x, y]);
3059
3060
            x = this.cfg.getProperty("x");
3061
            y = this.cfg.getProperty("y");
3062
3063
3064
            this.cfg.refireEvent("iframe");
3065
            this.moveEvent.fire([x, y]);
3066
        },
3067
3068
        /**
3069
        * The default event handler fired when the "x" property is changed.
3070
        * @method configX
3071
        * @param {String} type The CustomEvent type (usually the property name)
3072
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3073
        * handlers, args[0] will equal the newly applied value for the property.
3074
        * @param {Object} obj The scope object. For configuration handlers, 
3075
        * this will usually equal the owner.
3076
        */
3077
        configX: function (type, args, obj) {
3078
3079
            var x = args[0],
3080
                y = this.cfg.getProperty("y");
3081
3082
            this.cfg.setProperty("x", x, true);
3083
            this.cfg.setProperty("y", y, true);
3084
3085
            this.beforeMoveEvent.fire([x, y]);
3086
3087
            x = this.cfg.getProperty("x");
3088
            y = this.cfg.getProperty("y");
3089
3090
            Dom.setX(this.element, x, true);
3091
3092
            this.cfg.setProperty("xy", [x, y], true);
3093
3094
            this.cfg.refireEvent("iframe");
3095
            this.moveEvent.fire([x, y]);
3096
        },
3097
3098
        /**
3099
        * The default event handler fired when the "y" property is changed.
3100
        * @method configY
3101
        * @param {String} type The CustomEvent type (usually the property name)
3102
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3103
        * handlers, args[0] will equal the newly applied value for the property.
3104
        * @param {Object} obj The scope object. For configuration handlers, 
3105
        * this will usually equal the owner.
3106
        */
3107
        configY: function (type, args, obj) {
3108
3109
            var x = this.cfg.getProperty("x"),
3110
                y = args[0];
3111
3112
            this.cfg.setProperty("x", x, true);
3113
            this.cfg.setProperty("y", y, true);
3114
3115
            this.beforeMoveEvent.fire([x, y]);
3116
3117
            x = this.cfg.getProperty("x");
3118
            y = this.cfg.getProperty("y");
3119
3120
            Dom.setY(this.element, y, true);
3121
3122
            this.cfg.setProperty("xy", [x, y], true);
3123
3124
            this.cfg.refireEvent("iframe");
3125
            this.moveEvent.fire([x, y]);
3126
        },
3127
        
3128
        /**
3129
        * Shows the iframe shim, if it has been enabled.
3130
        * @method showIframe
3131
        */
3132
        showIframe: function () {
3133
3134
            var oIFrame = this.iframe,
3135
                oParentNode;
3136
3137
            if (oIFrame) {
3138
                oParentNode = this.element.parentNode;
3139
3140
                if (oParentNode != oIFrame.parentNode) {
3141
                    this._addToParent(oParentNode, oIFrame);
3142
                }
3143
                oIFrame.style.display = "block";
3144
            }
3145
        },
3146
3147
        /**
3148
        * Hides the iframe shim, if it has been enabled.
3149
        * @method hideIframe
3150
        */
3151
        hideIframe: function () {
3152
            if (this.iframe) {
3153
                this.iframe.style.display = "none";
3154
            }
3155
        },
3156
3157
        /**
3158
        * Syncronizes the size and position of iframe shim to that of its 
3159
        * corresponding Overlay instance.
3160
        * @method syncIframe
3161
        */
3162
        syncIframe: function () {
3163
3164
            var oIFrame = this.iframe,
3165
                oElement = this.element,
3166
                nOffset = Overlay.IFRAME_OFFSET,
3167
                nDimensionOffset = (nOffset * 2),
3168
                aXY;
3169
3170
            if (oIFrame) {
3171
                // Size <iframe>
3172
                oIFrame.style.width = (oElement.offsetWidth + nDimensionOffset + "px");
3173
                oIFrame.style.height = (oElement.offsetHeight + nDimensionOffset + "px");
3174
3175
                // Position <iframe>
3176
                aXY = this.cfg.getProperty("xy");
3177
3178
                if (!Lang.isArray(aXY) || (isNaN(aXY[0]) || isNaN(aXY[1]))) {
3179
                    this.syncPosition();
3180
                    aXY = this.cfg.getProperty("xy");
3181
                }
3182
                Dom.setXY(oIFrame, [(aXY[0] - nOffset), (aXY[1] - nOffset)]);
3183
            }
3184
        },
3185
3186
        /**
3187
         * Sets the zindex of the iframe shim, if it exists, based on the zindex of
3188
         * the Overlay element. The zindex of the iframe is set to be one less 
3189
         * than the Overlay element's zindex.
3190
         * 
3191
         * <p>NOTE: This method will not bump up the zindex of the Overlay element
3192
         * to ensure that the iframe shim has a non-negative zindex.
3193
         * If you require the iframe zindex to be 0 or higher, the zindex of 
3194
         * the Overlay element should be set to a value greater than 0, before 
3195
         * this method is called.
3196
         * </p>
3197
         * @method stackIframe
3198
         */
3199
        stackIframe: function () {
3200
            if (this.iframe) {
3201
                var overlayZ = Dom.getStyle(this.element, "zIndex");
3202
                if (!YAHOO.lang.isUndefined(overlayZ) && !isNaN(overlayZ)) {
3203
                    Dom.setStyle(this.iframe, "zIndex", (overlayZ - 1));
3204
                }
3205
            }
3206
        },
3207
3208
        /**
3209
        * The default event handler fired when the "iframe" property is changed.
3210
        * @method configIframe
3211
        * @param {String} type The CustomEvent type (usually the property name)
3212
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3213
        * handlers, args[0] will equal the newly applied value for the property.
3214
        * @param {Object} obj The scope object. For configuration handlers, 
3215
        * this will usually equal the owner.
3216
        */
3217
        configIframe: function (type, args, obj) {
3218
3219
            var bIFrame = args[0];
3220
3221
            function createIFrame() {
3222
3223
                var oIFrame = this.iframe,
3224
                    oElement = this.element,
3225
                    oParent;
3226
3227
                if (!oIFrame) {
3228
                    if (!m_oIFrameTemplate) {
3229
                        m_oIFrameTemplate = document.createElement("iframe");
3230
3231
                        if (this.isSecure) {
3232
                            m_oIFrameTemplate.src = Overlay.IFRAME_SRC;
3233
                        }
3234
3235
                        /*
3236
                            Set the opacity of the <iframe> to 0 so that it 
3237
                            doesn't modify the opacity of any transparent 
3238
                            elements that may be on top of it (like a shadow).
3239
                        */
3240
                        if (UA.ie) {
3241
                            m_oIFrameTemplate.style.filter = "alpha(opacity=0)";
3242
                            /*
3243
                                 Need to set the "frameBorder" property to 0 
3244
                                 supress the default <iframe> border in IE.  
3245
                                 Setting the CSS "border" property alone 
3246
                                 doesn't supress it.
3247
                            */
3248
                            m_oIFrameTemplate.frameBorder = 0;
3249
                        }
3250
                        else {
3251
                            m_oIFrameTemplate.style.opacity = "0";
3252
                        }
3253
3254
                        m_oIFrameTemplate.style.position = "absolute";
3255
                        m_oIFrameTemplate.style.border = "none";
3256
                        m_oIFrameTemplate.style.margin = "0";
3257
                        m_oIFrameTemplate.style.padding = "0";
3258
                        m_oIFrameTemplate.style.display = "none";
3259
                        m_oIFrameTemplate.tabIndex = -1;
3260
                        m_oIFrameTemplate.className = Overlay.CSS_IFRAME;
3261
                    }
3262
3263
                    oIFrame = m_oIFrameTemplate.cloneNode(false);
3264
                    oIFrame.id = this.id + "_f";
3265
                    oParent = oElement.parentNode;
3266
3267
                    var parentNode = oParent || document.body;
3268
3269
                    this._addToParent(parentNode, oIFrame);
3270
                    this.iframe = oIFrame;
3271
                }
3272
3273
                /*
3274
                     Show the <iframe> before positioning it since the "setXY" 
3275
                     method of DOM requires the element be in the document 
3276
                     and visible.
3277
                */
3278
                this.showIframe();
3279
3280
                /*
3281
                     Syncronize the size and position of the <iframe> to that 
3282
                     of the Overlay.
3283
                */
3284
                this.syncIframe();
3285
                this.stackIframe();
3286
3287
                // Add event listeners to update the <iframe> when necessary
3288
                if (!this._hasIframeEventListeners) {
3289
                    this.showEvent.subscribe(this.showIframe);
3290
                    this.hideEvent.subscribe(this.hideIframe);
3291
                    this.changeContentEvent.subscribe(this.syncIframe);
3292
3293
                    this._hasIframeEventListeners = true;
3294
                }
3295
            }
3296
3297
            function onBeforeShow() {
3298
                createIFrame.call(this);
3299
                this.beforeShowEvent.unsubscribe(onBeforeShow);
3300
                this._iframeDeferred = false;
3301
            }
3302
3303
            if (bIFrame) { // <iframe> shim is enabled
3304
3305
                if (this.cfg.getProperty("visible")) {
3306
                    createIFrame.call(this);
3307
                } else {
3308
                    if (!this._iframeDeferred) {
3309
                        this.beforeShowEvent.subscribe(onBeforeShow);
3310
                        this._iframeDeferred = true;
3311
                    }
3312
                }
3313
3314
            } else {    // <iframe> shim is disabled
3315
                this.hideIframe();
3316
3317
                if (this._hasIframeEventListeners) {
3318
                    this.showEvent.unsubscribe(this.showIframe);
3319
                    this.hideEvent.unsubscribe(this.hideIframe);
3320
                    this.changeContentEvent.unsubscribe(this.syncIframe);
3321
3322
                    this._hasIframeEventListeners = false;
3323
                }
3324
            }
3325
        },
3326
3327
        /**
3328
         * Set's the container's XY value from DOM if not already set.
3329
         * 
3330
         * Differs from syncPosition, in that the XY value is only sync'd with DOM if 
3331
         * not already set. The method also refire's the XY config property event, so any
3332
         * beforeMove, Move event listeners are invoked.
3333
         * 
3334
         * @method _primeXYFromDOM
3335
         * @protected
3336
         */
3337
        _primeXYFromDOM : function() {
3338
            if (YAHOO.lang.isUndefined(this.cfg.getProperty("xy"))) {
3339
                // Set CFG XY based on DOM XY
3340
                this.syncPosition();
3341
                // Account for XY being set silently in syncPosition (no moveTo fired/called)
3342
                this.cfg.refireEvent("xy");
3343
                this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
3344
            }
3345
        },
3346
3347
        /**
3348
        * The default event handler fired when the "constraintoviewport" 
3349
        * property is changed.
3350
        * @method configConstrainToViewport
3351
        * @param {String} type The CustomEvent type (usually the property name)
3352
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3353
        * handlers, args[0] will equal the newly applied value for 
3354
        * the property.
3355
        * @param {Object} obj The scope object. For configuration handlers, 
3356
        * this will usually equal the owner.
3357
        */
3358
        configConstrainToViewport: function (type, args, obj) {
3359
            var val = args[0];
3360
3361
            if (val) {
3362
                if (! Config.alreadySubscribed(this.beforeMoveEvent, this.enforceConstraints, this)) {
3363
                    this.beforeMoveEvent.subscribe(this.enforceConstraints, this, true);
3364
                }
3365
                if (! Config.alreadySubscribed(this.beforeShowEvent, this._primeXYFromDOM)) {
3366
                    this.beforeShowEvent.subscribe(this._primeXYFromDOM);
3367
                }
3368
            } else {
3369
                this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
3370
                this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
3371
            }
3372
        },
3373
3374
         /**
3375
        * The default event handler fired when the "context" property
3376
        * is changed.
3377
        *
3378
        * @method configContext
3379
        * @param {String} type The CustomEvent type (usually the property name)
3380
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3381
        * handlers, args[0] will equal the newly applied value for the property.
3382
        * @param {Object} obj The scope object. For configuration handlers, 
3383
        * this will usually equal the owner.
3384
        */
3385
        configContext: function (type, args, obj) {
3386
3387
            var contextArgs = args[0],
3388
                contextEl,
3389
                elementMagnetCorner,
3390
                contextMagnetCorner,
3391
                triggers,
3392
                offset,
3393
                defTriggers = this.CONTEXT_TRIGGERS;
3394
3395
            if (contextArgs) {
3396
3397
                contextEl = contextArgs[0];
3398
                elementMagnetCorner = contextArgs[1];
3399
                contextMagnetCorner = contextArgs[2];
3400
                triggers = contextArgs[3];
3401
                offset = contextArgs[4];
3402
3403
                if (defTriggers && defTriggers.length > 0) {
3404
                    triggers = (triggers || []).concat(defTriggers);
3405
                }
3406
3407
                if (contextEl) {
3408
                    if (typeof contextEl == "string") {
3409
                        this.cfg.setProperty("context", [
3410
                                document.getElementById(contextEl), 
3411
                                elementMagnetCorner,
3412
                                contextMagnetCorner,
3413
                                triggers,
3414
                                offset],
3415
                                true);
3416
                    }
3417
3418
                    if (elementMagnetCorner && contextMagnetCorner) {
3419
                        this.align(elementMagnetCorner, contextMagnetCorner, offset);
3420
                    }
3421
3422
                    if (this._contextTriggers) {
3423
                        // Unsubscribe Old Set
3424
                        this._processTriggers(this._contextTriggers, _UNSUBSCRIBE, this._alignOnTrigger);
3425
                    }
3426
3427
                    if (triggers) {
3428
                        // Subscribe New Set
3429
                        this._processTriggers(triggers, _SUBSCRIBE, this._alignOnTrigger);
3430
                        this._contextTriggers = triggers;
3431
                    }
3432
                }
3433
            }
3434
        },
3435
3436
        /**
3437
         * Custom Event handler for context alignment triggers. Invokes the align method
3438
         * 
3439
         * @method _alignOnTrigger
3440
         * @protected
3441
         * 
3442
         * @param {String} type The event type (not used by the default implementation)
3443
         * @param {Any[]} args The array of arguments for the trigger event (not used by the default implementation)
3444
         */
3445
        _alignOnTrigger: function(type, args) {
3446
            this.align();
3447
        },
3448
3449
        /**
3450
         * Helper method to locate the custom event instance for the event name string
3451
         * passed in. As a convenience measure, any custom events passed in are returned.
3452
         *
3453
         * @method _findTriggerCE
3454
         * @private
3455
         *
3456
         * @param {String|CustomEvent} t Either a CustomEvent, or event type (e.g. "windowScroll") for which a 
3457
         * custom event instance needs to be looked up from the Overlay._TRIGGER_MAP.
3458
         */
3459
        _findTriggerCE : function(t) {
3460
            var tce = null;
3461
            if (t instanceof CustomEvent) {
3462
                tce = t;
3463
            } else if (Overlay._TRIGGER_MAP[t]) {
3464
                tce = Overlay._TRIGGER_MAP[t];
3465
            }
3466
            return tce;
3467
        },
3468
3469
        /**
3470
         * Utility method that subscribes or unsubscribes the given 
3471
         * function from the list of trigger events provided.
3472
         *
3473
         * @method _processTriggers
3474
         * @protected 
3475
         *
3476
         * @param {Array[String|CustomEvent]} triggers An array of either CustomEvents, event type strings 
3477
         * (e.g. "beforeShow", "windowScroll") to/from which the provided function should be 
3478
         * subscribed/unsubscribed respectively.
3479
         *
3480
         * @param {String} mode Either "subscribe" or "unsubscribe", specifying whether or not
3481
         * we are subscribing or unsubscribing trigger listeners
3482
         * 
3483
         * @param {Function} fn The function to be subscribed/unsubscribed to/from the trigger event.
3484
         * Context is always set to the overlay instance, and no additional object argument 
3485
         * get passed to the subscribed function.
3486
         */
3487
        _processTriggers : function(triggers, mode, fn) {
3488
            var t, tce;
3489
3490
            for (var i = 0, l = triggers.length; i < l; ++i) {
3491
                t = triggers[i];
3492
                tce = this._findTriggerCE(t);
3493
                if (tce) {
3494
                    tce[mode](fn, this, true);
3495
                } else {
3496
                    this[mode](t, fn);
3497
                }
3498
            }
3499
        },
3500
3501
        // END BUILT-IN PROPERTY EVENT HANDLERS //
3502
        /**
3503
        * Aligns the Overlay to its context element using the specified corner 
3504
        * points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, 
3505
        * and BOTTOM_RIGHT.
3506
        * @method align
3507
        * @param {String} elementAlign  The String representing the corner of 
3508
        * the Overlay that should be aligned to the context element
3509
        * @param {String} contextAlign  The corner of the context element 
3510
        * that the elementAlign corner should stick to.
3511
        * @param {Number[]} xyOffset Optional. A 2 element array specifying the x and y pixel offsets which should be applied
3512
        * after aligning the element and context corners. For example, passing in [5, -10] for this value, would offset the 
3513
        * Overlay by 5 pixels along the X axis (horizontally) and -10 pixels along the Y axis (vertically) after aligning the specified corners.
3514
        */
3515
        align: function (elementAlign, contextAlign, xyOffset) {
3516
3517
            var contextArgs = this.cfg.getProperty("context"),
3518
                me = this,
3519
                context,
3520
                element,
3521
                contextRegion;
3522
3523
            function doAlign(v, h) {
3524
3525
                var alignX = null, alignY = null;
3526
3527
                switch (elementAlign) {
3528
    
3529
                    case Overlay.TOP_LEFT:
3530
                        alignX = h;
3531
                        alignY = v;
3532
                        break;
3533
        
3534
                    case Overlay.TOP_RIGHT:
3535
                        alignX = h - element.offsetWidth;
3536
                        alignY = v;
3537
                        break;
3538
        
3539
                    case Overlay.BOTTOM_LEFT:
3540
                        alignX = h;
3541
                        alignY = v - element.offsetHeight;
3542
                        break;
3543
        
3544
                    case Overlay.BOTTOM_RIGHT:
3545
                        alignX = h - element.offsetWidth; 
3546
                        alignY = v - element.offsetHeight;
3547
                        break;
3548
                }
3549
3550
                if (alignX !== null && alignY !== null) {
3551
                    if (xyOffset) {
3552
                        alignX += xyOffset[0];
3553
                        alignY += xyOffset[1];
3554
                    }
3555
                    me.moveTo(alignX, alignY);
3556
                }
3557
            }
3558
3559
            if (contextArgs) {
3560
                context = contextArgs[0];
3561
                element = this.element;
3562
                me = this;
3563
3564
                if (! elementAlign) {
3565
                    elementAlign = contextArgs[1];
3566
                }
3567
3568
                if (! contextAlign) {
3569
                    contextAlign = contextArgs[2];
3570
                }
3571
3572
                if (!xyOffset && contextArgs[4]) {
3573
                    xyOffset = contextArgs[4];
3574
                }
3575
3576
                if (element && context) {
3577
                    contextRegion = Dom.getRegion(context);
3578
3579
                    switch (contextAlign) {
3580
    
3581
                        case Overlay.TOP_LEFT:
3582
                            doAlign(contextRegion.top, contextRegion.left);
3583
                            break;
3584
        
3585
                        case Overlay.TOP_RIGHT:
3586
                            doAlign(contextRegion.top, contextRegion.right);
3587
                            break;
3588
        
3589
                        case Overlay.BOTTOM_LEFT:
3590
                            doAlign(contextRegion.bottom, contextRegion.left);
3591
                            break;
3592
        
3593
                        case Overlay.BOTTOM_RIGHT:
3594
                            doAlign(contextRegion.bottom, contextRegion.right);
3595
                            break;
3596
                    }
3597
                }
3598
            }
3599
        },
3600
3601
        /**
3602
        * The default event handler executed when the moveEvent is fired, if the 
3603
        * "constraintoviewport" is set to true.
3604
        * @method enforceConstraints
3605
        * @param {String} type The CustomEvent type (usually the property name)
3606
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3607
        * handlers, args[0] will equal the newly applied value for the property.
3608
        * @param {Object} obj The scope object. For configuration handlers, 
3609
        * this will usually equal the owner.
3610
        */
3611
        enforceConstraints: function (type, args, obj) {
3612
            var pos = args[0];
3613
3614
            var cXY = this.getConstrainedXY(pos[0], pos[1]);
3615
            this.cfg.setProperty("x", cXY[0], true);
3616
            this.cfg.setProperty("y", cXY[1], true);
3617
            this.cfg.setProperty("xy", cXY, true);
3618
        },
3619
3620
        /**
3621
         * Shared implementation method for getConstrainedX and getConstrainedY.
3622
         * 
3623
         * <p>
3624
         * Given a coordinate value, returns the calculated coordinate required to 
3625
         * position the Overlay if it is to be constrained to the viewport, based on the 
3626
         * current element size, viewport dimensions, scroll values and preventoverlap 
3627
         * settings
3628
         * </p>
3629
         *
3630
         * @method _getConstrainedPos
3631
         * @protected
3632
         * @param {String} pos The coordinate which needs to be constrained, either "x" or "y"
3633
         * @param {Number} The coordinate value which needs to be constrained
3634
         * @return {Number} The constrained coordinate value
3635
         */
3636
        _getConstrainedPos: function(pos, val) {
3637
3638
            var overlayEl = this.element,
3639
3640
                buffer = Overlay.VIEWPORT_OFFSET,
3641
3642
                x = (pos == "x"),
3643
3644
                overlaySize      = (x) ? overlayEl.offsetWidth : overlayEl.offsetHeight,
3645
                viewportSize     = (x) ? Dom.getViewportWidth() : Dom.getViewportHeight(),
3646
                docScroll        = (x) ? Dom.getDocumentScrollLeft() : Dom.getDocumentScrollTop(),
3647
                overlapPositions = (x) ? Overlay.PREVENT_OVERLAP_X : Overlay.PREVENT_OVERLAP_Y,
3648
3649
                context = this.cfg.getProperty("context"),
3650
3651
                bOverlayFitsInViewport = (overlaySize + buffer < viewportSize),
3652
                bPreventContextOverlap = this.cfg.getProperty("preventcontextoverlap") && context && overlapPositions[(context[1] + context[2])],
3653
3654
                minConstraint = docScroll + buffer,
3655
                maxConstraint = docScroll + viewportSize - overlaySize - buffer,
3656
3657
                constrainedVal = val;
3658
3659
            if (val < minConstraint || val > maxConstraint) {
3660
                if (bPreventContextOverlap) {
3661
                    constrainedVal = this._preventOverlap(pos, context[0], overlaySize, viewportSize, docScroll);
3662
                } else {
3663
                    if (bOverlayFitsInViewport) {
3664
                        if (val < minConstraint) {
3665
                            constrainedVal = minConstraint;
3666
                        } else if (val > maxConstraint) {
3667
                            constrainedVal = maxConstraint;
3668
                        }
3669
                    } else {
3670
                        constrainedVal = minConstraint;
3671
                    }
3672
                }
3673
            }
3674
3675
            return constrainedVal;
3676
        },
3677
3678
        /**
3679
         * Helper method, used to position the Overlap to prevent overlap with the 
3680
         * context element (used when preventcontextoverlap is enabled)
3681
         *
3682
         * @method _preventOverlap
3683
         * @protected
3684
         * @param {String} pos The coordinate to prevent overlap for, either "x" or "y".
3685
         * @param {HTMLElement} contextEl The context element
3686
         * @param {Number} overlaySize The related overlay dimension value (for "x", the width, for "y", the height)
3687
         * @param {Number} viewportSize The related viewport dimension value (for "x", the width, for "y", the height)
3688
         * @param {Object} docScroll  The related document scroll value (for "x", the scrollLeft, for "y", the scrollTop)
3689
         *
3690
         * @return {Number} The new coordinate value which was set to prevent overlap
3691
         */
3692
        _preventOverlap : function(pos, contextEl, overlaySize, viewportSize, docScroll) {
3693
            
3694
            var x = (pos == "x"),
3695
3696
                buffer = Overlay.VIEWPORT_OFFSET,
3697
3698
                overlay = this,
3699
3700
                contextElPos   = ((x) ? Dom.getX(contextEl) : Dom.getY(contextEl)) - docScroll,
3701
                contextElSize  = (x) ? contextEl.offsetWidth : contextEl.offsetHeight,
3702
3703
                minRegionSize = contextElPos - buffer,
3704
                maxRegionSize = (viewportSize - (contextElPos + contextElSize)) - buffer,
3705
3706
                bFlipped = false,
3707
3708
                flip = function () {
3709
                    var flippedVal;
3710
3711
                    if ((overlay.cfg.getProperty(pos) - docScroll) > contextElPos) {
3712
                        flippedVal = (contextElPos - overlaySize);
3713
                    } else {
3714
                        flippedVal = (contextElPos + contextElSize);
3715
                    }
3716
3717
                    overlay.cfg.setProperty(pos, (flippedVal + docScroll), true);
3718
3719
                    return flippedVal;
3720
                },
3721
3722
                setPosition = function () {
3723
3724
                    var displayRegionSize = ((overlay.cfg.getProperty(pos) - docScroll) > contextElPos) ? maxRegionSize : minRegionSize,
3725
                        position;
3726
3727
                    if (overlaySize > displayRegionSize) {
3728
                        if (bFlipped) {
3729
                            /*
3730
                                 All possible positions and values have been 
3731
                                 tried, but none were successful, so fall back 
3732
                                 to the original size and position.
3733
                            */
3734
                            flip();
3735
                        } else {
3736
                            flip();
3737
                            bFlipped = true;
3738
                            position = setPosition();
3739
                        }
3740
                    }
3741
3742
                    return position;
3743
                };
3744
3745
            setPosition();
3746
3747
            return this.cfg.getProperty(pos);
3748
        },
3749
3750
        /**
3751
         * Given x coordinate value, returns the calculated x coordinate required to 
3752
         * position the Overlay if it is to be constrained to the viewport, based on the 
3753
         * current element size, viewport dimensions and scroll values.
3754
         *
3755
         * @param {Number} x The X coordinate value to be constrained
3756
         * @return {Number} The constrained x coordinate
3757
         */		
3758
        getConstrainedX: function (x) {
3759
            return this._getConstrainedPos("x", x);
3760
        },
3761
3762
        /**
3763
         * Given y coordinate value, returns the calculated y coordinate required to 
3764
         * position the Overlay if it is to be constrained to the viewport, based on the 
3765
         * current element size, viewport dimensions and scroll values.
3766
         *
3767
         * @param {Number} y The Y coordinate value to be constrained
3768
         * @return {Number} The constrained y coordinate
3769
         */		
3770
        getConstrainedY : function (y) {
3771
            return this._getConstrainedPos("y", y);
3772
        },
3773
3774
        /**
3775
         * Given x, y coordinate values, returns the calculated coordinates required to 
3776
         * position the Overlay if it is to be constrained to the viewport, based on the 
3777
         * current element size, viewport dimensions and scroll values.
3778
         *
3779
         * @param {Number} x The X coordinate value to be constrained
3780
         * @param {Number} y The Y coordinate value to be constrained
3781
         * @return {Array} The constrained x and y coordinates at index 0 and 1 respectively;
3782
         */
3783
        getConstrainedXY: function(x, y) {
3784
            return [this.getConstrainedX(x), this.getConstrainedY(y)];
3785
        },
3786
3787
        /**
3788
        * Centers the container in the viewport.
3789
        * @method center
3790
        */
3791
        center: function () {
3792
3793
            var nViewportOffset = Overlay.VIEWPORT_OFFSET,
3794
                elementWidth = this.element.offsetWidth,
3795
                elementHeight = this.element.offsetHeight,
3796
                viewPortWidth = Dom.getViewportWidth(),
3797
                viewPortHeight = Dom.getViewportHeight(),
3798
                x,
3799
                y;
3800
3801
            if (elementWidth < viewPortWidth) {
3802
                x = (viewPortWidth / 2) - (elementWidth / 2) + Dom.getDocumentScrollLeft();
3803
            } else {
3804
                x = nViewportOffset + Dom.getDocumentScrollLeft();
3805
            }
3806
3807
            if (elementHeight < viewPortHeight) {
3808
                y = (viewPortHeight / 2) - (elementHeight / 2) + Dom.getDocumentScrollTop();
3809
            } else {
3810
                y = nViewportOffset + Dom.getDocumentScrollTop();
3811
            }
3812
3813
            this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
3814
            this.cfg.refireEvent("iframe");
3815
3816
            if (UA.webkit) {
3817
                this.forceContainerRedraw();
3818
            }
3819
        },
3820
3821
        /**
3822
        * Synchronizes the Panel's "xy", "x", and "y" properties with the 
3823
        * Panel's position in the DOM. This is primarily used to update  
3824
        * position information during drag & drop.
3825
        * @method syncPosition
3826
        */
3827
        syncPosition: function () {
3828
3829
            var pos = Dom.getXY(this.element);
3830
3831
            this.cfg.setProperty("x", pos[0], true);
3832
            this.cfg.setProperty("y", pos[1], true);
3833
            this.cfg.setProperty("xy", pos, true);
3834
3835
        },
3836
3837
        /**
3838
        * Event handler fired when the resize monitor element is resized.
3839
        * @method onDomResize
3840
        * @param {DOMEvent} e The resize DOM event
3841
        * @param {Object} obj The scope object
3842
        */
3843
        onDomResize: function (e, obj) {
3844
3845
            var me = this;
3846
3847
            Overlay.superclass.onDomResize.call(this, e, obj);
3848
3849
            setTimeout(function () {
3850
                me.syncPosition();
3851
                me.cfg.refireEvent("iframe");
3852
                me.cfg.refireEvent("context");
3853
            }, 0);
3854
        },
3855
3856
        /**
3857
         * Determines the content box height of the given element (height of the element, without padding or borders) in pixels.
3858
         *
3859
         * @method _getComputedHeight
3860
         * @private
3861
         * @param {HTMLElement} el The element for which the content height needs to be determined
3862
         * @return {Number} The content box height of the given element, or null if it could not be determined.
3863
         */
3864
        _getComputedHeight : (function() {
3865
3866
            if (document.defaultView && document.defaultView.getComputedStyle) {
3867
                return function(el) {
3868
                    var height = null;
3869
                    if (el.ownerDocument && el.ownerDocument.defaultView) {
3870
                        var computed = el.ownerDocument.defaultView.getComputedStyle(el, '');
3871
                        if (computed) {
3872
                            height = parseInt(computed.height, 10);
3873
                        }
3874
                    }
3875
                    return (Lang.isNumber(height)) ? height : null;
3876
                };
3877
            } else {
3878
                return function(el) {
3879
                    var height = null;
3880
                    if (el.style.pixelHeight) {
3881
                        height = el.style.pixelHeight;
3882
                    }
3883
                    return (Lang.isNumber(height)) ? height : null;
3884
                };
3885
            }
3886
        })(),
3887
3888
        /**
3889
         * autofillheight validator. Verifies that the autofill value is either null 
3890
         * or one of the strings : "body", "header" or "footer".
3891
         *
3892
         * @method _validateAutoFillHeight
3893
         * @protected
3894
         * @param {String} val
3895
         * @return true, if valid, false otherwise
3896
         */
3897
        _validateAutoFillHeight : function(val) {
3898
            return (!val) || (Lang.isString(val) && Overlay.STD_MOD_RE.test(val));
3899
        },
3900
3901
        /**
3902
         * The default custom event handler executed when the overlay's height is changed, 
3903
         * if the autofillheight property has been set.
3904
         *
3905
         * @method _autoFillOnHeightChange
3906
         * @protected
3907
         * @param {String} type The event type
3908
         * @param {Array} args The array of arguments passed to event subscribers
3909
         * @param {HTMLElement} el The header, body or footer element which is to be resized to fill
3910
         * out the containers height
3911
         */
3912
        _autoFillOnHeightChange : function(type, args, el) {
3913
            var height = this.cfg.getProperty("height");
3914
            if ((height && height !== "auto") || (height === 0)) {
3915
                this.fillHeight(el);
3916
            }
3917
        },
3918
3919
        /**
3920
         * Returns the sub-pixel height of the el, using getBoundingClientRect, if available,
3921
         * otherwise returns the offsetHeight
3922
         * @method _getPreciseHeight
3923
         * @private
3924
         * @param {HTMLElement} el
3925
         * @return {Float} The sub-pixel height if supported by the browser, else the rounded height.
3926
         */
3927
        _getPreciseHeight : function(el) {
3928
            var height = el.offsetHeight;
3929
3930
            if (el.getBoundingClientRect) {
3931
                var rect = el.getBoundingClientRect();
3932
                height = rect.bottom - rect.top;
3933
            }
3934
3935
            return height;
3936
        },
3937
3938
        /**
3939
         * <p>
3940
         * Sets the height on the provided header, body or footer element to 
3941
         * fill out the height of the container. It determines the height of the 
3942
         * containers content box, based on it's configured height value, and 
3943
         * sets the height of the autofillheight element to fill out any 
3944
         * space remaining after the other standard module element heights 
3945
         * have been accounted for.
3946
         * </p>
3947
         * <p><strong>NOTE:</strong> This method is not designed to work if an explicit 
3948
         * height has not been set on the container, since for an "auto" height container, 
3949
         * the heights of the header/body/footer will drive the height of the container.</p>
3950
         *
3951
         * @method fillHeight
3952
         * @param {HTMLElement} el The element which should be resized to fill out the height
3953
         * of the container element.
3954
         */
3955
        fillHeight : function(el) {
3956
            if (el) {
3957
                var container = this.innerElement || this.element,
3958
                    containerEls = [this.header, this.body, this.footer],
3959
                    containerEl,
3960
                    total = 0,
3961
                    filled = 0,
3962
                    remaining = 0,
3963
                    validEl = false;
3964
3965
                for (var i = 0, l = containerEls.length; i < l; i++) {
3966
                    containerEl = containerEls[i];
3967
                    if (containerEl) {
3968
                        if (el !== containerEl) {
3969
                            filled += this._getPreciseHeight(containerEl);
3970
                        } else {
3971
                            validEl = true;
3972
                        }
3973
                    }
3974
                }
3975
3976
                if (validEl) {
3977
3978
                    if (UA.ie || UA.opera) {
3979
                        // Need to set height to 0, to allow height to be reduced
3980
                        Dom.setStyle(el, 'height', 0 + 'px');
3981
                    }
3982
3983
                    total = this._getComputedHeight(container);
3984
3985
                    // Fallback, if we can't get computed value for content height
3986
                    if (total === null) {
3987
                        Dom.addClass(container, "yui-override-padding");
3988
                        total = container.clientHeight; // Content, No Border, 0 Padding (set by yui-override-padding)
3989
                        Dom.removeClass(container, "yui-override-padding");
3990
                    }
3991
    
3992
                    remaining = Math.max(total - filled, 0);
3993
    
3994
                    Dom.setStyle(el, "height", remaining + "px");
3995
    
3996
                    // Re-adjust height if required, to account for el padding and border
3997
                    if (el.offsetHeight != remaining) {
3998
                        remaining = Math.max(remaining - (el.offsetHeight - remaining), 0);
3999
                    }
4000
                    Dom.setStyle(el, "height", remaining + "px");
4001
                }
4002
            }
4003
        },
4004
4005
        /**
4006
        * Places the Overlay on top of all other instances of 
4007
        * YAHOO.widget.Overlay.
4008
        * @method bringToTop
4009
        */
4010
        bringToTop: function () {
4011
4012
            var aOverlays = [],
4013
                oElement = this.element;
4014
4015
            function compareZIndexDesc(p_oOverlay1, p_oOverlay2) {
4016
4017
                var sZIndex1 = Dom.getStyle(p_oOverlay1, "zIndex"),
4018
                    sZIndex2 = Dom.getStyle(p_oOverlay2, "zIndex"),
4019
4020
                    nZIndex1 = (!sZIndex1 || isNaN(sZIndex1)) ? 0 : parseInt(sZIndex1, 10),
4021
                    nZIndex2 = (!sZIndex2 || isNaN(sZIndex2)) ? 0 : parseInt(sZIndex2, 10);
4022
4023
                if (nZIndex1 > nZIndex2) {
4024
                    return -1;
4025
                } else if (nZIndex1 < nZIndex2) {
4026
                    return 1;
4027
                } else {
4028
                    return 0;
4029
                }
4030
            }
4031
4032
            function isOverlayElement(p_oElement) {
4033
4034
                var isOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY),
4035
                    Panel = YAHOO.widget.Panel;
4036
4037
                if (isOverlay && !Dom.isAncestor(oElement, p_oElement)) {
4038
                    if (Panel && Dom.hasClass(p_oElement, Panel.CSS_PANEL)) {
4039
                        aOverlays[aOverlays.length] = p_oElement.parentNode;
4040
                    } else {
4041
                        aOverlays[aOverlays.length] = p_oElement;
4042
                    }
4043
                }
4044
            }
4045
4046
            Dom.getElementsBy(isOverlayElement, "DIV", document.body);
4047
4048
            aOverlays.sort(compareZIndexDesc);
4049
4050
            var oTopOverlay = aOverlays[0],
4051
                nTopZIndex;
4052
4053
            if (oTopOverlay) {
4054
                nTopZIndex = Dom.getStyle(oTopOverlay, "zIndex");
4055
4056
                if (!isNaN(nTopZIndex)) {
4057
                    var bRequiresBump = false;
4058
4059
                    if (oTopOverlay != oElement) {
4060
                        bRequiresBump = true;
4061
                    } else if (aOverlays.length > 1) {
4062
                        var nNextZIndex = Dom.getStyle(aOverlays[1], "zIndex");
4063
                        // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
4064
                        if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
4065
                            bRequiresBump = true;
4066
                        }
4067
                    }
4068
                    if (bRequiresBump) {
4069
                        this.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
4070
                    }
4071
                }
4072
            }
4073
        },
4074
4075
        /**
4076
        * Removes the Overlay element from the DOM and sets all child 
4077
        * elements to null.
4078
        * @method destroy
4079
        */
4080
        destroy: function () {
4081
4082
            if (this.iframe) {
4083
                this.iframe.parentNode.removeChild(this.iframe);
4084
            }
4085
4086
            this.iframe = null;
4087
4088
            Overlay.windowResizeEvent.unsubscribe(
4089
                this.doCenterOnDOMEvent, this);
4090
    
4091
            Overlay.windowScrollEvent.unsubscribe(
4092
                this.doCenterOnDOMEvent, this);
4093
4094
            Module.textResizeEvent.unsubscribe(this._autoFillOnHeightChange);
4095
4096
            if (this._contextTriggers) {
4097
                // Unsubscribe context triggers - to cover context triggers which listen for global
4098
                // events such as windowResize and windowScroll. Easier just to unsubscribe all
4099
                this._processTriggers(this._contextTriggers, _UNSUBSCRIBE, this._alignOnTrigger);
4100
            }
4101
4102
            Overlay.superclass.destroy.call(this);
4103
        },
4104
4105
        /**
4106
         * Can be used to force the container to repaint/redraw it's contents.
4107
         * <p>
4108
         * By default applies and then removes a 1px bottom margin through the 
4109
         * application/removal of a "yui-force-redraw" class.
4110
         * </p>
4111
         * <p>
4112
         * It is currently used by Overlay to force a repaint for webkit 
4113
         * browsers, when centering.
4114
         * </p>
4115
         * @method forceContainerRedraw
4116
         */
4117
        forceContainerRedraw : function() {
4118
            var c = this;
4119
            Dom.addClass(c.element, "yui-force-redraw");
4120
            setTimeout(function() {
4121
                Dom.removeClass(c.element, "yui-force-redraw");
4122
            }, 0);
4123
        },
4124
4125
        /**
4126
        * Returns a String representation of the object.
4127
        * @method toString
4128
        * @return {String} The string representation of the Overlay.
4129
        */
4130
        toString: function () {
4131
            return "Overlay " + this.id;
4132
        }
4133
4134
    });
4135
}());
4136
(function () {
4137
4138
    /**
4139
    * OverlayManager is used for maintaining the focus status of 
4140
    * multiple Overlays.
4141
    * @namespace YAHOO.widget
4142
    * @namespace YAHOO.widget
4143
    * @class OverlayManager
4144
    * @constructor
4145
    * @param {Array} overlays Optional. A collection of Overlays to register 
4146
    * with the manager.
4147
    * @param {Object} userConfig  The object literal representing the user 
4148
    * configuration of the OverlayManager
4149
    */
4150
    YAHOO.widget.OverlayManager = function (userConfig) {
4151
        this.init(userConfig);
4152
    };
4153
4154
    var Overlay = YAHOO.widget.Overlay,
4155
        Event = YAHOO.util.Event,
4156
        Dom = YAHOO.util.Dom,
4157
        Config = YAHOO.util.Config,
4158
        CustomEvent = YAHOO.util.CustomEvent,
4159
        OverlayManager = YAHOO.widget.OverlayManager;
4160
4161
    /**
4162
    * The CSS class representing a focused Overlay
4163
    * @property OverlayManager.CSS_FOCUSED
4164
    * @static
4165
    * @final
4166
    * @type String
4167
    */
4168
    OverlayManager.CSS_FOCUSED = "focused";
4169
4170
    OverlayManager.prototype = {
4171
4172
        /**
4173
        * The class's constructor function
4174
        * @property contructor
4175
        * @type Function
4176
        */
4177
        constructor: OverlayManager,
4178
4179
        /**
4180
        * The array of Overlays that are currently registered
4181
        * @property overlays
4182
        * @type YAHOO.widget.Overlay[]
4183
        */
4184
        overlays: null,
4185
4186
        /**
4187
        * Initializes the default configuration of the OverlayManager
4188
        * @method initDefaultConfig
4189
        */
4190
        initDefaultConfig: function () {
4191
            /**
4192
            * The collection of registered Overlays in use by 
4193
            * the OverlayManager
4194
            * @config overlays
4195
            * @type YAHOO.widget.Overlay[]
4196
            * @default null
4197
            */
4198
            this.cfg.addProperty("overlays", { suppressEvent: true } );
4199
4200
            /**
4201
            * The default DOM event that should be used to focus an Overlay
4202
            * @config focusevent
4203
            * @type String
4204
            * @default "mousedown"
4205
            */
4206
            this.cfg.addProperty("focusevent", { value: "mousedown" } );
4207
        },
4208
4209
        /**
4210
        * Initializes the OverlayManager
4211
        * @method init
4212
        * @param {Overlay[]} overlays Optional. A collection of Overlays to 
4213
        * register with the manager.
4214
        * @param {Object} userConfig  The object literal representing the user 
4215
        * configuration of the OverlayManager
4216
        */
4217
        init: function (userConfig) {
4218
4219
            /**
4220
            * The OverlayManager's Config object used for monitoring 
4221
            * configuration properties.
4222
            * @property cfg
4223
            * @type Config
4224
            */
4225
            this.cfg = new Config(this);
4226
4227
            this.initDefaultConfig();
4228
4229
            if (userConfig) {
4230
                this.cfg.applyConfig(userConfig, true);
4231
            }
4232
            this.cfg.fireQueue();
4233
4234
            /**
4235
            * The currently activated Overlay
4236
            * @property activeOverlay
4237
            * @private
4238
            * @type YAHOO.widget.Overlay
4239
            */
4240
            var activeOverlay = null;
4241
4242
            /**
4243
            * Returns the currently focused Overlay
4244
            * @method getActive
4245
            * @return {Overlay} The currently focused Overlay
4246
            */
4247
            this.getActive = function () {
4248
                return activeOverlay;
4249
            };
4250
4251
            /**
4252
            * Focuses the specified Overlay
4253
            * @method focus
4254
            * @param {Overlay} overlay The Overlay to focus
4255
            * @param {String} overlay The id of the Overlay to focus
4256
            */
4257
            this.focus = function (overlay) {
4258
                var o = this.find(overlay);
4259
                if (o) {
4260
                    o.focus();
4261
                }
4262
            };
4263
4264
            /**
4265
            * Removes the specified Overlay from the manager
4266
            * @method remove
4267
            * @param {Overlay} overlay The Overlay to remove
4268
            * @param {String} overlay The id of the Overlay to remove
4269
            */
4270
            this.remove = function (overlay) {
4271
4272
                var o = this.find(overlay), 
4273
                        originalZ;
4274
4275
                if (o) {
4276
                    if (activeOverlay == o) {
4277
                        activeOverlay = null;
4278
                    }
4279
4280
                    var bDestroyed = (o.element === null && o.cfg === null) ? true : false;
4281
4282
                    if (!bDestroyed) {
4283
                        // Set it's zindex so that it's sorted to the end.
4284
                        originalZ = Dom.getStyle(o.element, "zIndex");
4285
                        o.cfg.setProperty("zIndex", -1000, true);
4286
                    }
4287
4288
                    this.overlays.sort(this.compareZIndexDesc);
4289
                    this.overlays = this.overlays.slice(0, (this.overlays.length - 1));
4290
4291
                    o.hideEvent.unsubscribe(o.blur);
4292
                    o.destroyEvent.unsubscribe(this._onOverlayDestroy, o);
4293
                    o.focusEvent.unsubscribe(this._onOverlayFocusHandler, o);
4294
                    o.blurEvent.unsubscribe(this._onOverlayBlurHandler, o);
4295
4296
                    if (!bDestroyed) {
4297
                        Event.removeListener(o.element, this.cfg.getProperty("focusevent"), this._onOverlayElementFocus);
4298
                        o.cfg.setProperty("zIndex", originalZ, true);
4299
                        o.cfg.setProperty("manager", null);
4300
                    }
4301
4302
                    /* _managed Flag for custom or existing. Don't want to remove existing */
4303
                    if (o.focusEvent._managed) { o.focusEvent = null; }
4304
                    if (o.blurEvent._managed) { o.blurEvent = null; }
4305
4306
                    if (o.focus._managed) { o.focus = null; }
4307
                    if (o.blur._managed) { o.blur = null; }
4308
                }
4309
            };
4310
4311
            /**
4312
            * Removes focus from all registered Overlays in the manager
4313
            * @method blurAll
4314
            */
4315
            this.blurAll = function () {
4316
4317
                var nOverlays = this.overlays.length,
4318
                    i;
4319
4320
                if (nOverlays > 0) {
4321
                    i = nOverlays - 1;
4322
                    do {
4323
                        this.overlays[i].blur();
4324
                    }
4325
                    while(i--);
4326
                }
4327
            };
4328
4329
            /**
4330
             * Updates the state of the OverlayManager and overlay, as a result of the overlay
4331
             * being blurred.
4332
             * 
4333
             * @method _manageBlur
4334
             * @param {Overlay} overlay The overlay instance which got blurred.
4335
             * @protected
4336
             */
4337
            this._manageBlur = function (overlay) {
4338
                var changed = false;
4339
                if (activeOverlay == overlay) {
4340
                    Dom.removeClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
4341
                    activeOverlay = null;
4342
                    changed = true;
4343
                }
4344
                return changed;
4345
            };
4346
4347
            /**
4348
             * Updates the state of the OverlayManager and overlay, as a result of the overlay 
4349
             * receiving focus.
4350
             *
4351
             * @method _manageFocus
4352
             * @param {Overlay} overlay The overlay instance which got focus.
4353
             * @protected
4354
             */
4355
            this._manageFocus = function(overlay) {
4356
                var changed = false;
4357
                if (activeOverlay != overlay) {
4358
                    if (activeOverlay) {
4359
                        activeOverlay.blur();
4360
                    }
4361
                    activeOverlay = overlay;
4362
                    this.bringToTop(activeOverlay);
4363
                    Dom.addClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
4364
                    changed = true;
4365
                }
4366
                return changed;
4367
            };
4368
4369
            var overlays = this.cfg.getProperty("overlays");
4370
4371
            if (! this.overlays) {
4372
                this.overlays = [];
4373
            }
4374
4375
            if (overlays) {
4376
                this.register(overlays);
4377
                this.overlays.sort(this.compareZIndexDesc);
4378
            }
4379
        },
4380
4381
        /**
4382
        * @method _onOverlayElementFocus
4383
        * @description Event handler for the DOM event that is used to focus 
4384
        * the Overlay instance as specified by the "focusevent" 
4385
        * configuration property.
4386
        * @private
4387
        * @param {Event} p_oEvent Object representing the DOM event 
4388
        * object passed back by the event utility (Event).
4389
        */
4390
        _onOverlayElementFocus: function (p_oEvent) {
4391
4392
            var oTarget = Event.getTarget(p_oEvent),
4393
                oClose = this.close;
4394
4395
            if (oClose && (oTarget == oClose || Dom.isAncestor(oClose, oTarget))) {
4396
                this.blur();
4397
            } else {
4398
                this.focus();
4399
            }
4400
        },
4401
4402
        /**
4403
        * @method _onOverlayDestroy
4404
        * @description "destroy" event handler for the Overlay.
4405
        * @private
4406
        * @param {String} p_sType String representing the name of the event  
4407
        * that was fired.
4408
        * @param {Array} p_aArgs Array of arguments sent when the event 
4409
        * was fired.
4410
        * @param {Overlay} p_oOverlay Object representing the overlay that 
4411
        * fired the event.
4412
        */
4413
        _onOverlayDestroy: function (p_sType, p_aArgs, p_oOverlay) {
4414
            this.remove(p_oOverlay);
4415
        },
4416
4417
        /**
4418
        * @method _onOverlayFocusHandler
4419
        *
4420
        * @description focusEvent Handler, used to delegate to _manageFocus with the correct arguments.
4421
        *
4422
        * @private
4423
        * @param {String} p_sType String representing the name of the event  
4424
        * that was fired.
4425
        * @param {Array} p_aArgs Array of arguments sent when the event 
4426
        * was fired.
4427
        * @param {Overlay} p_oOverlay Object representing the overlay that 
4428
        * fired the event.
4429
        */
4430
        _onOverlayFocusHandler: function(p_sType, p_aArgs, p_oOverlay) {
4431
            this._manageFocus(p_oOverlay);
4432
        },
4433
4434
        /**
4435
        * @method _onOverlayBlurHandler
4436
        * @description blurEvent Handler, used to delegate to _manageBlur with the correct arguments.
4437
        *
4438
        * @private
4439
        * @param {String} p_sType String representing the name of the event  
4440
        * that was fired.
4441
        * @param {Array} p_aArgs Array of arguments sent when the event 
4442
        * was fired.
4443
        * @param {Overlay} p_oOverlay Object representing the overlay that 
4444
        * fired the event.
4445
        */
4446
        _onOverlayBlurHandler: function(p_sType, p_aArgs, p_oOverlay) {
4447
            this._manageBlur(p_oOverlay);
4448
        },
4449
4450
        /**
4451
         * Subscribes to the Overlay based instance focusEvent, to allow the OverlayManager to
4452
         * monitor focus state.
4453
         * 
4454
         * If the instance already has a focusEvent (e.g. Menu), OverlayManager will subscribe 
4455
         * to the existing focusEvent, however if a focusEvent or focus method does not exist
4456
         * on the instance, the _bindFocus method will add them, and the focus method will 
4457
         * update the OverlayManager's state directly.
4458
         * 
4459
         * @method _bindFocus
4460
         * @param {Overlay} overlay The overlay for which focus needs to be managed
4461
         * @protected
4462
         */
4463
        _bindFocus : function(overlay) {
4464
            var mgr = this;
4465
4466
            if (!overlay.focusEvent) {
4467
                overlay.focusEvent = overlay.createEvent("focus");
4468
                overlay.focusEvent.signature = CustomEvent.LIST;
4469
                overlay.focusEvent._managed = true;
4470
            } else {
4471
                overlay.focusEvent.subscribe(mgr._onOverlayFocusHandler, overlay, mgr);
4472
            }
4473
4474
            if (!overlay.focus) {
4475
                Event.on(overlay.element, mgr.cfg.getProperty("focusevent"), mgr._onOverlayElementFocus, null, overlay);
4476
                overlay.focus = function () {
4477
                    if (mgr._manageFocus(this)) {
4478
                        // For Panel/Dialog
4479
                        if (this.cfg.getProperty("visible") && this.focusFirst) {
4480
                            this.focusFirst();
4481
                        }
4482
                        this.focusEvent.fire();
4483
                    }
4484
                };
4485
                overlay.focus._managed = true;
4486
            }
4487
        },
4488
4489
        /**
4490
         * Subscribes to the Overlay based instance's blurEvent to allow the OverlayManager to
4491
         * monitor blur state.
4492
         *
4493
         * If the instance already has a blurEvent (e.g. Menu), OverlayManager will subscribe 
4494
         * to the existing blurEvent, however if a blurEvent or blur method does not exist
4495
         * on the instance, the _bindBlur method will add them, and the blur method 
4496
         * update the OverlayManager's state directly.
4497
         *
4498
         * @method _bindBlur
4499
         * @param {Overlay} overlay The overlay for which blur needs to be managed
4500
         * @protected
4501
         */
4502
        _bindBlur : function(overlay) {
4503
            var mgr = this;
4504
4505
            if (!overlay.blurEvent) {
4506
                overlay.blurEvent = overlay.createEvent("blur");
4507
                overlay.blurEvent.signature = CustomEvent.LIST;
4508
                overlay.focusEvent._managed = true;
4509
            } else {
4510
                overlay.blurEvent.subscribe(mgr._onOverlayBlurHandler, overlay, mgr);
4511
            }
4512
4513
            if (!overlay.blur) {
4514
                overlay.blur = function () {
4515
                    if (mgr._manageBlur(this)) {
4516
                        this.blurEvent.fire();
4517
                    }
4518
                };
4519
                overlay.blur._managed = true;
4520
            }
4521
4522
            overlay.hideEvent.subscribe(overlay.blur);
4523
        },
4524
4525
        /**
4526
         * Subscribes to the Overlay based instance's destroyEvent, to allow the Overlay
4527
         * to be removed for the OverlayManager when destroyed.
4528
         * 
4529
         * @method _bindDestroy
4530
         * @param {Overlay} overlay The overlay instance being managed
4531
         * @protected
4532
         */
4533
        _bindDestroy : function(overlay) {
4534
            var mgr = this;
4535
            overlay.destroyEvent.subscribe(mgr._onOverlayDestroy, overlay, mgr);
4536
        },
4537
4538
        /**
4539
         * Ensures the zIndex configuration property on the managed overlay based instance
4540
         * is set to the computed zIndex value from the DOM (with "auto" translating to 0).
4541
         *
4542
         * @method _syncZIndex
4543
         * @param {Overlay} overlay The overlay instance being managed
4544
         * @protected
4545
         */
4546
        _syncZIndex : function(overlay) {
4547
            var zIndex = Dom.getStyle(overlay.element, "zIndex");
4548
            if (!isNaN(zIndex)) {
4549
                overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
4550
            } else {
4551
                overlay.cfg.setProperty("zIndex", 0);
4552
            }
4553
        },
4554
4555
        /**
4556
        * Registers an Overlay or an array of Overlays with the manager. Upon 
4557
        * registration, the Overlay receives functions for focus and blur, 
4558
        * along with CustomEvents for each.
4559
        *
4560
        * @method register
4561
        * @param {Overlay} overlay  An Overlay to register with the manager.
4562
        * @param {Overlay[]} overlay  An array of Overlays to register with 
4563
        * the manager.
4564
        * @return {boolean} true if any Overlays are registered.
4565
        */
4566
        register: function (overlay) {
4567
4568
            var registered = false,
4569
                i,
4570
                n;
4571
4572
            if (overlay instanceof Overlay) {
4573
4574
                overlay.cfg.addProperty("manager", { value: this } );
4575
4576
                this._bindFocus(overlay);
4577
                this._bindBlur(overlay);
4578
                this._bindDestroy(overlay);
4579
                this._syncZIndex(overlay);
4580
4581
                this.overlays.push(overlay);
4582
                this.bringToTop(overlay);
4583
4584
                registered = true;
4585
4586
            } else if (overlay instanceof Array) {
4587
4588
                for (i = 0, n = overlay.length; i < n; i++) {
4589
                    registered = this.register(overlay[i]) || registered;
4590
                }
4591
4592
            }
4593
4594
            return registered;
4595
        },
4596
4597
        /**
4598
        * Places the specified Overlay instance on top of all other 
4599
        * Overlay instances.
4600
        * @method bringToTop
4601
        * @param {YAHOO.widget.Overlay} p_oOverlay Object representing an 
4602
        * Overlay instance.
4603
        * @param {String} p_oOverlay String representing the id of an 
4604
        * Overlay instance.
4605
        */        
4606
        bringToTop: function (p_oOverlay) {
4607
4608
            var oOverlay = this.find(p_oOverlay),
4609
                nTopZIndex,
4610
                oTopOverlay,
4611
                aOverlays;
4612
4613
            if (oOverlay) {
4614
4615
                aOverlays = this.overlays;
4616
                aOverlays.sort(this.compareZIndexDesc);
4617
4618
                oTopOverlay = aOverlays[0];
4619
4620
                if (oTopOverlay) {
4621
                    nTopZIndex = Dom.getStyle(oTopOverlay.element, "zIndex");
4622
4623
                    if (!isNaN(nTopZIndex)) {
4624
4625
                        var bRequiresBump = false;
4626
4627
                        if (oTopOverlay !== oOverlay) {
4628
                            bRequiresBump = true;
4629
                        } else if (aOverlays.length > 1) {
4630
                            var nNextZIndex = Dom.getStyle(aOverlays[1].element, "zIndex");
4631
                            // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
4632
                            if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
4633
                                bRequiresBump = true;
4634
                            }
4635
                        }
4636
4637
                        if (bRequiresBump) {
4638
                            oOverlay.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
4639
                        }
4640
                    }
4641
                    aOverlays.sort(this.compareZIndexDesc);
4642
                }
4643
            }
4644
        },
4645
4646
        /**
4647
        * Attempts to locate an Overlay by instance or ID.
4648
        * @method find
4649
        * @param {Overlay} overlay  An Overlay to locate within the manager
4650
        * @param {String} overlay  An Overlay id to locate within the manager
4651
        * @return {Overlay} The requested Overlay, if found, or null if it 
4652
        * cannot be located.
4653
        */
4654
        find: function (overlay) {
4655
4656
            var isInstance = overlay instanceof Overlay,
4657
                overlays = this.overlays,
4658
                n = overlays.length,
4659
                found = null,
4660
                o,
4661
                i;
4662
4663
            if (isInstance || typeof overlay == "string") {
4664
                for (i = n-1; i >= 0; i--) {
4665
                    o = overlays[i];
4666
                    if ((isInstance && (o === overlay)) || (o.id == overlay)) {
4667
                        found = o;
4668
                        break;
4669
                    }
4670
                }
4671
            }
4672
4673
            return found;
4674
        },
4675
4676
        /**
4677
        * Used for sorting the manager's Overlays by z-index.
4678
        * @method compareZIndexDesc
4679
        * @private
4680
        * @return {Number} 0, 1, or -1, depending on where the Overlay should 
4681
        * fall in the stacking order.
4682
        */
4683
        compareZIndexDesc: function (o1, o2) {
4684
4685
            var zIndex1 = (o1.cfg) ? o1.cfg.getProperty("zIndex") : null, // Sort invalid (destroyed)
4686
                zIndex2 = (o2.cfg) ? o2.cfg.getProperty("zIndex") : null; // objects at bottom.
4687
4688
            if (zIndex1 === null && zIndex2 === null) {
4689
                return 0;
4690
            } else if (zIndex1 === null){
4691
                return 1;
4692
            } else if (zIndex2 === null) {
4693
                return -1;
4694
            } else if (zIndex1 > zIndex2) {
4695
                return -1;
4696
            } else if (zIndex1 < zIndex2) {
4697
                return 1;
4698
            } else {
4699
                return 0;
4700
            }
4701
        },
4702
4703
        /**
4704
        * Shows all Overlays in the manager.
4705
        * @method showAll
4706
        */
4707
        showAll: function () {
4708
            var overlays = this.overlays,
4709
                n = overlays.length,
4710
                i;
4711
4712
            for (i = n - 1; i >= 0; i--) {
4713
                overlays[i].show();
4714
            }
4715
        },
4716
4717
        /**
4718
        * Hides all Overlays in the manager.
4719
        * @method hideAll
4720
        */
4721
        hideAll: function () {
4722
            var overlays = this.overlays,
4723
                n = overlays.length,
4724
                i;
4725
4726
            for (i = n - 1; i >= 0; i--) {
4727
                overlays[i].hide();
4728
            }
4729
        },
4730
4731
        /**
4732
        * Returns a string representation of the object.
4733
        * @method toString
4734
        * @return {String} The string representation of the OverlayManager
4735
        */
4736
        toString: function () {
4737
            return "OverlayManager";
4738
        }
4739
    };
4740
}());
4741
(function () {
4742
4743
    /**
4744
    * Tooltip is an implementation of Overlay that behaves like an OS tooltip, 
4745
    * displaying when the user mouses over a particular element, and 
4746
    * disappearing on mouse out.
4747
    * @namespace YAHOO.widget
4748
    * @class Tooltip
4749
    * @extends YAHOO.widget.Overlay
4750
    * @constructor
4751
    * @param {String} el The element ID representing the Tooltip <em>OR</em>
4752
    * @param {HTMLElement} el The element representing the Tooltip
4753
    * @param {Object} userConfig The configuration object literal containing 
4754
    * the configuration that should be set for this Overlay. See configuration 
4755
    * documentation for more details.
4756
    */
4757
    YAHOO.widget.Tooltip = function (el, userConfig) {
4758
        YAHOO.widget.Tooltip.superclass.constructor.call(this, el, userConfig);
4759
    };
4760
4761
    var Lang = YAHOO.lang,
4762
        Event = YAHOO.util.Event,
4763
        CustomEvent = YAHOO.util.CustomEvent,
4764
        Dom = YAHOO.util.Dom,
4765
        Tooltip = YAHOO.widget.Tooltip,
4766
        UA = YAHOO.env.ua,
4767
        bIEQuirks = (UA.ie && (UA.ie <= 6 || document.compatMode == "BackCompat")),
4768
4769
        m_oShadowTemplate,
4770
4771
        /**
4772
        * Constant representing the Tooltip's configuration properties
4773
        * @property DEFAULT_CONFIG
4774
        * @private
4775
        * @final
4776
        * @type Object
4777
        */
4778
        DEFAULT_CONFIG = {
4779
4780
            "PREVENT_OVERLAP": { 
4781
                key: "preventoverlap", 
4782
                value: true, 
4783
                validator: Lang.isBoolean, 
4784
                supercedes: ["x", "y", "xy"] 
4785
            },
4786
4787
            "SHOW_DELAY": { 
4788
                key: "showdelay", 
4789
                value: 200, 
4790
                validator: Lang.isNumber 
4791
            }, 
4792
4793
            "AUTO_DISMISS_DELAY": { 
4794
                key: "autodismissdelay", 
4795
                value: 5000, 
4796
                validator: Lang.isNumber 
4797
            }, 
4798
4799
            "HIDE_DELAY": { 
4800
                key: "hidedelay", 
4801
                value: 250, 
4802
                validator: Lang.isNumber 
4803
            }, 
4804
4805
            "TEXT": { 
4806
                key: "text", 
4807
                suppressEvent: true 
4808
            }, 
4809
4810
            "CONTAINER": { 
4811
                key: "container"
4812
            },
4813
4814
            "DISABLED": {
4815
                key: "disabled",
4816
                value: false,
4817
                suppressEvent: true
4818
            },
4819
4820
            "XY_OFFSET": {
4821
                key: "xyoffset",
4822
                value: [0, 25],
4823
                suppressEvent: true
4824
            }
4825
        },
4826
4827
        /**
4828
        * Constant representing the name of the Tooltip's events
4829
        * @property EVENT_TYPES
4830
        * @private
4831
        * @final
4832
        * @type Object
4833
        */
4834
        EVENT_TYPES = {
4835
            "CONTEXT_MOUSE_OVER": "contextMouseOver",
4836
            "CONTEXT_MOUSE_OUT": "contextMouseOut",
4837
            "CONTEXT_TRIGGER": "contextTrigger"
4838
        };
4839
4840
    /**
4841
    * Constant representing the Tooltip CSS class
4842
    * @property YAHOO.widget.Tooltip.CSS_TOOLTIP
4843
    * @static
4844
    * @final
4845
    * @type String
4846
    */
4847
    Tooltip.CSS_TOOLTIP = "yui-tt";
4848
4849
    function restoreOriginalWidth(sOriginalWidth, sForcedWidth) {
4850
4851
        var oConfig = this.cfg,
4852
            sCurrentWidth = oConfig.getProperty("width");
4853
4854
        if (sCurrentWidth == sForcedWidth) {
4855
            oConfig.setProperty("width", sOriginalWidth);
4856
        }
4857
    }
4858
4859
    /* 
4860
        changeContent event handler that sets a Tooltip instance's "width"
4861
        configuration property to the value of its root HTML 
4862
        elements's offsetWidth if a specific width has not been set.
4863
    */
4864
4865
    function setWidthToOffsetWidth(p_sType, p_aArgs) {
4866
4867
        if ("_originalWidth" in this) {
4868
            restoreOriginalWidth.call(this, this._originalWidth, this._forcedWidth);
4869
        }
4870
4871
        var oBody = document.body,
4872
            oConfig = this.cfg,
4873
            sOriginalWidth = oConfig.getProperty("width"),
4874
            sNewWidth,
4875
            oClone;
4876
4877
        if ((!sOriginalWidth || sOriginalWidth == "auto") && 
4878
            (oConfig.getProperty("container") != oBody || 
4879
            oConfig.getProperty("x") >= Dom.getViewportWidth() || 
4880
            oConfig.getProperty("y") >= Dom.getViewportHeight())) {
4881
4882
            oClone = this.element.cloneNode(true);
4883
            oClone.style.visibility = "hidden";
4884
            oClone.style.top = "0px";
4885
            oClone.style.left = "0px";
4886
4887
            oBody.appendChild(oClone);
4888
4889
            sNewWidth = (oClone.offsetWidth + "px");
4890
4891
            oBody.removeChild(oClone);
4892
            oClone = null;
4893
4894
            oConfig.setProperty("width", sNewWidth);
4895
            oConfig.refireEvent("xy");
4896
4897
            this._originalWidth = sOriginalWidth || "";
4898
            this._forcedWidth = sNewWidth;
4899
        }
4900
    }
4901
4902
    // "onDOMReady" that renders the ToolTip
4903
4904
    function onDOMReady(p_sType, p_aArgs, p_oObject) {
4905
        this.render(p_oObject);
4906
    }
4907
4908
    //  "init" event handler that automatically renders the Tooltip
4909
4910
    function onInit() {
4911
        Event.onDOMReady(onDOMReady, this.cfg.getProperty("container"), this);
4912
    }
4913
4914
    YAHOO.extend(Tooltip, YAHOO.widget.Overlay, { 
4915
4916
        /**
4917
        * The Tooltip initialization method. This method is automatically 
4918
        * called by the constructor. A Tooltip is automatically rendered by 
4919
        * the init method, and it also is set to be invisible by default, 
4920
        * and constrained to viewport by default as well.
4921
        * @method init
4922
        * @param {String} el The element ID representing the Tooltip <em>OR</em>
4923
        * @param {HTMLElement} el The element representing the Tooltip
4924
        * @param {Object} userConfig The configuration object literal 
4925
        * containing the configuration that should be set for this Tooltip. 
4926
        * See configuration documentation for more details.
4927
        */
4928
        init: function (el, userConfig) {
4929
4930
4931
            Tooltip.superclass.init.call(this, el);
4932
4933
            this.beforeInitEvent.fire(Tooltip);
4934
4935
            Dom.addClass(this.element, Tooltip.CSS_TOOLTIP);
4936
4937
            if (userConfig) {
4938
                this.cfg.applyConfig(userConfig, true);
4939
            }
4940
4941
            this.cfg.queueProperty("visible", false);
4942
            this.cfg.queueProperty("constraintoviewport", true);
4943
4944
            this.setBody("");
4945
4946
            this.subscribe("changeContent", setWidthToOffsetWidth);
4947
            this.subscribe("init", onInit);
4948
            this.subscribe("render", this.onRender);
4949
4950
            this.initEvent.fire(Tooltip);
4951
        },
4952
4953
        /**
4954
        * Initializes the custom events for Tooltip
4955
        * @method initEvents
4956
        */
4957
        initEvents: function () {
4958
4959
            Tooltip.superclass.initEvents.call(this);
4960
            var SIGNATURE = CustomEvent.LIST;
4961
4962
            /**
4963
            * CustomEvent fired when user mouses over a context element. Returning false from
4964
            * a subscriber to this event will prevent the tooltip from being displayed for
4965
            * the current context element.
4966
            * 
4967
            * @event contextMouseOverEvent
4968
            * @param {HTMLElement} context The context element which the user just moused over
4969
            * @param {DOMEvent} e The DOM event object, associated with the mouse over
4970
            */
4971
            this.contextMouseOverEvent = this.createEvent(EVENT_TYPES.CONTEXT_MOUSE_OVER);
4972
            this.contextMouseOverEvent.signature = SIGNATURE;
4973
4974
            /**
4975
            * CustomEvent fired when the user mouses out of a context element.
4976
            * 
4977
            * @event contextMouseOutEvent
4978
            * @param {HTMLElement} context The context element which the user just moused out of
4979
            * @param {DOMEvent} e The DOM event object, associated with the mouse out
4980
            */
4981
            this.contextMouseOutEvent = this.createEvent(EVENT_TYPES.CONTEXT_MOUSE_OUT);
4982
            this.contextMouseOutEvent.signature = SIGNATURE;
4983
4984
            /**
4985
            * CustomEvent fired just before the tooltip is displayed for the current context.
4986
            * <p>
4987
            *  You can subscribe to this event if you need to set up the text for the 
4988
            *  tooltip based on the context element for which it is about to be displayed.
4989
            * </p>
4990
            * <p>This event differs from the beforeShow event in following respects:</p>
4991
            * <ol>
4992
            *   <li>
4993
            *    When moving from one context element to another, if the tooltip is not
4994
            *    hidden (the <code>hidedelay</code> is not reached), the beforeShow and Show events will not
4995
            *    be fired when the tooltip is displayed for the new context since it is already visible.
4996
            *    However the contextTrigger event is always fired before displaying the tooltip for
4997
            *    a new context.
4998
            *   </li>
4999
            *   <li>
5000
            *    The trigger event provides access to the context element, allowing you to 
5001
            *    set the text of the tooltip based on context element for which the tooltip is
5002
            *    triggered.
5003
            *   </li>
5004
            * </ol>
5005
            * <p>
5006
            *  It is not possible to prevent the tooltip from being displayed
5007
            *  using this event. You can use the contextMouseOverEvent if you need to prevent
5008
            *  the tooltip from being displayed.
5009
            * </p>
5010
            * @event contextTriggerEvent
5011
            * @param {HTMLElement} context The context element for which the tooltip is triggered
5012
            */
5013
            this.contextTriggerEvent = this.createEvent(EVENT_TYPES.CONTEXT_TRIGGER);
5014
            this.contextTriggerEvent.signature = SIGNATURE;
5015
        },
5016
5017
        /**
5018
        * Initializes the class's configurable properties which can be 
5019
        * changed using the Overlay's Config object (cfg).
5020
        * @method initDefaultConfig
5021
        */
5022
        initDefaultConfig: function () {
5023
5024
            Tooltip.superclass.initDefaultConfig.call(this);
5025
5026
            /**
5027
            * Specifies whether the Tooltip should be kept from overlapping 
5028
            * its context element.
5029
            * @config preventoverlap
5030
            * @type Boolean
5031
            * @default true
5032
            */
5033
            this.cfg.addProperty(DEFAULT_CONFIG.PREVENT_OVERLAP.key, {
5034
                value: DEFAULT_CONFIG.PREVENT_OVERLAP.value, 
5035
                validator: DEFAULT_CONFIG.PREVENT_OVERLAP.validator, 
5036
                supercedes: DEFAULT_CONFIG.PREVENT_OVERLAP.supercedes
5037
            });
5038
5039
            /**
5040
            * The number of milliseconds to wait before showing a Tooltip 
5041
            * on mouseover.
5042
            * @config showdelay
5043
            * @type Number
5044
            * @default 200
5045
            */
5046
            this.cfg.addProperty(DEFAULT_CONFIG.SHOW_DELAY.key, {
5047
                handler: this.configShowDelay,
5048
                value: 200, 
5049
                validator: DEFAULT_CONFIG.SHOW_DELAY.validator
5050
            });
5051
5052
            /**
5053
            * The number of milliseconds to wait before automatically 
5054
            * dismissing a Tooltip after the mouse has been resting on the 
5055
            * context element.
5056
            * @config autodismissdelay
5057
            * @type Number
5058
            * @default 5000
5059
            */
5060
            this.cfg.addProperty(DEFAULT_CONFIG.AUTO_DISMISS_DELAY.key, {
5061
                handler: this.configAutoDismissDelay,
5062
                value: DEFAULT_CONFIG.AUTO_DISMISS_DELAY.value,
5063
                validator: DEFAULT_CONFIG.AUTO_DISMISS_DELAY.validator
5064
            });
5065
5066
            /**
5067
            * The number of milliseconds to wait before hiding a Tooltip 
5068
            * after mouseout.
5069
            * @config hidedelay
5070
            * @type Number
5071
            * @default 250
5072
            */
5073
            this.cfg.addProperty(DEFAULT_CONFIG.HIDE_DELAY.key, {
5074
                handler: this.configHideDelay,
5075
                value: DEFAULT_CONFIG.HIDE_DELAY.value, 
5076
                validator: DEFAULT_CONFIG.HIDE_DELAY.validator
5077
            });
5078
5079
            /**
5080
            * Specifies the Tooltip's text. 
5081
            * @config text
5082
            * @type String
5083
            * @default null
5084
            */
5085
            this.cfg.addProperty(DEFAULT_CONFIG.TEXT.key, {
5086
                handler: this.configText,
5087
                suppressEvent: DEFAULT_CONFIG.TEXT.suppressEvent
5088
            });
5089
5090
            /**
5091
            * Specifies the container element that the Tooltip's markup 
5092
            * should be rendered into.
5093
            * @config container
5094
            * @type HTMLElement/String
5095
            * @default document.body
5096
            */
5097
            this.cfg.addProperty(DEFAULT_CONFIG.CONTAINER.key, {
5098
                handler: this.configContainer,
5099
                value: document.body
5100
            });
5101
5102
            /**
5103
            * Specifies whether or not the tooltip is disabled. Disabled tooltips
5104
            * will not be displayed. If the tooltip is driven by the title attribute
5105
            * of the context element, the title attribute will still be removed for 
5106
            * disabled tooltips, to prevent default tooltip behavior.
5107
            * 
5108
            * @config disabled
5109
            * @type Boolean
5110
            * @default false
5111
            */
5112
            this.cfg.addProperty(DEFAULT_CONFIG.DISABLED.key, {
5113
                handler: this.configContainer,
5114
                value: DEFAULT_CONFIG.DISABLED.value,
5115
                supressEvent: DEFAULT_CONFIG.DISABLED.suppressEvent
5116
            });
5117
5118
            /**
5119
            * Specifies the XY offset from the mouse position, where the tooltip should be displayed, specified
5120
            * as a 2 element array (e.g. [10, 20]); 
5121
            *
5122
            * @config xyoffset
5123
            * @type Array
5124
            * @default [0, 25]
5125
            */
5126
            this.cfg.addProperty(DEFAULT_CONFIG.XY_OFFSET.key, {
5127
                value: DEFAULT_CONFIG.XY_OFFSET.value.concat(),
5128
                supressEvent: DEFAULT_CONFIG.XY_OFFSET.suppressEvent 
5129
            });
5130
5131
            /**
5132
            * Specifies the element or elements that the Tooltip should be 
5133
            * anchored to on mouseover.
5134
            * @config context
5135
            * @type HTMLElement[]/String[]
5136
            * @default null
5137
            */ 
5138
5139
            /**
5140
            * String representing the width of the Tooltip.  <em>Please note:
5141
            * </em> As of version 2.3 if either no value or a value of "auto" 
5142
            * is specified, and the Toolip's "container" configuration property
5143
            * is set to something other than <code>document.body</code> or 
5144
            * its "context" element resides outside the immediately visible 
5145
            * portion of the document, the width of the Tooltip will be 
5146
            * calculated based on the offsetWidth of its root HTML and set just 
5147
            * before it is made visible.  The original value will be 
5148
            * restored when the Tooltip is hidden. This ensures the Tooltip is 
5149
            * rendered at a usable width.  For more information see 
5150
            * YUILibrary bug #1685496 and YUILibrary 
5151
            * bug #1735423.
5152
            * @config width
5153
            * @type String
5154
            * @default null
5155
            */
5156
        
5157
        },
5158
        
5159
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
5160
        
5161
        /**
5162
        * The default event handler fired when the "text" property is changed.
5163
        * @method configText
5164
        * @param {String} type The CustomEvent type (usually the property name)
5165
        * @param {Object[]} args The CustomEvent arguments. For configuration 
5166
        * handlers, args[0] will equal the newly applied value for the property.
5167
        * @param {Object} obj The scope object. For configuration handlers, 
5168
        * this will usually equal the owner.
5169
        */
5170
        configText: function (type, args, obj) {
5171
            var text = args[0];
5172
            if (text) {
5173
                this.setBody(text);
5174
            }
5175
        },
5176
        
5177
        /**
5178
        * The default event handler fired when the "container" property 
5179
        * is changed.
5180
        * @method configContainer
5181
        * @param {String} type The CustomEvent type (usually the property name)
5182
        * @param {Object[]} args The CustomEvent arguments. For 
5183
        * configuration handlers, args[0] will equal the newly applied value 
5184
        * for the property.
5185
        * @param {Object} obj The scope object. For configuration handlers,
5186
        * this will usually equal the owner.
5187
        */
5188
        configContainer: function (type, args, obj) {
5189
            var container = args[0];
5190
5191
            if (typeof container == 'string') {
5192
                this.cfg.setProperty("container", document.getElementById(container), true);
5193
            }
5194
        },
5195
        
5196
        /**
5197
        * @method _removeEventListeners
5198
        * @description Removes all of the DOM event handlers from the HTML
5199
        *  element(s) that trigger the display of the tooltip.
5200
        * @protected
5201
        */
5202
        _removeEventListeners: function () {
5203
        
5204
            var aElements = this._context,
5205
                nElements,
5206
                oElement,
5207
                i;
5208
5209
            if (aElements) {
5210
                nElements = aElements.length;
5211
                if (nElements > 0) {
5212
                    i = nElements - 1;
5213
                    do {
5214
                        oElement = aElements[i];
5215
                        Event.removeListener(oElement, "mouseover", this.onContextMouseOver);
5216
                        Event.removeListener(oElement, "mousemove", this.onContextMouseMove);
5217
                        Event.removeListener(oElement, "mouseout", this.onContextMouseOut);
5218
                    }
5219
                    while (i--);
5220
                }
5221
            }
5222
        },
5223
        
5224
        /**
5225
        * The default event handler fired when the "context" property 
5226
        * is changed.
5227
        * @method configContext
5228
        * @param {String} type The CustomEvent type (usually the property name)
5229
        * @param {Object[]} args The CustomEvent arguments. For configuration 
5230
        * handlers, args[0] will equal the newly applied value for the property.
5231
        * @param {Object} obj The scope object. For configuration handlers,
5232
        * this will usually equal the owner.
5233
        */
5234
        configContext: function (type, args, obj) {
5235
5236
            var context = args[0],
5237
                aElements,
5238
                nElements,
5239
                oElement,
5240
                i;
5241
5242
            if (context) {
5243
5244
                // Normalize parameter into an array
5245
                if (! (context instanceof Array)) {
5246
                    if (typeof context == "string") {
5247
                        this.cfg.setProperty("context", [document.getElementById(context)], true);
5248
                    } else { // Assuming this is an element
5249
                        this.cfg.setProperty("context", [context], true);
5250
                    }
5251
                    context = this.cfg.getProperty("context");
5252
                }
5253
5254
                // Remove any existing mouseover/mouseout listeners
5255
                this._removeEventListeners();
5256
5257
                // Add mouseover/mouseout listeners to context elements
5258
                this._context = context;
5259
5260
                aElements = this._context;
5261
5262
                if (aElements) {
5263
                    nElements = aElements.length;
5264
                    if (nElements > 0) {
5265
                        i = nElements - 1;
5266
                        do {
5267
                            oElement = aElements[i];
5268
                            Event.on(oElement, "mouseover", this.onContextMouseOver, this);
5269
                            Event.on(oElement, "mousemove", this.onContextMouseMove, this);
5270
                            Event.on(oElement, "mouseout", this.onContextMouseOut, this);
5271
                        }
5272
                        while (i--);
5273
                    }
5274
                }
5275
            }
5276
        },
5277
5278
        // END BUILT-IN PROPERTY EVENT HANDLERS //
5279
5280
        // BEGIN BUILT-IN DOM EVENT HANDLERS //
5281
5282
        /**
5283
        * The default event handler fired when the user moves the mouse while 
5284
        * over the context element.
5285
        * @method onContextMouseMove
5286
        * @param {DOMEvent} e The current DOM event
5287
        * @param {Object} obj The object argument
5288
        */
5289
        onContextMouseMove: function (e, obj) {
5290
            obj.pageX = Event.getPageX(e);
5291
            obj.pageY = Event.getPageY(e);
5292
        },
5293
5294
        /**
5295
        * The default event handler fired when the user mouses over the 
5296
        * context element.
5297
        * @method onContextMouseOver
5298
        * @param {DOMEvent} e The current DOM event
5299
        * @param {Object} obj The object argument
5300
        */
5301
        onContextMouseOver: function (e, obj) {
5302
            var context = this;
5303
5304
            if (context.title) {
5305
                obj._tempTitle = context.title;
5306
                context.title = "";
5307
            }
5308
5309
            // Fire first, to honor disabled set in the listner
5310
            if (obj.fireEvent("contextMouseOver", context, e) !== false 
5311
                    && !obj.cfg.getProperty("disabled")) {
5312
5313
                // Stop the tooltip from being hidden (set on last mouseout)
5314
                if (obj.hideProcId) {
5315
                    clearTimeout(obj.hideProcId);
5316
                    obj.hideProcId = null;
5317
                }
5318
5319
                Event.on(context, "mousemove", obj.onContextMouseMove, obj);
5320
5321
                /**
5322
                * The unique process ID associated with the thread responsible 
5323
                * for showing the Tooltip.
5324
                * @type int
5325
                */
5326
                obj.showProcId = obj.doShow(e, context);
5327
            }
5328
        },
5329
5330
        /**
5331
        * The default event handler fired when the user mouses out of 
5332
        * the context element.
5333
        * @method onContextMouseOut
5334
        * @param {DOMEvent} e The current DOM event
5335
        * @param {Object} obj The object argument
5336
        */
5337
        onContextMouseOut: function (e, obj) {
5338
            var el = this;
5339
5340
            if (obj._tempTitle) {
5341
                el.title = obj._tempTitle;
5342
                obj._tempTitle = null;
5343
            }
5344
5345
            if (obj.showProcId) {
5346
                clearTimeout(obj.showProcId);
5347
                obj.showProcId = null;
5348
            }
5349
5350
            if (obj.hideProcId) {
5351
                clearTimeout(obj.hideProcId);
5352
                obj.hideProcId = null;
5353
            }
5354
5355
            obj.fireEvent("contextMouseOut", el, e);
5356
5357
            obj.hideProcId = setTimeout(function () {
5358
                obj.hide();
5359
            }, obj.cfg.getProperty("hidedelay"));
5360
        },
5361
5362
        // END BUILT-IN DOM EVENT HANDLERS //
5363
5364
        /**
5365
        * Processes the showing of the Tooltip by setting the timeout delay 
5366
        * and offset of the Tooltip.
5367
        * @method doShow
5368
        * @param {DOMEvent} e The current DOM event
5369
        * @param {HTMLElement} context The current context element
5370
        * @return {Number} The process ID of the timeout function associated 
5371
        * with doShow
5372
        */
5373
        doShow: function (e, context) {
5374
5375
            var offset = this.cfg.getProperty("xyoffset"),
5376
                xOffset = offset[0],
5377
                yOffset = offset[1],
5378
                me = this;
5379
5380
            if (UA.opera && context.tagName && 
5381
                context.tagName.toUpperCase() == "A") {
5382
                yOffset += 12;
5383
            }
5384
5385
            return setTimeout(function () {
5386
5387
                var txt = me.cfg.getProperty("text");
5388
5389
                // title does not over-ride text
5390
                if (me._tempTitle && (txt === "" || YAHOO.lang.isUndefined(txt) || YAHOO.lang.isNull(txt))) {
5391
                    me.setBody(me._tempTitle);
5392
                } else {
5393
                    me.cfg.refireEvent("text");
5394
                }
5395
5396
                me.moveTo(me.pageX + xOffset, me.pageY + yOffset);
5397
5398
                if (me.cfg.getProperty("preventoverlap")) {
5399
                    me.preventOverlap(me.pageX, me.pageY);
5400
                }
5401
5402
                Event.removeListener(context, "mousemove", me.onContextMouseMove);
5403
5404
                me.contextTriggerEvent.fire(context);
5405
5406
                me.show();
5407
5408
                me.hideProcId = me.doHide();
5409
5410
            }, this.cfg.getProperty("showdelay"));
5411
        },
5412
5413
        /**
5414
        * Sets the timeout for the auto-dismiss delay, which by default is 5 
5415
        * seconds, meaning that a tooltip will automatically dismiss itself 
5416
        * after 5 seconds of being displayed.
5417
        * @method doHide
5418
        */
5419
        doHide: function () {
5420
5421
            var me = this;
5422
5423
5424
            return setTimeout(function () {
5425
5426
                me.hide();
5427
5428
            }, this.cfg.getProperty("autodismissdelay"));
5429
5430
        },
5431
5432
        /**
5433
        * Fired when the Tooltip is moved, this event handler is used to 
5434
        * prevent the Tooltip from overlapping with its context element.
5435
        * @method preventOverlay
5436
        * @param {Number} pageX The x coordinate position of the mouse pointer
5437
        * @param {Number} pageY The y coordinate position of the mouse pointer
5438
        */
5439
        preventOverlap: function (pageX, pageY) {
5440
        
5441
            var height = this.element.offsetHeight,
5442
                mousePoint = new YAHOO.util.Point(pageX, pageY),
5443
                elementRegion = Dom.getRegion(this.element);
5444
        
5445
            elementRegion.top -= 5;
5446
            elementRegion.left -= 5;
5447
            elementRegion.right += 5;
5448
            elementRegion.bottom += 5;
5449
        
5450
        
5451
            if (elementRegion.contains(mousePoint)) {
5452
                this.cfg.setProperty("y", (pageY - height - 5));
5453
            }
5454
        },
5455
5456
5457
        /**
5458
        * @method onRender
5459
        * @description "render" event handler for the Tooltip.
5460
        * @param {String} p_sType String representing the name of the event  
5461
        * that was fired.
5462
        * @param {Array} p_aArgs Array of arguments sent when the event 
5463
        * was fired.
5464
        */
5465
        onRender: function (p_sType, p_aArgs) {
5466
    
5467
            function sizeShadow() {
5468
    
5469
                var oElement = this.element,
5470
                    oShadow = this.underlay;
5471
            
5472
                if (oShadow) {
5473
                    oShadow.style.width = (oElement.offsetWidth + 6) + "px";
5474
                    oShadow.style.height = (oElement.offsetHeight + 1) + "px"; 
5475
                }
5476
            
5477
            }
5478
5479
            function addShadowVisibleClass() {
5480
                Dom.addClass(this.underlay, "yui-tt-shadow-visible");
5481
5482
                if (UA.ie) {
5483
                    this.forceUnderlayRedraw();
5484
                }
5485
            }
5486
5487
            function removeShadowVisibleClass() {
5488
                Dom.removeClass(this.underlay, "yui-tt-shadow-visible");
5489
            }
5490
5491
            function createShadow() {
5492
    
5493
                var oShadow = this.underlay,
5494
                    oElement,
5495
                    Module,
5496
                    nIE,
5497
                    me;
5498
    
5499
                if (!oShadow) {
5500
    
5501
                    oElement = this.element;
5502
                    Module = YAHOO.widget.Module;
5503
                    nIE = UA.ie;
5504
                    me = this;
5505
5506
                    if (!m_oShadowTemplate) {
5507
                        m_oShadowTemplate = document.createElement("div");
5508
                        m_oShadowTemplate.className = "yui-tt-shadow";
5509
                    }
5510
5511
                    oShadow = m_oShadowTemplate.cloneNode(false);
5512
5513
                    oElement.appendChild(oShadow);
5514
5515
                    this.underlay = oShadow;
5516
5517
                    // Backward compatibility, even though it's probably 
5518
                    // intended to be "private", it isn't marked as such in the api docs
5519
                    this._shadow = this.underlay;
5520
5521
                    addShadowVisibleClass.call(this);
5522
5523
                    this.subscribe("beforeShow", addShadowVisibleClass);
5524
                    this.subscribe("hide", removeShadowVisibleClass);
5525
5526
                    if (bIEQuirks) {
5527
                        window.setTimeout(function () { 
5528
                            sizeShadow.call(me); 
5529
                        }, 0);
5530
    
5531
                        this.cfg.subscribeToConfigEvent("width", sizeShadow);
5532
                        this.cfg.subscribeToConfigEvent("height", sizeShadow);
5533
                        this.subscribe("changeContent", sizeShadow);
5534
5535
                        Module.textResizeEvent.subscribe(sizeShadow, this, true);
5536
                        this.subscribe("destroy", function () {
5537
                            Module.textResizeEvent.unsubscribe(sizeShadow, this);
5538
                        });
5539
                    }
5540
                }
5541
            }
5542
5543
            function onBeforeShow() {
5544
                createShadow.call(this);
5545
                this.unsubscribe("beforeShow", onBeforeShow);
5546
            }
5547
5548
            if (this.cfg.getProperty("visible")) {
5549
                createShadow.call(this);
5550
            } else {
5551
                this.subscribe("beforeShow", onBeforeShow);
5552
            }
5553
        
5554
        },
5555
5556
        /**
5557
         * Forces the underlay element to be repainted, through the application/removal
5558
         * of a yui-force-redraw class to the underlay element.
5559
         * 
5560
         * @method forceUnderlayRedraw
5561
         */
5562
        forceUnderlayRedraw : function() {
5563
            var tt = this;
5564
            Dom.addClass(tt.underlay, "yui-force-redraw");
5565
            setTimeout(function() {Dom.removeClass(tt.underlay, "yui-force-redraw");}, 0);
5566
        },
5567
5568
        /**
5569
        * Removes the Tooltip element from the DOM and sets all child 
5570
        * elements to null.
5571
        * @method destroy
5572
        */
5573
        destroy: function () {
5574
        
5575
            // Remove any existing mouseover/mouseout listeners
5576
            this._removeEventListeners();
5577
5578
            Tooltip.superclass.destroy.call(this);  
5579
        
5580
        },
5581
        
5582
        /**
5583
        * Returns a string representation of the object.
5584
        * @method toString
5585
        * @return {String} The string representation of the Tooltip
5586
        */
5587
        toString: function () {
5588
            return "Tooltip " + this.id;
5589
        }
5590
    
5591
    });
5592
5593
}());
5594
(function () {
5595
5596
    /**
5597
    * Panel is an implementation of Overlay that behaves like an OS window, 
5598
    * with a draggable header and an optional close icon at the top right.
5599
    * @namespace YAHOO.widget
5600
    * @class Panel
5601
    * @extends YAHOO.widget.Overlay
5602
    * @constructor
5603
    * @param {String} el The element ID representing the Panel <em>OR</em>
5604
    * @param {HTMLElement} el The element representing the Panel
5605
    * @param {Object} userConfig The configuration object literal containing 
5606
    * the configuration that should be set for this Panel. See configuration 
5607
    * documentation for more details.
5608
    */
5609
    YAHOO.widget.Panel = function (el, userConfig) {
5610
        YAHOO.widget.Panel.superclass.constructor.call(this, el, userConfig);
5611
    };
5612
5613
    var _currentModal = null;
5614
5615
    var Lang = YAHOO.lang,
5616
        Util = YAHOO.util,
5617
        Dom = Util.Dom,
5618
        Event = Util.Event,
5619
        CustomEvent = Util.CustomEvent,
5620
        KeyListener = YAHOO.util.KeyListener,
5621
        Config = Util.Config,
5622
        Overlay = YAHOO.widget.Overlay,
5623
        Panel = YAHOO.widget.Panel,
5624
        UA = YAHOO.env.ua,
5625
5626
        bIEQuirks = (UA.ie && (UA.ie <= 6 || document.compatMode == "BackCompat")),
5627
5628
        m_oMaskTemplate,
5629
        m_oUnderlayTemplate,
5630
        m_oCloseIconTemplate,
5631
5632
        /**
5633
        * Constant representing the name of the Panel's events
5634
        * @property EVENT_TYPES
5635
        * @private
5636
        * @final
5637
        * @type Object
5638
        */
5639
        EVENT_TYPES = {
5640
            "SHOW_MASK": "showMask",
5641
            "HIDE_MASK": "hideMask",
5642
            "DRAG": "drag"
5643
        },
5644
5645
        /**
5646
        * Constant representing the Panel's configuration properties
5647
        * @property DEFAULT_CONFIG
5648
        * @private
5649
        * @final
5650
        * @type Object
5651
        */
5652
        DEFAULT_CONFIG = {
5653
5654
            "CLOSE": { 
5655
                key: "close", 
5656
                value: true, 
5657
                validator: Lang.isBoolean, 
5658
                supercedes: ["visible"] 
5659
            },
5660
5661
            "DRAGGABLE": {
5662
                key: "draggable", 
5663
                value: (Util.DD ? true : false), 
5664
                validator: Lang.isBoolean, 
5665
                supercedes: ["visible"]  
5666
            },
5667
5668
            "DRAG_ONLY" : {
5669
                key: "dragonly",
5670
                value: false,
5671
                validator: Lang.isBoolean,
5672
                supercedes: ["draggable"]
5673
            },
5674
5675
            "UNDERLAY": { 
5676
                key: "underlay", 
5677
                value: "shadow", 
5678
                supercedes: ["visible"] 
5679
            },
5680
5681
            "MODAL": { 
5682
                key: "modal", 
5683
                value: false, 
5684
                validator: Lang.isBoolean, 
5685
                supercedes: ["visible", "zindex"]
5686
            },
5687
5688
            "KEY_LISTENERS": {
5689
                key: "keylisteners",
5690
                suppressEvent: true,
5691
                supercedes: ["visible"]
5692
            },
5693
5694
            "STRINGS" : {
5695
                key: "strings",
5696
                supercedes: ["close"],
5697
                validator: Lang.isObject,
5698
                value: {
5699
                    close: "Close"
5700
                }
5701
            }
5702
        };
5703
5704
    /**
5705
    * Constant representing the default CSS class used for a Panel
5706
    * @property YAHOO.widget.Panel.CSS_PANEL
5707
    * @static
5708
    * @final
5709
    * @type String
5710
    */
5711
    Panel.CSS_PANEL = "yui-panel";
5712
    
5713
    /**
5714
    * Constant representing the default CSS class used for a Panel's 
5715
    * wrapping container
5716
    * @property YAHOO.widget.Panel.CSS_PANEL_CONTAINER
5717
    * @static
5718
    * @final
5719
    * @type String
5720
    */
5721
    Panel.CSS_PANEL_CONTAINER = "yui-panel-container";
5722
5723
    /**
5724
     * Constant representing the default set of focusable elements 
5725
     * on the pagewhich Modal Panels will prevent access to, when
5726
     * the modal mask is displayed
5727
     * 
5728
     * @property YAHOO.widget.Panel.FOCUSABLE
5729
     * @static
5730
     * @type Array
5731
     */
5732
    Panel.FOCUSABLE = [
5733
        "a",
5734
        "button",
5735
        "select",
5736
        "textarea",
5737
        "input",
5738
        "iframe"
5739
    ];
5740
5741
    // Private CustomEvent listeners
5742
5743
    /* 
5744
        "beforeRender" event handler that creates an empty header for a Panel 
5745
        instance if its "draggable" configuration property is set to "true" 
5746
        and no header has been created.
5747
    */
5748
5749
    function createHeader(p_sType, p_aArgs) {
5750
        if (!this.header && this.cfg.getProperty("draggable")) {
5751
            this.setHeader("&#160;");
5752
        }
5753
    }
5754
5755
    /* 
5756
        "hide" event handler that sets a Panel instance's "width"
5757
        configuration property back to its original value before 
5758
        "setWidthToOffsetWidth" was called.
5759
    */
5760
    
5761
    function restoreOriginalWidth(p_sType, p_aArgs, p_oObject) {
5762
5763
        var sOriginalWidth = p_oObject[0],
5764
            sNewWidth = p_oObject[1],
5765
            oConfig = this.cfg,
5766
            sCurrentWidth = oConfig.getProperty("width");
5767
5768
        if (sCurrentWidth == sNewWidth) {
5769
            oConfig.setProperty("width", sOriginalWidth);
5770
        }
5771
5772
        this.unsubscribe("hide", restoreOriginalWidth, p_oObject);
5773
    }
5774
5775
    /* 
5776
        "beforeShow" event handler that sets a Panel instance's "width"
5777
        configuration property to the value of its root HTML 
5778
        elements's offsetWidth
5779
    */
5780
5781
    function setWidthToOffsetWidth(p_sType, p_aArgs) {
5782
5783
        var oConfig,
5784
            sOriginalWidth,
5785
            sNewWidth;
5786
5787
        if (bIEQuirks) {
5788
5789
            oConfig = this.cfg;
5790
            sOriginalWidth = oConfig.getProperty("width");
5791
            
5792
            if (!sOriginalWidth || sOriginalWidth == "auto") {
5793
    
5794
                sNewWidth = (this.element.offsetWidth + "px");
5795
    
5796
                oConfig.setProperty("width", sNewWidth);
5797
5798
                this.subscribe("hide", restoreOriginalWidth, 
5799
                    [(sOriginalWidth || ""), sNewWidth]);
5800
            
5801
            }
5802
        }
5803
    }
5804
5805
    YAHOO.extend(Panel, Overlay, {
5806
5807
        /**
5808
        * The Overlay initialization method, which is executed for Overlay and 
5809
        * all of its subclasses. This method is automatically called by the 
5810
        * constructor, and  sets up all DOM references for pre-existing markup, 
5811
        * and creates required markup if it is not already present.
5812
        * @method init
5813
        * @param {String} el The element ID representing the Overlay <em>OR</em>
5814
        * @param {HTMLElement} el The element representing the Overlay
5815
        * @param {Object} userConfig The configuration object literal 
5816
        * containing the configuration that should be set for this Overlay. 
5817
        * See configuration documentation for more details.
5818
        */
5819
        init: function (el, userConfig) {
5820
            /*
5821
                 Note that we don't pass the user config in here yet because 
5822
                 we only want it executed once, at the lowest subclass level
5823
            */
5824
5825
            Panel.superclass.init.call(this, el/*, userConfig*/);
5826
5827
            this.beforeInitEvent.fire(Panel);
5828
5829
            Dom.addClass(this.element, Panel.CSS_PANEL);
5830
5831
            this.buildWrapper();
5832
5833
            if (userConfig) {
5834
                this.cfg.applyConfig(userConfig, true);
5835
            }
5836
5837
            this.subscribe("showMask", this._addFocusHandlers);
5838
            this.subscribe("hideMask", this._removeFocusHandlers);
5839
            this.subscribe("beforeRender", createHeader);
5840
5841
            this.subscribe("render", function() {
5842
                this.setFirstLastFocusable();
5843
                this.subscribe("changeContent", this.setFirstLastFocusable);
5844
            });
5845
5846
            this.subscribe("show", this.focusFirst);
5847
5848
            this.initEvent.fire(Panel);
5849
        },
5850
5851
        /**
5852
         * @method _onElementFocus
5853
         * @private
5854
         *
5855
         * "focus" event handler for a focuable element. Used to automatically
5856
         * blur the element when it receives focus to ensure that a Panel
5857
         * instance's modality is not compromised.
5858
         *
5859
         * @param {Event} e The DOM event object
5860
         */
5861
        _onElementFocus : function(e){
5862
5863
            if(_currentModal === this) {
5864
5865
                var target = Event.getTarget(e),
5866
                    doc = document.documentElement,
5867
                    insideDoc = (target !== doc && target !== window);
5868
5869
                // mask and documentElement checks added for IE, which focuses on the mask when it's clicked on, and focuses on 
5870
                // the documentElement, when the document scrollbars are clicked on
5871
                if (insideDoc && target !== this.element && target !== this.mask && !Dom.isAncestor(this.element, target)) {
5872
                    try {
5873
                        if (this.firstElement) {
5874
                            this.firstElement.focus();
5875
                        } else {
5876
                            if (this._modalFocus) {
5877
                                this._modalFocus.focus();
5878
                            } else {
5879
                                this.innerElement.focus();
5880
                            }
5881
                        }
5882
                    } catch(err){
5883
                        // Just in case we fail to focus
5884
                        try {
5885
                            if (insideDoc && target !== document.body) {
5886
                                target.blur();
5887
                            }
5888
                        } catch(err2) { }
5889
                    }
5890
                }
5891
            }
5892
        },
5893
5894
        /** 
5895
         *  @method _addFocusHandlers
5896
         *  @protected
5897
         *  
5898
         *  "showMask" event handler that adds a "focus" event handler to all
5899
         *  focusable elements in the document to enforce a Panel instance's 
5900
         *  modality from being compromised.
5901
         *
5902
         *  @param p_sType {String} Custom event type
5903
         *  @param p_aArgs {Array} Custom event arguments
5904
         */
5905
        _addFocusHandlers: function(p_sType, p_aArgs) {
5906
            if (!this.firstElement) {
5907
                if (UA.webkit || UA.opera) {
5908
                    if (!this._modalFocus) {
5909
                        this._createHiddenFocusElement();
5910
                    }
5911
                } else {
5912
                    this.innerElement.tabIndex = 0;
5913
                }
5914
            }
5915
            this.setTabLoop(this.firstElement, this.lastElement);
5916
            Event.onFocus(document.documentElement, this._onElementFocus, this, true);
5917
            _currentModal = this;
5918
        },
5919
5920
        /**
5921
         * Creates a hidden focusable element, used to focus on,
5922
         * to enforce modality for browsers in which focus cannot
5923
         * be applied to the container box.
5924
         * 
5925
         * @method _createHiddenFocusElement
5926
         * @private
5927
         */
5928
        _createHiddenFocusElement : function() {
5929
            var e = document.createElement("button");
5930
            e.style.height = "1px";
5931
            e.style.width = "1px";
5932
            e.style.position = "absolute";
5933
            e.style.left = "-10000em";
5934
            e.style.opacity = 0;
5935
            e.tabIndex = -1;
5936
            this.innerElement.appendChild(e);
5937
            this._modalFocus = e;
5938
        },
5939
5940
        /**
5941
         *  @method _removeFocusHandlers
5942
         *  @protected
5943
         *
5944
         *  "hideMask" event handler that removes all "focus" event handlers added 
5945
         *  by the "addFocusEventHandlers" method.
5946
         *
5947
         *  @param p_sType {String} Event type
5948
         *  @param p_aArgs {Array} Event Arguments
5949
         */
5950
        _removeFocusHandlers: function(p_sType, p_aArgs) {
5951
            Event.removeFocusListener(document.documentElement, this._onElementFocus, this);
5952
5953
            if (_currentModal == this) {
5954
                _currentModal = null;
5955
            }
5956
        },
5957
5958
        /**
5959
         * Sets focus to the first element in the Panel.
5960
         *
5961
         * @method focusFirst
5962
         */
5963
        focusFirst: function (type, args, obj) {
5964
            var el = this.firstElement;
5965
5966
            if (args && args[1]) {
5967
                Event.stopEvent(args[1]);
5968
            }
5969
5970
            if (el) {
5971
                try {
5972
                    el.focus();
5973
                } catch(err) {
5974
                    // Ignore
5975
                }
5976
            }
5977
        },
5978
5979
        /**
5980
         * Sets focus to the last element in the Panel.
5981
         *
5982
         * @method focusLast
5983
         */
5984
        focusLast: function (type, args, obj) {
5985
            var el = this.lastElement;
5986
5987
            if (args && args[1]) {
5988
                Event.stopEvent(args[1]);
5989
            }
5990
5991
            if (el) {
5992
                try {
5993
                    el.focus();
5994
                } catch(err) {
5995
                    // Ignore
5996
                }
5997
            }
5998
        },
5999
6000
        /**
6001
         * Sets up a tab, shift-tab loop between the first and last elements
6002
         * provided. NOTE: Sets up the preventBackTab and preventTabOut KeyListener
6003
         * instance properties, which are reset everytime this method is invoked.
6004
         *
6005
         * @method setTabLoop
6006
         * @param {HTMLElement} firstElement
6007
         * @param {HTMLElement} lastElement
6008
         *
6009
         */
6010
        setTabLoop : function(firstElement, lastElement) {
6011
6012
            var backTab = this.preventBackTab, tab = this.preventTabOut,
6013
                showEvent = this.showEvent, hideEvent = this.hideEvent;
6014
6015
            if (backTab) {
6016
                backTab.disable();
6017
                showEvent.unsubscribe(backTab.enable, backTab);
6018
                hideEvent.unsubscribe(backTab.disable, backTab);
6019
                backTab = this.preventBackTab = null;
6020
            }
6021
6022
            if (tab) {
6023
                tab.disable();
6024
                showEvent.unsubscribe(tab.enable, tab);
6025
                hideEvent.unsubscribe(tab.disable,tab);
6026
                tab = this.preventTabOut = null;
6027
            }
6028
6029
            if (firstElement) {
6030
                this.preventBackTab = new KeyListener(firstElement, 
6031
                    {shift:true, keys:9},
6032
                    {fn:this.focusLast, scope:this, correctScope:true}
6033
                );
6034
                backTab = this.preventBackTab;
6035
6036
                showEvent.subscribe(backTab.enable, backTab, true);
6037
                hideEvent.subscribe(backTab.disable,backTab, true);
6038
            }
6039
6040
            if (lastElement) {
6041
                this.preventTabOut = new KeyListener(lastElement, 
6042
                    {shift:false, keys:9}, 
6043
                    {fn:this.focusFirst, scope:this, correctScope:true}
6044
                );
6045
                tab = this.preventTabOut;
6046
6047
                showEvent.subscribe(tab.enable, tab, true);
6048
                hideEvent.subscribe(tab.disable,tab, true);
6049
            }
6050
        },
6051
6052
        /**
6053
         * Returns an array of the currently focusable items which reside within
6054
         * Panel. The set of focusable elements the method looks for are defined
6055
         * in the Panel.FOCUSABLE static property
6056
         *
6057
         * @method getFocusableElements
6058
         * @param {HTMLElement} root element to start from.
6059
         */
6060
        getFocusableElements : function(root) {
6061
6062
            root = root || this.innerElement;
6063
6064
            var focusable = {};
6065
            for (var i = 0; i < Panel.FOCUSABLE.length; i++) {
6066
                focusable[Panel.FOCUSABLE[i]] = true;
6067
            }
6068
6069
            function isFocusable(el) {
6070
                if (el.focus && el.type !== "hidden" && !el.disabled && focusable[el.tagName.toLowerCase()]) {
6071
                    return true;
6072
                }
6073
                return false;
6074
            }
6075
6076
            // Not looking by Tag, since we want elements in DOM order
6077
            return Dom.getElementsBy(isFocusable, null, root);
6078
        },
6079
6080
        /**
6081
         * Sets the firstElement and lastElement instance properties
6082
         * to the first and last focusable elements in the Panel.
6083
         *
6084
         * @method setFirstLastFocusable
6085
         */
6086
        setFirstLastFocusable : function() {
6087
6088
            this.firstElement = null;
6089
            this.lastElement = null;
6090
6091
            var elements = this.getFocusableElements();
6092
            this.focusableElements = elements;
6093
6094
            if (elements.length > 0) {
6095
                this.firstElement = elements[0];
6096
                this.lastElement = elements[elements.length - 1];
6097
            }
6098
6099
            if (this.cfg.getProperty("modal")) {
6100
                this.setTabLoop(this.firstElement, this.lastElement);
6101
            }
6102
        },
6103
6104
        /**
6105
         * Initializes the custom events for Module which are fired 
6106
         * automatically at appropriate times by the Module class.
6107
         */
6108
        initEvents: function () {
6109
            Panel.superclass.initEvents.call(this);
6110
6111
            var SIGNATURE = CustomEvent.LIST;
6112
6113
            /**
6114
            * CustomEvent fired after the modality mask is shown
6115
            * @event showMaskEvent
6116
            */
6117
            this.showMaskEvent = this.createEvent(EVENT_TYPES.SHOW_MASK);
6118
            this.showMaskEvent.signature = SIGNATURE;
6119
6120
            /**
6121
            * CustomEvent fired after the modality mask is hidden
6122
            * @event hideMaskEvent
6123
            */
6124
            this.hideMaskEvent = this.createEvent(EVENT_TYPES.HIDE_MASK);
6125
            this.hideMaskEvent.signature = SIGNATURE;
6126
6127
            /**
6128
            * CustomEvent when the Panel is dragged
6129
            * @event dragEvent
6130
            */
6131
            this.dragEvent = this.createEvent(EVENT_TYPES.DRAG);
6132
            this.dragEvent.signature = SIGNATURE;
6133
        },
6134
6135
        /**
6136
         * Initializes the class's configurable properties which can be changed 
6137
         * using the Panel's Config object (cfg).
6138
         * @method initDefaultConfig
6139
         */
6140
        initDefaultConfig: function () {
6141
            Panel.superclass.initDefaultConfig.call(this);
6142
6143
            // Add panel config properties //
6144
6145
            /**
6146
            * True if the Panel should display a "close" button
6147
            * @config close
6148
            * @type Boolean
6149
            * @default true
6150
            */
6151
            this.cfg.addProperty(DEFAULT_CONFIG.CLOSE.key, { 
6152
                handler: this.configClose, 
6153
                value: DEFAULT_CONFIG.CLOSE.value, 
6154
                validator: DEFAULT_CONFIG.CLOSE.validator, 
6155
                supercedes: DEFAULT_CONFIG.CLOSE.supercedes 
6156
            });
6157
6158
            /**
6159
            * Boolean specifying if the Panel should be draggable.  The default 
6160
            * value is "true" if the Drag and Drop utility is included, 
6161
            * otherwise it is "false." <strong>PLEASE NOTE:</strong> There is a 
6162
            * known issue in IE 6 (Strict Mode and Quirks Mode) and IE 7 
6163
            * (Quirks Mode) where Panels that either don't have a value set for 
6164
            * their "width" configuration property, or their "width" 
6165
            * configuration property is set to "auto" will only be draggable by
6166
            * placing the mouse on the text of the Panel's header element.
6167
            * To fix this bug, draggable Panels missing a value for their 
6168
            * "width" configuration property, or whose "width" configuration 
6169
            * property is set to "auto" will have it set to the value of 
6170
            * their root HTML element's offsetWidth before they are made 
6171
            * visible.  The calculated width is then removed when the Panel is   
6172
            * hidden. <em>This fix is only applied to draggable Panels in IE 6 
6173
            * (Strict Mode and Quirks Mode) and IE 7 (Quirks Mode)</em>. For 
6174
            * more information on this issue see:
6175
            * YUILibrary bugs #1726972 and #1589210.
6176
            * @config draggable
6177
            * @type Boolean
6178
            * @default true
6179
            */
6180
            this.cfg.addProperty(DEFAULT_CONFIG.DRAGGABLE.key, {
6181
                handler: this.configDraggable,
6182
                value: (Util.DD) ? true : false,
6183
                validator: DEFAULT_CONFIG.DRAGGABLE.validator,
6184
                supercedes: DEFAULT_CONFIG.DRAGGABLE.supercedes
6185
            });
6186
6187
            /**
6188
            * Boolean specifying if the draggable Panel should be drag only, not interacting with drop 
6189
            * targets on the page.
6190
            * <p>
6191
            * When set to true, draggable Panels will not check to see if they are over drop targets,
6192
            * or fire the DragDrop events required to support drop target interaction (onDragEnter, 
6193
            * onDragOver, onDragOut, onDragDrop etc.).
6194
            * If the Panel is not designed to be dropped on any target elements on the page, then this 
6195
            * flag can be set to true to improve performance.
6196
            * </p>
6197
            * <p>
6198
            * When set to false, all drop target related events will be fired.
6199
            * </p>
6200
            * <p>
6201
            * The property is set to false by default to maintain backwards compatibility but should be 
6202
            * set to true if drop target interaction is not required for the Panel, to improve performance.</p>
6203
            * 
6204
            * @config dragOnly
6205
            * @type Boolean
6206
            * @default false
6207
            */
6208
            this.cfg.addProperty(DEFAULT_CONFIG.DRAG_ONLY.key, { 
6209
                value: DEFAULT_CONFIG.DRAG_ONLY.value, 
6210
                validator: DEFAULT_CONFIG.DRAG_ONLY.validator, 
6211
                supercedes: DEFAULT_CONFIG.DRAG_ONLY.supercedes 
6212
            });
6213
6214
            /**
6215
            * Sets the type of underlay to display for the Panel. Valid values 
6216
            * are "shadow," "matte," and "none".  <strong>PLEASE NOTE:</strong> 
6217
            * The creation of the underlay element is deferred until the Panel 
6218
            * is initially made visible.  For Gecko-based browsers on Mac
6219
            * OS X the underlay elment is always created as it is used as a 
6220
            * shim to prevent Aqua scrollbars below a Panel instance from poking 
6221
            * through it (See YUILibrary bug #1723530).
6222
            * @config underlay
6223
            * @type String
6224
            * @default shadow
6225
            */
6226
            this.cfg.addProperty(DEFAULT_CONFIG.UNDERLAY.key, { 
6227
                handler: this.configUnderlay, 
6228
                value: DEFAULT_CONFIG.UNDERLAY.value, 
6229
                supercedes: DEFAULT_CONFIG.UNDERLAY.supercedes 
6230
            });
6231
        
6232
            /**
6233
            * True if the Panel should be displayed in a modal fashion, 
6234
            * automatically creating a transparent mask over the document that
6235
            * will not be removed until the Panel is dismissed.
6236
            * @config modal
6237
            * @type Boolean
6238
            * @default false
6239
            */
6240
            this.cfg.addProperty(DEFAULT_CONFIG.MODAL.key, { 
6241
                handler: this.configModal, 
6242
                value: DEFAULT_CONFIG.MODAL.value,
6243
                validator: DEFAULT_CONFIG.MODAL.validator, 
6244
                supercedes: DEFAULT_CONFIG.MODAL.supercedes 
6245
            });
6246
6247
            /**
6248
            * A KeyListener (or array of KeyListeners) that will be enabled 
6249
            * when the Panel is shown, and disabled when the Panel is hidden.
6250
            * @config keylisteners
6251
            * @type YAHOO.util.KeyListener[]
6252
            * @default null
6253
            */
6254
            this.cfg.addProperty(DEFAULT_CONFIG.KEY_LISTENERS.key, { 
6255
                handler: this.configKeyListeners, 
6256
                suppressEvent: DEFAULT_CONFIG.KEY_LISTENERS.suppressEvent, 
6257
                supercedes: DEFAULT_CONFIG.KEY_LISTENERS.supercedes 
6258
            });
6259
6260
            /**
6261
            * UI Strings used by the Panel
6262
            * 
6263
            * @config strings
6264
            * @type Object
6265
            * @default An object literal with the properties shown below:
6266
            *     <dl>
6267
            *         <dt>close</dt><dd><em>String</em> : The string to use for the close icon. Defaults to "Close".</dd>
6268
            *     </dl>
6269
            */
6270
            this.cfg.addProperty(DEFAULT_CONFIG.STRINGS.key, { 
6271
                value:DEFAULT_CONFIG.STRINGS.value,
6272
                handler:this.configStrings,
6273
                validator:DEFAULT_CONFIG.STRINGS.validator,
6274
                supercedes:DEFAULT_CONFIG.STRINGS.supercedes
6275
            });
6276
        },
6277
6278
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
6279
        
6280
        /**
6281
        * The default event handler fired when the "close" property is changed.
6282
        * The method controls the appending or hiding of the close icon at the 
6283
        * top right of the Panel.
6284
        * @method configClose
6285
        * @param {String} type The CustomEvent type (usually the property name)
6286
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6287
        * handlers, args[0] will equal the newly applied value for the property.
6288
        * @param {Object} obj The scope object. For configuration handlers, 
6289
        * this will usually equal the owner.
6290
        */
6291
        configClose: function (type, args, obj) {
6292
6293
            var val = args[0],
6294
                oClose = this.close,
6295
                strings = this.cfg.getProperty("strings");
6296
6297
            if (val) {
6298
                if (!oClose) {
6299
6300
                    if (!m_oCloseIconTemplate) {
6301
                        m_oCloseIconTemplate = document.createElement("a");
6302
                        m_oCloseIconTemplate.className = "container-close";
6303
                        m_oCloseIconTemplate.href = "#";
6304
                    }
6305
6306
                    oClose = m_oCloseIconTemplate.cloneNode(true);
6307
                    this.innerElement.appendChild(oClose);
6308
6309
                    oClose.innerHTML = (strings && strings.close) ? strings.close : "&#160;";
6310
6311
                    Event.on(oClose, "click", this._doClose, this, true);
6312
6313
                    this.close = oClose;
6314
6315
                } else {
6316
                    oClose.style.display = "block";
6317
                }
6318
6319
            } else {
6320
                if (oClose) {
6321
                    oClose.style.display = "none";
6322
                }
6323
            }
6324
6325
        },
6326
6327
        /**
6328
         * Event handler for the close icon
6329
         * 
6330
         * @method _doClose
6331
         * @protected
6332
         * 
6333
         * @param {DOMEvent} e
6334
         */
6335
        _doClose : function (e) {
6336
            Event.preventDefault(e);
6337
            this.hide();
6338
        },
6339
6340
        /**
6341
        * The default event handler fired when the "draggable" property 
6342
        * is changed.
6343
        * @method configDraggable
6344
        * @param {String} type The CustomEvent type (usually the property name)
6345
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6346
        * handlers, args[0] will equal the newly applied value for the property.
6347
        * @param {Object} obj The scope object. For configuration handlers, 
6348
        * this will usually equal the owner.
6349
        */
6350
        configDraggable: function (type, args, obj) {
6351
            var val = args[0];
6352
6353
            if (val) {
6354
                if (!Util.DD) {
6355
                    this.cfg.setProperty("draggable", false);
6356
                    return;
6357
                }
6358
6359
                if (this.header) {
6360
                    Dom.setStyle(this.header, "cursor", "move");
6361
                    this.registerDragDrop();
6362
                }
6363
6364
                this.subscribe("beforeShow", setWidthToOffsetWidth);
6365
6366
            } else {
6367
6368
                if (this.dd) {
6369
                    this.dd.unreg();
6370
                }
6371
6372
                if (this.header) {
6373
                    Dom.setStyle(this.header,"cursor","auto");
6374
                }
6375
6376
                this.unsubscribe("beforeShow", setWidthToOffsetWidth);
6377
            }
6378
        },
6379
      
6380
        /**
6381
        * The default event handler fired when the "underlay" property 
6382
        * is changed.
6383
        * @method configUnderlay
6384
        * @param {String} type The CustomEvent type (usually the property name)
6385
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6386
        * handlers, args[0] will equal the newly applied value for the property.
6387
        * @param {Object} obj The scope object. For configuration handlers, 
6388
        * this will usually equal the owner.
6389
        */
6390
        configUnderlay: function (type, args, obj) {
6391
6392
            var bMacGecko = (this.platform == "mac" && UA.gecko),
6393
                sUnderlay = args[0].toLowerCase(),
6394
                oUnderlay = this.underlay,
6395
                oElement = this.element;
6396
6397
            function createUnderlay() {
6398
                var bNew = false;
6399
                if (!oUnderlay) { // create if not already in DOM
6400
6401
                    if (!m_oUnderlayTemplate) {
6402
                        m_oUnderlayTemplate = document.createElement("div");
6403
                        m_oUnderlayTemplate.className = "underlay";
6404
                    }
6405
6406
                    oUnderlay = m_oUnderlayTemplate.cloneNode(false);
6407
                    this.element.appendChild(oUnderlay);
6408
6409
                    this.underlay = oUnderlay;
6410
6411
                    if (bIEQuirks) {
6412
                        this.sizeUnderlay();
6413
                        this.cfg.subscribeToConfigEvent("width", this.sizeUnderlay);
6414
                        this.cfg.subscribeToConfigEvent("height", this.sizeUnderlay);
6415
6416
                        this.changeContentEvent.subscribe(this.sizeUnderlay);
6417
                        YAHOO.widget.Module.textResizeEvent.subscribe(this.sizeUnderlay, this, true);
6418
                    }
6419
6420
                    if (UA.webkit && UA.webkit < 420) {
6421
                        this.changeContentEvent.subscribe(this.forceUnderlayRedraw);
6422
                    }
6423
6424
                    bNew = true;
6425
                }
6426
            }
6427
6428
            function onBeforeShow() {
6429
                var bNew = createUnderlay.call(this);
6430
                if (!bNew && bIEQuirks) {
6431
                    this.sizeUnderlay();
6432
                }
6433
                this._underlayDeferred = false;
6434
                this.beforeShowEvent.unsubscribe(onBeforeShow);
6435
            }
6436
6437
            function destroyUnderlay() {
6438
                if (this._underlayDeferred) {
6439
                    this.beforeShowEvent.unsubscribe(onBeforeShow);
6440
                    this._underlayDeferred = false;
6441
                }
6442
6443
                if (oUnderlay) {
6444
                    this.cfg.unsubscribeFromConfigEvent("width", this.sizeUnderlay);
6445
                    this.cfg.unsubscribeFromConfigEvent("height",this.sizeUnderlay);
6446
                    this.changeContentEvent.unsubscribe(this.sizeUnderlay);
6447
                    this.changeContentEvent.unsubscribe(this.forceUnderlayRedraw);
6448
                    YAHOO.widget.Module.textResizeEvent.unsubscribe(this.sizeUnderlay, this, true);
6449
6450
                    this.element.removeChild(oUnderlay);
6451
6452
                    this.underlay = null;
6453
                }
6454
            }
6455
6456
            switch (sUnderlay) {
6457
                case "shadow":
6458
                    Dom.removeClass(oElement, "matte");
6459
                    Dom.addClass(oElement, "shadow");
6460
                    break;
6461
                case "matte":
6462
                    if (!bMacGecko) {
6463
                        destroyUnderlay.call(this);
6464
                    }
6465
                    Dom.removeClass(oElement, "shadow");
6466
                    Dom.addClass(oElement, "matte");
6467
                    break;
6468
                default:
6469
                    if (!bMacGecko) {
6470
                        destroyUnderlay.call(this);
6471
                    }
6472
                    Dom.removeClass(oElement, "shadow");
6473
                    Dom.removeClass(oElement, "matte");
6474
                    break;
6475
            }
6476
6477
            if ((sUnderlay == "shadow") || (bMacGecko && !oUnderlay)) {
6478
                if (this.cfg.getProperty("visible")) {
6479
                    var bNew = createUnderlay.call(this);
6480
                    if (!bNew && bIEQuirks) {
6481
                        this.sizeUnderlay();
6482
                    }
6483
                } else {
6484
                    if (!this._underlayDeferred) {
6485
                        this.beforeShowEvent.subscribe(onBeforeShow);
6486
                        this._underlayDeferred = true;
6487
                    }
6488
                }
6489
            }
6490
        },
6491
        
6492
        /**
6493
        * The default event handler fired when the "modal" property is 
6494
        * changed. This handler subscribes or unsubscribes to the show and hide
6495
        * events to handle the display or hide of the modality mask.
6496
        * @method configModal
6497
        * @param {String} type The CustomEvent type (usually the property name)
6498
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6499
        * handlers, args[0] will equal the newly applied value for the property.
6500
        * @param {Object} obj The scope object. For configuration handlers, 
6501
        * this will usually equal the owner.
6502
        */
6503
        configModal: function (type, args, obj) {
6504
6505
            var modal = args[0];
6506
            if (modal) {
6507
                if (!this._hasModalityEventListeners) {
6508
6509
                    this.subscribe("beforeShow", this.buildMask);
6510
                    this.subscribe("beforeShow", this.bringToTop);
6511
                    this.subscribe("beforeShow", this.showMask);
6512
                    this.subscribe("hide", this.hideMask);
6513
6514
                    Overlay.windowResizeEvent.subscribe(this.sizeMask, 
6515
                        this, true);
6516
6517
                    this._hasModalityEventListeners = true;
6518
                }
6519
            } else {
6520
                if (this._hasModalityEventListeners) {
6521
6522
                    if (this.cfg.getProperty("visible")) {
6523
                        this.hideMask();
6524
                        this.removeMask();
6525
                    }
6526
6527
                    this.unsubscribe("beforeShow", this.buildMask);
6528
                    this.unsubscribe("beforeShow", this.bringToTop);
6529
                    this.unsubscribe("beforeShow", this.showMask);
6530
                    this.unsubscribe("hide", this.hideMask);
6531
6532
                    Overlay.windowResizeEvent.unsubscribe(this.sizeMask, this);
6533
6534
                    this._hasModalityEventListeners = false;
6535
                }
6536
            }
6537
        },
6538
6539
        /**
6540
        * Removes the modality mask.
6541
        * @method removeMask
6542
        */
6543
        removeMask: function () {
6544
6545
            var oMask = this.mask,
6546
                oParentNode;
6547
6548
            if (oMask) {
6549
                /*
6550
                    Hide the mask before destroying it to ensure that DOM
6551
                    event handlers on focusable elements get removed.
6552
                */
6553
                this.hideMask();
6554
6555
                oParentNode = oMask.parentNode;
6556
                if (oParentNode) {
6557
                    oParentNode.removeChild(oMask);
6558
                }
6559
6560
                this.mask = null;
6561
            }
6562
        },
6563
        
6564
        /**
6565
        * The default event handler fired when the "keylisteners" property 
6566
        * is changed.
6567
        * @method configKeyListeners
6568
        * @param {String} type The CustomEvent type (usually the property name)
6569
        * @param {Object[]} args The CustomEvent arguments. For configuration
6570
        * handlers, args[0] will equal the newly applied value for the property.
6571
        * @param {Object} obj The scope object. For configuration handlers, 
6572
        * this will usually equal the owner.
6573
        */
6574
        configKeyListeners: function (type, args, obj) {
6575
6576
            var listeners = args[0],
6577
                listener,
6578
                nListeners,
6579
                i;
6580
        
6581
            if (listeners) {
6582
6583
                if (listeners instanceof Array) {
6584
6585
                    nListeners = listeners.length;
6586
6587
                    for (i = 0; i < nListeners; i++) {
6588
6589
                        listener = listeners[i];
6590
        
6591
                        if (!Config.alreadySubscribed(this.showEvent, 
6592
                            listener.enable, listener)) {
6593
6594
                            this.showEvent.subscribe(listener.enable, 
6595
                                listener, true);
6596
6597
                        }
6598
6599
                        if (!Config.alreadySubscribed(this.hideEvent, 
6600
                            listener.disable, listener)) {
6601
6602
                            this.hideEvent.subscribe(listener.disable, 
6603
                                listener, true);
6604
6605
                            this.destroyEvent.subscribe(listener.disable, 
6606
                                listener, true);
6607
                        }
6608
                    }
6609
6610
                } else {
6611
6612
                    if (!Config.alreadySubscribed(this.showEvent, 
6613
                        listeners.enable, listeners)) {
6614
6615
                        this.showEvent.subscribe(listeners.enable, 
6616
                            listeners, true);
6617
                    }
6618
6619
                    if (!Config.alreadySubscribed(this.hideEvent, 
6620
                        listeners.disable, listeners)) {
6621
6622
                        this.hideEvent.subscribe(listeners.disable, 
6623
                            listeners, true);
6624
6625
                        this.destroyEvent.subscribe(listeners.disable, 
6626
                            listeners, true);
6627
6628
                    }
6629
6630
                }
6631
6632
            }
6633
6634
        },
6635
6636
        /**
6637
        * The default handler for the "strings" property
6638
        * @method configStrings
6639
        */
6640
        configStrings : function(type, args, obj) {
6641
            var val = Lang.merge(DEFAULT_CONFIG.STRINGS.value, args[0]);
6642
            this.cfg.setProperty(DEFAULT_CONFIG.STRINGS.key, val, true);
6643
        },
6644
6645
        /**
6646
        * The default event handler fired when the "height" property is changed.
6647
        * @method configHeight
6648
        * @param {String} type The CustomEvent type (usually the property name)
6649
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6650
        * handlers, args[0] will equal the newly applied value for the property.
6651
        * @param {Object} obj The scope object. For configuration handlers, 
6652
        * this will usually equal the owner.
6653
        */
6654
        configHeight: function (type, args, obj) {
6655
            var height = args[0],
6656
                el = this.innerElement;
6657
6658
            Dom.setStyle(el, "height", height);
6659
            this.cfg.refireEvent("iframe");
6660
        },
6661
6662
        /**
6663
         * The default custom event handler executed when the Panel's height is changed, 
6664
         * if the autofillheight property has been set.
6665
         *
6666
         * @method _autoFillOnHeightChange
6667
         * @protected
6668
         * @param {String} type The event type
6669
         * @param {Array} args The array of arguments passed to event subscribers
6670
         * @param {HTMLElement} el The header, body or footer element which is to be resized to fill
6671
         * out the containers height
6672
         */
6673
        _autoFillOnHeightChange : function(type, args, el) {
6674
            Panel.superclass._autoFillOnHeightChange.apply(this, arguments);
6675
            if (bIEQuirks) {
6676
                var panel = this;
6677
                setTimeout(function() {
6678
                    panel.sizeUnderlay();
6679
                },0);
6680
            }
6681
        },
6682
6683
        /**
6684
        * The default event handler fired when the "width" property is changed.
6685
        * @method configWidth
6686
        * @param {String} type The CustomEvent type (usually the property name)
6687
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6688
        * handlers, args[0] will equal the newly applied value for the property.
6689
        * @param {Object} obj The scope object. For configuration handlers, 
6690
        * this will usually equal the owner.
6691
        */
6692
        configWidth: function (type, args, obj) {
6693
    
6694
            var width = args[0],
6695
                el = this.innerElement;
6696
    
6697
            Dom.setStyle(el, "width", width);
6698
            this.cfg.refireEvent("iframe");
6699
    
6700
        },
6701
        
6702
        /**
6703
        * The default event handler fired when the "zIndex" property is changed.
6704
        * @method configzIndex
6705
        * @param {String} type The CustomEvent type (usually the property name)
6706
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6707
        * handlers, args[0] will equal the newly applied value for the property.
6708
        * @param {Object} obj The scope object. For configuration handlers, 
6709
        * this will usually equal the owner.
6710
        */
6711
        configzIndex: function (type, args, obj) {
6712
            Panel.superclass.configzIndex.call(this, type, args, obj);
6713
6714
            if (this.mask || this.cfg.getProperty("modal") === true) {
6715
                var panelZ = Dom.getStyle(this.element, "zIndex");
6716
                if (!panelZ || isNaN(panelZ)) {
6717
                    panelZ = 0;
6718
                }
6719
6720
                if (panelZ === 0) {
6721
                    // Recursive call to configzindex (which should be stopped
6722
                    // from going further because panelZ should no longer === 0)
6723
                    this.cfg.setProperty("zIndex", 1);
6724
                } else {
6725
                    this.stackMask();
6726
                }
6727
            }
6728
        },
6729
6730
        // END BUILT-IN PROPERTY EVENT HANDLERS //
6731
        /**
6732
        * Builds the wrapping container around the Panel that is used for 
6733
        * positioning the shadow and matte underlays. The container element is 
6734
        * assigned to a  local instance variable called container, and the 
6735
        * element is reinserted inside of it.
6736
        * @method buildWrapper
6737
        */
6738
        buildWrapper: function () {
6739
6740
            var elementParent = this.element.parentNode,
6741
                originalElement = this.element,
6742
                wrapper = document.createElement("div");
6743
6744
            wrapper.className = Panel.CSS_PANEL_CONTAINER;
6745
            wrapper.id = originalElement.id + "_c";
6746
6747
            if (elementParent) {
6748
                elementParent.insertBefore(wrapper, originalElement);
6749
            }
6750
6751
            wrapper.appendChild(originalElement);
6752
6753
            this.element = wrapper;
6754
            this.innerElement = originalElement;
6755
6756
            Dom.setStyle(this.innerElement, "visibility", "inherit");
6757
        },
6758
6759
        /**
6760
        * Adjusts the size of the shadow based on the size of the element.
6761
        * @method sizeUnderlay
6762
        */
6763
        sizeUnderlay: function () {
6764
            var oUnderlay = this.underlay,
6765
                oElement;
6766
6767
            if (oUnderlay) {
6768
                oElement = this.element;
6769
                oUnderlay.style.width = oElement.offsetWidth + "px";
6770
                oUnderlay.style.height = oElement.offsetHeight + "px";
6771
            }
6772
        },
6773
6774
        /**
6775
        * Registers the Panel's header for drag & drop capability.
6776
        * @method registerDragDrop
6777
        */
6778
        registerDragDrop: function () {
6779
6780
            var me = this;
6781
6782
            if (this.header) {
6783
6784
                if (!Util.DD) {
6785
                    return;
6786
                }
6787
6788
                var bDragOnly = (this.cfg.getProperty("dragonly") === true);
6789
6790
                /**
6791
                 * The YAHOO.util.DD instance, used to implement the draggable header for the panel if draggable is enabled
6792
                 *
6793
                 * @property dd
6794
                 * @type YAHOO.util.DD
6795
                 */
6796
                this.dd = new Util.DD(this.element.id, this.id, {dragOnly: bDragOnly});
6797
6798
                if (!this.header.id) {
6799
                    this.header.id = this.id + "_h";
6800
                }
6801
6802
                this.dd.startDrag = function () {
6803
6804
                    var offsetHeight,
6805
                        offsetWidth,
6806
                        viewPortWidth,
6807
                        viewPortHeight,
6808
                        scrollX,
6809
                        scrollY;
6810
6811
                    if (YAHOO.env.ua.ie == 6) {
6812
                        Dom.addClass(me.element,"drag");
6813
                    }
6814
6815
                    if (me.cfg.getProperty("constraintoviewport")) {
6816
6817
                        var nViewportOffset = Overlay.VIEWPORT_OFFSET;
6818
6819
                        offsetHeight = me.element.offsetHeight;
6820
                        offsetWidth = me.element.offsetWidth;
6821
6822
                        viewPortWidth = Dom.getViewportWidth();
6823
                        viewPortHeight = Dom.getViewportHeight();
6824
6825
                        scrollX = Dom.getDocumentScrollLeft();
6826
                        scrollY = Dom.getDocumentScrollTop();
6827
6828
                        if (offsetHeight + nViewportOffset < viewPortHeight) {
6829
                            this.minY = scrollY + nViewportOffset;
6830
                            this.maxY = scrollY + viewPortHeight - offsetHeight - nViewportOffset;
6831
                        } else {
6832
                            this.minY = scrollY + nViewportOffset;
6833
                            this.maxY = scrollY + nViewportOffset;
6834
                        }
6835
6836
                        if (offsetWidth + nViewportOffset < viewPortWidth) {
6837
                            this.minX = scrollX + nViewportOffset;
6838
                            this.maxX = scrollX + viewPortWidth - offsetWidth - nViewportOffset;
6839
                        } else {
6840
                            this.minX = scrollX + nViewportOffset;
6841
                            this.maxX = scrollX + nViewportOffset;
6842
                        }
6843
6844
                        this.constrainX = true;
6845
                        this.constrainY = true;
6846
                    } else {
6847
                        this.constrainX = false;
6848
                        this.constrainY = false;
6849
                    }
6850
6851
                    me.dragEvent.fire("startDrag", arguments);
6852
                };
6853
6854
                this.dd.onDrag = function () {
6855
                    me.syncPosition();
6856
                    me.cfg.refireEvent("iframe");
6857
                    if (this.platform == "mac" && YAHOO.env.ua.gecko) {
6858
                        this.showMacGeckoScrollbars();
6859
                    }
6860
6861
                    me.dragEvent.fire("onDrag", arguments);
6862
                };
6863
6864
                this.dd.endDrag = function () {
6865
6866
                    if (YAHOO.env.ua.ie == 6) {
6867
                        Dom.removeClass(me.element,"drag");
6868
                    }
6869
6870
                    me.dragEvent.fire("endDrag", arguments);
6871
                    me.moveEvent.fire(me.cfg.getProperty("xy"));
6872
6873
                };
6874
6875
                this.dd.setHandleElId(this.header.id);
6876
                this.dd.addInvalidHandleType("INPUT");
6877
                this.dd.addInvalidHandleType("SELECT");
6878
                this.dd.addInvalidHandleType("TEXTAREA");
6879
            }
6880
        },
6881
        
6882
        /**
6883
        * Builds the mask that is laid over the document when the Panel is 
6884
        * configured to be modal.
6885
        * @method buildMask
6886
        */
6887
        buildMask: function () {
6888
            var oMask = this.mask;
6889
            if (!oMask) {
6890
                if (!m_oMaskTemplate) {
6891
                    m_oMaskTemplate = document.createElement("div");
6892
                    m_oMaskTemplate.className = "mask";
6893
                    m_oMaskTemplate.innerHTML = "&#160;";
6894
                }
6895
                oMask = m_oMaskTemplate.cloneNode(true);
6896
                oMask.id = this.id + "_mask";
6897
6898
                document.body.insertBefore(oMask, document.body.firstChild);
6899
6900
                this.mask = oMask;
6901
6902
                if (YAHOO.env.ua.gecko && this.platform == "mac") {
6903
                    Dom.addClass(this.mask, "block-scrollbars");
6904
                }
6905
6906
                // Stack mask based on the element zindex
6907
                this.stackMask();
6908
            }
6909
        },
6910
6911
        /**
6912
        * Hides the modality mask.
6913
        * @method hideMask
6914
        */
6915
        hideMask: function () {
6916
            if (this.cfg.getProperty("modal") && this.mask) {
6917
                this.mask.style.display = "none";
6918
                Dom.removeClass(document.body, "masked");
6919
                this.hideMaskEvent.fire();
6920
            }
6921
        },
6922
6923
        /**
6924
        * Shows the modality mask.
6925
        * @method showMask
6926
        */
6927
        showMask: function () {
6928
            if (this.cfg.getProperty("modal") && this.mask) {
6929
                Dom.addClass(document.body, "masked");
6930
                this.sizeMask();
6931
                this.mask.style.display = "block";
6932
                this.showMaskEvent.fire();
6933
            }
6934
        },
6935
6936
        /**
6937
        * Sets the size of the modality mask to cover the entire scrollable 
6938
        * area of the document
6939
        * @method sizeMask
6940
        */
6941
        sizeMask: function () {
6942
            if (this.mask) {
6943
6944
                // Shrink mask first, so it doesn't affect the document size.
6945
                var mask = this.mask,
6946
                    viewWidth = Dom.getViewportWidth(),
6947
                    viewHeight = Dom.getViewportHeight();
6948
6949
                if (mask.offsetHeight > viewHeight) {
6950
                    mask.style.height = viewHeight + "px";
6951
                }
6952
6953
                if (mask.offsetWidth > viewWidth) {
6954
                    mask.style.width = viewWidth + "px";
6955
                }
6956
6957
                // Then size it to the document
6958
                mask.style.height = Dom.getDocumentHeight() + "px";
6959
                mask.style.width = Dom.getDocumentWidth() + "px";
6960
            }
6961
        },
6962
6963
        /**
6964
         * Sets the zindex of the mask, if it exists, based on the zindex of 
6965
         * the Panel element. The zindex of the mask is set to be one less 
6966
         * than the Panel element's zindex.
6967
         * 
6968
         * <p>NOTE: This method will not bump up the zindex of the Panel
6969
         * to ensure that the mask has a non-negative zindex. If you require the
6970
         * mask zindex to be 0 or higher, the zindex of the Panel 
6971
         * should be set to a value higher than 0, before this method is called.
6972
         * </p>
6973
         * @method stackMask
6974
         */
6975
        stackMask: function() {
6976
            if (this.mask) {
6977
                var panelZ = Dom.getStyle(this.element, "zIndex");
6978
                if (!YAHOO.lang.isUndefined(panelZ) && !isNaN(panelZ)) {
6979
                    Dom.setStyle(this.mask, "zIndex", panelZ - 1);
6980
                }
6981
            }
6982
        },
6983
6984
        /**
6985
        * Renders the Panel by inserting the elements that are not already in 
6986
        * the main Panel into their correct places. Optionally appends the 
6987
        * Panel to the specified node prior to the render's execution. NOTE: 
6988
        * For Panels without existing markup, the appendToNode argument is 
6989
        * REQUIRED. If this argument is ommitted and the current element is 
6990
        * not present in the document, the function will return false, 
6991
        * indicating that the render was a failure.
6992
        * @method render
6993
        * @param {String} appendToNode The element id to which the Module 
6994
        * should be appended to prior to rendering <em>OR</em>
6995
        * @param {HTMLElement} appendToNode The element to which the Module 
6996
        * should be appended to prior to rendering
6997
        * @return {boolean} Success or failure of the render
6998
        */
6999
        render: function (appendToNode) {
7000
            return Panel.superclass.render.call(this, appendToNode, this.innerElement);
7001
        },
7002
7003
        /**
7004
         * Renders the currently set header into it's proper position under the 
7005
         * module element. If the module element is not provided, "this.innerElement" 
7006
         * is used.
7007
         *
7008
         * @method _renderHeader
7009
         * @protected
7010
         * @param {HTMLElement} moduleElement Optional. A reference to the module element
7011
         */
7012
        _renderHeader: function(moduleElement){
7013
            moduleElement = moduleElement || this.innerElement;
7014
			Panel.superclass._renderHeader.call(this, moduleElement);
7015
        },
7016
7017
        /**
7018
         * Renders the currently set body into it's proper position under the 
7019
         * module element. If the module element is not provided, "this.innerElement" 
7020
         * is used.
7021
         * 
7022
         * @method _renderBody
7023
         * @protected
7024
         * @param {HTMLElement} moduleElement Optional. A reference to the module element.
7025
         */
7026
        _renderBody: function(moduleElement){
7027
            moduleElement = moduleElement || this.innerElement;
7028
            Panel.superclass._renderBody.call(this, moduleElement);
7029
        },
7030
7031
        /**
7032
         * Renders the currently set footer into it's proper position under the 
7033
         * module element. If the module element is not provided, "this.innerElement" 
7034
         * is used.
7035
         *
7036
         * @method _renderFooter
7037
         * @protected
7038
         * @param {HTMLElement} moduleElement Optional. A reference to the module element
7039
         */
7040
        _renderFooter: function(moduleElement){
7041
            moduleElement = moduleElement || this.innerElement;
7042
            Panel.superclass._renderFooter.call(this, moduleElement);
7043
        },
7044
        
7045
        /**
7046
        * Removes the Panel element from the DOM and sets all child elements
7047
        * to null.
7048
        * @method destroy
7049
        */
7050
        destroy: function () {
7051
            Overlay.windowResizeEvent.unsubscribe(this.sizeMask, this);
7052
            this.removeMask();
7053
            if (this.close) {
7054
                Event.purgeElement(this.close);
7055
            }
7056
            Panel.superclass.destroy.call(this);  
7057
        },
7058
7059
        /**
7060
         * Forces the underlay element to be repainted through the application/removal 
7061
         * of a yui-force-redraw class to the underlay element.
7062
         *
7063
         * @method forceUnderlayRedraw
7064
         */
7065
        forceUnderlayRedraw : function () {
7066
            var u = this.underlay;
7067
            Dom.addClass(u, "yui-force-redraw");
7068
            setTimeout(function(){Dom.removeClass(u, "yui-force-redraw");}, 0);
7069
        },
7070
7071
        /**
7072
        * Returns a String representation of the object.
7073
        * @method toString
7074
        * @return {String} The string representation of the Panel.
7075
        */
7076
        toString: function () {
7077
            return "Panel " + this.id;
7078
        }
7079
    
7080
    });
7081
7082
}());
7083
(function () {
7084
7085
    /**
7086
    * <p>
7087
    * Dialog is an implementation of Panel that can be used to submit form 
7088
    * data.
7089
    * </p>
7090
    * <p>
7091
    * Built-in functionality for buttons with event handlers is included. 
7092
    * If the optional YUI Button dependancy is included on the page, the buttons
7093
    * created will be instances of YAHOO.widget.Button, otherwise regular HTML buttons
7094
    * will be created.
7095
    * </p>
7096
    * <p>
7097
    * Forms can be processed in 3 ways -- via an asynchronous Connection utility call, 
7098
    * a simple form POST or GET, or manually. The YUI Connection utility should be
7099
    * included if you're using the default "async" postmethod, but is not required if
7100
    * you're using any of the other postmethod values.
7101
    * </p>
7102
    * @namespace YAHOO.widget
7103
    * @class Dialog
7104
    * @extends YAHOO.widget.Panel
7105
    * @constructor
7106
    * @param {String} el The element ID representing the Dialog <em>OR</em>
7107
    * @param {HTMLElement} el The element representing the Dialog
7108
    * @param {Object} userConfig The configuration object literal containing 
7109
    * the configuration that should be set for this Dialog. See configuration 
7110
    * documentation for more details.
7111
    */
7112
    YAHOO.widget.Dialog = function (el, userConfig) {
7113
        YAHOO.widget.Dialog.superclass.constructor.call(this, el, userConfig);
7114
    };
7115
7116
    var Event = YAHOO.util.Event,
7117
        CustomEvent = YAHOO.util.CustomEvent,
7118
        Dom = YAHOO.util.Dom,
7119
        Dialog = YAHOO.widget.Dialog,
7120
        Lang = YAHOO.lang,
7121
7122
        /**
7123
         * Constant representing the name of the Dialog's events
7124
         * @property EVENT_TYPES
7125
         * @private
7126
         * @final
7127
         * @type Object
7128
         */
7129
        EVENT_TYPES = {
7130
            "BEFORE_SUBMIT": "beforeSubmit",
7131
            "SUBMIT": "submit",
7132
            "MANUAL_SUBMIT": "manualSubmit",
7133
            "ASYNC_SUBMIT": "asyncSubmit",
7134
            "FORM_SUBMIT": "formSubmit",
7135
            "CANCEL": "cancel"
7136
        },
7137
7138
        /**
7139
        * Constant representing the Dialog's configuration properties
7140
        * @property DEFAULT_CONFIG
7141
        * @private
7142
        * @final
7143
        * @type Object
7144
        */
7145
        DEFAULT_CONFIG = {
7146
7147
            "POST_METHOD": { 
7148
                key: "postmethod", 
7149
                value: "async"
7150
            },
7151
7152
            "POST_DATA" : {
7153
                key: "postdata",
7154
                value: null
7155
            },
7156
7157
            "BUTTONS": {
7158
                key: "buttons",
7159
                value: "none",
7160
                supercedes: ["visible"]
7161
            },
7162
7163
            "HIDEAFTERSUBMIT" : {
7164
                key: "hideaftersubmit",
7165
                value: true
7166
            }
7167
7168
        };
7169
7170
    /**
7171
    * Constant representing the default CSS class used for a Dialog
7172
    * @property YAHOO.widget.Dialog.CSS_DIALOG
7173
    * @static
7174
    * @final
7175
    * @type String
7176
    */
7177
    Dialog.CSS_DIALOG = "yui-dialog";
7178
7179
    function removeButtonEventHandlers() {
7180
7181
        var aButtons = this._aButtons,
7182
            nButtons,
7183
            oButton,
7184
            i;
7185
7186
        if (Lang.isArray(aButtons)) {
7187
            nButtons = aButtons.length;
7188
7189
            if (nButtons > 0) {
7190
                i = nButtons - 1;
7191
                do {
7192
                    oButton = aButtons[i];
7193
7194
                    if (YAHOO.widget.Button && oButton instanceof YAHOO.widget.Button) {
7195
                        oButton.destroy();
7196
                    }
7197
                    else if (oButton.tagName.toUpperCase() == "BUTTON") {
7198
                        Event.purgeElement(oButton);
7199
                        Event.purgeElement(oButton, false);
7200
                    }
7201
                }
7202
                while (i--);
7203
            }
7204
        }
7205
    }
7206
7207
    YAHOO.extend(Dialog, YAHOO.widget.Panel, { 
7208
7209
        /**
7210
        * @property form
7211
        * @description Object reference to the Dialog's 
7212
        * <code>&#60;form&#62;</code> element.
7213
        * @default null 
7214
        * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
7215
        * level-one-html.html#ID-40002357">HTMLFormElement</a>
7216
        */
7217
        form: null,
7218
    
7219
        /**
7220
        * Initializes the class's configurable properties which can be changed 
7221
        * using the Dialog's Config object (cfg).
7222
        * @method initDefaultConfig
7223
        */
7224
        initDefaultConfig: function () {
7225
            Dialog.superclass.initDefaultConfig.call(this);
7226
7227
            /**
7228
            * The internally maintained callback object for use with the 
7229
            * Connection utility. The format of the callback object is 
7230
            * similar to Connection Manager's callback object and is 
7231
            * simply passed through to Connection Manager when the async 
7232
            * request is made.
7233
            * @property callback
7234
            * @type Object
7235
            */
7236
            this.callback = {
7237
7238
                /**
7239
                * The function to execute upon success of the 
7240
                * Connection submission (when the form does not
7241
                * contain a file input element).
7242
                * 
7243
                * @property callback.success
7244
                * @type Function
7245
                */
7246
                success: null,
7247
7248
                /**
7249
                * The function to execute upon failure of the 
7250
                * Connection submission
7251
                * @property callback.failure
7252
                * @type Function
7253
                */
7254
                failure: null,
7255
7256
                /**
7257
                *<p>
7258
                * The function to execute upon success of the 
7259
                * Connection submission, when the form contains
7260
                * a file input element.
7261
                * </p>
7262
                * <p>
7263
                * <em>NOTE:</em> Connection manager will not
7264
                * invoke the success or failure handlers for the file
7265
                * upload use case. This will be the only callback
7266
                * handler invoked.
7267
                * </p>
7268
                * <p>
7269
                * For more information, see the <a href="http://developer.yahoo.com/yui/connection/#file">
7270
                * Connection Manager documenation on file uploads</a>.
7271
                * </p>
7272
                * @property callback.upload
7273
                * @type Function
7274
                */
7275
7276
                /**
7277
                * The arbitraty argument or arguments to pass to the Connection 
7278
                * callback functions
7279
                * @property callback.argument
7280
                * @type Object
7281
                */
7282
                argument: null
7283
7284
            };
7285
7286
            // Add form dialog config properties //
7287
            /**
7288
            * The method to use for posting the Dialog's form. Possible values 
7289
            * are "async", "form", and "manual".
7290
            * @config postmethod
7291
            * @type String
7292
            * @default async
7293
            */
7294
            this.cfg.addProperty(DEFAULT_CONFIG.POST_METHOD.key, {
7295
                handler: this.configPostMethod, 
7296
                value: DEFAULT_CONFIG.POST_METHOD.value, 
7297
                validator: function (val) {
7298
                    if (val != "form" && val != "async" && val != "none" && 
7299
                        val != "manual") {
7300
                        return false;
7301
                    } else {
7302
                        return true;
7303
                    }
7304
                }
7305
            });
7306
7307
            /**
7308
            * Any additional post data which needs to be sent when using the 
7309
            * <a href="#config_postmethod">async</a> postmethod for dialog POST submissions.
7310
            * The format for the post data string is defined by Connection Manager's 
7311
            * <a href="YAHOO.util.Connect.html#method_asyncRequest">asyncRequest</a> 
7312
            * method.
7313
            * @config postdata
7314
            * @type String
7315
            * @default null
7316
            */
7317
            this.cfg.addProperty(DEFAULT_CONFIG.POST_DATA.key, {
7318
                value: DEFAULT_CONFIG.POST_DATA.value
7319
            });
7320
7321
            /**
7322
            * This property is used to configure whether or not the 
7323
            * dialog should be automatically hidden after submit.
7324
            * 
7325
            * @config hideaftersubmit
7326
            * @type Boolean
7327
            * @default true
7328
            */
7329
            this.cfg.addProperty(DEFAULT_CONFIG.HIDEAFTERSUBMIT.key, {
7330
                value: DEFAULT_CONFIG.HIDEAFTERSUBMIT.value
7331
            });
7332
7333
            /**
7334
            * Array of object literals, each containing a set of properties 
7335
            * defining a button to be appended into the Dialog's footer.
7336
            *
7337
            * <p>Each button object in the buttons array can have three properties:</p>
7338
            * <dl>
7339
            *    <dt>text:</dt>
7340
            *    <dd>
7341
            *       The text that will display on the face of the button. The text can 
7342
            *       include HTML, as long as it is compliant with HTML Button specifications.
7343
            *    </dd>
7344
            *    <dt>handler:</dt>
7345
            *    <dd>Can be either:
7346
            *    <ol>
7347
            *       <li>A reference to a function that should fire when the 
7348
            *       button is clicked.  (In this case scope of this function is 
7349
            *       always its Dialog instance.)</li>
7350
            *
7351
            *       <li>An object literal representing the code to be 
7352
            *       executed when the button is clicked.
7353
            *       
7354
            *       <p>Format:</p>
7355
            *
7356
            *       <p>
7357
            *       <code>{
7358
            *       <br>
7359
            *       <strong>fn:</strong> Function, &#47;&#47;
7360
            *       The handler to call when  the event fires.
7361
            *       <br>
7362
            *       <strong>obj:</strong> Object, &#47;&#47; 
7363
            *       An  object to pass back to the handler.
7364
            *       <br>
7365
            *       <strong>scope:</strong> Object &#47;&#47; 
7366
            *       The object to use for the scope of the handler.
7367
            *       <br>
7368
            *       }</code>
7369
            *       </p>
7370
            *       </li>
7371
            *     </ol>
7372
            *     </dd>
7373
            *     <dt>isDefault:</dt>
7374
            *     <dd>
7375
            *        An optional boolean value that specifies that a button 
7376
            *        should be highlighted and focused by default.
7377
            *     </dd>
7378
            * </dl>
7379
            *
7380
            * <em>NOTE:</em>If the YUI Button Widget is included on the page, 
7381
            * the buttons created will be instances of YAHOO.widget.Button. 
7382
            * Otherwise, HTML Buttons (<code>&#60;BUTTON&#62;</code>) will be 
7383
            * created.
7384
            *
7385
            * @config buttons
7386
            * @type {Array|String}
7387
            * @default "none"
7388
            */
7389
            this.cfg.addProperty(DEFAULT_CONFIG.BUTTONS.key, {
7390
                handler: this.configButtons,
7391
                value: DEFAULT_CONFIG.BUTTONS.value,
7392
                supercedes : DEFAULT_CONFIG.BUTTONS.supercedes
7393
            }); 
7394
7395
        },
7396
7397
        /**
7398
        * Initializes the custom events for Dialog which are fired 
7399
        * automatically at appropriate times by the Dialog class.
7400
        * @method initEvents
7401
        */
7402
        initEvents: function () {
7403
            Dialog.superclass.initEvents.call(this);
7404
7405
            var SIGNATURE = CustomEvent.LIST;
7406
7407
            /**
7408
            * CustomEvent fired prior to submission
7409
            * @event beforeSubmitEvent
7410
            */ 
7411
            this.beforeSubmitEvent = 
7412
                this.createEvent(EVENT_TYPES.BEFORE_SUBMIT);
7413
            this.beforeSubmitEvent.signature = SIGNATURE;
7414
            
7415
            /**
7416
            * CustomEvent fired after submission
7417
            * @event submitEvent
7418
            */
7419
            this.submitEvent = this.createEvent(EVENT_TYPES.SUBMIT);
7420
            this.submitEvent.signature = SIGNATURE;
7421
        
7422
            /**
7423
            * CustomEvent fired for manual submission, before the generic submit event is fired
7424
            * @event manualSubmitEvent
7425
            */
7426
            this.manualSubmitEvent = 
7427
                this.createEvent(EVENT_TYPES.MANUAL_SUBMIT);
7428
            this.manualSubmitEvent.signature = SIGNATURE;
7429
7430
            /**
7431
            * CustomEvent fired after asynchronous submission, before the generic submit event is fired
7432
            *
7433
            * @event asyncSubmitEvent
7434
            * @param {Object} conn The connection object, returned by YAHOO.util.Connect.asyncRequest
7435
            */
7436
            this.asyncSubmitEvent = this.createEvent(EVENT_TYPES.ASYNC_SUBMIT);
7437
            this.asyncSubmitEvent.signature = SIGNATURE;
7438
7439
            /**
7440
            * CustomEvent fired after form-based submission, before the generic submit event is fired
7441
            * @event formSubmitEvent
7442
            */
7443
            this.formSubmitEvent = this.createEvent(EVENT_TYPES.FORM_SUBMIT);
7444
            this.formSubmitEvent.signature = SIGNATURE;
7445
7446
            /**
7447
            * CustomEvent fired after cancel
7448
            * @event cancelEvent
7449
            */
7450
            this.cancelEvent = this.createEvent(EVENT_TYPES.CANCEL);
7451
            this.cancelEvent.signature = SIGNATURE;
7452
        
7453
        },
7454
        
7455
        /**
7456
        * The Dialog initialization method, which is executed for Dialog and 
7457
        * all of its subclasses. This method is automatically called by the 
7458
        * constructor, and  sets up all DOM references for pre-existing markup, 
7459
        * and creates required markup if it is not already present.
7460
        * 
7461
        * @method init
7462
        * @param {String} el The element ID representing the Dialog <em>OR</em>
7463
        * @param {HTMLElement} el The element representing the Dialog
7464
        * @param {Object} userConfig The configuration object literal 
7465
        * containing the configuration that should be set for this Dialog. 
7466
        * See configuration documentation for more details.
7467
        */
7468
        init: function (el, userConfig) {
7469
7470
            /*
7471
                 Note that we don't pass the user config in here yet because 
7472
                 we only want it executed once, at the lowest subclass level
7473
            */
7474
7475
            Dialog.superclass.init.call(this, el/*, userConfig*/); 
7476
7477
            this.beforeInitEvent.fire(Dialog);
7478
7479
            Dom.addClass(this.element, Dialog.CSS_DIALOG);
7480
7481
            this.cfg.setProperty("visible", false);
7482
7483
            if (userConfig) {
7484
                this.cfg.applyConfig(userConfig, true);
7485
            }
7486
7487
            this.showEvent.subscribe(this.focusFirst, this, true);
7488
            this.beforeHideEvent.subscribe(this.blurButtons, this, true);
7489
7490
            this.subscribe("changeBody", this.registerForm);
7491
7492
            this.initEvent.fire(Dialog);
7493
        },
7494
7495
        /**
7496
        * Submits the Dialog's form depending on the value of the 
7497
        * "postmethod" configuration property.  <strong>Please note:
7498
        * </strong> As of version 2.3 this method will automatically handle 
7499
        * asyncronous file uploads should the Dialog instance's form contain 
7500
        * <code>&#60;input type="file"&#62;</code> elements.  If a Dialog 
7501
        * instance will be handling asyncronous file uploads, its 
7502
        * <code>callback</code> property will need to be setup with a 
7503
        * <code>upload</code> handler rather than the standard 
7504
        * <code>success</code> and, or <code>failure</code> handlers.  For more 
7505
        * information, see the <a href="http://developer.yahoo.com/yui/
7506
        * connection/#file">Connection Manager documenation on file uploads</a>.
7507
        * @method doSubmit
7508
        */
7509
        doSubmit: function () {
7510
7511
            var Connect = YAHOO.util.Connect,
7512
                oForm = this.form,
7513
                bUseFileUpload = false,
7514
                bUseSecureFileUpload = false,
7515
                aElements,
7516
                nElements,
7517
                i,
7518
                formAttrs;
7519
7520
            switch (this.cfg.getProperty("postmethod")) {
7521
7522
                case "async":
7523
                    aElements = oForm.elements;
7524
                    nElements = aElements.length;
7525
7526
                    if (nElements > 0) {
7527
                        i = nElements - 1;
7528
                        do {
7529
                            if (aElements[i].type == "file") {
7530
                                bUseFileUpload = true;
7531
                                break;
7532
                            }
7533
                        }
7534
                        while(i--);
7535
                    }
7536
7537
                    if (bUseFileUpload && YAHOO.env.ua.ie && this.isSecure) {
7538
                        bUseSecureFileUpload = true;
7539
                    }
7540
7541
                    formAttrs = this._getFormAttributes(oForm);
7542
7543
                    Connect.setForm(oForm, bUseFileUpload, bUseSecureFileUpload);
7544
7545
                    var postData = this.cfg.getProperty("postdata");
7546
                    var c = Connect.asyncRequest(formAttrs.method, formAttrs.action, this.callback, postData);
7547
7548
                    this.asyncSubmitEvent.fire(c);
7549
7550
                    break;
7551
7552
                case "form":
7553
                    oForm.submit();
7554
                    this.formSubmitEvent.fire();
7555
                    break;
7556
7557
                case "none":
7558
                case "manual":
7559
                    this.manualSubmitEvent.fire();
7560
                    break;
7561
            }
7562
        },
7563
7564
        /**
7565
         * Retrieves important attributes (currently method and action) from
7566
         * the form element, accounting for any elements which may have the same name 
7567
         * as the attributes. Defaults to "POST" and "" for method and action respectively
7568
         * if the attribute cannot be retrieved.
7569
         *
7570
         * @method _getFormAttributes
7571
         * @protected
7572
         * @param {HTMLFormElement} oForm The HTML Form element from which to retrieve the attributes
7573
         * @return {Object} Object literal, with method and action String properties.
7574
         */
7575
        _getFormAttributes : function(oForm){
7576
            var attrs = {
7577
                method : null,
7578
                action : null
7579
            };
7580
7581
            if (oForm) {
7582
                if (oForm.getAttributeNode) {
7583
                    var action = oForm.getAttributeNode("action");
7584
                    var method = oForm.getAttributeNode("method");
7585
7586
                    if (action) {
7587
                        attrs.action = action.value;
7588
                    }
7589
7590
                    if (method) {
7591
                        attrs.method = method.value;
7592
                    }
7593
7594
                } else {
7595
                    attrs.action = oForm.getAttribute("action");
7596
                    attrs.method = oForm.getAttribute("method");
7597
                }
7598
            }
7599
7600
            attrs.method = (Lang.isString(attrs.method) ? attrs.method : "POST").toUpperCase();
7601
            attrs.action = Lang.isString(attrs.action) ? attrs.action : "";
7602
7603
            return attrs;
7604
        },
7605
7606
        /**
7607
        * Prepares the Dialog's internal FORM object, creating one if one is
7608
        * not currently present.
7609
        * @method registerForm
7610
        */
7611
        registerForm: function() {
7612
7613
            var form = this.element.getElementsByTagName("form")[0];
7614
7615
            if (this.form) {
7616
                if (this.form == form && Dom.isAncestor(this.element, this.form)) {
7617
                    return;
7618
                } else {
7619
                    Event.purgeElement(this.form);
7620
                    this.form = null;
7621
                }
7622
            }
7623
7624
            if (!form) {
7625
                form = document.createElement("form");
7626
                form.name = "frm_" + this.id;
7627
                this.body.appendChild(form);
7628
            }
7629
7630
            if (form) {
7631
                this.form = form;
7632
                Event.on(form, "submit", this._submitHandler, this, true);
7633
            }
7634
        },
7635
7636
        /**
7637
         * Internal handler for the form submit event
7638
         *
7639
         * @method _submitHandler
7640
         * @protected
7641
         * @param {DOMEvent} e The DOM Event object
7642
         */
7643
        _submitHandler : function(e) {
7644
            Event.stopEvent(e);
7645
            this.submit();
7646
            this.form.blur();
7647
        },
7648
7649
        /**
7650
         * Sets up a tab, shift-tab loop between the first and last elements
7651
         * provided. NOTE: Sets up the preventBackTab and preventTabOut KeyListener
7652
         * instance properties, which are reset everytime this method is invoked.
7653
         *
7654
         * @method setTabLoop
7655
         * @param {HTMLElement} firstElement
7656
         * @param {HTMLElement} lastElement
7657
         *
7658
         */
7659
        setTabLoop : function(firstElement, lastElement) {
7660
7661
            firstElement = firstElement || this.firstButton;
7662
            lastElement = this.lastButton || lastElement;
7663
7664
            Dialog.superclass.setTabLoop.call(this, firstElement, lastElement);
7665
        },
7666
7667
        /**
7668
         * Configures instance properties, pointing to the 
7669
         * first and last focusable elements in the Dialog's form.
7670
         *
7671
         * @method setFirstLastFocusable
7672
         */
7673
        setFirstLastFocusable : function() {
7674
7675
            Dialog.superclass.setFirstLastFocusable.call(this);
7676
7677
            var i, l, el, elements = this.focusableElements;
7678
7679
            this.firstFormElement = null;
7680
            this.lastFormElement = null;
7681
7682
            if (this.form && elements && elements.length > 0) {
7683
                l = elements.length;
7684
7685
                for (i = 0; i < l; ++i) {
7686
                    el = elements[i];
7687
                    if (this.form === el.form) {
7688
                        this.firstFormElement = el;
7689
                        break;
7690
                    }
7691
                }
7692
7693
                for (i = l-1; i >= 0; --i) {
7694
                    el = elements[i];
7695
                    if (this.form === el.form) {
7696
                        this.lastFormElement = el;
7697
                        break;
7698
                    }
7699
                }
7700
            }
7701
        },
7702
7703
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
7704
        /**
7705
        * The default event handler fired when the "close" property is 
7706
        * changed. The method controls the appending or hiding of the close
7707
        * icon at the top right of the Dialog.
7708
        * @method configClose
7709
        * @param {String} type The CustomEvent type (usually the property name)
7710
        * @param {Object[]} args The CustomEvent arguments. For 
7711
        * configuration handlers, args[0] will equal the newly applied value 
7712
        * for the property.
7713
        * @param {Object} obj The scope object. For configuration handlers, 
7714
        * this will usually equal the owner.
7715
        */
7716
        configClose: function (type, args, obj) {
7717
            Dialog.superclass.configClose.apply(this, arguments);
7718
        },
7719
7720
        /**
7721
         * Event handler for the close icon
7722
         * 
7723
         * @method _doClose
7724
         * @protected
7725
         * 
7726
         * @param {DOMEvent} e
7727
         */
7728
         _doClose : function(e) {
7729
            Event.preventDefault(e);
7730
            this.cancel();
7731
        },
7732
7733
        /**
7734
        * The default event handler for the "buttons" configuration property
7735
        * @method configButtons
7736
        * @param {String} type The CustomEvent type (usually the property name)
7737
        * @param {Object[]} args The CustomEvent arguments. For configuration 
7738
        * handlers, args[0] will equal the newly applied value for the property.
7739
        * @param {Object} obj The scope object. For configuration handlers, 
7740
        * this will usually equal the owner.
7741
        */
7742
        configButtons: function (type, args, obj) {
7743
7744
            var Button = YAHOO.widget.Button,
7745
                aButtons = args[0],
7746
                oInnerElement = this.innerElement,
7747
                oButton,
7748
                oButtonEl,
7749
                oYUIButton,
7750
                nButtons,
7751
                oSpan,
7752
                oFooter,
7753
                i;
7754
7755
            removeButtonEventHandlers.call(this);
7756
7757
            this._aButtons = null;
7758
7759
            if (Lang.isArray(aButtons)) {
7760
7761
                oSpan = document.createElement("span");
7762
                oSpan.className = "button-group";
7763
                nButtons = aButtons.length;
7764
7765
                this._aButtons = [];
7766
                this.defaultHtmlButton = null;
7767
7768
                for (i = 0; i < nButtons; i++) {
7769
                    oButton = aButtons[i];
7770
7771
                    if (Button) {
7772
                        oYUIButton = new Button({ label: oButton.text});
7773
                        oYUIButton.appendTo(oSpan);
7774
7775
                        oButtonEl = oYUIButton.get("element");
7776
7777
                        if (oButton.isDefault) {
7778
                            oYUIButton.addClass("default");
7779
                            this.defaultHtmlButton = oButtonEl;
7780
                        }
7781
7782
                        if (Lang.isFunction(oButton.handler)) {
7783
7784
                            oYUIButton.set("onclick", { 
7785
                                fn: oButton.handler, 
7786
                                obj: this, 
7787
                                scope: this 
7788
                            });
7789
7790
                        } else if (Lang.isObject(oButton.handler) && Lang.isFunction(oButton.handler.fn)) {
7791
7792
                            oYUIButton.set("onclick", { 
7793
                                fn: oButton.handler.fn, 
7794
                                obj: ((!Lang.isUndefined(oButton.handler.obj)) ? oButton.handler.obj : this), 
7795
                                scope: (oButton.handler.scope || this) 
7796
                            });
7797
7798
                        }
7799
7800
                        this._aButtons[this._aButtons.length] = oYUIButton;
7801
7802
                    } else {
7803
7804
                        oButtonEl = document.createElement("button");
7805
                        oButtonEl.setAttribute("type", "button");
7806
7807
                        if (oButton.isDefault) {
7808
                            oButtonEl.className = "default";
7809
                            this.defaultHtmlButton = oButtonEl;
7810
                        }
7811
7812
                        oButtonEl.innerHTML = oButton.text;
7813
7814
                        if (Lang.isFunction(oButton.handler)) {
7815
                            Event.on(oButtonEl, "click", oButton.handler, this, true);
7816
                        } else if (Lang.isObject(oButton.handler) && 
7817
                            Lang.isFunction(oButton.handler.fn)) {
7818
    
7819
                            Event.on(oButtonEl, "click", 
7820
                                oButton.handler.fn, 
7821
                                ((!Lang.isUndefined(oButton.handler.obj)) ? oButton.handler.obj : this), 
7822
                                (oButton.handler.scope || this));
7823
                        }
7824
7825
                        oSpan.appendChild(oButtonEl);
7826
                        this._aButtons[this._aButtons.length] = oButtonEl;
7827
                    }
7828
7829
                    oButton.htmlButton = oButtonEl;
7830
7831
                    if (i === 0) {
7832
                        this.firstButton = oButtonEl;
7833
                    }
7834
7835
                    if (i == (nButtons - 1)) {
7836
                        this.lastButton = oButtonEl;
7837
                    }
7838
                }
7839
7840
                this.setFooter(oSpan);
7841
7842
                oFooter = this.footer;
7843
7844
                if (Dom.inDocument(this.element) && !Dom.isAncestor(oInnerElement, oFooter)) {
7845
                    oInnerElement.appendChild(oFooter);
7846
                }
7847
7848
                this.buttonSpan = oSpan;
7849
7850
            } else { // Do cleanup
7851
                oSpan = this.buttonSpan;
7852
                oFooter = this.footer;
7853
                if (oSpan && oFooter) {
7854
                    oFooter.removeChild(oSpan);
7855
                    this.buttonSpan = null;
7856
                    this.firstButton = null;
7857
                    this.lastButton = null;
7858
                    this.defaultHtmlButton = null;
7859
                }
7860
            }
7861
7862
            this.changeContentEvent.fire();
7863
        },
7864
7865
        /**
7866
        * @method getButtons
7867
        * @description Returns an array containing each of the Dialog's 
7868
        * buttons, by default an array of HTML <code>&#60;BUTTON&#62;</code> 
7869
        * elements.  If the Dialog's buttons were created using the 
7870
        * YAHOO.widget.Button class (via the inclusion of the optional Button 
7871
        * dependancy on the page), an array of YAHOO.widget.Button instances 
7872
        * is returned.
7873
        * @return {Array}
7874
        */
7875
        getButtons: function () {
7876
            return this._aButtons || null;
7877
        },
7878
7879
        /**
7880
         * <p>
7881
         * Sets focus to the first focusable element in the Dialog's form if found, 
7882
         * else, the default button if found, else the first button defined via the 
7883
         * "buttons" configuration property.
7884
         * </p>
7885
         * <p>
7886
         * This method is invoked when the Dialog is made visible.
7887
         * </p>
7888
         * @method focusFirst
7889
         */
7890
        focusFirst: function (type, args, obj) {
7891
7892
            var el = this.firstFormElement;
7893
7894
            if (args && args[1]) {
7895
                Event.stopEvent(args[1]);
7896
            }
7897
7898
            if (el) {
7899
                try {
7900
                    el.focus();
7901
                } catch(oException) {
7902
                    // Ignore
7903
                }
7904
            } else {
7905
                if (this.defaultHtmlButton) {
7906
                    this.focusDefaultButton();
7907
                } else {
7908
                    this.focusFirstButton();
7909
                }
7910
            }
7911
        },
7912
7913
        /**
7914
        * Sets focus to the last element in the Dialog's form or the last 
7915
        * button defined via the "buttons" configuration property.
7916
        * @method focusLast
7917
        */
7918
        focusLast: function (type, args, obj) {
7919
7920
            var aButtons = this.cfg.getProperty("buttons"),
7921
                el = this.lastFormElement;
7922
7923
            if (args && args[1]) {
7924
                Event.stopEvent(args[1]);
7925
            }
7926
7927
            if (aButtons && Lang.isArray(aButtons)) {
7928
                this.focusLastButton();
7929
            } else {
7930
                if (el) {
7931
                    try {
7932
                        el.focus();
7933
                    } catch(oException) {
7934
                        // Ignore
7935
                    }
7936
                }
7937
            }
7938
        },
7939
7940
        /**
7941
         * Helper method to normalize button references. It either returns the 
7942
         * YUI Button instance for the given element if found,
7943
         * or the passes back the HTMLElement reference if a corresponding YUI Button
7944
         * reference is not found or YAHOO.widget.Button does not exist on the page.
7945
         *
7946
         * @method _getButton
7947
         * @private
7948
         * @param {HTMLElement} button
7949
         * @return {YAHOO.widget.Button|HTMLElement}
7950
         */
7951
        _getButton : function(button) {
7952
            var Button = YAHOO.widget.Button;
7953
7954
            // If we have an HTML button and YUI Button is on the page, 
7955
            // get the YUI Button reference if available.
7956
            if (Button && button && button.nodeName && button.id) {
7957
                button = Button.getButton(button.id) || button;
7958
            }
7959
7960
            return button;
7961
        },
7962
7963
        /**
7964
        * Sets the focus to the button that is designated as the default via 
7965
        * the "buttons" configuration property. By default, this method is 
7966
        * called when the Dialog is made visible.
7967
        * @method focusDefaultButton
7968
        */
7969
        focusDefaultButton: function () {
7970
            var button = this._getButton(this.defaultHtmlButton);
7971
            if (button) {
7972
                /*
7973
                    Place the call to the "focus" method inside a try/catch
7974
                    block to prevent IE from throwing JavaScript errors if
7975
                    the element is disabled or hidden.
7976
                */
7977
                try {
7978
                    button.focus();
7979
                } catch(oException) {
7980
                }
7981
            }
7982
        },
7983
7984
        /**
7985
        * Blurs all the buttons defined via the "buttons" 
7986
        * configuration property.
7987
        * @method blurButtons
7988
        */
7989
        blurButtons: function () {
7990
            
7991
            var aButtons = this.cfg.getProperty("buttons"),
7992
                nButtons,
7993
                oButton,
7994
                oElement,
7995
                i;
7996
7997
            if (aButtons && Lang.isArray(aButtons)) {
7998
                nButtons = aButtons.length;
7999
                if (nButtons > 0) {
8000
                    i = (nButtons - 1);
8001
                    do {
8002
                        oButton = aButtons[i];
8003
                        if (oButton) {
8004
                            oElement = this._getButton(oButton.htmlButton);
8005
                            if (oElement) {
8006
                                /*
8007
                                    Place the call to the "blur" method inside  
8008
                                    a try/catch block to prevent IE from  
8009
                                    throwing JavaScript errors if the element 
8010
                                    is disabled or hidden.
8011
                                */
8012
                                try {
8013
                                    oElement.blur();
8014
                                } catch(oException) {
8015
                                    // ignore
8016
                                }
8017
                            }
8018
                        }
8019
                    } while(i--);
8020
                }
8021
            }
8022
        },
8023
8024
        /**
8025
        * Sets the focus to the first button created via the "buttons"
8026
        * configuration property.
8027
        * @method focusFirstButton
8028
        */
8029
        focusFirstButton: function () {
8030
8031
            var aButtons = this.cfg.getProperty("buttons"),
8032
                oButton,
8033
                oElement;
8034
8035
            if (aButtons && Lang.isArray(aButtons)) {
8036
                oButton = aButtons[0];
8037
                if (oButton) {
8038
                    oElement = this._getButton(oButton.htmlButton);
8039
                    if (oElement) {
8040
                        /*
8041
                            Place the call to the "focus" method inside a 
8042
                            try/catch block to prevent IE from throwing 
8043
                            JavaScript errors if the element is disabled 
8044
                            or hidden.
8045
                        */
8046
                        try {
8047
                            oElement.focus();
8048
                        } catch(oException) {
8049
                            // ignore
8050
                        }
8051
                    }
8052
                }
8053
            }
8054
        },
8055
8056
        /**
8057
        * Sets the focus to the last button created via the "buttons" 
8058
        * configuration property.
8059
        * @method focusLastButton
8060
        */
8061
        focusLastButton: function () {
8062
8063
            var aButtons = this.cfg.getProperty("buttons"),
8064
                nButtons,
8065
                oButton,
8066
                oElement;
8067
8068
            if (aButtons && Lang.isArray(aButtons)) {
8069
                nButtons = aButtons.length;
8070
                if (nButtons > 0) {
8071
                    oButton = aButtons[(nButtons - 1)];
8072
8073
                    if (oButton) {
8074
                        oElement = this._getButton(oButton.htmlButton);
8075
                        if (oElement) {
8076
                            /*
8077
                                Place the call to the "focus" method inside a 
8078
                                try/catch block to prevent IE from throwing 
8079
                                JavaScript errors if the element is disabled
8080
                                or hidden.
8081
                            */
8082
        
8083
                            try {
8084
                                oElement.focus();
8085
                            } catch(oException) {
8086
                                // Ignore
8087
                            }
8088
                        }
8089
                    }
8090
                }
8091
            }
8092
        },
8093
8094
        /**
8095
        * The default event handler for the "postmethod" configuration property
8096
        * @method configPostMethod
8097
        * @param {String} type The CustomEvent type (usually the property name)
8098
        * @param {Object[]} args The CustomEvent arguments. For 
8099
        * configuration handlers, args[0] will equal the newly applied value 
8100
        * for the property.
8101
        * @param {Object} obj The scope object. For configuration handlers, 
8102
        * this will usually equal the owner.
8103
        */
8104
        configPostMethod: function (type, args, obj) {
8105
            this.registerForm();
8106
        },
8107
8108
        // END BUILT-IN PROPERTY EVENT HANDLERS //
8109
        
8110
        /**
8111
        * Built-in function hook for writing a validation function that will 
8112
        * be checked for a "true" value prior to a submit. This function, as 
8113
        * implemented by default, always returns true, so it should be 
8114
        * overridden if validation is necessary.
8115
        * @method validate
8116
        */
8117
        validate: function () {
8118
            return true;
8119
        },
8120
8121
        /**
8122
        * Executes a submit of the Dialog if validation 
8123
        * is successful. By default the Dialog is hidden
8124
        * after submission, but you can set the "hideaftersubmit"
8125
        * configuration property to false, to prevent the Dialog
8126
        * from being hidden.
8127
        * 
8128
        * @method submit
8129
        */
8130
        submit: function () {
8131
            if (this.validate()) {
8132
                if (this.beforeSubmitEvent.fire()) {
8133
                    this.doSubmit();
8134
                    this.submitEvent.fire();
8135
    
8136
                    if (this.cfg.getProperty("hideaftersubmit")) {
8137
                        this.hide();
8138
                    }
8139
    
8140
                    return true;
8141
                } else {
8142
                    return false;
8143
                }
8144
            } else {
8145
                return false;
8146
            }
8147
        },
8148
8149
        /**
8150
        * Executes the cancel of the Dialog followed by a hide.
8151
        * @method cancel
8152
        */
8153
        cancel: function () {
8154
            this.cancelEvent.fire();
8155
            this.hide();
8156
        },
8157
        
8158
        /**
8159
        * Returns a JSON-compatible data structure representing the data 
8160
        * currently contained in the form.
8161
        * @method getData
8162
        * @return {Object} A JSON object reprsenting the data of the 
8163
        * current form.
8164
        */
8165
        getData: function () {
8166
8167
            var oForm = this.form,
8168
                aElements,
8169
                nTotalElements,
8170
                oData,
8171
                sName,
8172
                oElement,
8173
                nElements,
8174
                sType,
8175
                sTagName,
8176
                aOptions,
8177
                nOptions,
8178
                aValues,
8179
                oOption,
8180
                oRadio,
8181
                oCheckbox,
8182
                valueAttr,
8183
                i,
8184
                n;    
8185
    
8186
            function isFormElement(p_oElement) {
8187
                var sTag = p_oElement.tagName.toUpperCase();
8188
                return ((sTag == "INPUT" || sTag == "TEXTAREA" || 
8189
                        sTag == "SELECT") && p_oElement.name == sName);
8190
            }
8191
8192
            if (oForm) {
8193
8194
                aElements = oForm.elements;
8195
                nTotalElements = aElements.length;
8196
                oData = {};
8197
8198
                for (i = 0; i < nTotalElements; i++) {
8199
                    sName = aElements[i].name;
8200
8201
                    /*
8202
                        Using "Dom.getElementsBy" to safeguard user from JS 
8203
                        errors that result from giving a form field (or set of 
8204
                        fields) the same name as a native method of a form 
8205
                        (like "submit") or a DOM collection (such as the "item"
8206
                        method). Originally tried accessing fields via the 
8207
                        "namedItem" method of the "element" collection, but 
8208
                        discovered that it won't return a collection of fields 
8209
                        in Gecko.
8210
                    */
8211
8212
                    oElement = Dom.getElementsBy(isFormElement, "*", oForm);
8213
                    nElements = oElement.length;
8214
8215
                    if (nElements > 0) {
8216
                        if (nElements == 1) {
8217
                            oElement = oElement[0];
8218
8219
                            sType = oElement.type;
8220
                            sTagName = oElement.tagName.toUpperCase();
8221
8222
                            switch (sTagName) {
8223
                                case "INPUT":
8224
                                    if (sType == "checkbox") {
8225
                                        oData[sName] = oElement.checked;
8226
                                    } else if (sType != "radio") {
8227
                                        oData[sName] = oElement.value;
8228
                                    }
8229
                                    break;
8230
8231
                                case "TEXTAREA":
8232
                                    oData[sName] = oElement.value;
8233
                                    break;
8234
    
8235
                                case "SELECT":
8236
                                    aOptions = oElement.options;
8237
                                    nOptions = aOptions.length;
8238
                                    aValues = [];
8239
    
8240
                                    for (n = 0; n < nOptions; n++) {
8241
                                        oOption = aOptions[n];
8242
                                        if (oOption.selected) {
8243
                                            valueAttr = oOption.attributes.value;
8244
                                            aValues[aValues.length] = (valueAttr && valueAttr.specified) ? oOption.value : oOption.text;
8245
                                        }
8246
                                    }
8247
                                    oData[sName] = aValues;
8248
                                    break;
8249
                            }
8250
        
8251
                        } else {
8252
                            sType = oElement[0].type;
8253
                            switch (sType) {
8254
                                case "radio":
8255
                                    for (n = 0; n < nElements; n++) {
8256
                                        oRadio = oElement[n];
8257
                                        if (oRadio.checked) {
8258
                                            oData[sName] = oRadio.value;
8259
                                            break;
8260
                                        }
8261
                                    }
8262
                                    break;
8263
        
8264
                                case "checkbox":
8265
                                    aValues = [];
8266
                                    for (n = 0; n < nElements; n++) {
8267
                                        oCheckbox = oElement[n];
8268
                                        if (oCheckbox.checked) {
8269
                                            aValues[aValues.length] =  oCheckbox.value;
8270
                                        }
8271
                                    }
8272
                                    oData[sName] = aValues;
8273
                                    break;
8274
                            }
8275
                        }
8276
                    }
8277
                }
8278
            }
8279
8280
            return oData;
8281
        },
8282
8283
        /**
8284
        * Removes the Panel element from the DOM and sets all child elements 
8285
        * to null.
8286
        * @method destroy
8287
        */
8288
        destroy: function () {
8289
            removeButtonEventHandlers.call(this);
8290
8291
            this._aButtons = null;
8292
8293
            var aForms = this.element.getElementsByTagName("form"),
8294
                oForm;
8295
8296
            if (aForms.length > 0) {
8297
                oForm = aForms[0];
8298
8299
                if (oForm) {
8300
                    Event.purgeElement(oForm);
8301
                    if (oForm.parentNode) {
8302
                        oForm.parentNode.removeChild(oForm);
8303
                    }
8304
                    this.form = null;
8305
                }
8306
            }
8307
            Dialog.superclass.destroy.call(this);
8308
        },
8309
8310
        /**
8311
        * Returns a string representation of the object.
8312
        * @method toString
8313
        * @return {String} The string representation of the Dialog
8314
        */
8315
        toString: function () {
8316
            return "Dialog " + this.id;
8317
        }
8318
    
8319
    });
8320
8321
}());
8322
(function () {
8323
8324
    /**
8325
    * SimpleDialog is a simple implementation of Dialog that can be used to 
8326
    * submit a single value. Forms can be processed in 3 ways -- via an 
8327
    * asynchronous Connection utility call, a simple form POST or GET, 
8328
    * or manually.
8329
    * @namespace YAHOO.widget
8330
    * @class SimpleDialog
8331
    * @extends YAHOO.widget.Dialog
8332
    * @constructor
8333
    * @param {String} el The element ID representing the SimpleDialog 
8334
    * <em>OR</em>
8335
    * @param {HTMLElement} el The element representing the SimpleDialog
8336
    * @param {Object} userConfig The configuration object literal containing 
8337
    * the configuration that should be set for this SimpleDialog. See 
8338
    * configuration documentation for more details.
8339
    */
8340
    YAHOO.widget.SimpleDialog = function (el, userConfig) {
8341
    
8342
        YAHOO.widget.SimpleDialog.superclass.constructor.call(this, 
8343
            el, userConfig);
8344
    
8345
    };
8346
8347
    var Dom = YAHOO.util.Dom,
8348
        SimpleDialog = YAHOO.widget.SimpleDialog,
8349
    
8350
        /**
8351
        * Constant representing the SimpleDialog's configuration properties
8352
        * @property DEFAULT_CONFIG
8353
        * @private
8354
        * @final
8355
        * @type Object
8356
        */
8357
        DEFAULT_CONFIG = {
8358
        
8359
            "ICON": { 
8360
                key: "icon", 
8361
                value: "none", 
8362
                suppressEvent: true  
8363
            },
8364
        
8365
            "TEXT": { 
8366
                key: "text", 
8367
                value: "", 
8368
                suppressEvent: true, 
8369
                supercedes: ["icon"] 
8370
            }
8371
        
8372
        };
8373
8374
    /**
8375
    * Constant for the standard network icon for a blocking action
8376
    * @property YAHOO.widget.SimpleDialog.ICON_BLOCK
8377
    * @static
8378
    * @final
8379
    * @type String
8380
    */
8381
    SimpleDialog.ICON_BLOCK = "blckicon";
8382
    
8383
    /**
8384
    * Constant for the standard network icon for alarm
8385
    * @property YAHOO.widget.SimpleDialog.ICON_ALARM
8386
    * @static
8387
    * @final
8388
    * @type String
8389
    */
8390
    SimpleDialog.ICON_ALARM = "alrticon";
8391
    
8392
    /**
8393
    * Constant for the standard network icon for help
8394
    * @property YAHOO.widget.SimpleDialog.ICON_HELP
8395
    * @static
8396
    * @final
8397
    * @type String
8398
    */
8399
    SimpleDialog.ICON_HELP  = "hlpicon";
8400
    
8401
    /**
8402
    * Constant for the standard network icon for info
8403
    * @property YAHOO.widget.SimpleDialog.ICON_INFO
8404
    * @static
8405
    * @final
8406
    * @type String
8407
    */
8408
    SimpleDialog.ICON_INFO  = "infoicon";
8409
    
8410
    /**
8411
    * Constant for the standard network icon for warn
8412
    * @property YAHOO.widget.SimpleDialog.ICON_WARN
8413
    * @static
8414
    * @final
8415
    * @type String
8416
    */
8417
    SimpleDialog.ICON_WARN  = "warnicon";
8418
    
8419
    /**
8420
    * Constant for the standard network icon for a tip
8421
    * @property YAHOO.widget.SimpleDialog.ICON_TIP
8422
    * @static
8423
    * @final
8424
    * @type String
8425
    */
8426
    SimpleDialog.ICON_TIP   = "tipicon";
8427
8428
    /**
8429
    * Constant representing the name of the CSS class applied to the element 
8430
    * created by the "icon" configuration property.
8431
    * @property YAHOO.widget.SimpleDialog.ICON_CSS_CLASSNAME
8432
    * @static
8433
    * @final
8434
    * @type String
8435
    */
8436
    SimpleDialog.ICON_CSS_CLASSNAME = "yui-icon";
8437
    
8438
    /**
8439
    * Constant representing the default CSS class used for a SimpleDialog
8440
    * @property YAHOO.widget.SimpleDialog.CSS_SIMPLEDIALOG
8441
    * @static
8442
    * @final
8443
    * @type String
8444
    */
8445
    SimpleDialog.CSS_SIMPLEDIALOG = "yui-simple-dialog";
8446
8447
    
8448
    YAHOO.extend(SimpleDialog, YAHOO.widget.Dialog, {
8449
    
8450
        /**
8451
        * Initializes the class's configurable properties which can be changed 
8452
        * using the SimpleDialog's Config object (cfg).
8453
        * @method initDefaultConfig
8454
        */
8455
        initDefaultConfig: function () {
8456
        
8457
            SimpleDialog.superclass.initDefaultConfig.call(this);
8458
        
8459
            // Add dialog config properties //
8460
        
8461
            /**
8462
            * Sets the informational icon for the SimpleDialog
8463
            * @config icon
8464
            * @type String
8465
            * @default "none"
8466
            */
8467
            this.cfg.addProperty(DEFAULT_CONFIG.ICON.key, {
8468
                handler: this.configIcon,
8469
                value: DEFAULT_CONFIG.ICON.value,
8470
                suppressEvent: DEFAULT_CONFIG.ICON.suppressEvent
8471
            });
8472
        
8473
            /**
8474
            * Sets the text for the SimpleDialog
8475
            * @config text
8476
            * @type String
8477
            * @default ""
8478
            */
8479
            this.cfg.addProperty(DEFAULT_CONFIG.TEXT.key, { 
8480
                handler: this.configText, 
8481
                value: DEFAULT_CONFIG.TEXT.value, 
8482
                suppressEvent: DEFAULT_CONFIG.TEXT.suppressEvent, 
8483
                supercedes: DEFAULT_CONFIG.TEXT.supercedes 
8484
            });
8485
        
8486
        },
8487
        
8488
        
8489
        /**
8490
        * The SimpleDialog initialization method, which is executed for 
8491
        * SimpleDialog and all of its subclasses. This method is automatically 
8492
        * called by the constructor, and  sets up all DOM references for 
8493
        * pre-existing markup, and creates required markup if it is not 
8494
        * already present.
8495
        * @method init
8496
        * @param {String} el The element ID representing the SimpleDialog 
8497
        * <em>OR</em>
8498
        * @param {HTMLElement} el The element representing the SimpleDialog
8499
        * @param {Object} userConfig The configuration object literal 
8500
        * containing the configuration that should be set for this 
8501
        * SimpleDialog. See configuration documentation for more details.
8502
        */
8503
        init: function (el, userConfig) {
8504
8505
            /*
8506
                Note that we don't pass the user config in here yet because we 
8507
                only want it executed once, at the lowest subclass level
8508
            */
8509
8510
            SimpleDialog.superclass.init.call(this, el/*, userConfig*/);
8511
        
8512
            this.beforeInitEvent.fire(SimpleDialog);
8513
        
8514
            Dom.addClass(this.element, SimpleDialog.CSS_SIMPLEDIALOG);
8515
        
8516
            this.cfg.queueProperty("postmethod", "manual");
8517
        
8518
            if (userConfig) {
8519
                this.cfg.applyConfig(userConfig, true);
8520
            }
8521
        
8522
            this.beforeRenderEvent.subscribe(function () {
8523
                if (! this.body) {
8524
                    this.setBody("");
8525
                }
8526
            }, this, true);
8527
        
8528
            this.initEvent.fire(SimpleDialog);
8529
        
8530
        },
8531
        
8532
        /**
8533
        * Prepares the SimpleDialog's internal FORM object, creating one if one 
8534
        * is not currently present, and adding the value hidden field.
8535
        * @method registerForm
8536
        */
8537
        registerForm: function () {
8538
8539
            SimpleDialog.superclass.registerForm.call(this);
8540
8541
            this.form.innerHTML += "<input type=\"hidden\" name=\"" + 
8542
                this.id + "\" value=\"\"/>";
8543
8544
        },
8545
        
8546
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
8547
        
8548
        /**
8549
        * Fired when the "icon" property is set.
8550
        * @method configIcon
8551
        * @param {String} type The CustomEvent type (usually the property name)
8552
        * @param {Object[]} args The CustomEvent arguments. For configuration 
8553
        * handlers, args[0] will equal the newly applied value for the property.
8554
        * @param {Object} obj The scope object. For configuration handlers, 
8555
        * this will usually equal the owner.
8556
        */
8557
        configIcon: function (type,args,obj) {
8558
        
8559
            var sIcon = args[0],
8560
                oBody = this.body,
8561
                sCSSClass = SimpleDialog.ICON_CSS_CLASSNAME,
8562
				aElements,
8563
                oIcon,
8564
                oIconParent;
8565
        
8566
            if (sIcon && sIcon != "none") {
8567
8568
                aElements = Dom.getElementsByClassName(sCSSClass, "*" , oBody);
8569
8570
				if (aElements.length === 1) {
8571
8572
					oIcon = aElements[0];
8573
                    oIconParent = oIcon.parentNode;
8574
8575
                    if (oIconParent) {
8576
8577
                        oIconParent.removeChild(oIcon);
8578
8579
                        oIcon = null;
8580
8581
                    }
8582
8583
				}
8584
8585
8586
                if (sIcon.indexOf(".") == -1) {
8587
8588
                    oIcon = document.createElement("span");
8589
                    oIcon.className = (sCSSClass + " " + sIcon);
8590
                    oIcon.innerHTML = "&#160;";
8591
8592
                } else {
8593
8594
                    oIcon = document.createElement("img");
8595
                    oIcon.src = (this.imageRoot + sIcon);
8596
                    oIcon.className = sCSSClass;
8597
8598
                }
8599
                
8600
8601
                if (oIcon) {
8602
                
8603
                    oBody.insertBefore(oIcon, oBody.firstChild);
8604
                
8605
                }
8606
8607
            }
8608
8609
        },
8610
8611
        /**
8612
        * Fired when the "text" property is set.
8613
        * @method configText
8614
        * @param {String} type The CustomEvent type (usually the property name)
8615
        * @param {Object[]} args The CustomEvent arguments. For configuration 
8616
        * handlers, args[0] will equal the newly applied value for the property.
8617
        * @param {Object} obj The scope object. For configuration handlers, 
8618
        * this will usually equal the owner.
8619
        */
8620
        configText: function (type,args,obj) {
8621
            var text = args[0];
8622
            if (text) {
8623
                this.setBody(text);
8624
                this.cfg.refireEvent("icon");
8625
            }
8626
        },
8627
        
8628
        // END BUILT-IN PROPERTY EVENT HANDLERS //
8629
        
8630
        /**
8631
        * Returns a string representation of the object.
8632
        * @method toString
8633
        * @return {String} The string representation of the SimpleDialog
8634
        */
8635
        toString: function () {
8636
            return "SimpleDialog " + this.id;
8637
        }
8638
8639
        /**
8640
        * <p>
8641
        * Sets the SimpleDialog's body content to the HTML specified. 
8642
        * If no body is present, one will be automatically created. 
8643
        * An empty string can be passed to the method to clear the contents of the body.
8644
        * </p>
8645
        * <p><strong>NOTE:</strong> SimpleDialog provides the <a href="#config_text">text</a>
8646
        * and <a href="#config_icon">icon</a> configuration properties to set the contents
8647
        * of it's body element in accordance with the UI design for a SimpleDialog (an 
8648
        * icon and message text). Calling setBody on the SimpleDialog will not enforce this 
8649
        * UI design constraint and will replace the entire contents of the SimpleDialog body. 
8650
        * It should only be used if you wish the replace the default icon/text body structure 
8651
        * of a SimpleDialog with your own custom markup.</p>
8652
        * 
8653
        * @method setBody
8654
        * @param {String} bodyContent The HTML used to set the body. 
8655
        * As a convenience, non HTMLElement objects can also be passed into 
8656
        * the method, and will be treated as strings, with the body innerHTML
8657
        * set to their default toString implementations.
8658
        * <em>OR</em>
8659
        * @param {HTMLElement} bodyContent The HTMLElement to add as the first and only child of the body element.
8660
        * <em>OR</em>
8661
        * @param {DocumentFragment} bodyContent The document fragment 
8662
        * containing elements which are to be added to the body
8663
        */
8664
    });
8665
8666
}());
8667
(function () {
8668
8669
    /**
8670
    * ContainerEffect encapsulates animation transitions that are executed when 
8671
    * an Overlay is shown or hidden.
8672
    * @namespace YAHOO.widget
8673
    * @class ContainerEffect
8674
    * @constructor
8675
    * @param {YAHOO.widget.Overlay} overlay The Overlay that the animation 
8676
    * should be associated with
8677
    * @param {Object} attrIn The object literal representing the animation 
8678
    * arguments to be used for the animate-in transition. The arguments for 
8679
    * this literal are: attributes(object, see YAHOO.util.Anim for description), 
8680
    * duration(Number), and method(i.e. Easing.easeIn).
8681
    * @param {Object} attrOut The object literal representing the animation 
8682
    * arguments to be used for the animate-out transition. The arguments for  
8683
    * this literal are: attributes(object, see YAHOO.util.Anim for description), 
8684
    * duration(Number), and method(i.e. Easing.easeIn).
8685
    * @param {HTMLElement} targetElement Optional. The target element that  
8686
    * should be animated during the transition. Defaults to overlay.element.
8687
    * @param {class} Optional. The animation class to instantiate. Defaults to 
8688
    * YAHOO.util.Anim. Other options include YAHOO.util.Motion.
8689
    */
8690
    YAHOO.widget.ContainerEffect = function (overlay, attrIn, attrOut, targetElement, animClass) {
8691
8692
        if (!animClass) {
8693
            animClass = YAHOO.util.Anim;
8694
        }
8695
8696
        /**
8697
        * The overlay to animate
8698
        * @property overlay
8699
        * @type YAHOO.widget.Overlay
8700
        */
8701
        this.overlay = overlay;
8702
    
8703
        /**
8704
        * The animation attributes to use when transitioning into view
8705
        * @property attrIn
8706
        * @type Object
8707
        */
8708
        this.attrIn = attrIn;
8709
    
8710
        /**
8711
        * The animation attributes to use when transitioning out of view
8712
        * @property attrOut
8713
        * @type Object
8714
        */
8715
        this.attrOut = attrOut;
8716
    
8717
        /**
8718
        * The target element to be animated
8719
        * @property targetElement
8720
        * @type HTMLElement
8721
        */
8722
        this.targetElement = targetElement || overlay.element;
8723
    
8724
        /**
8725
        * The animation class to use for animating the overlay
8726
        * @property animClass
8727
        * @type class
8728
        */
8729
        this.animClass = animClass;
8730
    
8731
    };
8732
8733
8734
    var Dom = YAHOO.util.Dom,
8735
        CustomEvent = YAHOO.util.CustomEvent,
8736
        ContainerEffect = YAHOO.widget.ContainerEffect;
8737
8738
8739
    /**
8740
    * A pre-configured ContainerEffect instance that can be used for fading 
8741
    * an overlay in and out.
8742
    * @method FADE
8743
    * @static
8744
    * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
8745
    * @param {Number} dur The duration of the animation
8746
    * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
8747
    */
8748
    ContainerEffect.FADE = function (overlay, dur) {
8749
8750
        var Easing = YAHOO.util.Easing,
8751
            fin = {
8752
                attributes: {opacity:{from:0, to:1}},
8753
                duration: dur,
8754
                method: Easing.easeIn
8755
            },
8756
            fout = {
8757
                attributes: {opacity:{to:0}},
8758
                duration: dur,
8759
                method: Easing.easeOut
8760
            },
8761
            fade = new ContainerEffect(overlay, fin, fout, overlay.element);
8762
8763
        fade.handleUnderlayStart = function() {
8764
            var underlay = this.overlay.underlay;
8765
            if (underlay && YAHOO.env.ua.ie) {
8766
                var hasFilters = (underlay.filters && underlay.filters.length > 0);
8767
                if(hasFilters) {
8768
                    Dom.addClass(overlay.element, "yui-effect-fade");
8769
                }
8770
            }
8771
        };
8772
8773
        fade.handleUnderlayComplete = function() {
8774
            var underlay = this.overlay.underlay;
8775
            if (underlay && YAHOO.env.ua.ie) {
8776
                Dom.removeClass(overlay.element, "yui-effect-fade");
8777
            }
8778
        };
8779
8780
        fade.handleStartAnimateIn = function (type, args, obj) {
8781
            Dom.addClass(obj.overlay.element, "hide-select");
8782
8783
            if (!obj.overlay.underlay) {
8784
                obj.overlay.cfg.refireEvent("underlay");
8785
            }
8786
8787
            obj.handleUnderlayStart();
8788
8789
            obj.overlay._setDomVisibility(true);
8790
            Dom.setStyle(obj.overlay.element, "opacity", 0);
8791
        };
8792
8793
        fade.handleCompleteAnimateIn = function (type,args,obj) {
8794
            Dom.removeClass(obj.overlay.element, "hide-select");
8795
8796
            if (obj.overlay.element.style.filter) {
8797
                obj.overlay.element.style.filter = null;
8798
            }
8799
8800
            obj.handleUnderlayComplete();
8801
8802
            obj.overlay.cfg.refireEvent("iframe");
8803
            obj.animateInCompleteEvent.fire();
8804
        };
8805
8806
        fade.handleStartAnimateOut = function (type, args, obj) {
8807
            Dom.addClass(obj.overlay.element, "hide-select");
8808
            obj.handleUnderlayStart();
8809
        };
8810
8811
        fade.handleCompleteAnimateOut =  function (type, args, obj) {
8812
            Dom.removeClass(obj.overlay.element, "hide-select");
8813
            if (obj.overlay.element.style.filter) {
8814
                obj.overlay.element.style.filter = null;
8815
            }
8816
            obj.overlay._setDomVisibility(false);
8817
            Dom.setStyle(obj.overlay.element, "opacity", 1);
8818
8819
            obj.handleUnderlayComplete();
8820
8821
            obj.overlay.cfg.refireEvent("iframe");
8822
            obj.animateOutCompleteEvent.fire();
8823
        };
8824
8825
        fade.init();
8826
        return fade;
8827
    };
8828
    
8829
    
8830
    /**
8831
    * A pre-configured ContainerEffect instance that can be used for sliding an 
8832
    * overlay in and out.
8833
    * @method SLIDE
8834
    * @static
8835
    * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
8836
    * @param {Number} dur The duration of the animation
8837
    * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
8838
    */
8839
    ContainerEffect.SLIDE = function (overlay, dur) {
8840
        var Easing = YAHOO.util.Easing,
8841
8842
            x = overlay.cfg.getProperty("x") || Dom.getX(overlay.element),
8843
            y = overlay.cfg.getProperty("y") || Dom.getY(overlay.element),
8844
            clientWidth = Dom.getClientWidth(),
8845
            offsetWidth = overlay.element.offsetWidth,
8846
8847
            sin =  { 
8848
                attributes: { points: { to: [x, y] } },
8849
                duration: dur,
8850
                method: Easing.easeIn 
8851
            },
8852
8853
            sout = {
8854
                attributes: { points: { to: [(clientWidth + 25), y] } },
8855
                duration: dur,
8856
                method: Easing.easeOut 
8857
            },
8858
8859
            slide = new ContainerEffect(overlay, sin, sout, overlay.element, YAHOO.util.Motion);
8860
8861
        slide.handleStartAnimateIn = function (type,args,obj) {
8862
            obj.overlay.element.style.left = ((-25) - offsetWidth) + "px";
8863
            obj.overlay.element.style.top  = y + "px";
8864
        };
8865
8866
        slide.handleTweenAnimateIn = function (type, args, obj) {
8867
        
8868
            var pos = Dom.getXY(obj.overlay.element),
8869
                currentX = pos[0],
8870
                currentY = pos[1];
8871
        
8872
            if (Dom.getStyle(obj.overlay.element, "visibility") == 
8873
                "hidden" && currentX < x) {
8874
8875
                obj.overlay._setDomVisibility(true);
8876
8877
            }
8878
        
8879
            obj.overlay.cfg.setProperty("xy", [currentX, currentY], true);
8880
            obj.overlay.cfg.refireEvent("iframe");
8881
        };
8882
        
8883
        slide.handleCompleteAnimateIn = function (type, args, obj) {
8884
            obj.overlay.cfg.setProperty("xy", [x, y], true);
8885
            obj.startX = x;
8886
            obj.startY = y;
8887
            obj.overlay.cfg.refireEvent("iframe");
8888
            obj.animateInCompleteEvent.fire();
8889
        };
8890
        
8891
        slide.handleStartAnimateOut = function (type, args, obj) {
8892
    
8893
            var vw = Dom.getViewportWidth(),
8894
                pos = Dom.getXY(obj.overlay.element),
8895
                yso = pos[1];
8896
    
8897
            obj.animOut.attributes.points.to = [(vw + 25), yso];
8898
        };
8899
        
8900
        slide.handleTweenAnimateOut = function (type, args, obj) {
8901
    
8902
            var pos = Dom.getXY(obj.overlay.element),
8903
                xto = pos[0],
8904
                yto = pos[1];
8905
        
8906
            obj.overlay.cfg.setProperty("xy", [xto, yto], true);
8907
            obj.overlay.cfg.refireEvent("iframe");
8908
        };
8909
        
8910
        slide.handleCompleteAnimateOut = function (type, args, obj) {
8911
            obj.overlay._setDomVisibility(false);
8912
8913
            obj.overlay.cfg.setProperty("xy", [x, y]);
8914
            obj.animateOutCompleteEvent.fire();
8915
        };
8916
8917
        slide.init();
8918
        return slide;
8919
    };
8920
8921
    ContainerEffect.prototype = {
8922
8923
        /**
8924
        * Initializes the animation classes and events.
8925
        * @method init
8926
        */
8927
        init: function () {
8928
8929
            this.beforeAnimateInEvent = this.createEvent("beforeAnimateIn");
8930
            this.beforeAnimateInEvent.signature = CustomEvent.LIST;
8931
            
8932
            this.beforeAnimateOutEvent = this.createEvent("beforeAnimateOut");
8933
            this.beforeAnimateOutEvent.signature = CustomEvent.LIST;
8934
        
8935
            this.animateInCompleteEvent = this.createEvent("animateInComplete");
8936
            this.animateInCompleteEvent.signature = CustomEvent.LIST;
8937
        
8938
            this.animateOutCompleteEvent = 
8939
                this.createEvent("animateOutComplete");
8940
            this.animateOutCompleteEvent.signature = CustomEvent.LIST;
8941
        
8942
            this.animIn = new this.animClass(this.targetElement, 
8943
                this.attrIn.attributes, this.attrIn.duration, 
8944
                this.attrIn.method);
8945
8946
            this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
8947
            this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
8948
8949
            this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn, 
8950
                this);
8951
        
8952
            this.animOut = new this.animClass(this.targetElement, 
8953
                this.attrOut.attributes, this.attrOut.duration, 
8954
                this.attrOut.method);
8955
8956
            this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
8957
            this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
8958
            this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut, 
8959
                this);
8960
8961
        },
8962
        
8963
        /**
8964
        * Triggers the in-animation.
8965
        * @method animateIn
8966
        */
8967
        animateIn: function () {
8968
            this.beforeAnimateInEvent.fire();
8969
            this.animIn.animate();
8970
        },
8971
8972
        /**
8973
        * Triggers the out-animation.
8974
        * @method animateOut
8975
        */
8976
        animateOut: function () {
8977
            this.beforeAnimateOutEvent.fire();
8978
            this.animOut.animate();
8979
        },
8980
8981
        /**
8982
        * The default onStart handler for the in-animation.
8983
        * @method handleStartAnimateIn
8984
        * @param {String} type The CustomEvent type
8985
        * @param {Object[]} args The CustomEvent arguments
8986
        * @param {Object} obj The scope object
8987
        */
8988
        handleStartAnimateIn: function (type, args, obj) { },
8989
8990
        /**
8991
        * The default onTween handler for the in-animation.
8992
        * @method handleTweenAnimateIn
8993
        * @param {String} type The CustomEvent type
8994
        * @param {Object[]} args The CustomEvent arguments
8995
        * @param {Object} obj The scope object
8996
        */
8997
        handleTweenAnimateIn: function (type, args, obj) { },
8998
8999
        /**
9000
        * The default onComplete handler for the in-animation.
9001
        * @method handleCompleteAnimateIn
9002
        * @param {String} type The CustomEvent type
9003
        * @param {Object[]} args The CustomEvent arguments
9004
        * @param {Object} obj The scope object
9005
        */
9006
        handleCompleteAnimateIn: function (type, args, obj) { },
9007
9008
        /**
9009
        * The default onStart handler for the out-animation.
9010
        * @method handleStartAnimateOut
9011
        * @param {String} type The CustomEvent type
9012
        * @param {Object[]} args The CustomEvent arguments
9013
        * @param {Object} obj The scope object
9014
        */
9015
        handleStartAnimateOut: function (type, args, obj) { },
9016
9017
        /**
9018
        * The default onTween handler for the out-animation.
9019
        * @method handleTweenAnimateOut
9020
        * @param {String} type The CustomEvent type
9021
        * @param {Object[]} args The CustomEvent arguments
9022
        * @param {Object} obj The scope object
9023
        */
9024
        handleTweenAnimateOut: function (type, args, obj) { },
9025
9026
        /**
9027
        * The default onComplete handler for the out-animation.
9028
        * @method handleCompleteAnimateOut
9029
        * @param {String} type The CustomEvent type
9030
        * @param {Object[]} args The CustomEvent arguments
9031
        * @param {Object} obj The scope object
9032
        */
9033
        handleCompleteAnimateOut: function (type, args, obj) { },
9034
        
9035
        /**
9036
        * Returns a string representation of the object.
9037
        * @method toString
9038
        * @return {String} The string representation of the ContainerEffect
9039
        */
9040
        toString: function () {
9041
            var output = "ContainerEffect";
9042
            if (this.overlay) {
9043
                output += " [" + this.overlay.toString() + "]";
9044
            }
9045
            return output;
9046
        }
9047
    };
9048
9049
    YAHOO.lang.augmentProto(ContainerEffect, YAHOO.util.EventProvider);
9050
9051
})();
9052
YAHOO.register("container", YAHOO.widget.Module, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/container/container_core-debug.js (-5136 lines)
Lines 1-5136 Link Here
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.8.0r4
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} overrideContext Optional. If true, will override
547
        * "this" within the handler to map to the scope Object passed into the
548
        * method.
549
        * @return {Boolean} True, if the subscription was successful, 
550
        * otherwise false.
551
        */ 
552
        subscribeToConfigEvent: function (key, handler, obj, overrideContext) {
553
    
554
            var property = this.config[key.toLowerCase()];
555
    
556
            if (property && property.event) {
557
                if (!Config.alreadySubscribed(property.event, handler, obj)) {
558
                    property.event.subscribe(handler, obj, overrideContext);
559
                }
560
                return true;
561
            } else {
562
                return false;
563
            }
564
    
565
        },
566
        
567
        /**
568
        * Unsubscribes an external handler from the change event for any 
569
        * given property. 
570
        * @method unsubscribeFromConfigEvent
571
        * @param {String} key The property name
572
        * @param {Function} handler The handler function to use subscribe to 
573
        * the property's event
574
        * @param {Object} obj The Object to use for scoping the event 
575
        * handler (see CustomEvent documentation)
576
        * @return {Boolean} True, if the unsubscription was successful, 
577
        * otherwise false.
578
        */
579
        unsubscribeFromConfigEvent: function (key, handler, obj) {
580
            var property = this.config[key.toLowerCase()];
581
            if (property && property.event) {
582
                return property.event.unsubscribe(handler, obj);
583
            } else {
584
                return false;
585
            }
586
        },
587
        
588
        /**
589
        * Returns a string representation of the Config object
590
        * @method toString
591
        * @return {String} The Config object in string format.
592
        */
593
        toString: function () {
594
            var output = "Config";
595
            if (this.owner) {
596
                output += " [" + this.owner.toString() + "]";
597
            }
598
            return output;
599
        },
600
        
601
        /**
602
        * Returns a string representation of the Config object's current 
603
        * CustomEvent queue
604
        * @method outputEventQueue
605
        * @return {String} The string list of CustomEvents currently queued 
606
        * for execution
607
        */
608
        outputEventQueue: function () {
609
610
            var output = "",
611
                queueItem,
612
                q,
613
                nQueue = this.eventQueue.length;
614
              
615
            for (q = 0; q < nQueue; q++) {
616
                queueItem = this.eventQueue[q];
617
                if (queueItem) {
618
                    output += queueItem[0] + "=" + queueItem[1] + ", ";
619
                }
620
            }
621
            return output;
622
        },
623
624
        /**
625
        * Sets all properties to null, unsubscribes all listeners from each 
626
        * property's change event and all listeners from the configChangedEvent.
627
        * @method destroy
628
        */
629
        destroy: function () {
630
631
            var oConfig = this.config,
632
                sProperty,
633
                oProperty;
634
635
636
            for (sProperty in oConfig) {
637
            
638
                if (Lang.hasOwnProperty(oConfig, sProperty)) {
639
640
                    oProperty = oConfig[sProperty];
641
642
                    oProperty.event.unsubscribeAll();
643
                    oProperty.event = null;
644
645
                }
646
            
647
            }
648
            
649
            this.configChangedEvent.unsubscribeAll();
650
            
651
            this.configChangedEvent = null;
652
            this.owner = null;
653
            this.config = null;
654
            this.initialConfig = null;
655
            this.eventQueue = null;
656
        
657
        }
658
659
    };
660
    
661
    
662
    
663
    /**
664
    * Checks to determine if a particular function/Object pair are already 
665
    * subscribed to the specified CustomEvent
666
    * @method YAHOO.util.Config.alreadySubscribed
667
    * @static
668
    * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check 
669
    * the subscriptions
670
    * @param {Function} fn The function to look for in the subscribers list
671
    * @param {Object} obj The execution scope Object for the subscription
672
    * @return {Boolean} true, if the function/Object pair is already subscribed 
673
    * to the CustomEvent passed in
674
    */
675
    Config.alreadySubscribed = function (evt, fn, obj) {
676
    
677
        var nSubscribers = evt.subscribers.length,
678
            subsc,
679
            i;
680
681
        if (nSubscribers > 0) {
682
            i = nSubscribers - 1;
683
            do {
684
                subsc = evt.subscribers[i];
685
                if (subsc && subsc.obj == obj && subsc.fn == fn) {
686
                    return true;
687
                }
688
            }
689
            while (i--);
690
        }
691
692
        return false;
693
694
    };
695
696
    YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
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
            "DESTROY": "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.DESTROY);
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 YUILibrary 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
                    // Setting the background color fixes an issue with IE6/IE7, where
1418
                    // elements in the DOM, with -ve margin-top which positioned them 
1419
                    // offscreen (so they would be overlapped by the iframe and its -ve top
1420
                    // setting), would have their -ve margin-top ignored, when the iframe 
1421
                    // was added.
1422
                    oIFrame.style.backgroundColor = "transparent";
1423
1424
                    oIFrame.style.borderWidth = "0";
1425
                    oIFrame.style.width = "2em";
1426
                    oIFrame.style.height = "2em";
1427
                    oIFrame.style.left = "0";
1428
                    oIFrame.style.top = (-1 * (oIFrame.offsetHeight + Module.RESIZE_MONITOR_BUFFER)) + "px";
1429
                    oIFrame.style.visibility = "visible";
1430
1431
                    /*
1432
                       Don't open/close the document for Gecko like we used to, since it
1433
                       leads to duplicate cookies. (See YUILibrary bug #1721755)
1434
                    */
1435
                    if (UA.webkit) {
1436
                        oDoc = oIFrame.contentWindow.document;
1437
                        oDoc.open();
1438
                        oDoc.close();
1439
                    }
1440
                }
1441
1442
                if (oIFrame && oIFrame.contentWindow) {
1443
                    Module.textResizeEvent.subscribe(this.onDomResize, this, true);
1444
1445
                    if (!Module.textResizeInitialized) {
1446
                        if (supportsCWResize) {
1447
                            if (!Event.on(oIFrame.contentWindow, "resize", fireTextResize)) {
1448
                                /*
1449
                                     This will fail in IE if document.domain has 
1450
                                     changed, so we must change the listener to 
1451
                                     use the oIFrame element instead
1452
                                */
1453
                                Event.on(oIFrame, "resize", fireTextResize);
1454
                            }
1455
                        }
1456
                        Module.textResizeInitialized = true;
1457
                    }
1458
                    this.resizeMonitor = oIFrame;
1459
                }
1460
            }
1461
        },
1462
1463
        /**
1464
         * Text resize monitor helper method.
1465
         * Determines if the browser supports resize events on iframe content windows.
1466
         * 
1467
         * @private
1468
         * @method _supportsCWResize
1469
         */
1470
        _supportsCWResize : function() {
1471
            /*
1472
                Gecko 1.8.0 (FF1.5), 1.8.1.0-5 (FF2) won't fire resize on contentWindow.
1473
                Gecko 1.8.1.6+ (FF2.0.0.6+) and all other browsers will fire resize on contentWindow.
1474
1475
                We don't want to start sniffing for patch versions, so fire textResize the same
1476
                way on all FF2 flavors
1477
             */
1478
            var bSupported = true;
1479
            if (UA.gecko && UA.gecko <= 1.8) {
1480
                bSupported = false;
1481
            }
1482
            return bSupported;
1483
        },
1484
1485
        /**
1486
        * Event handler fired when the resize monitor element is resized.
1487
        * @method onDomResize
1488
        * @param {DOMEvent} e The DOM resize event
1489
        * @param {Object} obj The scope object passed to the handler
1490
        */
1491
        onDomResize: function (e, obj) {
1492
1493
            var nTop = -1 * (this.resizeMonitor.offsetHeight + Module.RESIZE_MONITOR_BUFFER);
1494
1495
            this.resizeMonitor.style.top = nTop + "px";
1496
            this.resizeMonitor.style.left = "0";
1497
        },
1498
1499
        /**
1500
        * Sets the Module's header content to the string specified, or appends 
1501
        * the passed element to the header. If no header is present, one will 
1502
        * be automatically created. An empty string can be passed to the method
1503
        * to clear the contents of the header.
1504
        * 
1505
        * @method setHeader
1506
        * @param {String} headerContent The string used to set the header.
1507
        * As a convenience, non HTMLElement objects can also be passed into 
1508
        * the method, and will be treated as strings, with the header innerHTML
1509
        * set to their default toString implementations.
1510
        * <em>OR</em>
1511
        * @param {HTMLElement} headerContent The HTMLElement to append to 
1512
        * <em>OR</em>
1513
        * @param {DocumentFragment} headerContent The document fragment 
1514
        * containing elements which are to be added to the header
1515
        */
1516
        setHeader: function (headerContent) {
1517
            var oHeader = this.header || (this.header = createHeader());
1518
1519
            if (headerContent.nodeName) {
1520
                oHeader.innerHTML = "";
1521
                oHeader.appendChild(headerContent);
1522
            } else {
1523
                oHeader.innerHTML = headerContent;
1524
            }
1525
1526
            if (this._rendered) {
1527
                this._renderHeader();
1528
            }
1529
1530
            this.changeHeaderEvent.fire(headerContent);
1531
            this.changeContentEvent.fire();
1532
1533
        },
1534
1535
        /**
1536
        * Appends the passed element to the header. If no header is present, 
1537
        * one will be automatically created.
1538
        * @method appendToHeader
1539
        * @param {HTMLElement | DocumentFragment} element The element to 
1540
        * append to the header. In the case of a document fragment, the
1541
        * children of the fragment will be appended to the header.
1542
        */
1543
        appendToHeader: function (element) {
1544
            var oHeader = this.header || (this.header = createHeader());
1545
1546
            oHeader.appendChild(element);
1547
1548
            this.changeHeaderEvent.fire(element);
1549
            this.changeContentEvent.fire();
1550
1551
        },
1552
1553
        /**
1554
        * Sets the Module's body content to the HTML specified. 
1555
        * 
1556
        * If no body is present, one will be automatically created. 
1557
        * 
1558
        * An empty string can be passed to the method to clear the contents of the body.
1559
        * @method setBody
1560
        * @param {String} bodyContent The HTML used to set the body. 
1561
        * As a convenience, non HTMLElement objects can also be passed into 
1562
        * the method, and will be treated as strings, with the body innerHTML
1563
        * set to their default toString implementations.
1564
        * <em>OR</em>
1565
        * @param {HTMLElement} bodyContent The HTMLElement to add as the first and only
1566
        * child of the body element.
1567
        * <em>OR</em>
1568
        * @param {DocumentFragment} bodyContent The document fragment 
1569
        * containing elements which are to be added to the body
1570
        */
1571
        setBody: function (bodyContent) {
1572
            var oBody = this.body || (this.body = createBody());
1573
1574
            if (bodyContent.nodeName) {
1575
                oBody.innerHTML = "";
1576
                oBody.appendChild(bodyContent);
1577
            } else {
1578
                oBody.innerHTML = bodyContent;
1579
            }
1580
1581
            if (this._rendered) {
1582
                this._renderBody();
1583
            }
1584
1585
            this.changeBodyEvent.fire(bodyContent);
1586
            this.changeContentEvent.fire();
1587
        },
1588
1589
        /**
1590
        * Appends the passed element to the body. If no body is present, one 
1591
        * will be automatically created.
1592
        * @method appendToBody
1593
        * @param {HTMLElement | DocumentFragment} element The element to 
1594
        * append to the body. In the case of a document fragment, the
1595
        * children of the fragment will be appended to the body.
1596
        * 
1597
        */
1598
        appendToBody: function (element) {
1599
            var oBody = this.body || (this.body = createBody());
1600
        
1601
            oBody.appendChild(element);
1602
1603
            this.changeBodyEvent.fire(element);
1604
            this.changeContentEvent.fire();
1605
1606
        },
1607
        
1608
        /**
1609
        * Sets the Module's footer content to the HTML specified, or appends 
1610
        * the passed element to the footer. If no footer is present, one will 
1611
        * be automatically created. An empty string can be passed to the method
1612
        * to clear the contents of the footer.
1613
        * @method setFooter
1614
        * @param {String} footerContent The HTML used to set the footer 
1615
        * As a convenience, non HTMLElement objects can also be passed into 
1616
        * the method, and will be treated as strings, with the footer innerHTML
1617
        * set to their default toString implementations.
1618
        * <em>OR</em>
1619
        * @param {HTMLElement} footerContent The HTMLElement to append to 
1620
        * the footer
1621
        * <em>OR</em>
1622
        * @param {DocumentFragment} footerContent The document fragment containing 
1623
        * elements which are to be added to the footer
1624
        */
1625
        setFooter: function (footerContent) {
1626
1627
            var oFooter = this.footer || (this.footer = createFooter());
1628
1629
            if (footerContent.nodeName) {
1630
                oFooter.innerHTML = "";
1631
                oFooter.appendChild(footerContent);
1632
            } else {
1633
                oFooter.innerHTML = footerContent;
1634
            }
1635
1636
            if (this._rendered) {
1637
                this._renderFooter();
1638
            }
1639
1640
            this.changeFooterEvent.fire(footerContent);
1641
            this.changeContentEvent.fire();
1642
        },
1643
1644
        /**
1645
        * Appends the passed element to the footer. If no footer is present, 
1646
        * one will be automatically created.
1647
        * @method appendToFooter
1648
        * @param {HTMLElement | DocumentFragment} element The element to 
1649
        * append to the footer. In the case of a document fragment, the
1650
        * children of the fragment will be appended to the footer
1651
        */
1652
        appendToFooter: function (element) {
1653
1654
            var oFooter = this.footer || (this.footer = createFooter());
1655
1656
            oFooter.appendChild(element);
1657
1658
            this.changeFooterEvent.fire(element);
1659
            this.changeContentEvent.fire();
1660
1661
        },
1662
1663
        /**
1664
        * Renders the Module by inserting the elements that are not already 
1665
        * in the main Module into their correct places. Optionally appends 
1666
        * the Module to the specified node prior to the render's execution. 
1667
        * <p>
1668
        * For Modules without existing markup, the appendToNode argument 
1669
        * is REQUIRED. If this argument is ommitted and the current element is 
1670
        * not present in the document, the function will return false, 
1671
        * indicating that the render was a failure.
1672
        * </p>
1673
        * <p>
1674
        * NOTE: As of 2.3.1, if the appendToNode is the document's body element
1675
        * then the module is rendered as the first child of the body element, 
1676
        * and not appended to it, to avoid Operation Aborted errors in IE when 
1677
        * rendering the module before window's load event is fired. You can 
1678
        * use the appendtodocumentbody configuration property to change this 
1679
        * to append to document.body if required.
1680
        * </p>
1681
        * @method render
1682
        * @param {String} appendToNode The element id to which the Module 
1683
        * should be appended to prior to rendering <em>OR</em>
1684
        * @param {HTMLElement} appendToNode The element to which the Module 
1685
        * should be appended to prior to rendering
1686
        * @param {HTMLElement} moduleElement OPTIONAL. The element that 
1687
        * represents the actual Standard Module container.
1688
        * @return {Boolean} Success or failure of the render
1689
        */
1690
        render: function (appendToNode, moduleElement) {
1691
1692
            var me = this;
1693
1694
            function appendTo(parentNode) {
1695
                if (typeof parentNode == "string") {
1696
                    parentNode = document.getElementById(parentNode);
1697
                }
1698
1699
                if (parentNode) {
1700
                    me._addToParent(parentNode, me.element);
1701
                    me.appendEvent.fire();
1702
                }
1703
            }
1704
1705
            this.beforeRenderEvent.fire();
1706
1707
            if (! moduleElement) {
1708
                moduleElement = this.element;
1709
            }
1710
1711
            if (appendToNode) {
1712
                appendTo(appendToNode);
1713
            } else { 
1714
                // No node was passed in. If the element is not already in the Dom, this fails
1715
                if (! Dom.inDocument(this.element)) {
1716
                    YAHOO.log("Render failed. Must specify appendTo node if " + " Module isn't already in the DOM.", "error");
1717
                    return false;
1718
                }
1719
            }
1720
1721
            this._renderHeader(moduleElement);
1722
            this._renderBody(moduleElement);
1723
            this._renderFooter(moduleElement);
1724
1725
            this._rendered = true;
1726
1727
            this.renderEvent.fire();
1728
            return true;
1729
        },
1730
1731
        /**
1732
         * Renders the currently set header into it's proper position under the 
1733
         * module element. If the module element is not provided, "this.element" 
1734
         * is used.
1735
         * 
1736
         * @method _renderHeader
1737
         * @protected
1738
         * @param {HTMLElement} moduleElement Optional. A reference to the module element
1739
         */
1740
        _renderHeader: function(moduleElement){
1741
            moduleElement = moduleElement || this.element;
1742
1743
            // Need to get everything into the DOM if it isn't already
1744
            if (this.header && !Dom.inDocument(this.header)) {
1745
                // There is a header, but it's not in the DOM yet. Need to add it.
1746
                var firstChild = moduleElement.firstChild;
1747
                if (firstChild) {
1748
                    moduleElement.insertBefore(this.header, firstChild);
1749
                } else {
1750
                    moduleElement.appendChild(this.header);
1751
                }
1752
            }
1753
        },
1754
1755
        /**
1756
         * Renders the currently set body into it's proper position under the 
1757
         * module element. If the module element is not provided, "this.element" 
1758
         * is used.
1759
         * 
1760
         * @method _renderBody
1761
         * @protected
1762
         * @param {HTMLElement} moduleElement Optional. A reference to the module element.
1763
         */
1764
        _renderBody: function(moduleElement){
1765
            moduleElement = moduleElement || this.element;
1766
1767
            if (this.body && !Dom.inDocument(this.body)) {
1768
                // There is a body, but it's not in the DOM yet. Need to add it.
1769
                if (this.footer && Dom.isAncestor(moduleElement, this.footer)) {
1770
                    moduleElement.insertBefore(this.body, this.footer);
1771
                } else {
1772
                    moduleElement.appendChild(this.body);
1773
                }
1774
            }
1775
        },
1776
1777
        /**
1778
         * Renders the currently set footer into it's proper position under the 
1779
         * module element. If the module element is not provided, "this.element" 
1780
         * is used.
1781
         * 
1782
         * @method _renderFooter
1783
         * @protected
1784
         * @param {HTMLElement} moduleElement Optional. A reference to the module element
1785
         */
1786
        _renderFooter: function(moduleElement){
1787
            moduleElement = moduleElement || this.element;
1788
1789
            if (this.footer && !Dom.inDocument(this.footer)) {
1790
                // There is a footer, but it's not in the DOM yet. Need to add it.
1791
                moduleElement.appendChild(this.footer);
1792
            }
1793
        },
1794
1795
        /**
1796
        * Removes the Module element from the DOM and sets all child elements 
1797
        * to null.
1798
        * @method destroy
1799
        */
1800
        destroy: function () {
1801
1802
            var parent;
1803
1804
            if (this.element) {
1805
                Event.purgeElement(this.element, true);
1806
                parent = this.element.parentNode;
1807
            }
1808
1809
            if (parent) {
1810
                parent.removeChild(this.element);
1811
            }
1812
        
1813
            this.element = null;
1814
            this.header = null;
1815
            this.body = null;
1816
            this.footer = null;
1817
1818
            Module.textResizeEvent.unsubscribe(this.onDomResize, this);
1819
1820
            this.cfg.destroy();
1821
            this.cfg = null;
1822
1823
            this.destroyEvent.fire();
1824
        },
1825
1826
        /**
1827
        * Shows the Module element by setting the visible configuration 
1828
        * property to true. Also fires two events: beforeShowEvent prior to 
1829
        * the visibility change, and showEvent after.
1830
        * @method show
1831
        */
1832
        show: function () {
1833
            this.cfg.setProperty("visible", true);
1834
        },
1835
1836
        /**
1837
        * Hides the Module element by setting the visible configuration 
1838
        * property to false. Also fires two events: beforeHideEvent prior to 
1839
        * the visibility change, and hideEvent after.
1840
        * @method hide
1841
        */
1842
        hide: function () {
1843
            this.cfg.setProperty("visible", false);
1844
        },
1845
        
1846
        // BUILT-IN EVENT HANDLERS FOR MODULE //
1847
        /**
1848
        * Default event handler for changing the visibility property of a 
1849
        * Module. By default, this is achieved by switching the "display" style 
1850
        * between "block" and "none".
1851
        * This method is responsible for firing showEvent and hideEvent.
1852
        * @param {String} type The CustomEvent type (usually the property name)
1853
        * @param {Object[]} args The CustomEvent arguments. For configuration 
1854
        * handlers, args[0] will equal the newly applied value for the property.
1855
        * @param {Object} obj The scope object. For configuration handlers, 
1856
        * this will usually equal the owner.
1857
        * @method configVisible
1858
        */
1859
        configVisible: function (type, args, obj) {
1860
            var visible = args[0];
1861
            if (visible) {
1862
                this.beforeShowEvent.fire();
1863
                Dom.setStyle(this.element, "display", "block");
1864
                this.showEvent.fire();
1865
            } else {
1866
                this.beforeHideEvent.fire();
1867
                Dom.setStyle(this.element, "display", "none");
1868
                this.hideEvent.fire();
1869
            }
1870
        },
1871
1872
        /**
1873
        * Default event handler for the "monitorresize" configuration property
1874
        * @param {String} type The CustomEvent type (usually the property name)
1875
        * @param {Object[]} args The CustomEvent arguments. For configuration 
1876
        * handlers, args[0] will equal the newly applied value for the property.
1877
        * @param {Object} obj The scope object. For configuration handlers, 
1878
        * this will usually equal the owner.
1879
        * @method configMonitorResize
1880
        */
1881
        configMonitorResize: function (type, args, obj) {
1882
            var monitor = args[0];
1883
            if (monitor) {
1884
                this.initResizeMonitor();
1885
            } else {
1886
                Module.textResizeEvent.unsubscribe(this.onDomResize, this, true);
1887
                this.resizeMonitor = null;
1888
            }
1889
        },
1890
1891
        /**
1892
         * This method is a protected helper, used when constructing the DOM structure for the module 
1893
         * to account for situations which may cause Operation Aborted errors in IE. It should not 
1894
         * be used for general DOM construction.
1895
         * <p>
1896
         * If the parentNode is not document.body, the element is appended as the last element.
1897
         * </p>
1898
         * <p>
1899
         * If the parentNode is document.body the element is added as the first child to help
1900
         * prevent Operation Aborted errors in IE.
1901
         * </p>
1902
         *
1903
         * @param {parentNode} The HTML element to which the element will be added
1904
         * @param {element} The HTML element to be added to parentNode's children
1905
         * @method _addToParent
1906
         * @protected
1907
         */
1908
        _addToParent: function(parentNode, element) {
1909
            if (!this.cfg.getProperty("appendtodocumentbody") && parentNode === document.body && parentNode.firstChild) {
1910
                parentNode.insertBefore(element, parentNode.firstChild);
1911
            } else {
1912
                parentNode.appendChild(element);
1913
            }
1914
        },
1915
1916
        /**
1917
        * Returns a String representation of the Object.
1918
        * @method toString
1919
        * @return {String} The string representation of the Module
1920
        */
1921
        toString: function () {
1922
            return "Module " + this.id;
1923
        }
1924
    };
1925
1926
    YAHOO.lang.augmentProto(Module, YAHOO.util.EventProvider);
1927
1928
}());
1929
(function () {
1930
1931
    /**
1932
    * Overlay is a Module that is absolutely positioned above the page flow. It 
1933
    * has convenience methods for positioning and sizing, as well as options for 
1934
    * controlling zIndex and constraining the Overlay's position to the current 
1935
    * visible viewport. Overlay also contains a dynamicly generated IFRAME which 
1936
    * is placed beneath it for Internet Explorer 6 and 5.x so that it will be 
1937
    * properly rendered above SELECT elements.
1938
    * @namespace YAHOO.widget
1939
    * @class Overlay
1940
    * @extends YAHOO.widget.Module
1941
    * @param {String} el The element ID representing the Overlay <em>OR</em>
1942
    * @param {HTMLElement} el The element representing the Overlay
1943
    * @param {Object} userConfig The configuration object literal containing 
1944
    * the configuration that should be set for this Overlay. See configuration 
1945
    * documentation for more details.
1946
    * @constructor
1947
    */
1948
    YAHOO.widget.Overlay = function (el, userConfig) {
1949
        YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
1950
    };
1951
1952
    var Lang = YAHOO.lang,
1953
        CustomEvent = YAHOO.util.CustomEvent,
1954
        Module = YAHOO.widget.Module,
1955
        Event = YAHOO.util.Event,
1956
        Dom = YAHOO.util.Dom,
1957
        Config = YAHOO.util.Config,
1958
        UA = YAHOO.env.ua,
1959
        Overlay = YAHOO.widget.Overlay,
1960
1961
        _SUBSCRIBE = "subscribe",
1962
        _UNSUBSCRIBE = "unsubscribe",
1963
        _CONTAINED = "contained",
1964
1965
        m_oIFrameTemplate,
1966
1967
        /**
1968
        * Constant representing the name of the Overlay's events
1969
        * @property EVENT_TYPES
1970
        * @private
1971
        * @final
1972
        * @type Object
1973
        */
1974
        EVENT_TYPES = {
1975
            "BEFORE_MOVE": "beforeMove",
1976
            "MOVE": "move"
1977
        },
1978
1979
        /**
1980
        * Constant representing the Overlay's configuration properties
1981
        * @property DEFAULT_CONFIG
1982
        * @private
1983
        * @final
1984
        * @type Object
1985
        */
1986
        DEFAULT_CONFIG = {
1987
1988
            "X": { 
1989
                key: "x", 
1990
                validator: Lang.isNumber, 
1991
                suppressEvent: true, 
1992
                supercedes: ["iframe"]
1993
            },
1994
1995
            "Y": { 
1996
                key: "y", 
1997
                validator: Lang.isNumber, 
1998
                suppressEvent: true, 
1999
                supercedes: ["iframe"]
2000
            },
2001
2002
            "XY": { 
2003
                key: "xy", 
2004
                suppressEvent: true, 
2005
                supercedes: ["iframe"] 
2006
            },
2007
2008
            "CONTEXT": { 
2009
                key: "context", 
2010
                suppressEvent: true, 
2011
                supercedes: ["iframe"] 
2012
            },
2013
2014
            "FIXED_CENTER": { 
2015
                key: "fixedcenter", 
2016
                value: false, 
2017
                supercedes: ["iframe", "visible"] 
2018
            },
2019
2020
            "WIDTH": { 
2021
                key: "width",
2022
                suppressEvent: true,
2023
                supercedes: ["context", "fixedcenter", "iframe"]
2024
            }, 
2025
2026
            "HEIGHT": { 
2027
                key: "height", 
2028
                suppressEvent: true, 
2029
                supercedes: ["context", "fixedcenter", "iframe"] 
2030
            },
2031
2032
            "AUTO_FILL_HEIGHT" : {
2033
                key: "autofillheight",
2034
                supercedes: ["height"],
2035
                value:"body"
2036
            },
2037
2038
            "ZINDEX": { 
2039
                key: "zindex", 
2040
                value: null 
2041
            },
2042
2043
            "CONSTRAIN_TO_VIEWPORT": { 
2044
                key: "constraintoviewport", 
2045
                value: false, 
2046
                validator: Lang.isBoolean, 
2047
                supercedes: ["iframe", "x", "y", "xy"]
2048
            }, 
2049
2050
            "IFRAME": { 
2051
                key: "iframe", 
2052
                value: (UA.ie == 6 ? true : false), 
2053
                validator: Lang.isBoolean, 
2054
                supercedes: ["zindex"] 
2055
            },
2056
2057
            "PREVENT_CONTEXT_OVERLAP": {
2058
                key: "preventcontextoverlap",
2059
                value: false,
2060
                validator: Lang.isBoolean,  
2061
                supercedes: ["constraintoviewport"]
2062
            }
2063
2064
        };
2065
2066
    /**
2067
    * The URL that will be placed in the iframe
2068
    * @property YAHOO.widget.Overlay.IFRAME_SRC
2069
    * @static
2070
    * @final
2071
    * @type String
2072
    */
2073
    Overlay.IFRAME_SRC = "javascript:false;";
2074
2075
    /**
2076
    * Number representing how much the iframe shim should be offset from each 
2077
    * side of an Overlay instance, in pixels.
2078
    * @property YAHOO.widget.Overlay.IFRAME_SRC
2079
    * @default 3
2080
    * @static
2081
    * @final
2082
    * @type Number
2083
    */
2084
    Overlay.IFRAME_OFFSET = 3;
2085
2086
    /**
2087
    * Number representing the minimum distance an Overlay instance should be 
2088
    * positioned relative to the boundaries of the browser's viewport, in pixels.
2089
    * @property YAHOO.widget.Overlay.VIEWPORT_OFFSET
2090
    * @default 10
2091
    * @static
2092
    * @final
2093
    * @type Number
2094
    */
2095
    Overlay.VIEWPORT_OFFSET = 10;
2096
2097
    /**
2098
    * Constant representing the top left corner of an element, used for 
2099
    * configuring the context element alignment
2100
    * @property YAHOO.widget.Overlay.TOP_LEFT
2101
    * @static
2102
    * @final
2103
    * @type String
2104
    */
2105
    Overlay.TOP_LEFT = "tl";
2106
2107
    /**
2108
    * Constant representing the top right corner of an element, used for 
2109
    * configuring the context element alignment
2110
    * @property YAHOO.widget.Overlay.TOP_RIGHT
2111
    * @static
2112
    * @final
2113
    * @type String
2114
    */
2115
    Overlay.TOP_RIGHT = "tr";
2116
2117
    /**
2118
    * Constant representing the top bottom left corner of an element, used for 
2119
    * configuring the context element alignment
2120
    * @property YAHOO.widget.Overlay.BOTTOM_LEFT
2121
    * @static
2122
    * @final
2123
    * @type String
2124
    */
2125
    Overlay.BOTTOM_LEFT = "bl";
2126
2127
    /**
2128
    * Constant representing the bottom right corner of an element, used for 
2129
    * configuring the context element alignment
2130
    * @property YAHOO.widget.Overlay.BOTTOM_RIGHT
2131
    * @static
2132
    * @final
2133
    * @type String
2134
    */
2135
    Overlay.BOTTOM_RIGHT = "br";
2136
2137
    Overlay.PREVENT_OVERLAP_X = {
2138
        "tltr": true,
2139
        "blbr": true,
2140
        "brbl": true,
2141
        "trtl": true
2142
    };
2143
            
2144
    Overlay.PREVENT_OVERLAP_Y = {
2145
        "trbr": true,
2146
        "tlbl": true,
2147
        "bltl": true,
2148
        "brtr": true
2149
    };
2150
2151
    /**
2152
    * Constant representing the default CSS class used for an Overlay
2153
    * @property YAHOO.widget.Overlay.CSS_OVERLAY
2154
    * @static
2155
    * @final
2156
    * @type String
2157
    */
2158
    Overlay.CSS_OVERLAY = "yui-overlay";
2159
2160
    /**
2161
    * Constant representing the default hidden CSS class used for an Overlay. This class is 
2162
    * applied to the overlay's outer DIV whenever it's hidden.
2163
    *
2164
    * @property YAHOO.widget.Overlay.CSS_HIDDEN
2165
    * @static
2166
    * @final
2167
    * @type String
2168
    */
2169
    Overlay.CSS_HIDDEN = "yui-overlay-hidden";
2170
2171
    /**
2172
    * Constant representing the default CSS class used for an Overlay iframe shim.
2173
    * 
2174
    * @property YAHOO.widget.Overlay.CSS_IFRAME
2175
    * @static
2176
    * @final
2177
    * @type String
2178
    */
2179
    Overlay.CSS_IFRAME = "yui-overlay-iframe";
2180
2181
    /**
2182
     * Constant representing the names of the standard module elements
2183
     * used in the overlay.
2184
     * @property YAHOO.widget.Overlay.STD_MOD_RE
2185
     * @static
2186
     * @final
2187
     * @type RegExp
2188
     */
2189
    Overlay.STD_MOD_RE = /^\s*?(body|footer|header)\s*?$/i;
2190
2191
    /**
2192
    * A singleton CustomEvent used for reacting to the DOM event for 
2193
    * window scroll
2194
    * @event YAHOO.widget.Overlay.windowScrollEvent
2195
    */
2196
    Overlay.windowScrollEvent = new CustomEvent("windowScroll");
2197
2198
    /**
2199
    * A singleton CustomEvent used for reacting to the DOM event for
2200
    * window resize
2201
    * @event YAHOO.widget.Overlay.windowResizeEvent
2202
    */
2203
    Overlay.windowResizeEvent = new CustomEvent("windowResize");
2204
2205
    /**
2206
    * The DOM event handler used to fire the CustomEvent for window scroll
2207
    * @method YAHOO.widget.Overlay.windowScrollHandler
2208
    * @static
2209
    * @param {DOMEvent} e The DOM scroll event
2210
    */
2211
    Overlay.windowScrollHandler = function (e) {
2212
        var t = Event.getTarget(e);
2213
2214
        // - Webkit (Safari 2/3) and Opera 9.2x bubble scroll events from elements to window
2215
        // - FF2/3 and IE6/7, Opera 9.5x don't bubble scroll events from elements to window
2216
        // - IE doesn't recognize scroll registered on the document.
2217
        //
2218
        // Also, when document view is scrolled, IE doesn't provide a target, 
2219
        // rest of the browsers set target to window.document, apart from opera 
2220
        // which sets target to window.
2221
        if (!t || t === window || t === window.document) {
2222
            if (UA.ie) {
2223
2224
                if (! window.scrollEnd) {
2225
                    window.scrollEnd = -1;
2226
                }
2227
2228
                clearTimeout(window.scrollEnd);
2229
        
2230
                window.scrollEnd = setTimeout(function () { 
2231
                    Overlay.windowScrollEvent.fire(); 
2232
                }, 1);
2233
        
2234
            } else {
2235
                Overlay.windowScrollEvent.fire();
2236
            }
2237
        }
2238
    };
2239
2240
    /**
2241
    * The DOM event handler used to fire the CustomEvent for window resize
2242
    * @method YAHOO.widget.Overlay.windowResizeHandler
2243
    * @static
2244
    * @param {DOMEvent} e The DOM resize event
2245
    */
2246
    Overlay.windowResizeHandler = function (e) {
2247
2248
        if (UA.ie) {
2249
            if (! window.resizeEnd) {
2250
                window.resizeEnd = -1;
2251
            }
2252
2253
            clearTimeout(window.resizeEnd);
2254
2255
            window.resizeEnd = setTimeout(function () {
2256
                Overlay.windowResizeEvent.fire(); 
2257
            }, 100);
2258
        } else {
2259
            Overlay.windowResizeEvent.fire();
2260
        }
2261
    };
2262
2263
    /**
2264
    * A boolean that indicated whether the window resize and scroll events have 
2265
    * already been subscribed to.
2266
    * @property YAHOO.widget.Overlay._initialized
2267
    * @private
2268
    * @type Boolean
2269
    */
2270
    Overlay._initialized = null;
2271
2272
    if (Overlay._initialized === null) {
2273
        Event.on(window, "scroll", Overlay.windowScrollHandler);
2274
        Event.on(window, "resize", Overlay.windowResizeHandler);
2275
        Overlay._initialized = true;
2276
    }
2277
2278
    /**
2279
     * Internal map of special event types, which are provided
2280
     * by the instance. It maps the event type to the custom event 
2281
     * instance. Contains entries for the "windowScroll", "windowResize" and
2282
     * "textResize" static container events.
2283
     *
2284
     * @property YAHOO.widget.Overlay._TRIGGER_MAP
2285
     * @type Object
2286
     * @static
2287
     * @private
2288
     */
2289
    Overlay._TRIGGER_MAP = {
2290
        "windowScroll" : Overlay.windowScrollEvent,
2291
        "windowResize" : Overlay.windowResizeEvent,
2292
        "textResize"   : Module.textResizeEvent
2293
    };
2294
2295
    YAHOO.extend(Overlay, Module, {
2296
2297
        /**
2298
         * <p>
2299
         * Array of default event types which will trigger
2300
         * context alignment for the Overlay class.
2301
         * </p>
2302
         * <p>The array is empty by default for Overlay,
2303
         * but maybe populated in future releases, so classes extending
2304
         * Overlay which need to define their own set of CONTEXT_TRIGGERS
2305
         * should concatenate their super class's prototype.CONTEXT_TRIGGERS 
2306
         * value with their own array of values.
2307
         * </p>
2308
         * <p>
2309
         * E.g.:
2310
         * <code>CustomOverlay.prototype.CONTEXT_TRIGGERS = YAHOO.widget.Overlay.prototype.CONTEXT_TRIGGERS.concat(["windowScroll"]);</code>
2311
         * </p>
2312
         * 
2313
         * @property CONTEXT_TRIGGERS
2314
         * @type Array
2315
         * @final
2316
         */
2317
        CONTEXT_TRIGGERS : [],
2318
2319
        /**
2320
        * The Overlay initialization method, which is executed for Overlay and  
2321
        * all of its subclasses. This method is automatically called by the 
2322
        * constructor, and  sets up all DOM references for pre-existing markup, 
2323
        * and creates required markup if it is not already present.
2324
        * @method init
2325
        * @param {String} el The element ID representing the Overlay <em>OR</em>
2326
        * @param {HTMLElement} el The element representing the Overlay
2327
        * @param {Object} userConfig The configuration object literal 
2328
        * containing the configuration that should be set for this Overlay. 
2329
        * See configuration documentation for more details.
2330
        */
2331
        init: function (el, userConfig) {
2332
2333
            /*
2334
                 Note that we don't pass the user config in here yet because we
2335
                 only want it executed once, at the lowest subclass level
2336
            */
2337
2338
            Overlay.superclass.init.call(this, el/*, userConfig*/);
2339
2340
            this.beforeInitEvent.fire(Overlay);
2341
2342
            Dom.addClass(this.element, Overlay.CSS_OVERLAY);
2343
2344
            if (userConfig) {
2345
                this.cfg.applyConfig(userConfig, true);
2346
            }
2347
2348
            if (this.platform == "mac" && UA.gecko) {
2349
2350
                if (! Config.alreadySubscribed(this.showEvent,
2351
                    this.showMacGeckoScrollbars, this)) {
2352
2353
                    this.showEvent.subscribe(this.showMacGeckoScrollbars, 
2354
                        this, true);
2355
2356
                }
2357
2358
                if (! Config.alreadySubscribed(this.hideEvent, 
2359
                    this.hideMacGeckoScrollbars, this)) {
2360
2361
                    this.hideEvent.subscribe(this.hideMacGeckoScrollbars, 
2362
                        this, true);
2363
2364
                }
2365
            }
2366
2367
            this.initEvent.fire(Overlay);
2368
        },
2369
        
2370
        /**
2371
        * Initializes the custom events for Overlay which are fired  
2372
        * automatically at appropriate times by the Overlay class.
2373
        * @method initEvents
2374
        */
2375
        initEvents: function () {
2376
2377
            Overlay.superclass.initEvents.call(this);
2378
2379
            var SIGNATURE = CustomEvent.LIST;
2380
2381
            /**
2382
            * CustomEvent fired before the Overlay is moved.
2383
            * @event beforeMoveEvent
2384
            * @param {Number} x x coordinate
2385
            * @param {Number} y y coordinate
2386
            */
2387
            this.beforeMoveEvent = this.createEvent(EVENT_TYPES.BEFORE_MOVE);
2388
            this.beforeMoveEvent.signature = SIGNATURE;
2389
2390
            /**
2391
            * CustomEvent fired after the Overlay is moved.
2392
            * @event moveEvent
2393
            * @param {Number} x x coordinate
2394
            * @param {Number} y y coordinate
2395
            */
2396
            this.moveEvent = this.createEvent(EVENT_TYPES.MOVE);
2397
            this.moveEvent.signature = SIGNATURE;
2398
2399
        },
2400
        
2401
        /**
2402
        * Initializes the class's configurable properties which can be changed 
2403
        * using the Overlay's Config object (cfg).
2404
        * @method initDefaultConfig
2405
        */
2406
        initDefaultConfig: function () {
2407
    
2408
            Overlay.superclass.initDefaultConfig.call(this);
2409
2410
            var cfg = this.cfg;
2411
2412
            // Add overlay config properties //
2413
            
2414
            /**
2415
            * The absolute x-coordinate position of the Overlay
2416
            * @config x
2417
            * @type Number
2418
            * @default null
2419
            */
2420
            cfg.addProperty(DEFAULT_CONFIG.X.key, { 
2421
    
2422
                handler: this.configX, 
2423
                validator: DEFAULT_CONFIG.X.validator, 
2424
                suppressEvent: DEFAULT_CONFIG.X.suppressEvent, 
2425
                supercedes: DEFAULT_CONFIG.X.supercedes
2426
    
2427
            });
2428
2429
            /**
2430
            * The absolute y-coordinate position of the Overlay
2431
            * @config y
2432
            * @type Number
2433
            * @default null
2434
            */
2435
            cfg.addProperty(DEFAULT_CONFIG.Y.key, {
2436
2437
                handler: this.configY, 
2438
                validator: DEFAULT_CONFIG.Y.validator, 
2439
                suppressEvent: DEFAULT_CONFIG.Y.suppressEvent, 
2440
                supercedes: DEFAULT_CONFIG.Y.supercedes
2441
2442
            });
2443
2444
            /**
2445
            * An array with the absolute x and y positions of the Overlay
2446
            * @config xy
2447
            * @type Number[]
2448
            * @default null
2449
            */
2450
            cfg.addProperty(DEFAULT_CONFIG.XY.key, {
2451
                handler: this.configXY, 
2452
                suppressEvent: DEFAULT_CONFIG.XY.suppressEvent, 
2453
                supercedes: DEFAULT_CONFIG.XY.supercedes
2454
            });
2455
2456
            /**
2457
            * <p>
2458
            * The array of context arguments for context-sensitive positioning. 
2459
            * </p>
2460
            *
2461
            * <p>
2462
            * The format of the array is: <code>[contextElementOrId, overlayCorner, contextCorner, arrayOfTriggerEvents (optional), xyOffset (optional)]</code>, the
2463
            * the 5 array elements described in detail below:
2464
            * </p>
2465
            *
2466
            * <dl>
2467
            * <dt>contextElementOrId &#60;String|HTMLElement&#62;</dt>
2468
            * <dd>A reference to the context element to which the overlay should be aligned (or it's id).</dd>
2469
            * <dt>overlayCorner &#60;String&#62;</dt>
2470
            * <dd>The corner of the overlay which is to be used for alignment. This corner will be aligned to the 
2471
            * corner of the context element defined by the "contextCorner" entry which follows. Supported string values are: 
2472
            * "tr" (top right), "tl" (top left), "br" (bottom right), or "bl" (bottom left).</dd>
2473
            * <dt>contextCorner &#60;String&#62;</dt>
2474
            * <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>
2475
            * <dt>arrayOfTriggerEvents (optional) &#60;Array[String|CustomEvent]&#62;</dt>
2476
            * <dd>
2477
            * <p>
2478
            * 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> 
2479
            * 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. 
2480
            * This is useful in situations where the layout of the document may change, resulting in the context element's position being modified.
2481
            * </p>
2482
            * <p>
2483
            * The array can contain either event type strings for events the instance publishes (e.g. "beforeShow") or CustomEvent instances. Additionally the following
2484
            * 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).
2485
            * </p>
2486
            * </dd>
2487
            * <dt>xyOffset &#60;Number[]&#62;</dt>
2488
            * <dd>
2489
            * A 2 element Array specifying the X and Y pixel amounts by which the Overlay should be offset from the aligned corner. e.g. [5,0] offsets the Overlay 5 pixels to the left, <em>after</em> aligning the given context corners.
2490
            * NOTE: If using this property and no triggers need to be defined, the arrayOfTriggerEvents property should be set to null to maintain correct array positions for the arguments. 
2491
            * </dd>
2492
            * </dl>
2493
            *
2494
            * <p>
2495
            * For example, setting this property to <code>["img1", "tl", "bl"]</code> will 
2496
            * align the Overlay's top left corner to the bottom left corner of the
2497
            * context element with id "img1".
2498
            * </p>
2499
            * <p>
2500
            * Setting this property to <code>["img1", "tl", "bl", null, [0,5]</code> will 
2501
            * align the Overlay's top left corner to the bottom left corner of the
2502
            * context element with id "img1", and then offset it by 5 pixels on the Y axis (providing a 5 pixel gap between the bottom of the context element and top of the overlay).
2503
            * </p>
2504
            * <p>
2505
            * Adding the optional trigger values: <code>["img1", "tl", "bl", ["beforeShow", "windowResize"], [0,5]]</code>,
2506
            * will re-align the overlay position, whenever the "beforeShow" or "windowResize" events are fired.
2507
            * </p>
2508
            *
2509
            * @config context
2510
            * @type Array
2511
            * @default null
2512
            */
2513
            cfg.addProperty(DEFAULT_CONFIG.CONTEXT.key, {
2514
                handler: this.configContext, 
2515
                suppressEvent: DEFAULT_CONFIG.CONTEXT.suppressEvent, 
2516
                supercedes: DEFAULT_CONFIG.CONTEXT.supercedes
2517
            });
2518
2519
            /**
2520
            * Determines whether or not the Overlay should be anchored 
2521
            * to the center of the viewport.
2522
            * 
2523
            * <p>This property can be set to:</p>
2524
            * 
2525
            * <dl>
2526
            * <dt>true</dt>
2527
            * <dd>
2528
            * To enable fixed center positioning
2529
            * <p>
2530
            * When enabled, the overlay will 
2531
            * be positioned in the center of viewport when initially displayed, and 
2532
            * will remain in the center of the viewport whenever the window is 
2533
            * scrolled or resized.
2534
            * </p>
2535
            * <p>
2536
            * If the overlay is too big for the viewport, 
2537
            * it's top left corner will be aligned with the top left corner of the viewport.
2538
            * </p>
2539
            * </dd>
2540
            * <dt>false</dt>
2541
            * <dd>
2542
            * To disable fixed center positioning.
2543
            * <p>In this case the overlay can still be 
2544
            * centered as a one-off operation, by invoking the <code>center()</code> method,
2545
            * however it will not remain centered when the window is scrolled/resized.
2546
            * </dd>
2547
            * <dt>"contained"<dt>
2548
            * <dd>To enable fixed center positioning, as with the <code>true</code> option.
2549
            * <p>However, unlike setting the property to <code>true</code>, 
2550
            * when the property is set to <code>"contained"</code>, if the overlay is 
2551
            * too big for the viewport, it will not get automatically centered when the 
2552
            * user scrolls or resizes the window (until the window is large enough to contain the 
2553
            * overlay). This is useful in cases where the Overlay has both header and footer 
2554
            * UI controls which the user may need to access.
2555
            * </p>
2556
            * </dd>
2557
            * </dl>
2558
            *
2559
            * @config fixedcenter
2560
            * @type Boolean | String
2561
            * @default false
2562
            */
2563
            cfg.addProperty(DEFAULT_CONFIG.FIXED_CENTER.key, {
2564
                handler: this.configFixedCenter,
2565
                value: DEFAULT_CONFIG.FIXED_CENTER.value, 
2566
                validator: DEFAULT_CONFIG.FIXED_CENTER.validator, 
2567
                supercedes: DEFAULT_CONFIG.FIXED_CENTER.supercedes
2568
            });
2569
    
2570
            /**
2571
            * CSS width of the Overlay.
2572
            * @config width
2573
            * @type String
2574
            * @default null
2575
            */
2576
            cfg.addProperty(DEFAULT_CONFIG.WIDTH.key, {
2577
                handler: this.configWidth, 
2578
                suppressEvent: DEFAULT_CONFIG.WIDTH.suppressEvent, 
2579
                supercedes: DEFAULT_CONFIG.WIDTH.supercedes
2580
            });
2581
2582
            /**
2583
            * CSS height of the Overlay.
2584
            * @config height
2585
            * @type String
2586
            * @default null
2587
            */
2588
            cfg.addProperty(DEFAULT_CONFIG.HEIGHT.key, {
2589
                handler: this.configHeight, 
2590
                suppressEvent: DEFAULT_CONFIG.HEIGHT.suppressEvent, 
2591
                supercedes: DEFAULT_CONFIG.HEIGHT.supercedes
2592
            });
2593
2594
            /**
2595
            * Standard module element which should auto fill out the height of the Overlay if the height config property is set.
2596
            * Supported values are "header", "body", "footer".
2597
            *
2598
            * @config autofillheight
2599
            * @type String
2600
            * @default null
2601
            */
2602
            cfg.addProperty(DEFAULT_CONFIG.AUTO_FILL_HEIGHT.key, {
2603
                handler: this.configAutoFillHeight, 
2604
                value : DEFAULT_CONFIG.AUTO_FILL_HEIGHT.value,
2605
                validator : this._validateAutoFill,
2606
                supercedes: DEFAULT_CONFIG.AUTO_FILL_HEIGHT.supercedes
2607
            });
2608
2609
            /**
2610
            * CSS z-index of the Overlay.
2611
            * @config zIndex
2612
            * @type Number
2613
            * @default null
2614
            */
2615
            cfg.addProperty(DEFAULT_CONFIG.ZINDEX.key, {
2616
                handler: this.configzIndex,
2617
                value: DEFAULT_CONFIG.ZINDEX.value
2618
            });
2619
2620
            /**
2621
            * True if the Overlay should be prevented from being positioned 
2622
            * out of the viewport.
2623
            * @config constraintoviewport
2624
            * @type Boolean
2625
            * @default false
2626
            */
2627
            cfg.addProperty(DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.key, {
2628
2629
                handler: this.configConstrainToViewport, 
2630
                value: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.value, 
2631
                validator: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.validator, 
2632
                supercedes: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.supercedes
2633
2634
            });
2635
2636
            /**
2637
            * @config iframe
2638
            * @description Boolean indicating whether or not the Overlay should 
2639
            * have an IFRAME shim; used to prevent SELECT elements from 
2640
            * poking through an Overlay instance in IE6.  When set to "true", 
2641
            * the iframe shim is created when the Overlay instance is intially
2642
            * made visible.
2643
            * @type Boolean
2644
            * @default true for IE6 and below, false for all other browsers.
2645
            */
2646
            cfg.addProperty(DEFAULT_CONFIG.IFRAME.key, {
2647
2648
                handler: this.configIframe, 
2649
                value: DEFAULT_CONFIG.IFRAME.value, 
2650
                validator: DEFAULT_CONFIG.IFRAME.validator, 
2651
                supercedes: DEFAULT_CONFIG.IFRAME.supercedes
2652
2653
            });
2654
2655
            /**
2656
            * @config preventcontextoverlap
2657
            * @description Boolean indicating whether or not the Overlay should overlap its 
2658
            * context element (defined using the "context" configuration property) when the 
2659
            * "constraintoviewport" configuration property is set to "true".
2660
            * @type Boolean
2661
            * @default false
2662
            */
2663
            cfg.addProperty(DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.key, {
2664
                value: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.value, 
2665
                validator: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.validator, 
2666
                supercedes: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.supercedes
2667
            });
2668
        },
2669
2670
        /**
2671
        * Moves the Overlay to the specified position. This function is  
2672
        * identical to calling this.cfg.setProperty("xy", [x,y]);
2673
        * @method moveTo
2674
        * @param {Number} x The Overlay's new x position
2675
        * @param {Number} y The Overlay's new y position
2676
        */
2677
        moveTo: function (x, y) {
2678
            this.cfg.setProperty("xy", [x, y]);
2679
        },
2680
2681
        /**
2682
        * Adds a CSS class ("hide-scrollbars") and removes a CSS class 
2683
        * ("show-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
2684
        * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2685
        * @method hideMacGeckoScrollbars
2686
        */
2687
        hideMacGeckoScrollbars: function () {
2688
            Dom.replaceClass(this.element, "show-scrollbars", "hide-scrollbars");
2689
        },
2690
2691
        /**
2692
        * Adds a CSS class ("show-scrollbars") and removes a CSS class 
2693
        * ("hide-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
2694
        * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2695
        * @method showMacGeckoScrollbars
2696
        */
2697
        showMacGeckoScrollbars: function () {
2698
            Dom.replaceClass(this.element, "hide-scrollbars", "show-scrollbars");
2699
        },
2700
2701
        /**
2702
         * Internal implementation to set the visibility of the overlay in the DOM.
2703
         *
2704
         * @method _setDomVisibility
2705
         * @param {boolean} visible Whether to show or hide the Overlay's outer element
2706
         * @protected
2707
         */
2708
        _setDomVisibility : function(show) {
2709
            Dom.setStyle(this.element, "visibility", (show) ? "visible" : "hidden");
2710
            var hiddenClass = Overlay.CSS_HIDDEN;
2711
2712
            if (show) {
2713
                Dom.removeClass(this.element, hiddenClass);
2714
            } else {
2715
                Dom.addClass(this.element, hiddenClass);
2716
            }
2717
        },
2718
2719
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
2720
        /**
2721
        * The default event handler fired when the "visible" property is 
2722
        * changed.  This method is responsible for firing showEvent
2723
        * and hideEvent.
2724
        * @method configVisible
2725
        * @param {String} type The CustomEvent type (usually the property name)
2726
        * @param {Object[]} args The CustomEvent arguments. For configuration
2727
        * handlers, args[0] will equal the newly applied value for the property.
2728
        * @param {Object} obj The scope object. For configuration handlers, 
2729
        * this will usually equal the owner.
2730
        */
2731
        configVisible: function (type, args, obj) {
2732
2733
            var visible = args[0],
2734
                currentVis = Dom.getStyle(this.element, "visibility"),
2735
                effect = this.cfg.getProperty("effect"),
2736
                effectInstances = [],
2737
                isMacGecko = (this.platform == "mac" && UA.gecko),
2738
                alreadySubscribed = Config.alreadySubscribed,
2739
                eff, ei, e, i, j, k, h,
2740
                nEffects,
2741
                nEffectInstances;
2742
2743
            if (currentVis == "inherit") {
2744
                e = this.element.parentNode;
2745
2746
                while (e.nodeType != 9 && e.nodeType != 11) {
2747
                    currentVis = Dom.getStyle(e, "visibility");
2748
2749
                    if (currentVis != "inherit") {
2750
                        break;
2751
                    }
2752
2753
                    e = e.parentNode;
2754
                }
2755
2756
                if (currentVis == "inherit") {
2757
                    currentVis = "visible";
2758
                }
2759
            }
2760
2761
            if (effect) {
2762
                if (effect instanceof Array) {
2763
                    nEffects = effect.length;
2764
2765
                    for (i = 0; i < nEffects; i++) {
2766
                        eff = effect[i];
2767
                        effectInstances[effectInstances.length] = 
2768
                            eff.effect(this, eff.duration);
2769
2770
                    }
2771
                } else {
2772
                    effectInstances[effectInstances.length] = 
2773
                        effect.effect(this, effect.duration);
2774
                }
2775
            }
2776
2777
            if (visible) { // Show
2778
                if (isMacGecko) {
2779
                    this.showMacGeckoScrollbars();
2780
                }
2781
2782
                if (effect) { // Animate in
2783
                    if (visible) { // Animate in if not showing
2784
                        if (currentVis != "visible" || currentVis === "") {
2785
                            this.beforeShowEvent.fire();
2786
                            nEffectInstances = effectInstances.length;
2787
2788
                            for (j = 0; j < nEffectInstances; j++) {
2789
                                ei = effectInstances[j];
2790
                                if (j === 0 && !alreadySubscribed(
2791
                                        ei.animateInCompleteEvent, 
2792
                                        this.showEvent.fire, this.showEvent)) {
2793
2794
                                    /*
2795
                                         Delegate showEvent until end 
2796
                                         of animateInComplete
2797
                                    */
2798
2799
                                    ei.animateInCompleteEvent.subscribe(
2800
                                     this.showEvent.fire, this.showEvent, true);
2801
                                }
2802
                                ei.animateIn();
2803
                            }
2804
                        }
2805
                    }
2806
                } else { // Show
2807
                    if (currentVis != "visible" || currentVis === "") {
2808
                        this.beforeShowEvent.fire();
2809
2810
                        this._setDomVisibility(true);
2811
2812
                        this.cfg.refireEvent("iframe");
2813
                        this.showEvent.fire();
2814
                    } else {
2815
                        this._setDomVisibility(true);
2816
                    }
2817
                }
2818
            } else { // Hide
2819
2820
                if (isMacGecko) {
2821
                    this.hideMacGeckoScrollbars();
2822
                }
2823
2824
                if (effect) { // Animate out if showing
2825
                    if (currentVis == "visible") {
2826
                        this.beforeHideEvent.fire();
2827
2828
                        nEffectInstances = effectInstances.length;
2829
                        for (k = 0; k < nEffectInstances; k++) {
2830
                            h = effectInstances[k];
2831
    
2832
                            if (k === 0 && !alreadySubscribed(
2833
                                h.animateOutCompleteEvent, this.hideEvent.fire, 
2834
                                this.hideEvent)) {
2835
    
2836
                                /*
2837
                                     Delegate hideEvent until end 
2838
                                     of animateOutComplete
2839
                                */
2840
    
2841
                                h.animateOutCompleteEvent.subscribe(
2842
                                    this.hideEvent.fire, this.hideEvent, true);
2843
    
2844
                            }
2845
                            h.animateOut();
2846
                        }
2847
2848
                    } else if (currentVis === "") {
2849
                        this._setDomVisibility(false);
2850
                    }
2851
2852
                } else { // Simple hide
2853
2854
                    if (currentVis == "visible" || currentVis === "") {
2855
                        this.beforeHideEvent.fire();
2856
                        this._setDomVisibility(false);
2857
                        this.hideEvent.fire();
2858
                    } else {
2859
                        this._setDomVisibility(false);
2860
                    }
2861
                }
2862
            }
2863
        },
2864
2865
        /**
2866
        * Fixed center event handler used for centering on scroll/resize, but only if 
2867
        * the overlay is visible and, if "fixedcenter" is set to "contained", only if 
2868
        * the overlay fits within the viewport.
2869
        *
2870
        * @method doCenterOnDOMEvent
2871
        */
2872
        doCenterOnDOMEvent: function () {
2873
            var cfg = this.cfg,
2874
                fc = cfg.getProperty("fixedcenter");
2875
2876
            if (cfg.getProperty("visible")) {
2877
                if (fc && (fc !== _CONTAINED || this.fitsInViewport())) {
2878
                    this.center();
2879
                }
2880
            }
2881
        },
2882
2883
        /**
2884
         * Determines if the Overlay (including the offset value defined by Overlay.VIEWPORT_OFFSET) 
2885
         * will fit entirely inside the viewport, in both dimensions - width and height.
2886
         * 
2887
         * @method fitsInViewport
2888
         * @return boolean true if the Overlay will fit, false if not
2889
         */
2890
        fitsInViewport : function() {
2891
            var nViewportOffset = Overlay.VIEWPORT_OFFSET,
2892
                element = this.element,
2893
                elementWidth = element.offsetWidth,
2894
                elementHeight = element.offsetHeight,
2895
                viewportWidth = Dom.getViewportWidth(),
2896
                viewportHeight = Dom.getViewportHeight();
2897
2898
            return ((elementWidth + nViewportOffset < viewportWidth) && (elementHeight + nViewportOffset < viewportHeight));
2899
        },
2900
2901
        /**
2902
        * The default event handler fired when the "fixedcenter" property 
2903
        * is changed.
2904
        * @method configFixedCenter
2905
        * @param {String} type The CustomEvent type (usually the property name)
2906
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2907
        * handlers, args[0] will equal the newly applied value for the property.
2908
        * @param {Object} obj The scope object. For configuration handlers, 
2909
        * this will usually equal the owner.
2910
        */
2911
        configFixedCenter: function (type, args, obj) {
2912
2913
            var val = args[0],
2914
                alreadySubscribed = Config.alreadySubscribed,
2915
                windowResizeEvent = Overlay.windowResizeEvent,
2916
                windowScrollEvent = Overlay.windowScrollEvent;
2917
2918
            if (val) {
2919
                this.center();
2920
2921
                if (!alreadySubscribed(this.beforeShowEvent, this.center)) {
2922
                    this.beforeShowEvent.subscribe(this.center);
2923
                }
2924
2925
                if (!alreadySubscribed(windowResizeEvent, this.doCenterOnDOMEvent, this)) {
2926
                    windowResizeEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2927
                }
2928
2929
                if (!alreadySubscribed(windowScrollEvent, this.doCenterOnDOMEvent, this)) {
2930
                    windowScrollEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2931
                }
2932
2933
            } else {
2934
                this.beforeShowEvent.unsubscribe(this.center);
2935
2936
                windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2937
                windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2938
            }
2939
        },
2940
2941
        /**
2942
        * The default event handler fired when the "height" property is changed.
2943
        * @method configHeight
2944
        * @param {String} type The CustomEvent type (usually the property name)
2945
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2946
        * handlers, args[0] will equal the newly applied value for the property.
2947
        * @param {Object} obj The scope object. For configuration handlers, 
2948
        * this will usually equal the owner.
2949
        */
2950
        configHeight: function (type, args, obj) {
2951
2952
            var height = args[0],
2953
                el = this.element;
2954
2955
            Dom.setStyle(el, "height", height);
2956
            this.cfg.refireEvent("iframe");
2957
        },
2958
2959
        /**
2960
         * The default event handler fired when the "autofillheight" property is changed.
2961
         * @method configAutoFillHeight
2962
         *
2963
         * @param {String} type The CustomEvent type (usually the property name)
2964
         * @param {Object[]} args The CustomEvent arguments. For configuration 
2965
         * handlers, args[0] will equal the newly applied value for the property.
2966
         * @param {Object} obj The scope object. For configuration handlers, 
2967
         * this will usually equal the owner.
2968
         */
2969
        configAutoFillHeight: function (type, args, obj) {
2970
            var fillEl = args[0],
2971
                cfg = this.cfg,
2972
                autoFillHeight = "autofillheight",
2973
                height = "height",
2974
                currEl = cfg.getProperty(autoFillHeight),
2975
                autoFill = this._autoFillOnHeightChange;
2976
2977
            cfg.unsubscribeFromConfigEvent(height, autoFill);
2978
            Module.textResizeEvent.unsubscribe(autoFill);
2979
            this.changeContentEvent.unsubscribe(autoFill);
2980
2981
            if (currEl && fillEl !== currEl && this[currEl]) {
2982
                Dom.setStyle(this[currEl], height, "");
2983
            }
2984
2985
            if (fillEl) {
2986
                fillEl = Lang.trim(fillEl.toLowerCase());
2987
2988
                cfg.subscribeToConfigEvent(height, autoFill, this[fillEl], this);
2989
                Module.textResizeEvent.subscribe(autoFill, this[fillEl], this);
2990
                this.changeContentEvent.subscribe(autoFill, this[fillEl], this);
2991
2992
                cfg.setProperty(autoFillHeight, fillEl, true);
2993
            }
2994
        },
2995
2996
        /**
2997
        * The default event handler fired when the "width" property is changed.
2998
        * @method configWidth
2999
        * @param {String} type The CustomEvent type (usually the property name)
3000
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3001
        * handlers, args[0] will equal the newly applied value for the property.
3002
        * @param {Object} obj The scope object. For configuration handlers, 
3003
        * this will usually equal the owner.
3004
        */
3005
        configWidth: function (type, args, obj) {
3006
3007
            var width = args[0],
3008
                el = this.element;
3009
3010
            Dom.setStyle(el, "width", width);
3011
            this.cfg.refireEvent("iframe");
3012
        },
3013
3014
        /**
3015
        * The default event handler fired when the "zIndex" property is changed.
3016
        * @method configzIndex
3017
        * @param {String} type The CustomEvent type (usually the property name)
3018
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3019
        * handlers, args[0] will equal the newly applied value for the property.
3020
        * @param {Object} obj The scope object. For configuration handlers, 
3021
        * this will usually equal the owner.
3022
        */
3023
        configzIndex: function (type, args, obj) {
3024
3025
            var zIndex = args[0],
3026
                el = this.element;
3027
3028
            if (! zIndex) {
3029
                zIndex = Dom.getStyle(el, "zIndex");
3030
                if (! zIndex || isNaN(zIndex)) {
3031
                    zIndex = 0;
3032
                }
3033
            }
3034
3035
            if (this.iframe || this.cfg.getProperty("iframe") === true) {
3036
                if (zIndex <= 0) {
3037
                    zIndex = 1;
3038
                }
3039
            }
3040
3041
            Dom.setStyle(el, "zIndex", zIndex);
3042
            this.cfg.setProperty("zIndex", zIndex, true);
3043
3044
            if (this.iframe) {
3045
                this.stackIframe();
3046
            }
3047
        },
3048
3049
        /**
3050
        * The default event handler fired when the "xy" property is changed.
3051
        * @method configXY
3052
        * @param {String} type The CustomEvent type (usually the property name)
3053
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3054
        * handlers, args[0] will equal the newly applied value for the property.
3055
        * @param {Object} obj The scope object. For configuration handlers, 
3056
        * this will usually equal the owner.
3057
        */
3058
        configXY: function (type, args, obj) {
3059
3060
            var pos = args[0],
3061
                x = pos[0],
3062
                y = pos[1];
3063
3064
            this.cfg.setProperty("x", x);
3065
            this.cfg.setProperty("y", y);
3066
3067
            this.beforeMoveEvent.fire([x, y]);
3068
3069
            x = this.cfg.getProperty("x");
3070
            y = this.cfg.getProperty("y");
3071
3072
            YAHOO.log(("xy: " + [x, y]), "iframe");
3073
3074
            this.cfg.refireEvent("iframe");
3075
            this.moveEvent.fire([x, y]);
3076
        },
3077
3078
        /**
3079
        * The default event handler fired when the "x" property is changed.
3080
        * @method configX
3081
        * @param {String} type The CustomEvent type (usually the property name)
3082
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3083
        * handlers, args[0] will equal the newly applied value for the property.
3084
        * @param {Object} obj The scope object. For configuration handlers, 
3085
        * this will usually equal the owner.
3086
        */
3087
        configX: function (type, args, obj) {
3088
3089
            var x = args[0],
3090
                y = this.cfg.getProperty("y");
3091
3092
            this.cfg.setProperty("x", x, true);
3093
            this.cfg.setProperty("y", y, true);
3094
3095
            this.beforeMoveEvent.fire([x, y]);
3096
3097
            x = this.cfg.getProperty("x");
3098
            y = this.cfg.getProperty("y");
3099
3100
            Dom.setX(this.element, x, true);
3101
3102
            this.cfg.setProperty("xy", [x, y], true);
3103
3104
            this.cfg.refireEvent("iframe");
3105
            this.moveEvent.fire([x, y]);
3106
        },
3107
3108
        /**
3109
        * The default event handler fired when the "y" property is changed.
3110
        * @method configY
3111
        * @param {String} type The CustomEvent type (usually the property name)
3112
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3113
        * handlers, args[0] will equal the newly applied value for the property.
3114
        * @param {Object} obj The scope object. For configuration handlers, 
3115
        * this will usually equal the owner.
3116
        */
3117
        configY: function (type, args, obj) {
3118
3119
            var x = this.cfg.getProperty("x"),
3120
                y = args[0];
3121
3122
            this.cfg.setProperty("x", x, true);
3123
            this.cfg.setProperty("y", y, true);
3124
3125
            this.beforeMoveEvent.fire([x, y]);
3126
3127
            x = this.cfg.getProperty("x");
3128
            y = this.cfg.getProperty("y");
3129
3130
            Dom.setY(this.element, y, true);
3131
3132
            this.cfg.setProperty("xy", [x, y], true);
3133
3134
            this.cfg.refireEvent("iframe");
3135
            this.moveEvent.fire([x, y]);
3136
        },
3137
        
3138
        /**
3139
        * Shows the iframe shim, if it has been enabled.
3140
        * @method showIframe
3141
        */
3142
        showIframe: function () {
3143
3144
            var oIFrame = this.iframe,
3145
                oParentNode;
3146
3147
            if (oIFrame) {
3148
                oParentNode = this.element.parentNode;
3149
3150
                if (oParentNode != oIFrame.parentNode) {
3151
                    this._addToParent(oParentNode, oIFrame);
3152
                }
3153
                oIFrame.style.display = "block";
3154
            }
3155
        },
3156
3157
        /**
3158
        * Hides the iframe shim, if it has been enabled.
3159
        * @method hideIframe
3160
        */
3161
        hideIframe: function () {
3162
            if (this.iframe) {
3163
                this.iframe.style.display = "none";
3164
            }
3165
        },
3166
3167
        /**
3168
        * Syncronizes the size and position of iframe shim to that of its 
3169
        * corresponding Overlay instance.
3170
        * @method syncIframe
3171
        */
3172
        syncIframe: function () {
3173
3174
            var oIFrame = this.iframe,
3175
                oElement = this.element,
3176
                nOffset = Overlay.IFRAME_OFFSET,
3177
                nDimensionOffset = (nOffset * 2),
3178
                aXY;
3179
3180
            if (oIFrame) {
3181
                // Size <iframe>
3182
                oIFrame.style.width = (oElement.offsetWidth + nDimensionOffset + "px");
3183
                oIFrame.style.height = (oElement.offsetHeight + nDimensionOffset + "px");
3184
3185
                // Position <iframe>
3186
                aXY = this.cfg.getProperty("xy");
3187
3188
                if (!Lang.isArray(aXY) || (isNaN(aXY[0]) || isNaN(aXY[1]))) {
3189
                    this.syncPosition();
3190
                    aXY = this.cfg.getProperty("xy");
3191
                }
3192
                Dom.setXY(oIFrame, [(aXY[0] - nOffset), (aXY[1] - nOffset)]);
3193
            }
3194
        },
3195
3196
        /**
3197
         * Sets the zindex of the iframe shim, if it exists, based on the zindex of
3198
         * the Overlay element. The zindex of the iframe is set to be one less 
3199
         * than the Overlay element's zindex.
3200
         * 
3201
         * <p>NOTE: This method will not bump up the zindex of the Overlay element
3202
         * to ensure that the iframe shim has a non-negative zindex.
3203
         * If you require the iframe zindex to be 0 or higher, the zindex of 
3204
         * the Overlay element should be set to a value greater than 0, before 
3205
         * this method is called.
3206
         * </p>
3207
         * @method stackIframe
3208
         */
3209
        stackIframe: function () {
3210
            if (this.iframe) {
3211
                var overlayZ = Dom.getStyle(this.element, "zIndex");
3212
                if (!YAHOO.lang.isUndefined(overlayZ) && !isNaN(overlayZ)) {
3213
                    Dom.setStyle(this.iframe, "zIndex", (overlayZ - 1));
3214
                }
3215
            }
3216
        },
3217
3218
        /**
3219
        * The default event handler fired when the "iframe" property is changed.
3220
        * @method configIframe
3221
        * @param {String} type The CustomEvent type (usually the property name)
3222
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3223
        * handlers, args[0] will equal the newly applied value for the property.
3224
        * @param {Object} obj The scope object. For configuration handlers, 
3225
        * this will usually equal the owner.
3226
        */
3227
        configIframe: function (type, args, obj) {
3228
3229
            var bIFrame = args[0];
3230
3231
            function createIFrame() {
3232
3233
                var oIFrame = this.iframe,
3234
                    oElement = this.element,
3235
                    oParent;
3236
3237
                if (!oIFrame) {
3238
                    if (!m_oIFrameTemplate) {
3239
                        m_oIFrameTemplate = document.createElement("iframe");
3240
3241
                        if (this.isSecure) {
3242
                            m_oIFrameTemplate.src = Overlay.IFRAME_SRC;
3243
                        }
3244
3245
                        /*
3246
                            Set the opacity of the <iframe> to 0 so that it 
3247
                            doesn't modify the opacity of any transparent 
3248
                            elements that may be on top of it (like a shadow).
3249
                        */
3250
                        if (UA.ie) {
3251
                            m_oIFrameTemplate.style.filter = "alpha(opacity=0)";
3252
                            /*
3253
                                 Need to set the "frameBorder" property to 0 
3254
                                 supress the default <iframe> border in IE.  
3255
                                 Setting the CSS "border" property alone 
3256
                                 doesn't supress it.
3257
                            */
3258
                            m_oIFrameTemplate.frameBorder = 0;
3259
                        }
3260
                        else {
3261
                            m_oIFrameTemplate.style.opacity = "0";
3262
                        }
3263
3264
                        m_oIFrameTemplate.style.position = "absolute";
3265
                        m_oIFrameTemplate.style.border = "none";
3266
                        m_oIFrameTemplate.style.margin = "0";
3267
                        m_oIFrameTemplate.style.padding = "0";
3268
                        m_oIFrameTemplate.style.display = "none";
3269
                        m_oIFrameTemplate.tabIndex = -1;
3270
                        m_oIFrameTemplate.className = Overlay.CSS_IFRAME;
3271
                    }
3272
3273
                    oIFrame = m_oIFrameTemplate.cloneNode(false);
3274
                    oIFrame.id = this.id + "_f";
3275
                    oParent = oElement.parentNode;
3276
3277
                    var parentNode = oParent || document.body;
3278
3279
                    this._addToParent(parentNode, oIFrame);
3280
                    this.iframe = oIFrame;
3281
                }
3282
3283
                /*
3284
                     Show the <iframe> before positioning it since the "setXY" 
3285
                     method of DOM requires the element be in the document 
3286
                     and visible.
3287
                */
3288
                this.showIframe();
3289
3290
                /*
3291
                     Syncronize the size and position of the <iframe> to that 
3292
                     of the Overlay.
3293
                */
3294
                this.syncIframe();
3295
                this.stackIframe();
3296
3297
                // Add event listeners to update the <iframe> when necessary
3298
                if (!this._hasIframeEventListeners) {
3299
                    this.showEvent.subscribe(this.showIframe);
3300
                    this.hideEvent.subscribe(this.hideIframe);
3301
                    this.changeContentEvent.subscribe(this.syncIframe);
3302
3303
                    this._hasIframeEventListeners = true;
3304
                }
3305
            }
3306
3307
            function onBeforeShow() {
3308
                createIFrame.call(this);
3309
                this.beforeShowEvent.unsubscribe(onBeforeShow);
3310
                this._iframeDeferred = false;
3311
            }
3312
3313
            if (bIFrame) { // <iframe> shim is enabled
3314
3315
                if (this.cfg.getProperty("visible")) {
3316
                    createIFrame.call(this);
3317
                } else {
3318
                    if (!this._iframeDeferred) {
3319
                        this.beforeShowEvent.subscribe(onBeforeShow);
3320
                        this._iframeDeferred = true;
3321
                    }
3322
                }
3323
3324
            } else {    // <iframe> shim is disabled
3325
                this.hideIframe();
3326
3327
                if (this._hasIframeEventListeners) {
3328
                    this.showEvent.unsubscribe(this.showIframe);
3329
                    this.hideEvent.unsubscribe(this.hideIframe);
3330
                    this.changeContentEvent.unsubscribe(this.syncIframe);
3331
3332
                    this._hasIframeEventListeners = false;
3333
                }
3334
            }
3335
        },
3336
3337
        /**
3338
         * Set's the container's XY value from DOM if not already set.
3339
         * 
3340
         * Differs from syncPosition, in that the XY value is only sync'd with DOM if 
3341
         * not already set. The method also refire's the XY config property event, so any
3342
         * beforeMove, Move event listeners are invoked.
3343
         * 
3344
         * @method _primeXYFromDOM
3345
         * @protected
3346
         */
3347
        _primeXYFromDOM : function() {
3348
            if (YAHOO.lang.isUndefined(this.cfg.getProperty("xy"))) {
3349
                // Set CFG XY based on DOM XY
3350
                this.syncPosition();
3351
                // Account for XY being set silently in syncPosition (no moveTo fired/called)
3352
                this.cfg.refireEvent("xy");
3353
                this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
3354
            }
3355
        },
3356
3357
        /**
3358
        * The default event handler fired when the "constraintoviewport" 
3359
        * property is changed.
3360
        * @method configConstrainToViewport
3361
        * @param {String} type The CustomEvent type (usually the property name)
3362
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3363
        * handlers, args[0] will equal the newly applied value for 
3364
        * the property.
3365
        * @param {Object} obj The scope object. For configuration handlers, 
3366
        * this will usually equal the owner.
3367
        */
3368
        configConstrainToViewport: function (type, args, obj) {
3369
            var val = args[0];
3370
3371
            if (val) {
3372
                if (! Config.alreadySubscribed(this.beforeMoveEvent, this.enforceConstraints, this)) {
3373
                    this.beforeMoveEvent.subscribe(this.enforceConstraints, this, true);
3374
                }
3375
                if (! Config.alreadySubscribed(this.beforeShowEvent, this._primeXYFromDOM)) {
3376
                    this.beforeShowEvent.subscribe(this._primeXYFromDOM);
3377
                }
3378
            } else {
3379
                this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
3380
                this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
3381
            }
3382
        },
3383
3384
         /**
3385
        * The default event handler fired when the "context" property
3386
        * is changed.
3387
        *
3388
        * @method configContext
3389
        * @param {String} type The CustomEvent type (usually the property name)
3390
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3391
        * handlers, args[0] will equal the newly applied value for the property.
3392
        * @param {Object} obj The scope object. For configuration handlers, 
3393
        * this will usually equal the owner.
3394
        */
3395
        configContext: function (type, args, obj) {
3396
3397
            var contextArgs = args[0],
3398
                contextEl,
3399
                elementMagnetCorner,
3400
                contextMagnetCorner,
3401
                triggers,
3402
                offset,
3403
                defTriggers = this.CONTEXT_TRIGGERS;
3404
3405
            if (contextArgs) {
3406
3407
                contextEl = contextArgs[0];
3408
                elementMagnetCorner = contextArgs[1];
3409
                contextMagnetCorner = contextArgs[2];
3410
                triggers = contextArgs[3];
3411
                offset = contextArgs[4];
3412
3413
                if (defTriggers && defTriggers.length > 0) {
3414
                    triggers = (triggers || []).concat(defTriggers);
3415
                }
3416
3417
                if (contextEl) {
3418
                    if (typeof contextEl == "string") {
3419
                        this.cfg.setProperty("context", [
3420
                                document.getElementById(contextEl), 
3421
                                elementMagnetCorner,
3422
                                contextMagnetCorner,
3423
                                triggers,
3424
                                offset],
3425
                                true);
3426
                    }
3427
3428
                    if (elementMagnetCorner && contextMagnetCorner) {
3429
                        this.align(elementMagnetCorner, contextMagnetCorner, offset);
3430
                    }
3431
3432
                    if (this._contextTriggers) {
3433
                        // Unsubscribe Old Set
3434
                        this._processTriggers(this._contextTriggers, _UNSUBSCRIBE, this._alignOnTrigger);
3435
                    }
3436
3437
                    if (triggers) {
3438
                        // Subscribe New Set
3439
                        this._processTriggers(triggers, _SUBSCRIBE, this._alignOnTrigger);
3440
                        this._contextTriggers = triggers;
3441
                    }
3442
                }
3443
            }
3444
        },
3445
3446
        /**
3447
         * Custom Event handler for context alignment triggers. Invokes the align method
3448
         * 
3449
         * @method _alignOnTrigger
3450
         * @protected
3451
         * 
3452
         * @param {String} type The event type (not used by the default implementation)
3453
         * @param {Any[]} args The array of arguments for the trigger event (not used by the default implementation)
3454
         */
3455
        _alignOnTrigger: function(type, args) {
3456
            this.align();
3457
        },
3458
3459
        /**
3460
         * Helper method to locate the custom event instance for the event name string
3461
         * passed in. As a convenience measure, any custom events passed in are returned.
3462
         *
3463
         * @method _findTriggerCE
3464
         * @private
3465
         *
3466
         * @param {String|CustomEvent} t Either a CustomEvent, or event type (e.g. "windowScroll") for which a 
3467
         * custom event instance needs to be looked up from the Overlay._TRIGGER_MAP.
3468
         */
3469
        _findTriggerCE : function(t) {
3470
            var tce = null;
3471
            if (t instanceof CustomEvent) {
3472
                tce = t;
3473
            } else if (Overlay._TRIGGER_MAP[t]) {
3474
                tce = Overlay._TRIGGER_MAP[t];
3475
            }
3476
            return tce;
3477
        },
3478
3479
        /**
3480
         * Utility method that subscribes or unsubscribes the given 
3481
         * function from the list of trigger events provided.
3482
         *
3483
         * @method _processTriggers
3484
         * @protected 
3485
         *
3486
         * @param {Array[String|CustomEvent]} triggers An array of either CustomEvents, event type strings 
3487
         * (e.g. "beforeShow", "windowScroll") to/from which the provided function should be 
3488
         * subscribed/unsubscribed respectively.
3489
         *
3490
         * @param {String} mode Either "subscribe" or "unsubscribe", specifying whether or not
3491
         * we are subscribing or unsubscribing trigger listeners
3492
         * 
3493
         * @param {Function} fn The function to be subscribed/unsubscribed to/from the trigger event.
3494
         * Context is always set to the overlay instance, and no additional object argument 
3495
         * get passed to the subscribed function.
3496
         */
3497
        _processTriggers : function(triggers, mode, fn) {
3498
            var t, tce;
3499
3500
            for (var i = 0, l = triggers.length; i < l; ++i) {
3501
                t = triggers[i];
3502
                tce = this._findTriggerCE(t);
3503
                if (tce) {
3504
                    tce[mode](fn, this, true);
3505
                } else {
3506
                    this[mode](t, fn);
3507
                }
3508
            }
3509
        },
3510
3511
        // END BUILT-IN PROPERTY EVENT HANDLERS //
3512
        /**
3513
        * Aligns the Overlay to its context element using the specified corner 
3514
        * points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, 
3515
        * and BOTTOM_RIGHT.
3516
        * @method align
3517
        * @param {String} elementAlign  The String representing the corner of 
3518
        * the Overlay that should be aligned to the context element
3519
        * @param {String} contextAlign  The corner of the context element 
3520
        * that the elementAlign corner should stick to.
3521
        * @param {Number[]} xyOffset Optional. A 2 element array specifying the x and y pixel offsets which should be applied
3522
        * after aligning the element and context corners. For example, passing in [5, -10] for this value, would offset the 
3523
        * Overlay by 5 pixels along the X axis (horizontally) and -10 pixels along the Y axis (vertically) after aligning the specified corners.
3524
        */
3525
        align: function (elementAlign, contextAlign, xyOffset) {
3526
3527
            var contextArgs = this.cfg.getProperty("context"),
3528
                me = this,
3529
                context,
3530
                element,
3531
                contextRegion;
3532
3533
            function doAlign(v, h) {
3534
3535
                var alignX = null, alignY = null;
3536
3537
                switch (elementAlign) {
3538
    
3539
                    case Overlay.TOP_LEFT:
3540
                        alignX = h;
3541
                        alignY = v;
3542
                        break;
3543
        
3544
                    case Overlay.TOP_RIGHT:
3545
                        alignX = h - element.offsetWidth;
3546
                        alignY = v;
3547
                        break;
3548
        
3549
                    case Overlay.BOTTOM_LEFT:
3550
                        alignX = h;
3551
                        alignY = v - element.offsetHeight;
3552
                        break;
3553
        
3554
                    case Overlay.BOTTOM_RIGHT:
3555
                        alignX = h - element.offsetWidth; 
3556
                        alignY = v - element.offsetHeight;
3557
                        break;
3558
                }
3559
3560
                if (alignX !== null && alignY !== null) {
3561
                    if (xyOffset) {
3562
                        alignX += xyOffset[0];
3563
                        alignY += xyOffset[1];
3564
                    }
3565
                    me.moveTo(alignX, alignY);
3566
                }
3567
            }
3568
3569
            if (contextArgs) {
3570
                context = contextArgs[0];
3571
                element = this.element;
3572
                me = this;
3573
3574
                if (! elementAlign) {
3575
                    elementAlign = contextArgs[1];
3576
                }
3577
3578
                if (! contextAlign) {
3579
                    contextAlign = contextArgs[2];
3580
                }
3581
3582
                if (!xyOffset && contextArgs[4]) {
3583
                    xyOffset = contextArgs[4];
3584
                }
3585
3586
                if (element && context) {
3587
                    contextRegion = Dom.getRegion(context);
3588
3589
                    switch (contextAlign) {
3590
    
3591
                        case Overlay.TOP_LEFT:
3592
                            doAlign(contextRegion.top, contextRegion.left);
3593
                            break;
3594
        
3595
                        case Overlay.TOP_RIGHT:
3596
                            doAlign(contextRegion.top, contextRegion.right);
3597
                            break;
3598
        
3599
                        case Overlay.BOTTOM_LEFT:
3600
                            doAlign(contextRegion.bottom, contextRegion.left);
3601
                            break;
3602
        
3603
                        case Overlay.BOTTOM_RIGHT:
3604
                            doAlign(contextRegion.bottom, contextRegion.right);
3605
                            break;
3606
                    }
3607
                }
3608
            }
3609
        },
3610
3611
        /**
3612
        * The default event handler executed when the moveEvent is fired, if the 
3613
        * "constraintoviewport" is set to true.
3614
        * @method enforceConstraints
3615
        * @param {String} type The CustomEvent type (usually the property name)
3616
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3617
        * handlers, args[0] will equal the newly applied value for the property.
3618
        * @param {Object} obj The scope object. For configuration handlers, 
3619
        * this will usually equal the owner.
3620
        */
3621
        enforceConstraints: function (type, args, obj) {
3622
            var pos = args[0];
3623
3624
            var cXY = this.getConstrainedXY(pos[0], pos[1]);
3625
            this.cfg.setProperty("x", cXY[0], true);
3626
            this.cfg.setProperty("y", cXY[1], true);
3627
            this.cfg.setProperty("xy", cXY, true);
3628
        },
3629
3630
        /**
3631
         * Shared implementation method for getConstrainedX and getConstrainedY.
3632
         * 
3633
         * <p>
3634
         * Given a coordinate value, returns the calculated coordinate required to 
3635
         * position the Overlay if it is to be constrained to the viewport, based on the 
3636
         * current element size, viewport dimensions, scroll values and preventoverlap 
3637
         * settings
3638
         * </p>
3639
         *
3640
         * @method _getConstrainedPos
3641
         * @protected
3642
         * @param {String} pos The coordinate which needs to be constrained, either "x" or "y"
3643
         * @param {Number} The coordinate value which needs to be constrained
3644
         * @return {Number} The constrained coordinate value
3645
         */
3646
        _getConstrainedPos: function(pos, val) {
3647
3648
            var overlayEl = this.element,
3649
3650
                buffer = Overlay.VIEWPORT_OFFSET,
3651
3652
                x = (pos == "x"),
3653
3654
                overlaySize      = (x) ? overlayEl.offsetWidth : overlayEl.offsetHeight,
3655
                viewportSize     = (x) ? Dom.getViewportWidth() : Dom.getViewportHeight(),
3656
                docScroll        = (x) ? Dom.getDocumentScrollLeft() : Dom.getDocumentScrollTop(),
3657
                overlapPositions = (x) ? Overlay.PREVENT_OVERLAP_X : Overlay.PREVENT_OVERLAP_Y,
3658
3659
                context = this.cfg.getProperty("context"),
3660
3661
                bOverlayFitsInViewport = (overlaySize + buffer < viewportSize),
3662
                bPreventContextOverlap = this.cfg.getProperty("preventcontextoverlap") && context && overlapPositions[(context[1] + context[2])],
3663
3664
                minConstraint = docScroll + buffer,
3665
                maxConstraint = docScroll + viewportSize - overlaySize - buffer,
3666
3667
                constrainedVal = val;
3668
3669
            if (val < minConstraint || val > maxConstraint) {
3670
                if (bPreventContextOverlap) {
3671
                    constrainedVal = this._preventOverlap(pos, context[0], overlaySize, viewportSize, docScroll);
3672
                } else {
3673
                    if (bOverlayFitsInViewport) {
3674
                        if (val < minConstraint) {
3675
                            constrainedVal = minConstraint;
3676
                        } else if (val > maxConstraint) {
3677
                            constrainedVal = maxConstraint;
3678
                        }
3679
                    } else {
3680
                        constrainedVal = minConstraint;
3681
                    }
3682
                }
3683
            }
3684
3685
            return constrainedVal;
3686
        },
3687
3688
        /**
3689
         * Helper method, used to position the Overlap to prevent overlap with the 
3690
         * context element (used when preventcontextoverlap is enabled)
3691
         *
3692
         * @method _preventOverlap
3693
         * @protected
3694
         * @param {String} pos The coordinate to prevent overlap for, either "x" or "y".
3695
         * @param {HTMLElement} contextEl The context element
3696
         * @param {Number} overlaySize The related overlay dimension value (for "x", the width, for "y", the height)
3697
         * @param {Number} viewportSize The related viewport dimension value (for "x", the width, for "y", the height)
3698
         * @param {Object} docScroll  The related document scroll value (for "x", the scrollLeft, for "y", the scrollTop)
3699
         *
3700
         * @return {Number} The new coordinate value which was set to prevent overlap
3701
         */
3702
        _preventOverlap : function(pos, contextEl, overlaySize, viewportSize, docScroll) {
3703
            
3704
            var x = (pos == "x"),
3705
3706
                buffer = Overlay.VIEWPORT_OFFSET,
3707
3708
                overlay = this,
3709
3710
                contextElPos   = ((x) ? Dom.getX(contextEl) : Dom.getY(contextEl)) - docScroll,
3711
                contextElSize  = (x) ? contextEl.offsetWidth : contextEl.offsetHeight,
3712
3713
                minRegionSize = contextElPos - buffer,
3714
                maxRegionSize = (viewportSize - (contextElPos + contextElSize)) - buffer,
3715
3716
                bFlipped = false,
3717
3718
                flip = function () {
3719
                    var flippedVal;
3720
3721
                    if ((overlay.cfg.getProperty(pos) - docScroll) > contextElPos) {
3722
                        flippedVal = (contextElPos - overlaySize);
3723
                    } else {
3724
                        flippedVal = (contextElPos + contextElSize);
3725
                    }
3726
3727
                    overlay.cfg.setProperty(pos, (flippedVal + docScroll), true);
3728
3729
                    return flippedVal;
3730
                },
3731
3732
                setPosition = function () {
3733
3734
                    var displayRegionSize = ((overlay.cfg.getProperty(pos) - docScroll) > contextElPos) ? maxRegionSize : minRegionSize,
3735
                        position;
3736
3737
                    if (overlaySize > displayRegionSize) {
3738
                        if (bFlipped) {
3739
                            /*
3740
                                 All possible positions and values have been 
3741
                                 tried, but none were successful, so fall back 
3742
                                 to the original size and position.
3743
                            */
3744
                            flip();
3745
                        } else {
3746
                            flip();
3747
                            bFlipped = true;
3748
                            position = setPosition();
3749
                        }
3750
                    }
3751
3752
                    return position;
3753
                };
3754
3755
            setPosition();
3756
3757
            return this.cfg.getProperty(pos);
3758
        },
3759
3760
        /**
3761
         * Given x coordinate value, returns the calculated x coordinate required to 
3762
         * position the Overlay if it is to be constrained to the viewport, based on the 
3763
         * current element size, viewport dimensions and scroll values.
3764
         *
3765
         * @param {Number} x The X coordinate value to be constrained
3766
         * @return {Number} The constrained x coordinate
3767
         */		
3768
        getConstrainedX: function (x) {
3769
            return this._getConstrainedPos("x", x);
3770
        },
3771
3772
        /**
3773
         * Given y coordinate value, returns the calculated y coordinate required to 
3774
         * position the Overlay if it is to be constrained to the viewport, based on the 
3775
         * current element size, viewport dimensions and scroll values.
3776
         *
3777
         * @param {Number} y The Y coordinate value to be constrained
3778
         * @return {Number} The constrained y coordinate
3779
         */		
3780
        getConstrainedY : function (y) {
3781
            return this._getConstrainedPos("y", y);
3782
        },
3783
3784
        /**
3785
         * Given x, y coordinate values, returns the calculated coordinates required to 
3786
         * position the Overlay if it is to be constrained to the viewport, based on the 
3787
         * current element size, viewport dimensions and scroll values.
3788
         *
3789
         * @param {Number} x The X coordinate value to be constrained
3790
         * @param {Number} y The Y coordinate value to be constrained
3791
         * @return {Array} The constrained x and y coordinates at index 0 and 1 respectively;
3792
         */
3793
        getConstrainedXY: function(x, y) {
3794
            return [this.getConstrainedX(x), this.getConstrainedY(y)];
3795
        },
3796
3797
        /**
3798
        * Centers the container in the viewport.
3799
        * @method center
3800
        */
3801
        center: function () {
3802
3803
            var nViewportOffset = Overlay.VIEWPORT_OFFSET,
3804
                elementWidth = this.element.offsetWidth,
3805
                elementHeight = this.element.offsetHeight,
3806
                viewPortWidth = Dom.getViewportWidth(),
3807
                viewPortHeight = Dom.getViewportHeight(),
3808
                x,
3809
                y;
3810
3811
            if (elementWidth < viewPortWidth) {
3812
                x = (viewPortWidth / 2) - (elementWidth / 2) + Dom.getDocumentScrollLeft();
3813
            } else {
3814
                x = nViewportOffset + Dom.getDocumentScrollLeft();
3815
            }
3816
3817
            if (elementHeight < viewPortHeight) {
3818
                y = (viewPortHeight / 2) - (elementHeight / 2) + Dom.getDocumentScrollTop();
3819
            } else {
3820
                y = nViewportOffset + Dom.getDocumentScrollTop();
3821
            }
3822
3823
            this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
3824
            this.cfg.refireEvent("iframe");
3825
3826
            if (UA.webkit) {
3827
                this.forceContainerRedraw();
3828
            }
3829
        },
3830
3831
        /**
3832
        * Synchronizes the Panel's "xy", "x", and "y" properties with the 
3833
        * Panel's position in the DOM. This is primarily used to update  
3834
        * position information during drag & drop.
3835
        * @method syncPosition
3836
        */
3837
        syncPosition: function () {
3838
3839
            var pos = Dom.getXY(this.element);
3840
3841
            this.cfg.setProperty("x", pos[0], true);
3842
            this.cfg.setProperty("y", pos[1], true);
3843
            this.cfg.setProperty("xy", pos, true);
3844
3845
        },
3846
3847
        /**
3848
        * Event handler fired when the resize monitor element is resized.
3849
        * @method onDomResize
3850
        * @param {DOMEvent} e The resize DOM event
3851
        * @param {Object} obj The scope object
3852
        */
3853
        onDomResize: function (e, obj) {
3854
3855
            var me = this;
3856
3857
            Overlay.superclass.onDomResize.call(this, e, obj);
3858
3859
            setTimeout(function () {
3860
                me.syncPosition();
3861
                me.cfg.refireEvent("iframe");
3862
                me.cfg.refireEvent("context");
3863
            }, 0);
3864
        },
3865
3866
        /**
3867
         * Determines the content box height of the given element (height of the element, without padding or borders) in pixels.
3868
         *
3869
         * @method _getComputedHeight
3870
         * @private
3871
         * @param {HTMLElement} el The element for which the content height needs to be determined
3872
         * @return {Number} The content box height of the given element, or null if it could not be determined.
3873
         */
3874
        _getComputedHeight : (function() {
3875
3876
            if (document.defaultView && document.defaultView.getComputedStyle) {
3877
                return function(el) {
3878
                    var height = null;
3879
                    if (el.ownerDocument && el.ownerDocument.defaultView) {
3880
                        var computed = el.ownerDocument.defaultView.getComputedStyle(el, '');
3881
                        if (computed) {
3882
                            height = parseInt(computed.height, 10);
3883
                        }
3884
                    }
3885
                    return (Lang.isNumber(height)) ? height : null;
3886
                };
3887
            } else {
3888
                return function(el) {
3889
                    var height = null;
3890
                    if (el.style.pixelHeight) {
3891
                        height = el.style.pixelHeight;
3892
                    }
3893
                    return (Lang.isNumber(height)) ? height : null;
3894
                };
3895
            }
3896
        })(),
3897
3898
        /**
3899
         * autofillheight validator. Verifies that the autofill value is either null 
3900
         * or one of the strings : "body", "header" or "footer".
3901
         *
3902
         * @method _validateAutoFillHeight
3903
         * @protected
3904
         * @param {String} val
3905
         * @return true, if valid, false otherwise
3906
         */
3907
        _validateAutoFillHeight : function(val) {
3908
            return (!val) || (Lang.isString(val) && Overlay.STD_MOD_RE.test(val));
3909
        },
3910
3911
        /**
3912
         * The default custom event handler executed when the overlay's height is changed, 
3913
         * if the autofillheight property has been set.
3914
         *
3915
         * @method _autoFillOnHeightChange
3916
         * @protected
3917
         * @param {String} type The event type
3918
         * @param {Array} args The array of arguments passed to event subscribers
3919
         * @param {HTMLElement} el The header, body or footer element which is to be resized to fill
3920
         * out the containers height
3921
         */
3922
        _autoFillOnHeightChange : function(type, args, el) {
3923
            var height = this.cfg.getProperty("height");
3924
            if ((height && height !== "auto") || (height === 0)) {
3925
                this.fillHeight(el);
3926
            }
3927
        },
3928
3929
        /**
3930
         * Returns the sub-pixel height of the el, using getBoundingClientRect, if available,
3931
         * otherwise returns the offsetHeight
3932
         * @method _getPreciseHeight
3933
         * @private
3934
         * @param {HTMLElement} el
3935
         * @return {Float} The sub-pixel height if supported by the browser, else the rounded height.
3936
         */
3937
        _getPreciseHeight : function(el) {
3938
            var height = el.offsetHeight;
3939
3940
            if (el.getBoundingClientRect) {
3941
                var rect = el.getBoundingClientRect();
3942
                height = rect.bottom - rect.top;
3943
            }
3944
3945
            return height;
3946
        },
3947
3948
        /**
3949
         * <p>
3950
         * Sets the height on the provided header, body or footer element to 
3951
         * fill out the height of the container. It determines the height of the 
3952
         * containers content box, based on it's configured height value, and 
3953
         * sets the height of the autofillheight element to fill out any 
3954
         * space remaining after the other standard module element heights 
3955
         * have been accounted for.
3956
         * </p>
3957
         * <p><strong>NOTE:</strong> This method is not designed to work if an explicit 
3958
         * height has not been set on the container, since for an "auto" height container, 
3959
         * the heights of the header/body/footer will drive the height of the container.</p>
3960
         *
3961
         * @method fillHeight
3962
         * @param {HTMLElement} el The element which should be resized to fill out the height
3963
         * of the container element.
3964
         */
3965
        fillHeight : function(el) {
3966
            if (el) {
3967
                var container = this.innerElement || this.element,
3968
                    containerEls = [this.header, this.body, this.footer],
3969
                    containerEl,
3970
                    total = 0,
3971
                    filled = 0,
3972
                    remaining = 0,
3973
                    validEl = false;
3974
3975
                for (var i = 0, l = containerEls.length; i < l; i++) {
3976
                    containerEl = containerEls[i];
3977
                    if (containerEl) {
3978
                        if (el !== containerEl) {
3979
                            filled += this._getPreciseHeight(containerEl);
3980
                        } else {
3981
                            validEl = true;
3982
                        }
3983
                    }
3984
                }
3985
3986
                if (validEl) {
3987
3988
                    if (UA.ie || UA.opera) {
3989
                        // Need to set height to 0, to allow height to be reduced
3990
                        Dom.setStyle(el, 'height', 0 + 'px');
3991
                    }
3992
3993
                    total = this._getComputedHeight(container);
3994
3995
                    // Fallback, if we can't get computed value for content height
3996
                    if (total === null) {
3997
                        Dom.addClass(container, "yui-override-padding");
3998
                        total = container.clientHeight; // Content, No Border, 0 Padding (set by yui-override-padding)
3999
                        Dom.removeClass(container, "yui-override-padding");
4000
                    }
4001
    
4002
                    remaining = Math.max(total - filled, 0);
4003
    
4004
                    Dom.setStyle(el, "height", remaining + "px");
4005
    
4006
                    // Re-adjust height if required, to account for el padding and border
4007
                    if (el.offsetHeight != remaining) {
4008
                        remaining = Math.max(remaining - (el.offsetHeight - remaining), 0);
4009
                    }
4010
                    Dom.setStyle(el, "height", remaining + "px");
4011
                }
4012
            }
4013
        },
4014
4015
        /**
4016
        * Places the Overlay on top of all other instances of 
4017
        * YAHOO.widget.Overlay.
4018
        * @method bringToTop
4019
        */
4020
        bringToTop: function () {
4021
4022
            var aOverlays = [],
4023
                oElement = this.element;
4024
4025
            function compareZIndexDesc(p_oOverlay1, p_oOverlay2) {
4026
4027
                var sZIndex1 = Dom.getStyle(p_oOverlay1, "zIndex"),
4028
                    sZIndex2 = Dom.getStyle(p_oOverlay2, "zIndex"),
4029
4030
                    nZIndex1 = (!sZIndex1 || isNaN(sZIndex1)) ? 0 : parseInt(sZIndex1, 10),
4031
                    nZIndex2 = (!sZIndex2 || isNaN(sZIndex2)) ? 0 : parseInt(sZIndex2, 10);
4032
4033
                if (nZIndex1 > nZIndex2) {
4034
                    return -1;
4035
                } else if (nZIndex1 < nZIndex2) {
4036
                    return 1;
4037
                } else {
4038
                    return 0;
4039
                }
4040
            }
4041
4042
            function isOverlayElement(p_oElement) {
4043
4044
                var isOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY),
4045
                    Panel = YAHOO.widget.Panel;
4046
4047
                if (isOverlay && !Dom.isAncestor(oElement, p_oElement)) {
4048
                    if (Panel && Dom.hasClass(p_oElement, Panel.CSS_PANEL)) {
4049
                        aOverlays[aOverlays.length] = p_oElement.parentNode;
4050
                    } else {
4051
                        aOverlays[aOverlays.length] = p_oElement;
4052
                    }
4053
                }
4054
            }
4055
4056
            Dom.getElementsBy(isOverlayElement, "DIV", document.body);
4057
4058
            aOverlays.sort(compareZIndexDesc);
4059
4060
            var oTopOverlay = aOverlays[0],
4061
                nTopZIndex;
4062
4063
            if (oTopOverlay) {
4064
                nTopZIndex = Dom.getStyle(oTopOverlay, "zIndex");
4065
4066
                if (!isNaN(nTopZIndex)) {
4067
                    var bRequiresBump = false;
4068
4069
                    if (oTopOverlay != oElement) {
4070
                        bRequiresBump = true;
4071
                    } else if (aOverlays.length > 1) {
4072
                        var nNextZIndex = Dom.getStyle(aOverlays[1], "zIndex");
4073
                        // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
4074
                        if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
4075
                            bRequiresBump = true;
4076
                        }
4077
                    }
4078
                    if (bRequiresBump) {
4079
                        this.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
4080
                    }
4081
                }
4082
            }
4083
        },
4084
4085
        /**
4086
        * Removes the Overlay element from the DOM and sets all child 
4087
        * elements to null.
4088
        * @method destroy
4089
        */
4090
        destroy: function () {
4091
4092
            if (this.iframe) {
4093
                this.iframe.parentNode.removeChild(this.iframe);
4094
            }
4095
4096
            this.iframe = null;
4097
4098
            Overlay.windowResizeEvent.unsubscribe(
4099
                this.doCenterOnDOMEvent, this);
4100
    
4101
            Overlay.windowScrollEvent.unsubscribe(
4102
                this.doCenterOnDOMEvent, this);
4103
4104
            Module.textResizeEvent.unsubscribe(this._autoFillOnHeightChange);
4105
4106
            if (this._contextTriggers) {
4107
                // Unsubscribe context triggers - to cover context triggers which listen for global
4108
                // events such as windowResize and windowScroll. Easier just to unsubscribe all
4109
                this._processTriggers(this._contextTriggers, _UNSUBSCRIBE, this._alignOnTrigger);
4110
            }
4111
4112
            Overlay.superclass.destroy.call(this);
4113
        },
4114
4115
        /**
4116
         * Can be used to force the container to repaint/redraw it's contents.
4117
         * <p>
4118
         * By default applies and then removes a 1px bottom margin through the 
4119
         * application/removal of a "yui-force-redraw" class.
4120
         * </p>
4121
         * <p>
4122
         * It is currently used by Overlay to force a repaint for webkit 
4123
         * browsers, when centering.
4124
         * </p>
4125
         * @method forceContainerRedraw
4126
         */
4127
        forceContainerRedraw : function() {
4128
            var c = this;
4129
            Dom.addClass(c.element, "yui-force-redraw");
4130
            setTimeout(function() {
4131
                Dom.removeClass(c.element, "yui-force-redraw");
4132
            }, 0);
4133
        },
4134
4135
        /**
4136
        * Returns a String representation of the object.
4137
        * @method toString
4138
        * @return {String} The string representation of the Overlay.
4139
        */
4140
        toString: function () {
4141
            return "Overlay " + this.id;
4142
        }
4143
4144
    });
4145
}());
4146
(function () {
4147
4148
    /**
4149
    * OverlayManager is used for maintaining the focus status of 
4150
    * multiple Overlays.
4151
    * @namespace YAHOO.widget
4152
    * @namespace YAHOO.widget
4153
    * @class OverlayManager
4154
    * @constructor
4155
    * @param {Array} overlays Optional. A collection of Overlays to register 
4156
    * with the manager.
4157
    * @param {Object} userConfig  The object literal representing the user 
4158
    * configuration of the OverlayManager
4159
    */
4160
    YAHOO.widget.OverlayManager = function (userConfig) {
4161
        this.init(userConfig);
4162
    };
4163
4164
    var Overlay = YAHOO.widget.Overlay,
4165
        Event = YAHOO.util.Event,
4166
        Dom = YAHOO.util.Dom,
4167
        Config = YAHOO.util.Config,
4168
        CustomEvent = YAHOO.util.CustomEvent,
4169
        OverlayManager = YAHOO.widget.OverlayManager;
4170
4171
    /**
4172
    * The CSS class representing a focused Overlay
4173
    * @property OverlayManager.CSS_FOCUSED
4174
    * @static
4175
    * @final
4176
    * @type String
4177
    */
4178
    OverlayManager.CSS_FOCUSED = "focused";
4179
4180
    OverlayManager.prototype = {
4181
4182
        /**
4183
        * The class's constructor function
4184
        * @property contructor
4185
        * @type Function
4186
        */
4187
        constructor: OverlayManager,
4188
4189
        /**
4190
        * The array of Overlays that are currently registered
4191
        * @property overlays
4192
        * @type YAHOO.widget.Overlay[]
4193
        */
4194
        overlays: null,
4195
4196
        /**
4197
        * Initializes the default configuration of the OverlayManager
4198
        * @method initDefaultConfig
4199
        */
4200
        initDefaultConfig: function () {
4201
            /**
4202
            * The collection of registered Overlays in use by 
4203
            * the OverlayManager
4204
            * @config overlays
4205
            * @type YAHOO.widget.Overlay[]
4206
            * @default null
4207
            */
4208
            this.cfg.addProperty("overlays", { suppressEvent: true } );
4209
4210
            /**
4211
            * The default DOM event that should be used to focus an Overlay
4212
            * @config focusevent
4213
            * @type String
4214
            * @default "mousedown"
4215
            */
4216
            this.cfg.addProperty("focusevent", { value: "mousedown" } );
4217
        },
4218
4219
        /**
4220
        * Initializes the OverlayManager
4221
        * @method init
4222
        * @param {Overlay[]} overlays Optional. A collection of Overlays to 
4223
        * register with the manager.
4224
        * @param {Object} userConfig  The object literal representing the user 
4225
        * configuration of the OverlayManager
4226
        */
4227
        init: function (userConfig) {
4228
4229
            /**
4230
            * The OverlayManager's Config object used for monitoring 
4231
            * configuration properties.
4232
            * @property cfg
4233
            * @type Config
4234
            */
4235
            this.cfg = new Config(this);
4236
4237
            this.initDefaultConfig();
4238
4239
            if (userConfig) {
4240
                this.cfg.applyConfig(userConfig, true);
4241
            }
4242
            this.cfg.fireQueue();
4243
4244
            /**
4245
            * The currently activated Overlay
4246
            * @property activeOverlay
4247
            * @private
4248
            * @type YAHOO.widget.Overlay
4249
            */
4250
            var activeOverlay = null;
4251
4252
            /**
4253
            * Returns the currently focused Overlay
4254
            * @method getActive
4255
            * @return {Overlay} The currently focused Overlay
4256
            */
4257
            this.getActive = function () {
4258
                return activeOverlay;
4259
            };
4260
4261
            /**
4262
            * Focuses the specified Overlay
4263
            * @method focus
4264
            * @param {Overlay} overlay The Overlay to focus
4265
            * @param {String} overlay The id of the Overlay to focus
4266
            */
4267
            this.focus = function (overlay) {
4268
                var o = this.find(overlay);
4269
                if (o) {
4270
                    o.focus();
4271
                }
4272
            };
4273
4274
            /**
4275
            * Removes the specified Overlay from the manager
4276
            * @method remove
4277
            * @param {Overlay} overlay The Overlay to remove
4278
            * @param {String} overlay The id of the Overlay to remove
4279
            */
4280
            this.remove = function (overlay) {
4281
4282
                var o = this.find(overlay), 
4283
                        originalZ;
4284
4285
                if (o) {
4286
                    if (activeOverlay == o) {
4287
                        activeOverlay = null;
4288
                    }
4289
4290
                    var bDestroyed = (o.element === null && o.cfg === null) ? true : false;
4291
4292
                    if (!bDestroyed) {
4293
                        // Set it's zindex so that it's sorted to the end.
4294
                        originalZ = Dom.getStyle(o.element, "zIndex");
4295
                        o.cfg.setProperty("zIndex", -1000, true);
4296
                    }
4297
4298
                    this.overlays.sort(this.compareZIndexDesc);
4299
                    this.overlays = this.overlays.slice(0, (this.overlays.length - 1));
4300
4301
                    o.hideEvent.unsubscribe(o.blur);
4302
                    o.destroyEvent.unsubscribe(this._onOverlayDestroy, o);
4303
                    o.focusEvent.unsubscribe(this._onOverlayFocusHandler, o);
4304
                    o.blurEvent.unsubscribe(this._onOverlayBlurHandler, o);
4305
4306
                    if (!bDestroyed) {
4307
                        Event.removeListener(o.element, this.cfg.getProperty("focusevent"), this._onOverlayElementFocus);
4308
                        o.cfg.setProperty("zIndex", originalZ, true);
4309
                        o.cfg.setProperty("manager", null);
4310
                    }
4311
4312
                    /* _managed Flag for custom or existing. Don't want to remove existing */
4313
                    if (o.focusEvent._managed) { o.focusEvent = null; }
4314
                    if (o.blurEvent._managed) { o.blurEvent = null; }
4315
4316
                    if (o.focus._managed) { o.focus = null; }
4317
                    if (o.blur._managed) { o.blur = null; }
4318
                }
4319
            };
4320
4321
            /**
4322
            * Removes focus from all registered Overlays in the manager
4323
            * @method blurAll
4324
            */
4325
            this.blurAll = function () {
4326
4327
                var nOverlays = this.overlays.length,
4328
                    i;
4329
4330
                if (nOverlays > 0) {
4331
                    i = nOverlays - 1;
4332
                    do {
4333
                        this.overlays[i].blur();
4334
                    }
4335
                    while(i--);
4336
                }
4337
            };
4338
4339
            /**
4340
             * Updates the state of the OverlayManager and overlay, as a result of the overlay
4341
             * being blurred.
4342
             * 
4343
             * @method _manageBlur
4344
             * @param {Overlay} overlay The overlay instance which got blurred.
4345
             * @protected
4346
             */
4347
            this._manageBlur = function (overlay) {
4348
                var changed = false;
4349
                if (activeOverlay == overlay) {
4350
                    Dom.removeClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
4351
                    activeOverlay = null;
4352
                    changed = true;
4353
                }
4354
                return changed;
4355
            };
4356
4357
            /**
4358
             * Updates the state of the OverlayManager and overlay, as a result of the overlay 
4359
             * receiving focus.
4360
             *
4361
             * @method _manageFocus
4362
             * @param {Overlay} overlay The overlay instance which got focus.
4363
             * @protected
4364
             */
4365
            this._manageFocus = function(overlay) {
4366
                var changed = false;
4367
                if (activeOverlay != overlay) {
4368
                    if (activeOverlay) {
4369
                        activeOverlay.blur();
4370
                    }
4371
                    activeOverlay = overlay;
4372
                    this.bringToTop(activeOverlay);
4373
                    Dom.addClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
4374
                    changed = true;
4375
                }
4376
                return changed;
4377
            };
4378
4379
            var overlays = this.cfg.getProperty("overlays");
4380
4381
            if (! this.overlays) {
4382
                this.overlays = [];
4383
            }
4384
4385
            if (overlays) {
4386
                this.register(overlays);
4387
                this.overlays.sort(this.compareZIndexDesc);
4388
            }
4389
        },
4390
4391
        /**
4392
        * @method _onOverlayElementFocus
4393
        * @description Event handler for the DOM event that is used to focus 
4394
        * the Overlay instance as specified by the "focusevent" 
4395
        * configuration property.
4396
        * @private
4397
        * @param {Event} p_oEvent Object representing the DOM event 
4398
        * object passed back by the event utility (Event).
4399
        */
4400
        _onOverlayElementFocus: function (p_oEvent) {
4401
4402
            var oTarget = Event.getTarget(p_oEvent),
4403
                oClose = this.close;
4404
4405
            if (oClose && (oTarget == oClose || Dom.isAncestor(oClose, oTarget))) {
4406
                this.blur();
4407
            } else {
4408
                this.focus();
4409
            }
4410
        },
4411
4412
        /**
4413
        * @method _onOverlayDestroy
4414
        * @description "destroy" event handler for the Overlay.
4415
        * @private
4416
        * @param {String} p_sType String representing the name of the event  
4417
        * that was fired.
4418
        * @param {Array} p_aArgs Array of arguments sent when the event 
4419
        * was fired.
4420
        * @param {Overlay} p_oOverlay Object representing the overlay that 
4421
        * fired the event.
4422
        */
4423
        _onOverlayDestroy: function (p_sType, p_aArgs, p_oOverlay) {
4424
            this.remove(p_oOverlay);
4425
        },
4426
4427
        /**
4428
        * @method _onOverlayFocusHandler
4429
        *
4430
        * @description focusEvent Handler, used to delegate to _manageFocus with the correct arguments.
4431
        *
4432
        * @private
4433
        * @param {String} p_sType String representing the name of the event  
4434
        * that was fired.
4435
        * @param {Array} p_aArgs Array of arguments sent when the event 
4436
        * was fired.
4437
        * @param {Overlay} p_oOverlay Object representing the overlay that 
4438
        * fired the event.
4439
        */
4440
        _onOverlayFocusHandler: function(p_sType, p_aArgs, p_oOverlay) {
4441
            this._manageFocus(p_oOverlay);
4442
        },
4443
4444
        /**
4445
        * @method _onOverlayBlurHandler
4446
        * @description blurEvent Handler, used to delegate to _manageBlur with the correct arguments.
4447
        *
4448
        * @private
4449
        * @param {String} p_sType String representing the name of the event  
4450
        * that was fired.
4451
        * @param {Array} p_aArgs Array of arguments sent when the event 
4452
        * was fired.
4453
        * @param {Overlay} p_oOverlay Object representing the overlay that 
4454
        * fired the event.
4455
        */
4456
        _onOverlayBlurHandler: function(p_sType, p_aArgs, p_oOverlay) {
4457
            this._manageBlur(p_oOverlay);
4458
        },
4459
4460
        /**
4461
         * Subscribes to the Overlay based instance focusEvent, to allow the OverlayManager to
4462
         * monitor focus state.
4463
         * 
4464
         * If the instance already has a focusEvent (e.g. Menu), OverlayManager will subscribe 
4465
         * to the existing focusEvent, however if a focusEvent or focus method does not exist
4466
         * on the instance, the _bindFocus method will add them, and the focus method will 
4467
         * update the OverlayManager's state directly.
4468
         * 
4469
         * @method _bindFocus
4470
         * @param {Overlay} overlay The overlay for which focus needs to be managed
4471
         * @protected
4472
         */
4473
        _bindFocus : function(overlay) {
4474
            var mgr = this;
4475
4476
            if (!overlay.focusEvent) {
4477
                overlay.focusEvent = overlay.createEvent("focus");
4478
                overlay.focusEvent.signature = CustomEvent.LIST;
4479
                overlay.focusEvent._managed = true;
4480
            } else {
4481
                overlay.focusEvent.subscribe(mgr._onOverlayFocusHandler, overlay, mgr);
4482
            }
4483
4484
            if (!overlay.focus) {
4485
                Event.on(overlay.element, mgr.cfg.getProperty("focusevent"), mgr._onOverlayElementFocus, null, overlay);
4486
                overlay.focus = function () {
4487
                    if (mgr._manageFocus(this)) {
4488
                        // For Panel/Dialog
4489
                        if (this.cfg.getProperty("visible") && this.focusFirst) {
4490
                            this.focusFirst();
4491
                        }
4492
                        this.focusEvent.fire();
4493
                    }
4494
                };
4495
                overlay.focus._managed = true;
4496
            }
4497
        },
4498
4499
        /**
4500
         * Subscribes to the Overlay based instance's blurEvent to allow the OverlayManager to
4501
         * monitor blur state.
4502
         *
4503
         * If the instance already has a blurEvent (e.g. Menu), OverlayManager will subscribe 
4504
         * to the existing blurEvent, however if a blurEvent or blur method does not exist
4505
         * on the instance, the _bindBlur method will add them, and the blur method 
4506
         * update the OverlayManager's state directly.
4507
         *
4508
         * @method _bindBlur
4509
         * @param {Overlay} overlay The overlay for which blur needs to be managed
4510
         * @protected
4511
         */
4512
        _bindBlur : function(overlay) {
4513
            var mgr = this;
4514
4515
            if (!overlay.blurEvent) {
4516
                overlay.blurEvent = overlay.createEvent("blur");
4517
                overlay.blurEvent.signature = CustomEvent.LIST;
4518
                overlay.focusEvent._managed = true;
4519
            } else {
4520
                overlay.blurEvent.subscribe(mgr._onOverlayBlurHandler, overlay, mgr);
4521
            }
4522
4523
            if (!overlay.blur) {
4524
                overlay.blur = function () {
4525
                    if (mgr._manageBlur(this)) {
4526
                        this.blurEvent.fire();
4527
                    }
4528
                };
4529
                overlay.blur._managed = true;
4530
            }
4531
4532
            overlay.hideEvent.subscribe(overlay.blur);
4533
        },
4534
4535
        /**
4536
         * Subscribes to the Overlay based instance's destroyEvent, to allow the Overlay
4537
         * to be removed for the OverlayManager when destroyed.
4538
         * 
4539
         * @method _bindDestroy
4540
         * @param {Overlay} overlay The overlay instance being managed
4541
         * @protected
4542
         */
4543
        _bindDestroy : function(overlay) {
4544
            var mgr = this;
4545
            overlay.destroyEvent.subscribe(mgr._onOverlayDestroy, overlay, mgr);
4546
        },
4547
4548
        /**
4549
         * Ensures the zIndex configuration property on the managed overlay based instance
4550
         * is set to the computed zIndex value from the DOM (with "auto" translating to 0).
4551
         *
4552
         * @method _syncZIndex
4553
         * @param {Overlay} overlay The overlay instance being managed
4554
         * @protected
4555
         */
4556
        _syncZIndex : function(overlay) {
4557
            var zIndex = Dom.getStyle(overlay.element, "zIndex");
4558
            if (!isNaN(zIndex)) {
4559
                overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
4560
            } else {
4561
                overlay.cfg.setProperty("zIndex", 0);
4562
            }
4563
        },
4564
4565
        /**
4566
        * Registers an Overlay or an array of Overlays with the manager. Upon 
4567
        * registration, the Overlay receives functions for focus and blur, 
4568
        * along with CustomEvents for each.
4569
        *
4570
        * @method register
4571
        * @param {Overlay} overlay  An Overlay to register with the manager.
4572
        * @param {Overlay[]} overlay  An array of Overlays to register with 
4573
        * the manager.
4574
        * @return {boolean} true if any Overlays are registered.
4575
        */
4576
        register: function (overlay) {
4577
4578
            var registered = false,
4579
                i,
4580
                n;
4581
4582
            if (overlay instanceof Overlay) {
4583
4584
                overlay.cfg.addProperty("manager", { value: this } );
4585
4586
                this._bindFocus(overlay);
4587
                this._bindBlur(overlay);
4588
                this._bindDestroy(overlay);
4589
                this._syncZIndex(overlay);
4590
4591
                this.overlays.push(overlay);
4592
                this.bringToTop(overlay);
4593
4594
                registered = true;
4595
4596
            } else if (overlay instanceof Array) {
4597
4598
                for (i = 0, n = overlay.length; i < n; i++) {
4599
                    registered = this.register(overlay[i]) || registered;
4600
                }
4601
4602
            }
4603
4604
            return registered;
4605
        },
4606
4607
        /**
4608
        * Places the specified Overlay instance on top of all other 
4609
        * Overlay instances.
4610
        * @method bringToTop
4611
        * @param {YAHOO.widget.Overlay} p_oOverlay Object representing an 
4612
        * Overlay instance.
4613
        * @param {String} p_oOverlay String representing the id of an 
4614
        * Overlay instance.
4615
        */        
4616
        bringToTop: function (p_oOverlay) {
4617
4618
            var oOverlay = this.find(p_oOverlay),
4619
                nTopZIndex,
4620
                oTopOverlay,
4621
                aOverlays;
4622
4623
            if (oOverlay) {
4624
4625
                aOverlays = this.overlays;
4626
                aOverlays.sort(this.compareZIndexDesc);
4627
4628
                oTopOverlay = aOverlays[0];
4629
4630
                if (oTopOverlay) {
4631
                    nTopZIndex = Dom.getStyle(oTopOverlay.element, "zIndex");
4632
4633
                    if (!isNaN(nTopZIndex)) {
4634
4635
                        var bRequiresBump = false;
4636
4637
                        if (oTopOverlay !== oOverlay) {
4638
                            bRequiresBump = true;
4639
                        } else if (aOverlays.length > 1) {
4640
                            var nNextZIndex = Dom.getStyle(aOverlays[1].element, "zIndex");
4641
                            // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
4642
                            if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
4643
                                bRequiresBump = true;
4644
                            }
4645
                        }
4646
4647
                        if (bRequiresBump) {
4648
                            oOverlay.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
4649
                        }
4650
                    }
4651
                    aOverlays.sort(this.compareZIndexDesc);
4652
                }
4653
            }
4654
        },
4655
4656
        /**
4657
        * Attempts to locate an Overlay by instance or ID.
4658
        * @method find
4659
        * @param {Overlay} overlay  An Overlay to locate within the manager
4660
        * @param {String} overlay  An Overlay id to locate within the manager
4661
        * @return {Overlay} The requested Overlay, if found, or null if it 
4662
        * cannot be located.
4663
        */
4664
        find: function (overlay) {
4665
4666
            var isInstance = overlay instanceof Overlay,
4667
                overlays = this.overlays,
4668
                n = overlays.length,
4669
                found = null,
4670
                o,
4671
                i;
4672
4673
            if (isInstance || typeof overlay == "string") {
4674
                for (i = n-1; i >= 0; i--) {
4675
                    o = overlays[i];
4676
                    if ((isInstance && (o === overlay)) || (o.id == overlay)) {
4677
                        found = o;
4678
                        break;
4679
                    }
4680
                }
4681
            }
4682
4683
            return found;
4684
        },
4685
4686
        /**
4687
        * Used for sorting the manager's Overlays by z-index.
4688
        * @method compareZIndexDesc
4689
        * @private
4690
        * @return {Number} 0, 1, or -1, depending on where the Overlay should 
4691
        * fall in the stacking order.
4692
        */
4693
        compareZIndexDesc: function (o1, o2) {
4694
4695
            var zIndex1 = (o1.cfg) ? o1.cfg.getProperty("zIndex") : null, // Sort invalid (destroyed)
4696
                zIndex2 = (o2.cfg) ? o2.cfg.getProperty("zIndex") : null; // objects at bottom.
4697
4698
            if (zIndex1 === null && zIndex2 === null) {
4699
                return 0;
4700
            } else if (zIndex1 === null){
4701
                return 1;
4702
            } else if (zIndex2 === null) {
4703
                return -1;
4704
            } else if (zIndex1 > zIndex2) {
4705
                return -1;
4706
            } else if (zIndex1 < zIndex2) {
4707
                return 1;
4708
            } else {
4709
                return 0;
4710
            }
4711
        },
4712
4713
        /**
4714
        * Shows all Overlays in the manager.
4715
        * @method showAll
4716
        */
4717
        showAll: function () {
4718
            var overlays = this.overlays,
4719
                n = overlays.length,
4720
                i;
4721
4722
            for (i = n - 1; i >= 0; i--) {
4723
                overlays[i].show();
4724
            }
4725
        },
4726
4727
        /**
4728
        * Hides all Overlays in the manager.
4729
        * @method hideAll
4730
        */
4731
        hideAll: function () {
4732
            var overlays = this.overlays,
4733
                n = overlays.length,
4734
                i;
4735
4736
            for (i = n - 1; i >= 0; i--) {
4737
                overlays[i].hide();
4738
            }
4739
        },
4740
4741
        /**
4742
        * Returns a string representation of the object.
4743
        * @method toString
4744
        * @return {String} The string representation of the OverlayManager
4745
        */
4746
        toString: function () {
4747
            return "OverlayManager";
4748
        }
4749
    };
4750
}());
4751
(function () {
4752
4753
    /**
4754
    * ContainerEffect encapsulates animation transitions that are executed when 
4755
    * an Overlay is shown or hidden.
4756
    * @namespace YAHOO.widget
4757
    * @class ContainerEffect
4758
    * @constructor
4759
    * @param {YAHOO.widget.Overlay} overlay The Overlay that the animation 
4760
    * should be associated with
4761
    * @param {Object} attrIn The object literal representing the animation 
4762
    * arguments to be used for the animate-in transition. The arguments for 
4763
    * this literal are: attributes(object, see YAHOO.util.Anim for description), 
4764
    * duration(Number), and method(i.e. Easing.easeIn).
4765
    * @param {Object} attrOut The object literal representing the animation 
4766
    * arguments to be used for the animate-out transition. The arguments for  
4767
    * this literal are: attributes(object, see YAHOO.util.Anim for description), 
4768
    * duration(Number), and method(i.e. Easing.easeIn).
4769
    * @param {HTMLElement} targetElement Optional. The target element that  
4770
    * should be animated during the transition. Defaults to overlay.element.
4771
    * @param {class} Optional. The animation class to instantiate. Defaults to 
4772
    * YAHOO.util.Anim. Other options include YAHOO.util.Motion.
4773
    */
4774
    YAHOO.widget.ContainerEffect = function (overlay, attrIn, attrOut, targetElement, animClass) {
4775
4776
        if (!animClass) {
4777
            animClass = YAHOO.util.Anim;
4778
        }
4779
4780
        /**
4781
        * The overlay to animate
4782
        * @property overlay
4783
        * @type YAHOO.widget.Overlay
4784
        */
4785
        this.overlay = overlay;
4786
    
4787
        /**
4788
        * The animation attributes to use when transitioning into view
4789
        * @property attrIn
4790
        * @type Object
4791
        */
4792
        this.attrIn = attrIn;
4793
    
4794
        /**
4795
        * The animation attributes to use when transitioning out of view
4796
        * @property attrOut
4797
        * @type Object
4798
        */
4799
        this.attrOut = attrOut;
4800
    
4801
        /**
4802
        * The target element to be animated
4803
        * @property targetElement
4804
        * @type HTMLElement
4805
        */
4806
        this.targetElement = targetElement || overlay.element;
4807
    
4808
        /**
4809
        * The animation class to use for animating the overlay
4810
        * @property animClass
4811
        * @type class
4812
        */
4813
        this.animClass = animClass;
4814
    
4815
    };
4816
4817
4818
    var Dom = YAHOO.util.Dom,
4819
        CustomEvent = YAHOO.util.CustomEvent,
4820
        ContainerEffect = YAHOO.widget.ContainerEffect;
4821
4822
4823
    /**
4824
    * A pre-configured ContainerEffect instance that can be used for fading 
4825
    * an overlay in and out.
4826
    * @method FADE
4827
    * @static
4828
    * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
4829
    * @param {Number} dur The duration of the animation
4830
    * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
4831
    */
4832
    ContainerEffect.FADE = function (overlay, dur) {
4833
4834
        var Easing = YAHOO.util.Easing,
4835
            fin = {
4836
                attributes: {opacity:{from:0, to:1}},
4837
                duration: dur,
4838
                method: Easing.easeIn
4839
            },
4840
            fout = {
4841
                attributes: {opacity:{to:0}},
4842
                duration: dur,
4843
                method: Easing.easeOut
4844
            },
4845
            fade = new ContainerEffect(overlay, fin, fout, overlay.element);
4846
4847
        fade.handleUnderlayStart = function() {
4848
            var underlay = this.overlay.underlay;
4849
            if (underlay && YAHOO.env.ua.ie) {
4850
                var hasFilters = (underlay.filters && underlay.filters.length > 0);
4851
                if(hasFilters) {
4852
                    Dom.addClass(overlay.element, "yui-effect-fade");
4853
                }
4854
            }
4855
        };
4856
4857
        fade.handleUnderlayComplete = function() {
4858
            var underlay = this.overlay.underlay;
4859
            if (underlay && YAHOO.env.ua.ie) {
4860
                Dom.removeClass(overlay.element, "yui-effect-fade");
4861
            }
4862
        };
4863
4864
        fade.handleStartAnimateIn = function (type, args, obj) {
4865
            Dom.addClass(obj.overlay.element, "hide-select");
4866
4867
            if (!obj.overlay.underlay) {
4868
                obj.overlay.cfg.refireEvent("underlay");
4869
            }
4870
4871
            obj.handleUnderlayStart();
4872
4873
            obj.overlay._setDomVisibility(true);
4874
            Dom.setStyle(obj.overlay.element, "opacity", 0);
4875
        };
4876
4877
        fade.handleCompleteAnimateIn = function (type,args,obj) {
4878
            Dom.removeClass(obj.overlay.element, "hide-select");
4879
4880
            if (obj.overlay.element.style.filter) {
4881
                obj.overlay.element.style.filter = null;
4882
            }
4883
4884
            obj.handleUnderlayComplete();
4885
4886
            obj.overlay.cfg.refireEvent("iframe");
4887
            obj.animateInCompleteEvent.fire();
4888
        };
4889
4890
        fade.handleStartAnimateOut = function (type, args, obj) {
4891
            Dom.addClass(obj.overlay.element, "hide-select");
4892
            obj.handleUnderlayStart();
4893
        };
4894
4895
        fade.handleCompleteAnimateOut =  function (type, args, obj) {
4896
            Dom.removeClass(obj.overlay.element, "hide-select");
4897
            if (obj.overlay.element.style.filter) {
4898
                obj.overlay.element.style.filter = null;
4899
            }
4900
            obj.overlay._setDomVisibility(false);
4901
            Dom.setStyle(obj.overlay.element, "opacity", 1);
4902
4903
            obj.handleUnderlayComplete();
4904
4905
            obj.overlay.cfg.refireEvent("iframe");
4906
            obj.animateOutCompleteEvent.fire();
4907
        };
4908
4909
        fade.init();
4910
        return fade;
4911
    };
4912
    
4913
    
4914
    /**
4915
    * A pre-configured ContainerEffect instance that can be used for sliding an 
4916
    * overlay in and out.
4917
    * @method SLIDE
4918
    * @static
4919
    * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
4920
    * @param {Number} dur The duration of the animation
4921
    * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
4922
    */
4923
    ContainerEffect.SLIDE = function (overlay, dur) {
4924
        var Easing = YAHOO.util.Easing,
4925
4926
            x = overlay.cfg.getProperty("x") || Dom.getX(overlay.element),
4927
            y = overlay.cfg.getProperty("y") || Dom.getY(overlay.element),
4928
            clientWidth = Dom.getClientWidth(),
4929
            offsetWidth = overlay.element.offsetWidth,
4930
4931
            sin =  { 
4932
                attributes: { points: { to: [x, y] } },
4933
                duration: dur,
4934
                method: Easing.easeIn 
4935
            },
4936
4937
            sout = {
4938
                attributes: { points: { to: [(clientWidth + 25), y] } },
4939
                duration: dur,
4940
                method: Easing.easeOut 
4941
            },
4942
4943
            slide = new ContainerEffect(overlay, sin, sout, overlay.element, YAHOO.util.Motion);
4944
4945
        slide.handleStartAnimateIn = function (type,args,obj) {
4946
            obj.overlay.element.style.left = ((-25) - offsetWidth) + "px";
4947
            obj.overlay.element.style.top  = y + "px";
4948
        };
4949
4950
        slide.handleTweenAnimateIn = function (type, args, obj) {
4951
        
4952
            var pos = Dom.getXY(obj.overlay.element),
4953
                currentX = pos[0],
4954
                currentY = pos[1];
4955
        
4956
            if (Dom.getStyle(obj.overlay.element, "visibility") == 
4957
                "hidden" && currentX < x) {
4958
4959
                obj.overlay._setDomVisibility(true);
4960
4961
            }
4962
        
4963
            obj.overlay.cfg.setProperty("xy", [currentX, currentY], true);
4964
            obj.overlay.cfg.refireEvent("iframe");
4965
        };
4966
        
4967
        slide.handleCompleteAnimateIn = function (type, args, obj) {
4968
            obj.overlay.cfg.setProperty("xy", [x, y], true);
4969
            obj.startX = x;
4970
            obj.startY = y;
4971
            obj.overlay.cfg.refireEvent("iframe");
4972
            obj.animateInCompleteEvent.fire();
4973
        };
4974
        
4975
        slide.handleStartAnimateOut = function (type, args, obj) {
4976
    
4977
            var vw = Dom.getViewportWidth(),
4978
                pos = Dom.getXY(obj.overlay.element),
4979
                yso = pos[1];
4980
    
4981
            obj.animOut.attributes.points.to = [(vw + 25), yso];
4982
        };
4983
        
4984
        slide.handleTweenAnimateOut = function (type, args, obj) {
4985
    
4986
            var pos = Dom.getXY(obj.overlay.element),
4987
                xto = pos[0],
4988
                yto = pos[1];
4989
        
4990
            obj.overlay.cfg.setProperty("xy", [xto, yto], true);
4991
            obj.overlay.cfg.refireEvent("iframe");
4992
        };
4993
        
4994
        slide.handleCompleteAnimateOut = function (type, args, obj) {
4995
            obj.overlay._setDomVisibility(false);
4996
4997
            obj.overlay.cfg.setProperty("xy", [x, y]);
4998
            obj.animateOutCompleteEvent.fire();
4999
        };
5000
5001
        slide.init();
5002
        return slide;
5003
    };
5004
5005
    ContainerEffect.prototype = {
5006
5007
        /**
5008
        * Initializes the animation classes and events.
5009
        * @method init
5010
        */
5011
        init: function () {
5012
5013
            this.beforeAnimateInEvent = this.createEvent("beforeAnimateIn");
5014
            this.beforeAnimateInEvent.signature = CustomEvent.LIST;
5015
            
5016
            this.beforeAnimateOutEvent = this.createEvent("beforeAnimateOut");
5017
            this.beforeAnimateOutEvent.signature = CustomEvent.LIST;
5018
        
5019
            this.animateInCompleteEvent = this.createEvent("animateInComplete");
5020
            this.animateInCompleteEvent.signature = CustomEvent.LIST;
5021
        
5022
            this.animateOutCompleteEvent = 
5023
                this.createEvent("animateOutComplete");
5024
            this.animateOutCompleteEvent.signature = CustomEvent.LIST;
5025
        
5026
            this.animIn = new this.animClass(this.targetElement, 
5027
                this.attrIn.attributes, this.attrIn.duration, 
5028
                this.attrIn.method);
5029
5030
            this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
5031
            this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
5032
5033
            this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn, 
5034
                this);
5035
        
5036
            this.animOut = new this.animClass(this.targetElement, 
5037
                this.attrOut.attributes, this.attrOut.duration, 
5038
                this.attrOut.method);
5039
5040
            this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
5041
            this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
5042
            this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut, 
5043
                this);
5044
5045
        },
5046
        
5047
        /**
5048
        * Triggers the in-animation.
5049
        * @method animateIn
5050
        */
5051
        animateIn: function () {
5052
            this.beforeAnimateInEvent.fire();
5053
            this.animIn.animate();
5054
        },
5055
5056
        /**
5057
        * Triggers the out-animation.
5058
        * @method animateOut
5059
        */
5060
        animateOut: function () {
5061
            this.beforeAnimateOutEvent.fire();
5062
            this.animOut.animate();
5063
        },
5064
5065
        /**
5066
        * The default onStart handler for the in-animation.
5067
        * @method handleStartAnimateIn
5068
        * @param {String} type The CustomEvent type
5069
        * @param {Object[]} args The CustomEvent arguments
5070
        * @param {Object} obj The scope object
5071
        */
5072
        handleStartAnimateIn: function (type, args, obj) { },
5073
5074
        /**
5075
        * The default onTween handler for the in-animation.
5076
        * @method handleTweenAnimateIn
5077
        * @param {String} type The CustomEvent type
5078
        * @param {Object[]} args The CustomEvent arguments
5079
        * @param {Object} obj The scope object
5080
        */
5081
        handleTweenAnimateIn: function (type, args, obj) { },
5082
5083
        /**
5084
        * The default onComplete handler for the in-animation.
5085
        * @method handleCompleteAnimateIn
5086
        * @param {String} type The CustomEvent type
5087
        * @param {Object[]} args The CustomEvent arguments
5088
        * @param {Object} obj The scope object
5089
        */
5090
        handleCompleteAnimateIn: function (type, args, obj) { },
5091
5092
        /**
5093
        * The default onStart handler for the out-animation.
5094
        * @method handleStartAnimateOut
5095
        * @param {String} type The CustomEvent type
5096
        * @param {Object[]} args The CustomEvent arguments
5097
        * @param {Object} obj The scope object
5098
        */
5099
        handleStartAnimateOut: function (type, args, obj) { },
5100
5101
        /**
5102
        * The default onTween handler for the out-animation.
5103
        * @method handleTweenAnimateOut
5104
        * @param {String} type The CustomEvent type
5105
        * @param {Object[]} args The CustomEvent arguments
5106
        * @param {Object} obj The scope object
5107
        */
5108
        handleTweenAnimateOut: function (type, args, obj) { },
5109
5110
        /**
5111
        * The default onComplete handler for the out-animation.
5112
        * @method handleCompleteAnimateOut
5113
        * @param {String} type The CustomEvent type
5114
        * @param {Object[]} args The CustomEvent arguments
5115
        * @param {Object} obj The scope object
5116
        */
5117
        handleCompleteAnimateOut: function (type, args, obj) { },
5118
        
5119
        /**
5120
        * Returns a string representation of the object.
5121
        * @method toString
5122
        * @return {String} The string representation of the ContainerEffect
5123
        */
5124
        toString: function () {
5125
            var output = "ContainerEffect";
5126
            if (this.overlay) {
5127
                output += " [" + this.overlay.toString() + "]";
5128
            }
5129
            return output;
5130
        }
5131
    };
5132
5133
    YAHOO.lang.augmentProto(ContainerEffect, YAHOO.util.EventProvider);
5134
5135
})();
5136
YAHOO.register("containercore", YAHOO.widget.Module, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/container/container_core-min.js (-14 lines)
Lines 1-14 Link Here
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.8.0r4
6
*/
7
(function(){YAHOO.util.Config=function(D){if(D){this.init(D);}};var B=YAHOO.lang,C=YAHOO.util.CustomEvent,A=YAHOO.util.Config;A.CONFIG_CHANGED_EVENT="configChanged";A.BOOLEAN_TYPE="boolean";A.prototype={owner:null,queueInProgress:false,config:null,initialConfig:null,eventQueue:null,configChangedEvent:null,init:function(D){this.owner=D;this.configChangedEvent=this.createEvent(A.CONFIG_CHANGED_EVENT);this.configChangedEvent.signature=C.LIST;this.queueInProgress=false;this.config={};this.initialConfig={};this.eventQueue=[];},checkBoolean:function(D){return(typeof D==A.BOOLEAN_TYPE);},checkNumber:function(D){return(!isNaN(D));},fireEvent:function(D,F){var E=this.config[D];if(E&&E.event){E.event.fire(F);}},addProperty:function(E,D){E=E.toLowerCase();this.config[E]=D;D.event=this.createEvent(E,{scope:this.owner});D.event.signature=C.LIST;D.key=E;if(D.handler){D.event.subscribe(D.handler,this.owner);}this.setProperty(E,D.value,true);if(!D.suppressEvent){this.queueProperty(E,D.value);}},getConfig:function(){var D={},F=this.config,G,E;for(G in F){if(B.hasOwnProperty(F,G)){E=F[G];if(E&&E.event){D[G]=E.value;}}}return D;},getProperty:function(D){var E=this.config[D.toLowerCase()];if(E&&E.event){return E.value;}else{return undefined;}},resetProperty:function(D){D=D.toLowerCase();var E=this.config[D];if(E&&E.event){if(this.initialConfig[D]&&!B.isUndefined(this.initialConfig[D])){this.setProperty(D,this.initialConfig[D]);return true;}}else{return false;}},setProperty:function(E,G,D){var F;E=E.toLowerCase();if(this.queueInProgress&&!D){this.queueProperty(E,G);return true;}else{F=this.config[E];if(F&&F.event){if(F.validator&&!F.validator(G)){return false;}else{F.value=G;if(!D){this.fireEvent(E,G);this.configChangedEvent.fire([E,G]);}return true;}}else{return false;}}},queueProperty:function(S,P){S=S.toLowerCase();var R=this.config[S],K=false,J,G,H,I,O,Q,F,M,N,D,L,T,E;if(R&&R.event){if(!B.isUndefined(P)&&R.validator&&!R.validator(P)){return false;}else{if(!B.isUndefined(P)){R.value=P;}else{P=R.value;}K=false;J=this.eventQueue.length;for(L=0;L<J;L++){G=this.eventQueue[L];if(G){H=G[0];I=G[1];if(H==S){this.eventQueue[L]=null;this.eventQueue.push([S,(!B.isUndefined(P)?P:I)]);K=true;break;}}}if(!K&&!B.isUndefined(P)){this.eventQueue.push([S,P]);}}if(R.supercedes){O=R.supercedes.length;for(T=0;T<O;T++){Q=R.supercedes[T];F=this.eventQueue.length;for(E=0;E<F;E++){M=this.eventQueue[E];if(M){N=M[0];D=M[1];if(N==Q.toLowerCase()){this.eventQueue.push([N,D]);this.eventQueue[E]=null;break;}}}}}return true;}else{return false;}},refireEvent:function(D){D=D.toLowerCase();var E=this.config[D];if(E&&E.event&&!B.isUndefined(E.value)){if(this.queueInProgress){this.queueProperty(D);}else{this.fireEvent(D,E.value);}}},applyConfig:function(D,G){var F,E;if(G){E={};for(F in D){if(B.hasOwnProperty(D,F)){E[F.toLowerCase()]=D[F];}}this.initialConfig=E;}for(F in D){if(B.hasOwnProperty(D,F)){this.queueProperty(F,D[F]);}}},refresh:function(){var D;for(D in this.config){if(B.hasOwnProperty(this.config,D)){this.refireEvent(D);}}},fireQueue:function(){var E,H,D,G,F;this.queueInProgress=true;for(E=0;E<this.eventQueue.length;E++){H=this.eventQueue[E];if(H){D=H[0];G=H[1];F=this.config[D];F.value=G;this.eventQueue[E]=null;this.fireEvent(D,G);}}this.queueInProgress=false;this.eventQueue=[];},subscribeToConfigEvent:function(D,E,G,H){var F=this.config[D.toLowerCase()];if(F&&F.event){if(!A.alreadySubscribed(F.event,E,G)){F.event.subscribe(E,G,H);}return true;}else{return false;}},unsubscribeFromConfigEvent:function(D,E,G){var F=this.config[D.toLowerCase()];if(F&&F.event){return F.event.unsubscribe(E,G);}else{return false;}},toString:function(){var D="Config";if(this.owner){D+=" ["+this.owner.toString()+"]";}return D;},outputEventQueue:function(){var D="",G,E,F=this.eventQueue.length;for(E=0;E<F;E++){G=this.eventQueue[E];if(G){D+=G[0]+"="+G[1]+", ";}}return D;},destroy:function(){var E=this.config,D,F;for(D in E){if(B.hasOwnProperty(E,D)){F=E[D];F.event.unsubscribeAll();F.event=null;}}this.configChangedEvent.unsubscribeAll();this.configChangedEvent=null;this.owner=null;this.config=null;this.initialConfig=null;this.eventQueue=null;}};A.alreadySubscribed=function(E,H,I){var F=E.subscribers.length,D,G;if(F>0){G=F-1;do{D=E.subscribers[G];if(D&&D.obj==I&&D.fn==H){return true;}}while(G--);}return false;};YAHOO.lang.augmentProto(A,YAHOO.util.EventProvider);}());(function(){YAHOO.widget.Module=function(R,Q){if(R){this.init(R,Q);}else{}};var F=YAHOO.util.Dom,D=YAHOO.util.Config,N=YAHOO.util.Event,M=YAHOO.util.CustomEvent,G=YAHOO.widget.Module,I=YAHOO.env.ua,H,P,O,E,A={"BEFORE_INIT":"beforeInit","INIT":"init","APPEND":"append","BEFORE_RENDER":"beforeRender","RENDER":"render","CHANGE_HEADER":"changeHeader","CHANGE_BODY":"changeBody","CHANGE_FOOTER":"changeFooter","CHANGE_CONTENT":"changeContent","DESTROY":"destroy","BEFORE_SHOW":"beforeShow","SHOW":"show","BEFORE_HIDE":"beforeHide","HIDE":"hide"},J={"VISIBLE":{key:"visible",value:true,validator:YAHOO.lang.isBoolean},"EFFECT":{key:"effect",suppressEvent:true,supercedes:["visible"]},"MONITOR_RESIZE":{key:"monitorresize",value:true},"APPEND_TO_DOCUMENT_BODY":{key:"appendtodocumentbody",value:false}};G.IMG_ROOT=null;G.IMG_ROOT_SSL=null;G.CSS_MODULE="yui-module";G.CSS_HEADER="hd";G.CSS_BODY="bd";G.CSS_FOOTER="ft";G.RESIZE_MONITOR_SECURE_URL="javascript:false;";G.RESIZE_MONITOR_BUFFER=1;G.textResizeEvent=new M("textResize");G.forceDocumentRedraw=function(){var Q=document.documentElement;if(Q){Q.className+=" ";Q.className=YAHOO.lang.trim(Q.className);}};function L(){if(!H){H=document.createElement("div");H.innerHTML=('<div class="'+G.CSS_HEADER+'"></div>'+'<div class="'+G.CSS_BODY+'"></div><div class="'+G.CSS_FOOTER+'"></div>');P=H.firstChild;O=P.nextSibling;E=O.nextSibling;}return H;}function K(){if(!P){L();}return(P.cloneNode(false));}function B(){if(!O){L();}return(O.cloneNode(false));}function C(){if(!E){L();}return(E.cloneNode(false));}G.prototype={constructor:G,element:null,header:null,body:null,footer:null,id:null,imageRoot:G.IMG_ROOT,initEvents:function(){var Q=M.LIST;
8
this.beforeInitEvent=this.createEvent(A.BEFORE_INIT);this.beforeInitEvent.signature=Q;this.initEvent=this.createEvent(A.INIT);this.initEvent.signature=Q;this.appendEvent=this.createEvent(A.APPEND);this.appendEvent.signature=Q;this.beforeRenderEvent=this.createEvent(A.BEFORE_RENDER);this.beforeRenderEvent.signature=Q;this.renderEvent=this.createEvent(A.RENDER);this.renderEvent.signature=Q;this.changeHeaderEvent=this.createEvent(A.CHANGE_HEADER);this.changeHeaderEvent.signature=Q;this.changeBodyEvent=this.createEvent(A.CHANGE_BODY);this.changeBodyEvent.signature=Q;this.changeFooterEvent=this.createEvent(A.CHANGE_FOOTER);this.changeFooterEvent.signature=Q;this.changeContentEvent=this.createEvent(A.CHANGE_CONTENT);this.changeContentEvent.signature=Q;this.destroyEvent=this.createEvent(A.DESTROY);this.destroyEvent.signature=Q;this.beforeShowEvent=this.createEvent(A.BEFORE_SHOW);this.beforeShowEvent.signature=Q;this.showEvent=this.createEvent(A.SHOW);this.showEvent.signature=Q;this.beforeHideEvent=this.createEvent(A.BEFORE_HIDE);this.beforeHideEvent.signature=Q;this.hideEvent=this.createEvent(A.HIDE);this.hideEvent.signature=Q;},platform:function(){var Q=navigator.userAgent.toLowerCase();if(Q.indexOf("windows")!=-1||Q.indexOf("win32")!=-1){return"windows";}else{if(Q.indexOf("macintosh")!=-1){return"mac";}else{return false;}}}(),browser:function(){var Q=navigator.userAgent.toLowerCase();if(Q.indexOf("opera")!=-1){return"opera";}else{if(Q.indexOf("msie 7")!=-1){return"ie7";}else{if(Q.indexOf("msie")!=-1){return"ie";}else{if(Q.indexOf("safari")!=-1){return"safari";}else{if(Q.indexOf("gecko")!=-1){return"gecko";}else{return false;}}}}}}(),isSecure:function(){if(window.location.href.toLowerCase().indexOf("https")===0){return true;}else{return false;}}(),initDefaultConfig:function(){this.cfg.addProperty(J.VISIBLE.key,{handler:this.configVisible,value:J.VISIBLE.value,validator:J.VISIBLE.validator});this.cfg.addProperty(J.EFFECT.key,{suppressEvent:J.EFFECT.suppressEvent,supercedes:J.EFFECT.supercedes});this.cfg.addProperty(J.MONITOR_RESIZE.key,{handler:this.configMonitorResize,value:J.MONITOR_RESIZE.value});this.cfg.addProperty(J.APPEND_TO_DOCUMENT_BODY.key,{value:J.APPEND_TO_DOCUMENT_BODY.value});},init:function(V,U){var S,W;this.initEvents();this.beforeInitEvent.fire(G);this.cfg=new D(this);if(this.isSecure){this.imageRoot=G.IMG_ROOT_SSL;}if(typeof V=="string"){S=V;V=document.getElementById(V);if(!V){V=(L()).cloneNode(false);V.id=S;}}this.id=F.generateId(V);this.element=V;W=this.element.firstChild;if(W){var R=false,Q=false,T=false;do{if(1==W.nodeType){if(!R&&F.hasClass(W,G.CSS_HEADER)){this.header=W;R=true;}else{if(!Q&&F.hasClass(W,G.CSS_BODY)){this.body=W;Q=true;}else{if(!T&&F.hasClass(W,G.CSS_FOOTER)){this.footer=W;T=true;}}}}}while((W=W.nextSibling));}this.initDefaultConfig();F.addClass(this.element,G.CSS_MODULE);if(U){this.cfg.applyConfig(U,true);}if(!D.alreadySubscribed(this.renderEvent,this.cfg.fireQueue,this.cfg)){this.renderEvent.subscribe(this.cfg.fireQueue,this.cfg,true);}this.initEvent.fire(G);},initResizeMonitor:function(){var R=(I.gecko&&this.platform=="windows");if(R){var Q=this;setTimeout(function(){Q._initResizeMonitor();},0);}else{this._initResizeMonitor();}},_initResizeMonitor:function(){var Q,S,U;function W(){G.textResizeEvent.fire();}if(!I.opera){S=F.get("_yuiResizeMonitor");var V=this._supportsCWResize();if(!S){S=document.createElement("iframe");if(this.isSecure&&G.RESIZE_MONITOR_SECURE_URL&&I.ie){S.src=G.RESIZE_MONITOR_SECURE_URL;}if(!V){U=["<html><head><script ",'type="text/javascript">',"window.onresize=function(){window.parent.","YAHOO.widget.Module.textResizeEvent.","fire();};<","/script></head>","<body></body></html>"].join("");S.src="data:text/html;charset=utf-8,"+encodeURIComponent(U);}S.id="_yuiResizeMonitor";S.title="Text Resize Monitor";S.style.position="absolute";S.style.visibility="hidden";var R=document.body,T=R.firstChild;if(T){R.insertBefore(S,T);}else{R.appendChild(S);}S.style.backgroundColor="transparent";S.style.borderWidth="0";S.style.width="2em";S.style.height="2em";S.style.left="0";S.style.top=(-1*(S.offsetHeight+G.RESIZE_MONITOR_BUFFER))+"px";S.style.visibility="visible";if(I.webkit){Q=S.contentWindow.document;Q.open();Q.close();}}if(S&&S.contentWindow){G.textResizeEvent.subscribe(this.onDomResize,this,true);if(!G.textResizeInitialized){if(V){if(!N.on(S.contentWindow,"resize",W)){N.on(S,"resize",W);}}G.textResizeInitialized=true;}this.resizeMonitor=S;}}},_supportsCWResize:function(){var Q=true;if(I.gecko&&I.gecko<=1.8){Q=false;}return Q;},onDomResize:function(S,R){var Q=-1*(this.resizeMonitor.offsetHeight+G.RESIZE_MONITOR_BUFFER);this.resizeMonitor.style.top=Q+"px";this.resizeMonitor.style.left="0";},setHeader:function(R){var Q=this.header||(this.header=K());if(R.nodeName){Q.innerHTML="";Q.appendChild(R);}else{Q.innerHTML=R;}if(this._rendered){this._renderHeader();}this.changeHeaderEvent.fire(R);this.changeContentEvent.fire();},appendToHeader:function(R){var Q=this.header||(this.header=K());Q.appendChild(R);this.changeHeaderEvent.fire(R);this.changeContentEvent.fire();},setBody:function(R){var Q=this.body||(this.body=B());if(R.nodeName){Q.innerHTML="";Q.appendChild(R);}else{Q.innerHTML=R;}if(this._rendered){this._renderBody();}this.changeBodyEvent.fire(R);this.changeContentEvent.fire();},appendToBody:function(R){var Q=this.body||(this.body=B());Q.appendChild(R);this.changeBodyEvent.fire(R);this.changeContentEvent.fire();},setFooter:function(R){var Q=this.footer||(this.footer=C());if(R.nodeName){Q.innerHTML="";Q.appendChild(R);}else{Q.innerHTML=R;}if(this._rendered){this._renderFooter();}this.changeFooterEvent.fire(R);this.changeContentEvent.fire();},appendToFooter:function(R){var Q=this.footer||(this.footer=C());Q.appendChild(R);this.changeFooterEvent.fire(R);this.changeContentEvent.fire();},render:function(S,Q){var T=this;function R(U){if(typeof U=="string"){U=document.getElementById(U);}if(U){T._addToParent(U,T.element);T.appendEvent.fire();}}this.beforeRenderEvent.fire();
9
if(!Q){Q=this.element;}if(S){R(S);}else{if(!F.inDocument(this.element)){return false;}}this._renderHeader(Q);this._renderBody(Q);this._renderFooter(Q);this._rendered=true;this.renderEvent.fire();return true;},_renderHeader:function(Q){Q=Q||this.element;if(this.header&&!F.inDocument(this.header)){var R=Q.firstChild;if(R){Q.insertBefore(this.header,R);}else{Q.appendChild(this.header);}}},_renderBody:function(Q){Q=Q||this.element;if(this.body&&!F.inDocument(this.body)){if(this.footer&&F.isAncestor(Q,this.footer)){Q.insertBefore(this.body,this.footer);}else{Q.appendChild(this.body);}}},_renderFooter:function(Q){Q=Q||this.element;if(this.footer&&!F.inDocument(this.footer)){Q.appendChild(this.footer);}},destroy:function(){var Q;if(this.element){N.purgeElement(this.element,true);Q=this.element.parentNode;}if(Q){Q.removeChild(this.element);}this.element=null;this.header=null;this.body=null;this.footer=null;G.textResizeEvent.unsubscribe(this.onDomResize,this);this.cfg.destroy();this.cfg=null;this.destroyEvent.fire();},show:function(){this.cfg.setProperty("visible",true);},hide:function(){this.cfg.setProperty("visible",false);},configVisible:function(R,Q,S){var T=Q[0];if(T){this.beforeShowEvent.fire();F.setStyle(this.element,"display","block");this.showEvent.fire();}else{this.beforeHideEvent.fire();F.setStyle(this.element,"display","none");this.hideEvent.fire();}},configMonitorResize:function(S,R,T){var Q=R[0];if(Q){this.initResizeMonitor();}else{G.textResizeEvent.unsubscribe(this.onDomResize,this,true);this.resizeMonitor=null;}},_addToParent:function(Q,R){if(!this.cfg.getProperty("appendtodocumentbody")&&Q===document.body&&Q.firstChild){Q.insertBefore(R,Q.firstChild);}else{Q.appendChild(R);}},toString:function(){return"Module "+this.id;}};YAHOO.lang.augmentProto(G,YAHOO.util.EventProvider);}());(function(){YAHOO.widget.Overlay=function(P,O){YAHOO.widget.Overlay.superclass.constructor.call(this,P,O);};var I=YAHOO.lang,M=YAHOO.util.CustomEvent,G=YAHOO.widget.Module,N=YAHOO.util.Event,F=YAHOO.util.Dom,D=YAHOO.util.Config,K=YAHOO.env.ua,B=YAHOO.widget.Overlay,H="subscribe",E="unsubscribe",C="contained",J,A={"BEFORE_MOVE":"beforeMove","MOVE":"move"},L={"X":{key:"x",validator:I.isNumber,suppressEvent:true,supercedes:["iframe"]},"Y":{key:"y",validator:I.isNumber,suppressEvent:true,supercedes:["iframe"]},"XY":{key:"xy",suppressEvent:true,supercedes:["iframe"]},"CONTEXT":{key:"context",suppressEvent:true,supercedes:["iframe"]},"FIXED_CENTER":{key:"fixedcenter",value:false,supercedes:["iframe","visible"]},"WIDTH":{key:"width",suppressEvent:true,supercedes:["context","fixedcenter","iframe"]},"HEIGHT":{key:"height",suppressEvent:true,supercedes:["context","fixedcenter","iframe"]},"AUTO_FILL_HEIGHT":{key:"autofillheight",supercedes:["height"],value:"body"},"ZINDEX":{key:"zindex",value:null},"CONSTRAIN_TO_VIEWPORT":{key:"constraintoviewport",value:false,validator:I.isBoolean,supercedes:["iframe","x","y","xy"]},"IFRAME":{key:"iframe",value:(K.ie==6?true:false),validator:I.isBoolean,supercedes:["zindex"]},"PREVENT_CONTEXT_OVERLAP":{key:"preventcontextoverlap",value:false,validator:I.isBoolean,supercedes:["constraintoviewport"]}};B.IFRAME_SRC="javascript:false;";B.IFRAME_OFFSET=3;B.VIEWPORT_OFFSET=10;B.TOP_LEFT="tl";B.TOP_RIGHT="tr";B.BOTTOM_LEFT="bl";B.BOTTOM_RIGHT="br";B.PREVENT_OVERLAP_X={"tltr":true,"blbr":true,"brbl":true,"trtl":true};B.PREVENT_OVERLAP_Y={"trbr":true,"tlbl":true,"bltl":true,"brtr":true};B.CSS_OVERLAY="yui-overlay";B.CSS_HIDDEN="yui-overlay-hidden";B.CSS_IFRAME="yui-overlay-iframe";B.STD_MOD_RE=/^\s*?(body|footer|header)\s*?$/i;B.windowScrollEvent=new M("windowScroll");B.windowResizeEvent=new M("windowResize");B.windowScrollHandler=function(P){var O=N.getTarget(P);if(!O||O===window||O===window.document){if(K.ie){if(!window.scrollEnd){window.scrollEnd=-1;}clearTimeout(window.scrollEnd);window.scrollEnd=setTimeout(function(){B.windowScrollEvent.fire();},1);}else{B.windowScrollEvent.fire();}}};B.windowResizeHandler=function(O){if(K.ie){if(!window.resizeEnd){window.resizeEnd=-1;}clearTimeout(window.resizeEnd);window.resizeEnd=setTimeout(function(){B.windowResizeEvent.fire();},100);}else{B.windowResizeEvent.fire();}};B._initialized=null;if(B._initialized===null){N.on(window,"scroll",B.windowScrollHandler);N.on(window,"resize",B.windowResizeHandler);B._initialized=true;}B._TRIGGER_MAP={"windowScroll":B.windowScrollEvent,"windowResize":B.windowResizeEvent,"textResize":G.textResizeEvent};YAHOO.extend(B,G,{CONTEXT_TRIGGERS:[],init:function(P,O){B.superclass.init.call(this,P);this.beforeInitEvent.fire(B);F.addClass(this.element,B.CSS_OVERLAY);if(O){this.cfg.applyConfig(O,true);}if(this.platform=="mac"&&K.gecko){if(!D.alreadySubscribed(this.showEvent,this.showMacGeckoScrollbars,this)){this.showEvent.subscribe(this.showMacGeckoScrollbars,this,true);}if(!D.alreadySubscribed(this.hideEvent,this.hideMacGeckoScrollbars,this)){this.hideEvent.subscribe(this.hideMacGeckoScrollbars,this,true);}}this.initEvent.fire(B);},initEvents:function(){B.superclass.initEvents.call(this);var O=M.LIST;this.beforeMoveEvent=this.createEvent(A.BEFORE_MOVE);this.beforeMoveEvent.signature=O;this.moveEvent=this.createEvent(A.MOVE);this.moveEvent.signature=O;},initDefaultConfig:function(){B.superclass.initDefaultConfig.call(this);var O=this.cfg;O.addProperty(L.X.key,{handler:this.configX,validator:L.X.validator,suppressEvent:L.X.suppressEvent,supercedes:L.X.supercedes});O.addProperty(L.Y.key,{handler:this.configY,validator:L.Y.validator,suppressEvent:L.Y.suppressEvent,supercedes:L.Y.supercedes});O.addProperty(L.XY.key,{handler:this.configXY,suppressEvent:L.XY.suppressEvent,supercedes:L.XY.supercedes});O.addProperty(L.CONTEXT.key,{handler:this.configContext,suppressEvent:L.CONTEXT.suppressEvent,supercedes:L.CONTEXT.supercedes});O.addProperty(L.FIXED_CENTER.key,{handler:this.configFixedCenter,value:L.FIXED_CENTER.value,validator:L.FIXED_CENTER.validator,supercedes:L.FIXED_CENTER.supercedes});O.addProperty(L.WIDTH.key,{handler:this.configWidth,suppressEvent:L.WIDTH.suppressEvent,supercedes:L.WIDTH.supercedes});
10
O.addProperty(L.HEIGHT.key,{handler:this.configHeight,suppressEvent:L.HEIGHT.suppressEvent,supercedes:L.HEIGHT.supercedes});O.addProperty(L.AUTO_FILL_HEIGHT.key,{handler:this.configAutoFillHeight,value:L.AUTO_FILL_HEIGHT.value,validator:this._validateAutoFill,supercedes:L.AUTO_FILL_HEIGHT.supercedes});O.addProperty(L.ZINDEX.key,{handler:this.configzIndex,value:L.ZINDEX.value});O.addProperty(L.CONSTRAIN_TO_VIEWPORT.key,{handler:this.configConstrainToViewport,value:L.CONSTRAIN_TO_VIEWPORT.value,validator:L.CONSTRAIN_TO_VIEWPORT.validator,supercedes:L.CONSTRAIN_TO_VIEWPORT.supercedes});O.addProperty(L.IFRAME.key,{handler:this.configIframe,value:L.IFRAME.value,validator:L.IFRAME.validator,supercedes:L.IFRAME.supercedes});O.addProperty(L.PREVENT_CONTEXT_OVERLAP.key,{value:L.PREVENT_CONTEXT_OVERLAP.value,validator:L.PREVENT_CONTEXT_OVERLAP.validator,supercedes:L.PREVENT_CONTEXT_OVERLAP.supercedes});},moveTo:function(O,P){this.cfg.setProperty("xy",[O,P]);},hideMacGeckoScrollbars:function(){F.replaceClass(this.element,"show-scrollbars","hide-scrollbars");},showMacGeckoScrollbars:function(){F.replaceClass(this.element,"hide-scrollbars","show-scrollbars");},_setDomVisibility:function(O){F.setStyle(this.element,"visibility",(O)?"visible":"hidden");var P=B.CSS_HIDDEN;if(O){F.removeClass(this.element,P);}else{F.addClass(this.element,P);}},configVisible:function(R,O,X){var Q=O[0],S=F.getStyle(this.element,"visibility"),Y=this.cfg.getProperty("effect"),V=[],U=(this.platform=="mac"&&K.gecko),g=D.alreadySubscribed,W,P,f,c,b,a,d,Z,T;if(S=="inherit"){f=this.element.parentNode;while(f.nodeType!=9&&f.nodeType!=11){S=F.getStyle(f,"visibility");if(S!="inherit"){break;}f=f.parentNode;}if(S=="inherit"){S="visible";}}if(Y){if(Y instanceof Array){Z=Y.length;for(c=0;c<Z;c++){W=Y[c];V[V.length]=W.effect(this,W.duration);}}else{V[V.length]=Y.effect(this,Y.duration);}}if(Q){if(U){this.showMacGeckoScrollbars();}if(Y){if(Q){if(S!="visible"||S===""){this.beforeShowEvent.fire();T=V.length;for(b=0;b<T;b++){P=V[b];if(b===0&&!g(P.animateInCompleteEvent,this.showEvent.fire,this.showEvent)){P.animateInCompleteEvent.subscribe(this.showEvent.fire,this.showEvent,true);}P.animateIn();}}}}else{if(S!="visible"||S===""){this.beforeShowEvent.fire();this._setDomVisibility(true);this.cfg.refireEvent("iframe");this.showEvent.fire();}else{this._setDomVisibility(true);}}}else{if(U){this.hideMacGeckoScrollbars();}if(Y){if(S=="visible"){this.beforeHideEvent.fire();T=V.length;for(a=0;a<T;a++){d=V[a];if(a===0&&!g(d.animateOutCompleteEvent,this.hideEvent.fire,this.hideEvent)){d.animateOutCompleteEvent.subscribe(this.hideEvent.fire,this.hideEvent,true);}d.animateOut();}}else{if(S===""){this._setDomVisibility(false);}}}else{if(S=="visible"||S===""){this.beforeHideEvent.fire();this._setDomVisibility(false);this.hideEvent.fire();}else{this._setDomVisibility(false);}}}},doCenterOnDOMEvent:function(){var O=this.cfg,P=O.getProperty("fixedcenter");if(O.getProperty("visible")){if(P&&(P!==C||this.fitsInViewport())){this.center();}}},fitsInViewport:function(){var S=B.VIEWPORT_OFFSET,Q=this.element,T=Q.offsetWidth,R=Q.offsetHeight,O=F.getViewportWidth(),P=F.getViewportHeight();return((T+S<O)&&(R+S<P));},configFixedCenter:function(S,Q,T){var U=Q[0],P=D.alreadySubscribed,R=B.windowResizeEvent,O=B.windowScrollEvent;if(U){this.center();if(!P(this.beforeShowEvent,this.center)){this.beforeShowEvent.subscribe(this.center);}if(!P(R,this.doCenterOnDOMEvent,this)){R.subscribe(this.doCenterOnDOMEvent,this,true);}if(!P(O,this.doCenterOnDOMEvent,this)){O.subscribe(this.doCenterOnDOMEvent,this,true);}}else{this.beforeShowEvent.unsubscribe(this.center);R.unsubscribe(this.doCenterOnDOMEvent,this);O.unsubscribe(this.doCenterOnDOMEvent,this);}},configHeight:function(R,P,S){var O=P[0],Q=this.element;F.setStyle(Q,"height",O);this.cfg.refireEvent("iframe");},configAutoFillHeight:function(T,S,P){var V=S[0],Q=this.cfg,U="autofillheight",W="height",R=Q.getProperty(U),O=this._autoFillOnHeightChange;Q.unsubscribeFromConfigEvent(W,O);G.textResizeEvent.unsubscribe(O);this.changeContentEvent.unsubscribe(O);if(R&&V!==R&&this[R]){F.setStyle(this[R],W,"");}if(V){V=I.trim(V.toLowerCase());Q.subscribeToConfigEvent(W,O,this[V],this);G.textResizeEvent.subscribe(O,this[V],this);this.changeContentEvent.subscribe(O,this[V],this);Q.setProperty(U,V,true);}},configWidth:function(R,O,S){var Q=O[0],P=this.element;F.setStyle(P,"width",Q);this.cfg.refireEvent("iframe");},configzIndex:function(Q,O,R){var S=O[0],P=this.element;if(!S){S=F.getStyle(P,"zIndex");if(!S||isNaN(S)){S=0;}}if(this.iframe||this.cfg.getProperty("iframe")===true){if(S<=0){S=1;}}F.setStyle(P,"zIndex",S);this.cfg.setProperty("zIndex",S,true);if(this.iframe){this.stackIframe();}},configXY:function(Q,P,R){var T=P[0],O=T[0],S=T[1];this.cfg.setProperty("x",O);this.cfg.setProperty("y",S);this.beforeMoveEvent.fire([O,S]);O=this.cfg.getProperty("x");S=this.cfg.getProperty("y");this.cfg.refireEvent("iframe");this.moveEvent.fire([O,S]);},configX:function(Q,P,R){var O=P[0],S=this.cfg.getProperty("y");this.cfg.setProperty("x",O,true);this.cfg.setProperty("y",S,true);this.beforeMoveEvent.fire([O,S]);O=this.cfg.getProperty("x");S=this.cfg.getProperty("y");F.setX(this.element,O,true);this.cfg.setProperty("xy",[O,S],true);this.cfg.refireEvent("iframe");this.moveEvent.fire([O,S]);},configY:function(Q,P,R){var O=this.cfg.getProperty("x"),S=P[0];this.cfg.setProperty("x",O,true);this.cfg.setProperty("y",S,true);this.beforeMoveEvent.fire([O,S]);O=this.cfg.getProperty("x");S=this.cfg.getProperty("y");F.setY(this.element,S,true);this.cfg.setProperty("xy",[O,S],true);this.cfg.refireEvent("iframe");this.moveEvent.fire([O,S]);},showIframe:function(){var P=this.iframe,O;if(P){O=this.element.parentNode;if(O!=P.parentNode){this._addToParent(O,P);}P.style.display="block";}},hideIframe:function(){if(this.iframe){this.iframe.style.display="none";}},syncIframe:function(){var O=this.iframe,Q=this.element,S=B.IFRAME_OFFSET,P=(S*2),R;if(O){O.style.width=(Q.offsetWidth+P+"px");
11
O.style.height=(Q.offsetHeight+P+"px");R=this.cfg.getProperty("xy");if(!I.isArray(R)||(isNaN(R[0])||isNaN(R[1]))){this.syncPosition();R=this.cfg.getProperty("xy");}F.setXY(O,[(R[0]-S),(R[1]-S)]);}},stackIframe:function(){if(this.iframe){var O=F.getStyle(this.element,"zIndex");if(!YAHOO.lang.isUndefined(O)&&!isNaN(O)){F.setStyle(this.iframe,"zIndex",(O-1));}}},configIframe:function(R,Q,S){var O=Q[0];function T(){var V=this.iframe,W=this.element,X;if(!V){if(!J){J=document.createElement("iframe");if(this.isSecure){J.src=B.IFRAME_SRC;}if(K.ie){J.style.filter="alpha(opacity=0)";J.frameBorder=0;}else{J.style.opacity="0";}J.style.position="absolute";J.style.border="none";J.style.margin="0";J.style.padding="0";J.style.display="none";J.tabIndex=-1;J.className=B.CSS_IFRAME;}V=J.cloneNode(false);V.id=this.id+"_f";X=W.parentNode;var U=X||document.body;this._addToParent(U,V);this.iframe=V;}this.showIframe();this.syncIframe();this.stackIframe();if(!this._hasIframeEventListeners){this.showEvent.subscribe(this.showIframe);this.hideEvent.subscribe(this.hideIframe);this.changeContentEvent.subscribe(this.syncIframe);this._hasIframeEventListeners=true;}}function P(){T.call(this);this.beforeShowEvent.unsubscribe(P);this._iframeDeferred=false;}if(O){if(this.cfg.getProperty("visible")){T.call(this);}else{if(!this._iframeDeferred){this.beforeShowEvent.subscribe(P);this._iframeDeferred=true;}}}else{this.hideIframe();if(this._hasIframeEventListeners){this.showEvent.unsubscribe(this.showIframe);this.hideEvent.unsubscribe(this.hideIframe);this.changeContentEvent.unsubscribe(this.syncIframe);this._hasIframeEventListeners=false;}}},_primeXYFromDOM:function(){if(YAHOO.lang.isUndefined(this.cfg.getProperty("xy"))){this.syncPosition();this.cfg.refireEvent("xy");this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);}},configConstrainToViewport:function(P,O,Q){var R=O[0];if(R){if(!D.alreadySubscribed(this.beforeMoveEvent,this.enforceConstraints,this)){this.beforeMoveEvent.subscribe(this.enforceConstraints,this,true);}if(!D.alreadySubscribed(this.beforeShowEvent,this._primeXYFromDOM)){this.beforeShowEvent.subscribe(this._primeXYFromDOM);}}else{this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);this.beforeMoveEvent.unsubscribe(this.enforceConstraints,this);}},configContext:function(U,T,Q){var X=T[0],R,O,V,S,P,W=this.CONTEXT_TRIGGERS;if(X){R=X[0];O=X[1];V=X[2];S=X[3];P=X[4];if(W&&W.length>0){S=(S||[]).concat(W);}if(R){if(typeof R=="string"){this.cfg.setProperty("context",[document.getElementById(R),O,V,S,P],true);}if(O&&V){this.align(O,V,P);}if(this._contextTriggers){this._processTriggers(this._contextTriggers,E,this._alignOnTrigger);}if(S){this._processTriggers(S,H,this._alignOnTrigger);this._contextTriggers=S;}}}},_alignOnTrigger:function(P,O){this.align();},_findTriggerCE:function(O){var P=null;if(O instanceof M){P=O;}else{if(B._TRIGGER_MAP[O]){P=B._TRIGGER_MAP[O];}}return P;},_processTriggers:function(S,U,R){var Q,T;for(var P=0,O=S.length;P<O;++P){Q=S[P];T=this._findTriggerCE(Q);if(T){T[U](R,this,true);}else{this[U](Q,R);}}},align:function(P,W,S){var V=this.cfg.getProperty("context"),T=this,O,Q,U;function R(Z,a){var Y=null,X=null;switch(P){case B.TOP_LEFT:Y=a;X=Z;break;case B.TOP_RIGHT:Y=a-Q.offsetWidth;X=Z;break;case B.BOTTOM_LEFT:Y=a;X=Z-Q.offsetHeight;break;case B.BOTTOM_RIGHT:Y=a-Q.offsetWidth;X=Z-Q.offsetHeight;break;}if(Y!==null&&X!==null){if(S){Y+=S[0];X+=S[1];}T.moveTo(Y,X);}}if(V){O=V[0];Q=this.element;T=this;if(!P){P=V[1];}if(!W){W=V[2];}if(!S&&V[4]){S=V[4];}if(Q&&O){U=F.getRegion(O);switch(W){case B.TOP_LEFT:R(U.top,U.left);break;case B.TOP_RIGHT:R(U.top,U.right);break;case B.BOTTOM_LEFT:R(U.bottom,U.left);break;case B.BOTTOM_RIGHT:R(U.bottom,U.right);break;}}}},enforceConstraints:function(P,O,Q){var S=O[0];var R=this.getConstrainedXY(S[0],S[1]);this.cfg.setProperty("x",R[0],true);this.cfg.setProperty("y",R[1],true);this.cfg.setProperty("xy",R,true);},_getConstrainedPos:function(X,P){var T=this.element,R=B.VIEWPORT_OFFSET,Z=(X=="x"),Y=(Z)?T.offsetWidth:T.offsetHeight,S=(Z)?F.getViewportWidth():F.getViewportHeight(),c=(Z)?F.getDocumentScrollLeft():F.getDocumentScrollTop(),b=(Z)?B.PREVENT_OVERLAP_X:B.PREVENT_OVERLAP_Y,O=this.cfg.getProperty("context"),U=(Y+R<S),W=this.cfg.getProperty("preventcontextoverlap")&&O&&b[(O[1]+O[2])],V=c+R,a=c+S-Y-R,Q=P;if(P<V||P>a){if(W){Q=this._preventOverlap(X,O[0],Y,S,c);}else{if(U){if(P<V){Q=V;}else{if(P>a){Q=a;}}}else{Q=V;}}}return Q;},_preventOverlap:function(X,W,Y,U,b){var Z=(X=="x"),T=B.VIEWPORT_OFFSET,S=this,Q=((Z)?F.getX(W):F.getY(W))-b,O=(Z)?W.offsetWidth:W.offsetHeight,P=Q-T,R=(U-(Q+O))-T,c=false,V=function(){var d;if((S.cfg.getProperty(X)-b)>Q){d=(Q-Y);}else{d=(Q+O);}S.cfg.setProperty(X,(d+b),true);return d;},a=function(){var e=((S.cfg.getProperty(X)-b)>Q)?R:P,d;if(Y>e){if(c){V();}else{V();c=true;d=a();}}return d;};a();return this.cfg.getProperty(X);},getConstrainedX:function(O){return this._getConstrainedPos("x",O);},getConstrainedY:function(O){return this._getConstrainedPos("y",O);},getConstrainedXY:function(O,P){return[this.getConstrainedX(O),this.getConstrainedY(P)];},center:function(){var R=B.VIEWPORT_OFFSET,S=this.element.offsetWidth,Q=this.element.offsetHeight,P=F.getViewportWidth(),T=F.getViewportHeight(),O,U;if(S<P){O=(P/2)-(S/2)+F.getDocumentScrollLeft();}else{O=R+F.getDocumentScrollLeft();}if(Q<T){U=(T/2)-(Q/2)+F.getDocumentScrollTop();}else{U=R+F.getDocumentScrollTop();}this.cfg.setProperty("xy",[parseInt(O,10),parseInt(U,10)]);this.cfg.refireEvent("iframe");if(K.webkit){this.forceContainerRedraw();}},syncPosition:function(){var O=F.getXY(this.element);this.cfg.setProperty("x",O[0],true);this.cfg.setProperty("y",O[1],true);this.cfg.setProperty("xy",O,true);},onDomResize:function(Q,P){var O=this;B.superclass.onDomResize.call(this,Q,P);setTimeout(function(){O.syncPosition();O.cfg.refireEvent("iframe");O.cfg.refireEvent("context");},0);},_getComputedHeight:(function(){if(document.defaultView&&document.defaultView.getComputedStyle){return function(P){var O=null;
12
if(P.ownerDocument&&P.ownerDocument.defaultView){var Q=P.ownerDocument.defaultView.getComputedStyle(P,"");if(Q){O=parseInt(Q.height,10);}}return(I.isNumber(O))?O:null;};}else{return function(P){var O=null;if(P.style.pixelHeight){O=P.style.pixelHeight;}return(I.isNumber(O))?O:null;};}})(),_validateAutoFillHeight:function(O){return(!O)||(I.isString(O)&&B.STD_MOD_RE.test(O));},_autoFillOnHeightChange:function(R,P,Q){var O=this.cfg.getProperty("height");if((O&&O!=="auto")||(O===0)){this.fillHeight(Q);}},_getPreciseHeight:function(P){var O=P.offsetHeight;if(P.getBoundingClientRect){var Q=P.getBoundingClientRect();O=Q.bottom-Q.top;}return O;},fillHeight:function(R){if(R){var P=this.innerElement||this.element,O=[this.header,this.body,this.footer],V,W=0,X=0,T=0,Q=false;for(var U=0,S=O.length;U<S;U++){V=O[U];if(V){if(R!==V){X+=this._getPreciseHeight(V);}else{Q=true;}}}if(Q){if(K.ie||K.opera){F.setStyle(R,"height",0+"px");}W=this._getComputedHeight(P);if(W===null){F.addClass(P,"yui-override-padding");W=P.clientHeight;F.removeClass(P,"yui-override-padding");}T=Math.max(W-X,0);F.setStyle(R,"height",T+"px");if(R.offsetHeight!=T){T=Math.max(T-(R.offsetHeight-T),0);}F.setStyle(R,"height",T+"px");}}},bringToTop:function(){var S=[],R=this.element;function V(Z,Y){var b=F.getStyle(Z,"zIndex"),a=F.getStyle(Y,"zIndex"),X=(!b||isNaN(b))?0:parseInt(b,10),W=(!a||isNaN(a))?0:parseInt(a,10);if(X>W){return -1;}else{if(X<W){return 1;}else{return 0;}}}function Q(Y){var X=F.hasClass(Y,B.CSS_OVERLAY),W=YAHOO.widget.Panel;if(X&&!F.isAncestor(R,Y)){if(W&&F.hasClass(Y,W.CSS_PANEL)){S[S.length]=Y.parentNode;}else{S[S.length]=Y;}}}F.getElementsBy(Q,"DIV",document.body);S.sort(V);var O=S[0],U;if(O){U=F.getStyle(O,"zIndex");if(!isNaN(U)){var T=false;if(O!=R){T=true;}else{if(S.length>1){var P=F.getStyle(S[1],"zIndex");if(!isNaN(P)&&(U==P)){T=true;}}}if(T){this.cfg.setProperty("zindex",(parseInt(U,10)+2));}}}},destroy:function(){if(this.iframe){this.iframe.parentNode.removeChild(this.iframe);}this.iframe=null;B.windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent,this);B.windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent,this);G.textResizeEvent.unsubscribe(this._autoFillOnHeightChange);if(this._contextTriggers){this._processTriggers(this._contextTriggers,E,this._alignOnTrigger);}B.superclass.destroy.call(this);},forceContainerRedraw:function(){var O=this;F.addClass(O.element,"yui-force-redraw");setTimeout(function(){F.removeClass(O.element,"yui-force-redraw");},0);},toString:function(){return"Overlay "+this.id;}});}());(function(){YAHOO.widget.OverlayManager=function(G){this.init(G);};var D=YAHOO.widget.Overlay,C=YAHOO.util.Event,E=YAHOO.util.Dom,B=YAHOO.util.Config,F=YAHOO.util.CustomEvent,A=YAHOO.widget.OverlayManager;A.CSS_FOCUSED="focused";A.prototype={constructor:A,overlays:null,initDefaultConfig:function(){this.cfg.addProperty("overlays",{suppressEvent:true});this.cfg.addProperty("focusevent",{value:"mousedown"});},init:function(I){this.cfg=new B(this);this.initDefaultConfig();if(I){this.cfg.applyConfig(I,true);}this.cfg.fireQueue();var H=null;this.getActive=function(){return H;};this.focus=function(J){var K=this.find(J);if(K){K.focus();}};this.remove=function(K){var M=this.find(K),J;if(M){if(H==M){H=null;}var L=(M.element===null&&M.cfg===null)?true:false;if(!L){J=E.getStyle(M.element,"zIndex");M.cfg.setProperty("zIndex",-1000,true);}this.overlays.sort(this.compareZIndexDesc);this.overlays=this.overlays.slice(0,(this.overlays.length-1));M.hideEvent.unsubscribe(M.blur);M.destroyEvent.unsubscribe(this._onOverlayDestroy,M);M.focusEvent.unsubscribe(this._onOverlayFocusHandler,M);M.blurEvent.unsubscribe(this._onOverlayBlurHandler,M);if(!L){C.removeListener(M.element,this.cfg.getProperty("focusevent"),this._onOverlayElementFocus);M.cfg.setProperty("zIndex",J,true);M.cfg.setProperty("manager",null);}if(M.focusEvent._managed){M.focusEvent=null;}if(M.blurEvent._managed){M.blurEvent=null;}if(M.focus._managed){M.focus=null;}if(M.blur._managed){M.blur=null;}}};this.blurAll=function(){var K=this.overlays.length,J;if(K>0){J=K-1;do{this.overlays[J].blur();}while(J--);}};this._manageBlur=function(J){var K=false;if(H==J){E.removeClass(H.element,A.CSS_FOCUSED);H=null;K=true;}return K;};this._manageFocus=function(J){var K=false;if(H!=J){if(H){H.blur();}H=J;this.bringToTop(H);E.addClass(H.element,A.CSS_FOCUSED);K=true;}return K;};var G=this.cfg.getProperty("overlays");if(!this.overlays){this.overlays=[];}if(G){this.register(G);this.overlays.sort(this.compareZIndexDesc);}},_onOverlayElementFocus:function(I){var G=C.getTarget(I),H=this.close;if(H&&(G==H||E.isAncestor(H,G))){this.blur();}else{this.focus();}},_onOverlayDestroy:function(H,G,I){this.remove(I);},_onOverlayFocusHandler:function(H,G,I){this._manageFocus(I);},_onOverlayBlurHandler:function(H,G,I){this._manageBlur(I);},_bindFocus:function(G){var H=this;if(!G.focusEvent){G.focusEvent=G.createEvent("focus");G.focusEvent.signature=F.LIST;G.focusEvent._managed=true;}else{G.focusEvent.subscribe(H._onOverlayFocusHandler,G,H);}if(!G.focus){C.on(G.element,H.cfg.getProperty("focusevent"),H._onOverlayElementFocus,null,G);G.focus=function(){if(H._manageFocus(this)){if(this.cfg.getProperty("visible")&&this.focusFirst){this.focusFirst();}this.focusEvent.fire();}};G.focus._managed=true;}},_bindBlur:function(G){var H=this;if(!G.blurEvent){G.blurEvent=G.createEvent("blur");G.blurEvent.signature=F.LIST;G.focusEvent._managed=true;}else{G.blurEvent.subscribe(H._onOverlayBlurHandler,G,H);}if(!G.blur){G.blur=function(){if(H._manageBlur(this)){this.blurEvent.fire();}};G.blur._managed=true;}G.hideEvent.subscribe(G.blur);},_bindDestroy:function(G){var H=this;G.destroyEvent.subscribe(H._onOverlayDestroy,G,H);},_syncZIndex:function(G){var H=E.getStyle(G.element,"zIndex");if(!isNaN(H)){G.cfg.setProperty("zIndex",parseInt(H,10));}else{G.cfg.setProperty("zIndex",0);}},register:function(G){var J=false,H,I;if(G instanceof D){G.cfg.addProperty("manager",{value:this});this._bindFocus(G);this._bindBlur(G);this._bindDestroy(G);
13
this._syncZIndex(G);this.overlays.push(G);this.bringToTop(G);J=true;}else{if(G instanceof Array){for(H=0,I=G.length;H<I;H++){J=this.register(G[H])||J;}}}return J;},bringToTop:function(M){var I=this.find(M),L,G,J;if(I){J=this.overlays;J.sort(this.compareZIndexDesc);G=J[0];if(G){L=E.getStyle(G.element,"zIndex");if(!isNaN(L)){var K=false;if(G!==I){K=true;}else{if(J.length>1){var H=E.getStyle(J[1].element,"zIndex");if(!isNaN(H)&&(L==H)){K=true;}}}if(K){I.cfg.setProperty("zindex",(parseInt(L,10)+2));}}J.sort(this.compareZIndexDesc);}}},find:function(G){var K=G instanceof D,I=this.overlays,M=I.length,J=null,L,H;if(K||typeof G=="string"){for(H=M-1;H>=0;H--){L=I[H];if((K&&(L===G))||(L.id==G)){J=L;break;}}}return J;},compareZIndexDesc:function(J,I){var H=(J.cfg)?J.cfg.getProperty("zIndex"):null,G=(I.cfg)?I.cfg.getProperty("zIndex"):null;if(H===null&&G===null){return 0;}else{if(H===null){return 1;}else{if(G===null){return -1;}else{if(H>G){return -1;}else{if(H<G){return 1;}else{return 0;}}}}}},showAll:function(){var H=this.overlays,I=H.length,G;for(G=I-1;G>=0;G--){H[G].show();}},hideAll:function(){var H=this.overlays,I=H.length,G;for(G=I-1;G>=0;G--){H[G].hide();}},toString:function(){return"OverlayManager";}};}());(function(){YAHOO.widget.ContainerEffect=function(E,H,G,D,F){if(!F){F=YAHOO.util.Anim;}this.overlay=E;this.attrIn=H;this.attrOut=G;this.targetElement=D||E.element;this.animClass=F;};var B=YAHOO.util.Dom,C=YAHOO.util.CustomEvent,A=YAHOO.widget.ContainerEffect;A.FADE=function(D,F){var G=YAHOO.util.Easing,I={attributes:{opacity:{from:0,to:1}},duration:F,method:G.easeIn},E={attributes:{opacity:{to:0}},duration:F,method:G.easeOut},H=new A(D,I,E,D.element);H.handleUnderlayStart=function(){var K=this.overlay.underlay;if(K&&YAHOO.env.ua.ie){var J=(K.filters&&K.filters.length>0);if(J){B.addClass(D.element,"yui-effect-fade");}}};H.handleUnderlayComplete=function(){var J=this.overlay.underlay;if(J&&YAHOO.env.ua.ie){B.removeClass(D.element,"yui-effect-fade");}};H.handleStartAnimateIn=function(K,J,L){B.addClass(L.overlay.element,"hide-select");if(!L.overlay.underlay){L.overlay.cfg.refireEvent("underlay");}L.handleUnderlayStart();L.overlay._setDomVisibility(true);B.setStyle(L.overlay.element,"opacity",0);};H.handleCompleteAnimateIn=function(K,J,L){B.removeClass(L.overlay.element,"hide-select");if(L.overlay.element.style.filter){L.overlay.element.style.filter=null;}L.handleUnderlayComplete();L.overlay.cfg.refireEvent("iframe");L.animateInCompleteEvent.fire();};H.handleStartAnimateOut=function(K,J,L){B.addClass(L.overlay.element,"hide-select");L.handleUnderlayStart();};H.handleCompleteAnimateOut=function(K,J,L){B.removeClass(L.overlay.element,"hide-select");if(L.overlay.element.style.filter){L.overlay.element.style.filter=null;}L.overlay._setDomVisibility(false);B.setStyle(L.overlay.element,"opacity",1);L.handleUnderlayComplete();L.overlay.cfg.refireEvent("iframe");L.animateOutCompleteEvent.fire();};H.init();return H;};A.SLIDE=function(F,D){var I=YAHOO.util.Easing,L=F.cfg.getProperty("x")||B.getX(F.element),K=F.cfg.getProperty("y")||B.getY(F.element),M=B.getClientWidth(),H=F.element.offsetWidth,J={attributes:{points:{to:[L,K]}},duration:D,method:I.easeIn},E={attributes:{points:{to:[(M+25),K]}},duration:D,method:I.easeOut},G=new A(F,J,E,F.element,YAHOO.util.Motion);G.handleStartAnimateIn=function(O,N,P){P.overlay.element.style.left=((-25)-H)+"px";P.overlay.element.style.top=K+"px";};G.handleTweenAnimateIn=function(Q,P,R){var S=B.getXY(R.overlay.element),O=S[0],N=S[1];if(B.getStyle(R.overlay.element,"visibility")=="hidden"&&O<L){R.overlay._setDomVisibility(true);}R.overlay.cfg.setProperty("xy",[O,N],true);R.overlay.cfg.refireEvent("iframe");};G.handleCompleteAnimateIn=function(O,N,P){P.overlay.cfg.setProperty("xy",[L,K],true);P.startX=L;P.startY=K;P.overlay.cfg.refireEvent("iframe");P.animateInCompleteEvent.fire();};G.handleStartAnimateOut=function(O,N,R){var P=B.getViewportWidth(),S=B.getXY(R.overlay.element),Q=S[1];R.animOut.attributes.points.to=[(P+25),Q];};G.handleTweenAnimateOut=function(P,O,Q){var S=B.getXY(Q.overlay.element),N=S[0],R=S[1];Q.overlay.cfg.setProperty("xy",[N,R],true);Q.overlay.cfg.refireEvent("iframe");};G.handleCompleteAnimateOut=function(O,N,P){P.overlay._setDomVisibility(false);P.overlay.cfg.setProperty("xy",[L,K]);P.animateOutCompleteEvent.fire();};G.init();return G;};A.prototype={init:function(){this.beforeAnimateInEvent=this.createEvent("beforeAnimateIn");this.beforeAnimateInEvent.signature=C.LIST;this.beforeAnimateOutEvent=this.createEvent("beforeAnimateOut");this.beforeAnimateOutEvent.signature=C.LIST;this.animateInCompleteEvent=this.createEvent("animateInComplete");this.animateInCompleteEvent.signature=C.LIST;this.animateOutCompleteEvent=this.createEvent("animateOutComplete");this.animateOutCompleteEvent.signature=C.LIST;this.animIn=new this.animClass(this.targetElement,this.attrIn.attributes,this.attrIn.duration,this.attrIn.method);this.animIn.onStart.subscribe(this.handleStartAnimateIn,this);this.animIn.onTween.subscribe(this.handleTweenAnimateIn,this);this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn,this);this.animOut=new this.animClass(this.targetElement,this.attrOut.attributes,this.attrOut.duration,this.attrOut.method);this.animOut.onStart.subscribe(this.handleStartAnimateOut,this);this.animOut.onTween.subscribe(this.handleTweenAnimateOut,this);this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut,this);},animateIn:function(){this.beforeAnimateInEvent.fire();this.animIn.animate();},animateOut:function(){this.beforeAnimateOutEvent.fire();this.animOut.animate();},handleStartAnimateIn:function(E,D,F){},handleTweenAnimateIn:function(E,D,F){},handleCompleteAnimateIn:function(E,D,F){},handleStartAnimateOut:function(E,D,F){},handleTweenAnimateOut:function(E,D,F){},handleCompleteAnimateOut:function(E,D,F){},toString:function(){var D="ContainerEffect";if(this.overlay){D+=" ["+this.overlay.toString()+"]";}return D;}};YAHOO.lang.augmentProto(A,YAHOO.util.EventProvider);
14
})();YAHOO.register("containercore",YAHOO.widget.Module,{version:"2.8.0r4",build:"2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/container/container_core.js (-5126 lines)
Lines 1-5126 Link Here
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.8.0r4
6
*/
7
(function () {
8
9
    /**
10
    * Config is a utility used within an Object to allow the implementer to
11
    * maintain a list of local configuration properties and listen for changes 
12
    * to those properties dynamically using CustomEvent. The initial values are 
13
    * also maintained so that the configuration can be reset at any given point 
14
    * to its initial state.
15
    * @namespace YAHOO.util
16
    * @class Config
17
    * @constructor
18
    * @param {Object} owner The owner Object to which this Config Object belongs
19
    */
20
    YAHOO.util.Config = function (owner) {
21
22
        if (owner) {
23
            this.init(owner);
24
        }
25
26
27
    };
28
29
30
    var Lang = YAHOO.lang,
31
        CustomEvent = YAHOO.util.CustomEvent,
32
        Config = YAHOO.util.Config;
33
34
35
    /**
36
     * Constant representing the CustomEvent type for the config changed event.
37
     * @property YAHOO.util.Config.CONFIG_CHANGED_EVENT
38
     * @private
39
     * @static
40
     * @final
41
     */
42
    Config.CONFIG_CHANGED_EVENT = "configChanged";
43
    
44
    /**
45
     * Constant representing the boolean type string
46
     * @property YAHOO.util.Config.BOOLEAN_TYPE
47
     * @private
48
     * @static
49
     * @final
50
     */
51
    Config.BOOLEAN_TYPE = "boolean";
52
    
53
    Config.prototype = {
54
     
55
        /**
56
        * Object reference to the owner of this Config Object
57
        * @property owner
58
        * @type Object
59
        */
60
        owner: null,
61
        
62
        /**
63
        * Boolean flag that specifies whether a queue is currently 
64
        * being executed
65
        * @property queueInProgress
66
        * @type Boolean
67
        */
68
        queueInProgress: false,
69
        
70
        /**
71
        * Maintains the local collection of configuration property objects and 
72
        * their specified values
73
        * @property config
74
        * @private
75
        * @type Object
76
        */ 
77
        config: null,
78
        
79
        /**
80
        * Maintains the local collection of configuration property objects as 
81
        * they were initially applied.
82
        * This object is used when resetting a property.
83
        * @property initialConfig
84
        * @private
85
        * @type Object
86
        */ 
87
        initialConfig: null,
88
        
89
        /**
90
        * Maintains the local, normalized CustomEvent queue
91
        * @property eventQueue
92
        * @private
93
        * @type Object
94
        */ 
95
        eventQueue: null,
96
        
97
        /**
98
        * Custom Event, notifying subscribers when Config properties are set 
99
        * (setProperty is called without the silent flag
100
        * @event configChangedEvent
101
        */
102
        configChangedEvent: null,
103
    
104
        /**
105
        * Initializes the configuration Object and all of its local members.
106
        * @method init
107
        * @param {Object} owner The owner Object to which this Config 
108
        * Object belongs
109
        */
110
        init: function (owner) {
111
    
112
            this.owner = owner;
113
    
114
            this.configChangedEvent = 
115
                this.createEvent(Config.CONFIG_CHANGED_EVENT);
116
    
117
            this.configChangedEvent.signature = CustomEvent.LIST;
118
            this.queueInProgress = false;
119
            this.config = {};
120
            this.initialConfig = {};
121
            this.eventQueue = [];
122
        
123
        },
124
        
125
        /**
126
        * Validates that the value passed in is a Boolean.
127
        * @method checkBoolean
128
        * @param {Object} val The value to validate
129
        * @return {Boolean} true, if the value is valid
130
        */ 
131
        checkBoolean: function (val) {
132
            return (typeof val == Config.BOOLEAN_TYPE);
133
        },
134
        
135
        /**
136
        * Validates that the value passed in is a number.
137
        * @method checkNumber
138
        * @param {Object} val The value to validate
139
        * @return {Boolean} true, if the value is valid
140
        */
141
        checkNumber: function (val) {
142
            return (!isNaN(val));
143
        },
144
        
145
        /**
146
        * Fires a configuration property event using the specified value. 
147
        * @method fireEvent
148
        * @private
149
        * @param {String} key The configuration property's name
150
        * @param {value} Object The value of the correct type for the property
151
        */ 
152
        fireEvent: function ( key, value ) {
153
            var property = this.config[key];
154
        
155
            if (property && property.event) {
156
                property.event.fire(value);
157
            } 
158
        },
159
        
160
        /**
161
        * Adds a property to the Config Object's private config hash.
162
        * @method addProperty
163
        * @param {String} key The configuration property's name
164
        * @param {Object} propertyObject The Object containing all of this 
165
        * property's arguments
166
        */
167
        addProperty: function ( key, propertyObject ) {
168
            key = key.toLowerCase();
169
        
170
            this.config[key] = propertyObject;
171
        
172
            propertyObject.event = this.createEvent(key, { scope: this.owner });
173
            propertyObject.event.signature = CustomEvent.LIST;
174
            
175
            
176
            propertyObject.key = key;
177
        
178
            if (propertyObject.handler) {
179
                propertyObject.event.subscribe(propertyObject.handler, 
180
                    this.owner);
181
            }
182
        
183
            this.setProperty(key, propertyObject.value, true);
184
            
185
            if (! propertyObject.suppressEvent) {
186
                this.queueProperty(key, propertyObject.value);
187
            }
188
            
189
        },
190
        
191
        /**
192
        * Returns a key-value configuration map of the values currently set in  
193
        * the Config Object.
194
        * @method getConfig
195
        * @return {Object} The current config, represented in a key-value map
196
        */
197
        getConfig: function () {
198
        
199
            var cfg = {},
200
                currCfg = this.config,
201
                prop,
202
                property;
203
                
204
            for (prop in currCfg) {
205
                if (Lang.hasOwnProperty(currCfg, prop)) {
206
                    property = currCfg[prop];
207
                    if (property && property.event) {
208
                        cfg[prop] = property.value;
209
                    }
210
                }
211
            }
212
213
            return cfg;
214
        },
215
        
216
        /**
217
        * Returns the value of specified property.
218
        * @method getProperty
219
        * @param {String} key The name of the property
220
        * @return {Object}  The value of the specified property
221
        */
222
        getProperty: function (key) {
223
            var property = this.config[key.toLowerCase()];
224
            if (property && property.event) {
225
                return property.value;
226
            } else {
227
                return undefined;
228
            }
229
        },
230
        
231
        /**
232
        * Resets the specified property's value to its initial value.
233
        * @method resetProperty
234
        * @param {String} key The name of the property
235
        * @return {Boolean} True is the property was reset, false if not
236
        */
237
        resetProperty: function (key) {
238
    
239
            key = key.toLowerCase();
240
        
241
            var property = this.config[key];
242
    
243
            if (property && property.event) {
244
    
245
                if (this.initialConfig[key] && 
246
                    !Lang.isUndefined(this.initialConfig[key])) {
247
    
248
                    this.setProperty(key, this.initialConfig[key]);
249
250
                    return true;
251
    
252
                }
253
    
254
            } else {
255
    
256
                return false;
257
            }
258
    
259
        },
260
        
261
        /**
262
        * Sets the value of a property. If the silent property is passed as 
263
        * true, the property's event will not be fired.
264
        * @method setProperty
265
        * @param {String} key The name of the property
266
        * @param {String} value The value to set the property to
267
        * @param {Boolean} silent Whether the value should be set silently, 
268
        * without firing the property event.
269
        * @return {Boolean} True, if the set was successful, false if it failed.
270
        */
271
        setProperty: function (key, value, silent) {
272
        
273
            var property;
274
        
275
            key = key.toLowerCase();
276
        
277
            if (this.queueInProgress && ! silent) {
278
                // Currently running through a queue... 
279
                this.queueProperty(key,value);
280
                return true;
281
    
282
            } else {
283
                property = this.config[key];
284
                if (property && property.event) {
285
                    if (property.validator && !property.validator(value)) {
286
                        return false;
287
                    } else {
288
                        property.value = value;
289
                        if (! silent) {
290
                            this.fireEvent(key, value);
291
                            this.configChangedEvent.fire([key, value]);
292
                        }
293
                        return true;
294
                    }
295
                } else {
296
                    return false;
297
                }
298
            }
299
        },
300
        
301
        /**
302
        * Sets the value of a property and queues its event to execute. If the 
303
        * event is already scheduled to execute, it is
304
        * moved from its current position to the end of the queue.
305
        * @method queueProperty
306
        * @param {String} key The name of the property
307
        * @param {String} value The value to set the property to
308
        * @return {Boolean}  true, if the set was successful, false if 
309
        * it failed.
310
        */ 
311
        queueProperty: function (key, value) {
312
        
313
            key = key.toLowerCase();
314
        
315
            var property = this.config[key],
316
                foundDuplicate = false,
317
                iLen,
318
                queueItem,
319
                queueItemKey,
320
                queueItemValue,
321
                sLen,
322
                supercedesCheck,
323
                qLen,
324
                queueItemCheck,
325
                queueItemCheckKey,
326
                queueItemCheckValue,
327
                i,
328
                s,
329
                q;
330
                                
331
            if (property && property.event) {
332
    
333
                if (!Lang.isUndefined(value) && property.validator && 
334
                    !property.validator(value)) { // validator
335
                    return false;
336
                } else {
337
        
338
                    if (!Lang.isUndefined(value)) {
339
                        property.value = value;
340
                    } else {
341
                        value = property.value;
342
                    }
343
        
344
                    foundDuplicate = false;
345
                    iLen = this.eventQueue.length;
346
        
347
                    for (i = 0; i < iLen; i++) {
348
                        queueItem = this.eventQueue[i];
349
        
350
                        if (queueItem) {
351
                            queueItemKey = queueItem[0];
352
                            queueItemValue = queueItem[1];
353
354
                            if (queueItemKey == key) {
355
    
356
                                /*
357
                                    found a dupe... push to end of queue, null 
358
                                    current item, and break
359
                                */
360
    
361
                                this.eventQueue[i] = null;
362
    
363
                                this.eventQueue.push(
364
                                    [key, (!Lang.isUndefined(value) ? 
365
                                    value : queueItemValue)]);
366
    
367
                                foundDuplicate = true;
368
                                break;
369
                            }
370
                        }
371
                    }
372
                    
373
                    // this is a refire, or a new property in the queue
374
    
375
                    if (! foundDuplicate && !Lang.isUndefined(value)) { 
376
                        this.eventQueue.push([key, value]);
377
                    }
378
                }
379
        
380
                if (property.supercedes) {
381
382
                    sLen = property.supercedes.length;
383
384
                    for (s = 0; s < sLen; s++) {
385
386
                        supercedesCheck = property.supercedes[s];
387
                        qLen = this.eventQueue.length;
388
389
                        for (q = 0; q < qLen; q++) {
390
                            queueItemCheck = this.eventQueue[q];
391
392
                            if (queueItemCheck) {
393
                                queueItemCheckKey = queueItemCheck[0];
394
                                queueItemCheckValue = queueItemCheck[1];
395
396
                                if (queueItemCheckKey == 
397
                                    supercedesCheck.toLowerCase() ) {
398
399
                                    this.eventQueue.push([queueItemCheckKey, 
400
                                        queueItemCheckValue]);
401
402
                                    this.eventQueue[q] = null;
403
                                    break;
404
405
                                }
406
                            }
407
                        }
408
                    }
409
                }
410
411
412
                return true;
413
            } else {
414
                return false;
415
            }
416
        },
417
        
418
        /**
419
        * Fires the event for a property using the property's current value.
420
        * @method refireEvent
421
        * @param {String} key The name of the property
422
        */
423
        refireEvent: function (key) {
424
    
425
            key = key.toLowerCase();
426
        
427
            var property = this.config[key];
428
    
429
            if (property && property.event && 
430
    
431
                !Lang.isUndefined(property.value)) {
432
    
433
                if (this.queueInProgress) {
434
    
435
                    this.queueProperty(key);
436
    
437
                } else {
438
    
439
                    this.fireEvent(key, property.value);
440
    
441
                }
442
    
443
            }
444
        },
445
        
446
        /**
447
        * Applies a key-value Object literal to the configuration, replacing  
448
        * any existing values, and queueing the property events.
449
        * Although the values will be set, fireQueue() must be called for their 
450
        * associated events to execute.
451
        * @method applyConfig
452
        * @param {Object} userConfig The configuration Object literal
453
        * @param {Boolean} init  When set to true, the initialConfig will 
454
        * be set to the userConfig passed in, so that calling a reset will 
455
        * reset the properties to the passed values.
456
        */
457
        applyConfig: function (userConfig, init) {
458
        
459
            var sKey,
460
                oConfig;
461
462
            if (init) {
463
                oConfig = {};
464
                for (sKey in userConfig) {
465
                    if (Lang.hasOwnProperty(userConfig, sKey)) {
466
                        oConfig[sKey.toLowerCase()] = userConfig[sKey];
467
                    }
468
                }
469
                this.initialConfig = oConfig;
470
            }
471
472
            for (sKey in userConfig) {
473
                if (Lang.hasOwnProperty(userConfig, sKey)) {
474
                    this.queueProperty(sKey, userConfig[sKey]);
475
                }
476
            }
477
        },
478
        
479
        /**
480
        * Refires the events for all configuration properties using their 
481
        * current values.
482
        * @method refresh
483
        */
484
        refresh: function () {
485
486
            var prop;
487
488
            for (prop in this.config) {
489
                if (Lang.hasOwnProperty(this.config, prop)) {
490
                    this.refireEvent(prop);
491
                }
492
            }
493
        },
494
        
495
        /**
496
        * Fires the normalized list of queued property change events
497
        * @method fireQueue
498
        */
499
        fireQueue: function () {
500
        
501
            var i, 
502
                queueItem,
503
                key,
504
                value,
505
                property;
506
        
507
            this.queueInProgress = true;
508
            for (i = 0;i < this.eventQueue.length; i++) {
509
                queueItem = this.eventQueue[i];
510
                if (queueItem) {
511
        
512
                    key = queueItem[0];
513
                    value = queueItem[1];
514
                    property = this.config[key];
515
516
                    property.value = value;
517
518
                    // Clear out queue entry, to avoid it being 
519
                    // re-added to the queue by any queueProperty/supercedes
520
                    // calls which are invoked during fireEvent
521
                    this.eventQueue[i] = null;
522
523
                    this.fireEvent(key,value);
524
                }
525
            }
526
            
527
            this.queueInProgress = false;
528
            this.eventQueue = [];
529
        },
530
        
531
        /**
532
        * Subscribes an external handler to the change event for any 
533
        * given property. 
534
        * @method subscribeToConfigEvent
535
        * @param {String} key The property name
536
        * @param {Function} handler The handler function to use subscribe to 
537
        * the property's event
538
        * @param {Object} obj The Object to use for scoping the event handler 
539
        * (see CustomEvent documentation)
540
        * @param {Boolean} overrideContext Optional. If true, will override
541
        * "this" within the handler to map to the scope Object passed into the
542
        * method.
543
        * @return {Boolean} True, if the subscription was successful, 
544
        * otherwise false.
545
        */ 
546
        subscribeToConfigEvent: function (key, handler, obj, overrideContext) {
547
    
548
            var property = this.config[key.toLowerCase()];
549
    
550
            if (property && property.event) {
551
                if (!Config.alreadySubscribed(property.event, handler, obj)) {
552
                    property.event.subscribe(handler, obj, overrideContext);
553
                }
554
                return true;
555
            } else {
556
                return false;
557
            }
558
    
559
        },
560
        
561
        /**
562
        * Unsubscribes an external handler from the change event for any 
563
        * given property. 
564
        * @method unsubscribeFromConfigEvent
565
        * @param {String} key The property name
566
        * @param {Function} handler The handler function to use subscribe to 
567
        * the property's event
568
        * @param {Object} obj The Object to use for scoping the event 
569
        * handler (see CustomEvent documentation)
570
        * @return {Boolean} True, if the unsubscription was successful, 
571
        * otherwise false.
572
        */
573
        unsubscribeFromConfigEvent: function (key, handler, obj) {
574
            var property = this.config[key.toLowerCase()];
575
            if (property && property.event) {
576
                return property.event.unsubscribe(handler, obj);
577
            } else {
578
                return false;
579
            }
580
        },
581
        
582
        /**
583
        * Returns a string representation of the Config object
584
        * @method toString
585
        * @return {String} The Config object in string format.
586
        */
587
        toString: function () {
588
            var output = "Config";
589
            if (this.owner) {
590
                output += " [" + this.owner.toString() + "]";
591
            }
592
            return output;
593
        },
594
        
595
        /**
596
        * Returns a string representation of the Config object's current 
597
        * CustomEvent queue
598
        * @method outputEventQueue
599
        * @return {String} The string list of CustomEvents currently queued 
600
        * for execution
601
        */
602
        outputEventQueue: function () {
603
604
            var output = "",
605
                queueItem,
606
                q,
607
                nQueue = this.eventQueue.length;
608
              
609
            for (q = 0; q < nQueue; q++) {
610
                queueItem = this.eventQueue[q];
611
                if (queueItem) {
612
                    output += queueItem[0] + "=" + queueItem[1] + ", ";
613
                }
614
            }
615
            return output;
616
        },
617
618
        /**
619
        * Sets all properties to null, unsubscribes all listeners from each 
620
        * property's change event and all listeners from the configChangedEvent.
621
        * @method destroy
622
        */
623
        destroy: function () {
624
625
            var oConfig = this.config,
626
                sProperty,
627
                oProperty;
628
629
630
            for (sProperty in oConfig) {
631
            
632
                if (Lang.hasOwnProperty(oConfig, sProperty)) {
633
634
                    oProperty = oConfig[sProperty];
635
636
                    oProperty.event.unsubscribeAll();
637
                    oProperty.event = null;
638
639
                }
640
            
641
            }
642
            
643
            this.configChangedEvent.unsubscribeAll();
644
            
645
            this.configChangedEvent = null;
646
            this.owner = null;
647
            this.config = null;
648
            this.initialConfig = null;
649
            this.eventQueue = null;
650
        
651
        }
652
653
    };
654
    
655
    
656
    
657
    /**
658
    * Checks to determine if a particular function/Object pair are already 
659
    * subscribed to the specified CustomEvent
660
    * @method YAHOO.util.Config.alreadySubscribed
661
    * @static
662
    * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check 
663
    * the subscriptions
664
    * @param {Function} fn The function to look for in the subscribers list
665
    * @param {Object} obj The execution scope Object for the subscription
666
    * @return {Boolean} true, if the function/Object pair is already subscribed 
667
    * to the CustomEvent passed in
668
    */
669
    Config.alreadySubscribed = function (evt, fn, obj) {
670
    
671
        var nSubscribers = evt.subscribers.length,
672
            subsc,
673
            i;
674
675
        if (nSubscribers > 0) {
676
            i = nSubscribers - 1;
677
            do {
678
                subsc = evt.subscribers[i];
679
                if (subsc && subsc.obj == obj && subsc.fn == fn) {
680
                    return true;
681
                }
682
            }
683
            while (i--);
684
        }
685
686
        return false;
687
688
    };
689
690
    YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
691
692
}());
693
(function () {
694
695
    /**
696
    * The Container family of components is designed to enable developers to 
697
    * create different kinds of content-containing modules on the web. Module 
698
    * and Overlay are the most basic containers, and they can be used directly 
699
    * or extended to build custom containers. Also part of the Container family 
700
    * are four UI controls that extend Module and Overlay: Tooltip, Panel, 
701
    * Dialog, and SimpleDialog.
702
    * @module container
703
    * @title Container
704
    * @requires yahoo, dom, event 
705
    * @optional dragdrop, animation, button
706
    */
707
    
708
    /**
709
    * Module is a JavaScript representation of the Standard Module Format. 
710
    * Standard Module Format is a simple standard for markup containers where 
711
    * child nodes representing the header, body, and footer of the content are 
712
    * denoted using the CSS classes "hd", "bd", and "ft" respectively. 
713
    * Module is the base class for all other classes in the YUI 
714
    * Container package.
715
    * @namespace YAHOO.widget
716
    * @class Module
717
    * @constructor
718
    * @param {String} el The element ID representing the Module <em>OR</em>
719
    * @param {HTMLElement} el The element representing the Module
720
    * @param {Object} userConfig The configuration Object literal containing 
721
    * the configuration that should be set for this module. See configuration 
722
    * documentation for more details.
723
    */
724
    YAHOO.widget.Module = function (el, userConfig) {
725
        if (el) {
726
            this.init(el, userConfig);
727
        } else {
728
        }
729
    };
730
731
    var Dom = YAHOO.util.Dom,
732
        Config = YAHOO.util.Config,
733
        Event = YAHOO.util.Event,
734
        CustomEvent = YAHOO.util.CustomEvent,
735
        Module = YAHOO.widget.Module,
736
        UA = YAHOO.env.ua,
737
738
        m_oModuleTemplate,
739
        m_oHeaderTemplate,
740
        m_oBodyTemplate,
741
        m_oFooterTemplate,
742
743
        /**
744
        * Constant representing the name of the Module's events
745
        * @property EVENT_TYPES
746
        * @private
747
        * @final
748
        * @type Object
749
        */
750
        EVENT_TYPES = {
751
            "BEFORE_INIT": "beforeInit",
752
            "INIT": "init",
753
            "APPEND": "append",
754
            "BEFORE_RENDER": "beforeRender",
755
            "RENDER": "render",
756
            "CHANGE_HEADER": "changeHeader",
757
            "CHANGE_BODY": "changeBody",
758
            "CHANGE_FOOTER": "changeFooter",
759
            "CHANGE_CONTENT": "changeContent",
760
            "DESTROY": "destroy",
761
            "BEFORE_SHOW": "beforeShow",
762
            "SHOW": "show",
763
            "BEFORE_HIDE": "beforeHide",
764
            "HIDE": "hide"
765
        },
766
            
767
        /**
768
        * Constant representing the Module's configuration properties
769
        * @property DEFAULT_CONFIG
770
        * @private
771
        * @final
772
        * @type Object
773
        */
774
        DEFAULT_CONFIG = {
775
        
776
            "VISIBLE": { 
777
                key: "visible", 
778
                value: true, 
779
                validator: YAHOO.lang.isBoolean 
780
            },
781
782
            "EFFECT": {
783
                key: "effect",
784
                suppressEvent: true,
785
                supercedes: ["visible"]
786
            },
787
788
            "MONITOR_RESIZE": {
789
                key: "monitorresize",
790
                value: true
791
            },
792
793
            "APPEND_TO_DOCUMENT_BODY": {
794
                key: "appendtodocumentbody",
795
                value: false
796
            }
797
        };
798
799
    /**
800
    * Constant representing the prefix path to use for non-secure images
801
    * @property YAHOO.widget.Module.IMG_ROOT
802
    * @static
803
    * @final
804
    * @type String
805
    */
806
    Module.IMG_ROOT = null;
807
    
808
    /**
809
    * Constant representing the prefix path to use for securely served images
810
    * @property YAHOO.widget.Module.IMG_ROOT_SSL
811
    * @static
812
    * @final
813
    * @type String
814
    */
815
    Module.IMG_ROOT_SSL = null;
816
    
817
    /**
818
    * Constant for the default CSS class name that represents a Module
819
    * @property YAHOO.widget.Module.CSS_MODULE
820
    * @static
821
    * @final
822
    * @type String
823
    */
824
    Module.CSS_MODULE = "yui-module";
825
    
826
    /**
827
    * Constant representing the module header
828
    * @property YAHOO.widget.Module.CSS_HEADER
829
    * @static
830
    * @final
831
    * @type String
832
    */
833
    Module.CSS_HEADER = "hd";
834
835
    /**
836
    * Constant representing the module body
837
    * @property YAHOO.widget.Module.CSS_BODY
838
    * @static
839
    * @final
840
    * @type String
841
    */
842
    Module.CSS_BODY = "bd";
843
    
844
    /**
845
    * Constant representing the module footer
846
    * @property YAHOO.widget.Module.CSS_FOOTER
847
    * @static
848
    * @final
849
    * @type String
850
    */
851
    Module.CSS_FOOTER = "ft";
852
    
853
    /**
854
    * Constant representing the url for the "src" attribute of the iframe 
855
    * used to monitor changes to the browser's base font size
856
    * @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL
857
    * @static
858
    * @final
859
    * @type String
860
    */
861
    Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;";
862
863
    /**
864
    * Constant representing the buffer amount (in pixels) to use when positioning
865
    * the text resize monitor offscreen. The resize monitor is positioned
866
    * offscreen by an amount eqaul to its offsetHeight + the buffer value.
867
    * 
868
    * @property YAHOO.widget.Module.RESIZE_MONITOR_BUFFER
869
    * @static
870
    * @type Number
871
    */
872
    // Set to 1, to work around pixel offset in IE8, which increases when zoom is used
873
    Module.RESIZE_MONITOR_BUFFER = 1;
874
875
    /**
876
    * Singleton CustomEvent fired when the font size is changed in the browser.
877
    * Opera's "zoom" functionality currently does not support text 
878
    * size detection.
879
    * @event YAHOO.widget.Module.textResizeEvent
880
    */
881
    Module.textResizeEvent = new CustomEvent("textResize");
882
883
    /**
884
     * Helper utility method, which forces a document level 
885
     * redraw for Opera, which can help remove repaint
886
     * irregularities after applying DOM changes.
887
     *
888
     * @method YAHOO.widget.Module.forceDocumentRedraw
889
     * @static
890
     */
891
    Module.forceDocumentRedraw = function() {
892
        var docEl = document.documentElement;
893
        if (docEl) {
894
            docEl.className += " ";
895
            docEl.className = YAHOO.lang.trim(docEl.className);
896
        }
897
    };
898
899
    function createModuleTemplate() {
900
901
        if (!m_oModuleTemplate) {
902
            m_oModuleTemplate = document.createElement("div");
903
            
904
            m_oModuleTemplate.innerHTML = ("<div class=\"" + 
905
                Module.CSS_HEADER + "\"></div>" + "<div class=\"" + 
906
                Module.CSS_BODY + "\"></div><div class=\"" + 
907
                Module.CSS_FOOTER + "\"></div>");
908
909
            m_oHeaderTemplate = m_oModuleTemplate.firstChild;
910
            m_oBodyTemplate = m_oHeaderTemplate.nextSibling;
911
            m_oFooterTemplate = m_oBodyTemplate.nextSibling;
912
        }
913
914
        return m_oModuleTemplate;
915
    }
916
917
    function createHeader() {
918
        if (!m_oHeaderTemplate) {
919
            createModuleTemplate();
920
        }
921
        return (m_oHeaderTemplate.cloneNode(false));
922
    }
923
924
    function createBody() {
925
        if (!m_oBodyTemplate) {
926
            createModuleTemplate();
927
        }
928
        return (m_oBodyTemplate.cloneNode(false));
929
    }
930
931
    function createFooter() {
932
        if (!m_oFooterTemplate) {
933
            createModuleTemplate();
934
        }
935
        return (m_oFooterTemplate.cloneNode(false));
936
    }
937
938
    Module.prototype = {
939
940
        /**
941
        * The class's constructor function
942
        * @property contructor
943
        * @type Function
944
        */
945
        constructor: Module,
946
        
947
        /**
948
        * The main module element that contains the header, body, and footer
949
        * @property element
950
        * @type HTMLElement
951
        */
952
        element: null,
953
954
        /**
955
        * The header element, denoted with CSS class "hd"
956
        * @property header
957
        * @type HTMLElement
958
        */
959
        header: null,
960
961
        /**
962
        * The body element, denoted with CSS class "bd"
963
        * @property body
964
        * @type HTMLElement
965
        */
966
        body: null,
967
968
        /**
969
        * The footer element, denoted with CSS class "ft"
970
        * @property footer
971
        * @type HTMLElement
972
        */
973
        footer: null,
974
975
        /**
976
        * The id of the element
977
        * @property id
978
        * @type String
979
        */
980
        id: null,
981
982
        /**
983
        * A string representing the root path for all images created by
984
        * a Module instance.
985
        * @deprecated It is recommend that any images for a Module be applied
986
        * via CSS using the "background-image" property.
987
        * @property imageRoot
988
        * @type String
989
        */
990
        imageRoot: Module.IMG_ROOT,
991
992
        /**
993
        * Initializes the custom events for Module which are fired 
994
        * automatically at appropriate times by the Module class.
995
        * @method initEvents
996
        */
997
        initEvents: function () {
998
999
            var SIGNATURE = CustomEvent.LIST;
1000
1001
            /**
1002
            * CustomEvent fired prior to class initalization.
1003
            * @event beforeInitEvent
1004
            * @param {class} classRef class reference of the initializing 
1005
            * class, such as this.beforeInitEvent.fire(Module)
1006
            */
1007
            this.beforeInitEvent = this.createEvent(EVENT_TYPES.BEFORE_INIT);
1008
            this.beforeInitEvent.signature = SIGNATURE;
1009
1010
            /**
1011
            * CustomEvent fired after class initalization.
1012
            * @event initEvent
1013
            * @param {class} classRef class reference of the initializing 
1014
            * class, such as this.beforeInitEvent.fire(Module)
1015
            */  
1016
            this.initEvent = this.createEvent(EVENT_TYPES.INIT);
1017
            this.initEvent.signature = SIGNATURE;
1018
1019
            /**
1020
            * CustomEvent fired when the Module is appended to the DOM
1021
            * @event appendEvent
1022
            */
1023
            this.appendEvent = this.createEvent(EVENT_TYPES.APPEND);
1024
            this.appendEvent.signature = SIGNATURE;
1025
1026
            /**
1027
            * CustomEvent fired before the Module is rendered
1028
            * @event beforeRenderEvent
1029
            */
1030
            this.beforeRenderEvent = this.createEvent(EVENT_TYPES.BEFORE_RENDER);
1031
            this.beforeRenderEvent.signature = SIGNATURE;
1032
        
1033
            /**
1034
            * CustomEvent fired after the Module is rendered
1035
            * @event renderEvent
1036
            */
1037
            this.renderEvent = this.createEvent(EVENT_TYPES.RENDER);
1038
            this.renderEvent.signature = SIGNATURE;
1039
        
1040
            /**
1041
            * CustomEvent fired when the header content of the Module 
1042
            * is modified
1043
            * @event changeHeaderEvent
1044
            * @param {String/HTMLElement} content String/element representing 
1045
            * the new header content
1046
            */
1047
            this.changeHeaderEvent = this.createEvent(EVENT_TYPES.CHANGE_HEADER);
1048
            this.changeHeaderEvent.signature = SIGNATURE;
1049
            
1050
            /**
1051
            * CustomEvent fired when the body content of the Module is modified
1052
            * @event changeBodyEvent
1053
            * @param {String/HTMLElement} content String/element representing 
1054
            * the new body content
1055
            */  
1056
            this.changeBodyEvent = this.createEvent(EVENT_TYPES.CHANGE_BODY);
1057
            this.changeBodyEvent.signature = SIGNATURE;
1058
            
1059
            /**
1060
            * CustomEvent fired when the footer content of the Module 
1061
            * is modified
1062
            * @event changeFooterEvent
1063
            * @param {String/HTMLElement} content String/element representing 
1064
            * the new footer content
1065
            */
1066
            this.changeFooterEvent = this.createEvent(EVENT_TYPES.CHANGE_FOOTER);
1067
            this.changeFooterEvent.signature = SIGNATURE;
1068
        
1069
            /**
1070
            * CustomEvent fired when the content of the Module is modified
1071
            * @event changeContentEvent
1072
            */
1073
            this.changeContentEvent = this.createEvent(EVENT_TYPES.CHANGE_CONTENT);
1074
            this.changeContentEvent.signature = SIGNATURE;
1075
1076
            /**
1077
            * CustomEvent fired when the Module is destroyed
1078
            * @event destroyEvent
1079
            */
1080
            this.destroyEvent = this.createEvent(EVENT_TYPES.DESTROY);
1081
            this.destroyEvent.signature = SIGNATURE;
1082
1083
            /**
1084
            * CustomEvent fired before the Module is shown
1085
            * @event beforeShowEvent
1086
            */
1087
            this.beforeShowEvent = this.createEvent(EVENT_TYPES.BEFORE_SHOW);
1088
            this.beforeShowEvent.signature = SIGNATURE;
1089
1090
            /**
1091
            * CustomEvent fired after the Module is shown
1092
            * @event showEvent
1093
            */
1094
            this.showEvent = this.createEvent(EVENT_TYPES.SHOW);
1095
            this.showEvent.signature = SIGNATURE;
1096
1097
            /**
1098
            * CustomEvent fired before the Module is hidden
1099
            * @event beforeHideEvent
1100
            */
1101
            this.beforeHideEvent = this.createEvent(EVENT_TYPES.BEFORE_HIDE);
1102
            this.beforeHideEvent.signature = SIGNATURE;
1103
1104
            /**
1105
            * CustomEvent fired after the Module is hidden
1106
            * @event hideEvent
1107
            */
1108
            this.hideEvent = this.createEvent(EVENT_TYPES.HIDE);
1109
            this.hideEvent.signature = SIGNATURE;
1110
        }, 
1111
1112
        /**
1113
        * String representing the current user-agent platform
1114
        * @property platform
1115
        * @type String
1116
        */
1117
        platform: function () {
1118
            var ua = navigator.userAgent.toLowerCase();
1119
1120
            if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
1121
                return "windows";
1122
            } else if (ua.indexOf("macintosh") != -1) {
1123
                return "mac";
1124
            } else {
1125
                return false;
1126
            }
1127
        }(),
1128
        
1129
        /**
1130
        * String representing the user-agent of the browser
1131
        * @deprecated Use YAHOO.env.ua
1132
        * @property browser
1133
        * @type String
1134
        */
1135
        browser: function () {
1136
            var ua = navigator.userAgent.toLowerCase();
1137
            /*
1138
                 Check Opera first in case of spoof and check Safari before
1139
                 Gecko since Safari's user agent string includes "like Gecko"
1140
            */
1141
            if (ua.indexOf('opera') != -1) { 
1142
                return 'opera';
1143
            } else if (ua.indexOf('msie 7') != -1) {
1144
                return 'ie7';
1145
            } else if (ua.indexOf('msie') != -1) {
1146
                return 'ie';
1147
            } else if (ua.indexOf('safari') != -1) { 
1148
                return 'safari';
1149
            } else if (ua.indexOf('gecko') != -1) {
1150
                return 'gecko';
1151
            } else {
1152
                return false;
1153
            }
1154
        }(),
1155
        
1156
        /**
1157
        * Boolean representing whether or not the current browsing context is 
1158
        * secure (https)
1159
        * @property isSecure
1160
        * @type Boolean
1161
        */
1162
        isSecure: function () {
1163
            if (window.location.href.toLowerCase().indexOf("https") === 0) {
1164
                return true;
1165
            } else {
1166
                return false;
1167
            }
1168
        }(),
1169
        
1170
        /**
1171
        * Initializes the custom events for Module which are fired 
1172
        * automatically at appropriate times by the Module class.
1173
        */
1174
        initDefaultConfig: function () {
1175
            // Add properties //
1176
            /**
1177
            * Specifies whether the Module is visible on the page.
1178
            * @config visible
1179
            * @type Boolean
1180
            * @default true
1181
            */
1182
            this.cfg.addProperty(DEFAULT_CONFIG.VISIBLE.key, {
1183
                handler: this.configVisible, 
1184
                value: DEFAULT_CONFIG.VISIBLE.value, 
1185
                validator: DEFAULT_CONFIG.VISIBLE.validator
1186
            });
1187
1188
            /**
1189
            * <p>
1190
            * Object or array of objects representing the ContainerEffect 
1191
            * classes that are active for animating the container.
1192
            * </p>
1193
            * <p>
1194
            * <strong>NOTE:</strong> Although this configuration 
1195
            * property is introduced at the Module level, an out of the box
1196
            * implementation is not shipped for the Module class so setting
1197
            * the proroperty on the Module class has no effect. The Overlay 
1198
            * class is the first class to provide out of the box ContainerEffect 
1199
            * support.
1200
            * </p>
1201
            * @config effect
1202
            * @type Object
1203
            * @default null
1204
            */
1205
            this.cfg.addProperty(DEFAULT_CONFIG.EFFECT.key, {
1206
                suppressEvent: DEFAULT_CONFIG.EFFECT.suppressEvent, 
1207
                supercedes: DEFAULT_CONFIG.EFFECT.supercedes
1208
            });
1209
1210
            /**
1211
            * Specifies whether to create a special proxy iframe to monitor 
1212
            * for user font resizing in the document
1213
            * @config monitorresize
1214
            * @type Boolean
1215
            * @default true
1216
            */
1217
            this.cfg.addProperty(DEFAULT_CONFIG.MONITOR_RESIZE.key, {
1218
                handler: this.configMonitorResize,
1219
                value: DEFAULT_CONFIG.MONITOR_RESIZE.value
1220
            });
1221
1222
            /**
1223
            * Specifies if the module should be rendered as the first child 
1224
            * of document.body or appended as the last child when render is called
1225
            * with document.body as the "appendToNode".
1226
            * <p>
1227
            * Appending to the body while the DOM is still being constructed can 
1228
            * lead to Operation Aborted errors in IE hence this flag is set to 
1229
            * false by default.
1230
            * </p>
1231
            * 
1232
            * @config appendtodocumentbody
1233
            * @type Boolean
1234
            * @default false
1235
            */
1236
            this.cfg.addProperty(DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.key, {
1237
                value: DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.value
1238
            });
1239
        },
1240
1241
        /**
1242
        * The Module class's initialization method, which is executed for
1243
        * Module and all of its subclasses. This method is automatically 
1244
        * called by the constructor, and  sets up all DOM references for 
1245
        * pre-existing markup, and creates required markup if it is not 
1246
        * already present.
1247
        * <p>
1248
        * If the element passed in does not have an id, one will be generated
1249
        * for it.
1250
        * </p>
1251
        * @method init
1252
        * @param {String} el The element ID representing the Module <em>OR</em>
1253
        * @param {HTMLElement} el The element representing the Module
1254
        * @param {Object} userConfig The configuration Object literal 
1255
        * containing the configuration that should be set for this module. 
1256
        * See configuration documentation for more details.
1257
        */
1258
        init: function (el, userConfig) {
1259
1260
            var elId, child;
1261
1262
            this.initEvents();
1263
            this.beforeInitEvent.fire(Module);
1264
1265
            /**
1266
            * The Module's Config object used for monitoring 
1267
            * configuration properties.
1268
            * @property cfg
1269
            * @type YAHOO.util.Config
1270
            */
1271
            this.cfg = new Config(this);
1272
1273
            if (this.isSecure) {
1274
                this.imageRoot = Module.IMG_ROOT_SSL;
1275
            }
1276
1277
            if (typeof el == "string") {
1278
                elId = el;
1279
                el = document.getElementById(el);
1280
                if (! el) {
1281
                    el = (createModuleTemplate()).cloneNode(false);
1282
                    el.id = elId;
1283
                }
1284
            }
1285
1286
            this.id = Dom.generateId(el);
1287
            this.element = el;
1288
1289
            child = this.element.firstChild;
1290
1291
            if (child) {
1292
                var fndHd = false, fndBd = false, fndFt = false;
1293
                do {
1294
                    // We're looking for elements
1295
                    if (1 == child.nodeType) {
1296
                        if (!fndHd && Dom.hasClass(child, Module.CSS_HEADER)) {
1297
                            this.header = child;
1298
                            fndHd = true;
1299
                        } else if (!fndBd && Dom.hasClass(child, Module.CSS_BODY)) {
1300
                            this.body = child;
1301
                            fndBd = true;
1302
                        } else if (!fndFt && Dom.hasClass(child, Module.CSS_FOOTER)){
1303
                            this.footer = child;
1304
                            fndFt = true;
1305
                        }
1306
                    }
1307
                } while ((child = child.nextSibling));
1308
            }
1309
1310
            this.initDefaultConfig();
1311
1312
            Dom.addClass(this.element, Module.CSS_MODULE);
1313
1314
            if (userConfig) {
1315
                this.cfg.applyConfig(userConfig, true);
1316
            }
1317
1318
            /*
1319
                Subscribe to the fireQueue() method of Config so that any 
1320
                queued configuration changes are excecuted upon render of 
1321
                the Module
1322
            */ 
1323
1324
            if (!Config.alreadySubscribed(this.renderEvent, this.cfg.fireQueue, this.cfg)) {
1325
                this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
1326
            }
1327
1328
            this.initEvent.fire(Module);
1329
        },
1330
1331
        /**
1332
        * Initialize an empty IFRAME that is placed out of the visible area 
1333
        * that can be used to detect text resize.
1334
        * @method initResizeMonitor
1335
        */
1336
        initResizeMonitor: function () {
1337
1338
            var isGeckoWin = (UA.gecko && this.platform == "windows");
1339
            if (isGeckoWin) {
1340
                // Help prevent spinning loading icon which 
1341
                // started with FireFox 2.0.0.8/Win
1342
                var self = this;
1343
                setTimeout(function(){self._initResizeMonitor();}, 0);
1344
            } else {
1345
                this._initResizeMonitor();
1346
            }
1347
        },
1348
1349
        /**
1350
         * Create and initialize the text resize monitoring iframe.
1351
         * 
1352
         * @protected
1353
         * @method _initResizeMonitor
1354
         */
1355
        _initResizeMonitor : function() {
1356
1357
            var oDoc, 
1358
                oIFrame, 
1359
                sHTML;
1360
1361
            function fireTextResize() {
1362
                Module.textResizeEvent.fire();
1363
            }
1364
1365
            if (!UA.opera) {
1366
                oIFrame = Dom.get("_yuiResizeMonitor");
1367
1368
                var supportsCWResize = this._supportsCWResize();
1369
1370
                if (!oIFrame) {
1371
                    oIFrame = document.createElement("iframe");
1372
1373
                    if (this.isSecure && Module.RESIZE_MONITOR_SECURE_URL && UA.ie) {
1374
                        oIFrame.src = Module.RESIZE_MONITOR_SECURE_URL;
1375
                    }
1376
1377
                    if (!supportsCWResize) {
1378
                        // Can't monitor on contentWindow, so fire from inside iframe
1379
                        sHTML = ["<html><head><script ",
1380
                                 "type=\"text/javascript\">",
1381
                                 "window.onresize=function(){window.parent.",
1382
                                 "YAHOO.widget.Module.textResizeEvent.",
1383
                                 "fire();};<",
1384
                                 "\/script></head>",
1385
                                 "<body></body></html>"].join('');
1386
1387
                        oIFrame.src = "data:text/html;charset=utf-8," + encodeURIComponent(sHTML);
1388
                    }
1389
1390
                    oIFrame.id = "_yuiResizeMonitor";
1391
                    oIFrame.title = "Text Resize Monitor";
1392
                    /*
1393
                        Need to set "position" property before inserting the 
1394
                        iframe into the document or Safari's status bar will 
1395
                        forever indicate the iframe is loading 
1396
                        (See YUILibrary bug #1723064)
1397
                    */
1398
                    oIFrame.style.position = "absolute";
1399
                    oIFrame.style.visibility = "hidden";
1400
1401
                    var db = document.body,
1402
                        fc = db.firstChild;
1403
                    if (fc) {
1404
                        db.insertBefore(oIFrame, fc);
1405
                    } else {
1406
                        db.appendChild(oIFrame);
1407
                    }
1408
1409
                    // Setting the background color fixes an issue with IE6/IE7, where
1410
                    // elements in the DOM, with -ve margin-top which positioned them 
1411
                    // offscreen (so they would be overlapped by the iframe and its -ve top
1412
                    // setting), would have their -ve margin-top ignored, when the iframe 
1413
                    // was added.
1414
                    oIFrame.style.backgroundColor = "transparent";
1415
1416
                    oIFrame.style.borderWidth = "0";
1417
                    oIFrame.style.width = "2em";
1418
                    oIFrame.style.height = "2em";
1419
                    oIFrame.style.left = "0";
1420
                    oIFrame.style.top = (-1 * (oIFrame.offsetHeight + Module.RESIZE_MONITOR_BUFFER)) + "px";
1421
                    oIFrame.style.visibility = "visible";
1422
1423
                    /*
1424
                       Don't open/close the document for Gecko like we used to, since it
1425
                       leads to duplicate cookies. (See YUILibrary bug #1721755)
1426
                    */
1427
                    if (UA.webkit) {
1428
                        oDoc = oIFrame.contentWindow.document;
1429
                        oDoc.open();
1430
                        oDoc.close();
1431
                    }
1432
                }
1433
1434
                if (oIFrame && oIFrame.contentWindow) {
1435
                    Module.textResizeEvent.subscribe(this.onDomResize, this, true);
1436
1437
                    if (!Module.textResizeInitialized) {
1438
                        if (supportsCWResize) {
1439
                            if (!Event.on(oIFrame.contentWindow, "resize", fireTextResize)) {
1440
                                /*
1441
                                     This will fail in IE if document.domain has 
1442
                                     changed, so we must change the listener to 
1443
                                     use the oIFrame element instead
1444
                                */
1445
                                Event.on(oIFrame, "resize", fireTextResize);
1446
                            }
1447
                        }
1448
                        Module.textResizeInitialized = true;
1449
                    }
1450
                    this.resizeMonitor = oIFrame;
1451
                }
1452
            }
1453
        },
1454
1455
        /**
1456
         * Text resize monitor helper method.
1457
         * Determines if the browser supports resize events on iframe content windows.
1458
         * 
1459
         * @private
1460
         * @method _supportsCWResize
1461
         */
1462
        _supportsCWResize : function() {
1463
            /*
1464
                Gecko 1.8.0 (FF1.5), 1.8.1.0-5 (FF2) won't fire resize on contentWindow.
1465
                Gecko 1.8.1.6+ (FF2.0.0.6+) and all other browsers will fire resize on contentWindow.
1466
1467
                We don't want to start sniffing for patch versions, so fire textResize the same
1468
                way on all FF2 flavors
1469
             */
1470
            var bSupported = true;
1471
            if (UA.gecko && UA.gecko <= 1.8) {
1472
                bSupported = false;
1473
            }
1474
            return bSupported;
1475
        },
1476
1477
        /**
1478
        * Event handler fired when the resize monitor element is resized.
1479
        * @method onDomResize
1480
        * @param {DOMEvent} e The DOM resize event
1481
        * @param {Object} obj The scope object passed to the handler
1482
        */
1483
        onDomResize: function (e, obj) {
1484
1485
            var nTop = -1 * (this.resizeMonitor.offsetHeight + Module.RESIZE_MONITOR_BUFFER);
1486
1487
            this.resizeMonitor.style.top = nTop + "px";
1488
            this.resizeMonitor.style.left = "0";
1489
        },
1490
1491
        /**
1492
        * Sets the Module's header content to the string specified, or appends 
1493
        * the passed element to the header. If no header is present, one will 
1494
        * be automatically created. An empty string can be passed to the method
1495
        * to clear the contents of the header.
1496
        * 
1497
        * @method setHeader
1498
        * @param {String} headerContent The string used to set the header.
1499
        * As a convenience, non HTMLElement objects can also be passed into 
1500
        * the method, and will be treated as strings, with the header innerHTML
1501
        * set to their default toString implementations.
1502
        * <em>OR</em>
1503
        * @param {HTMLElement} headerContent The HTMLElement to append to 
1504
        * <em>OR</em>
1505
        * @param {DocumentFragment} headerContent The document fragment 
1506
        * containing elements which are to be added to the header
1507
        */
1508
        setHeader: function (headerContent) {
1509
            var oHeader = this.header || (this.header = createHeader());
1510
1511
            if (headerContent.nodeName) {
1512
                oHeader.innerHTML = "";
1513
                oHeader.appendChild(headerContent);
1514
            } else {
1515
                oHeader.innerHTML = headerContent;
1516
            }
1517
1518
            if (this._rendered) {
1519
                this._renderHeader();
1520
            }
1521
1522
            this.changeHeaderEvent.fire(headerContent);
1523
            this.changeContentEvent.fire();
1524
1525
        },
1526
1527
        /**
1528
        * Appends the passed element to the header. If no header is present, 
1529
        * one will be automatically created.
1530
        * @method appendToHeader
1531
        * @param {HTMLElement | DocumentFragment} element The element to 
1532
        * append to the header. In the case of a document fragment, the
1533
        * children of the fragment will be appended to the header.
1534
        */
1535
        appendToHeader: function (element) {
1536
            var oHeader = this.header || (this.header = createHeader());
1537
1538
            oHeader.appendChild(element);
1539
1540
            this.changeHeaderEvent.fire(element);
1541
            this.changeContentEvent.fire();
1542
1543
        },
1544
1545
        /**
1546
        * Sets the Module's body content to the HTML specified. 
1547
        * 
1548
        * If no body is present, one will be automatically created. 
1549
        * 
1550
        * An empty string can be passed to the method to clear the contents of the body.
1551
        * @method setBody
1552
        * @param {String} bodyContent The HTML used to set the body. 
1553
        * As a convenience, non HTMLElement objects can also be passed into 
1554
        * the method, and will be treated as strings, with the body innerHTML
1555
        * set to their default toString implementations.
1556
        * <em>OR</em>
1557
        * @param {HTMLElement} bodyContent The HTMLElement to add as the first and only
1558
        * child of the body element.
1559
        * <em>OR</em>
1560
        * @param {DocumentFragment} bodyContent The document fragment 
1561
        * containing elements which are to be added to the body
1562
        */
1563
        setBody: function (bodyContent) {
1564
            var oBody = this.body || (this.body = createBody());
1565
1566
            if (bodyContent.nodeName) {
1567
                oBody.innerHTML = "";
1568
                oBody.appendChild(bodyContent);
1569
            } else {
1570
                oBody.innerHTML = bodyContent;
1571
            }
1572
1573
            if (this._rendered) {
1574
                this._renderBody();
1575
            }
1576
1577
            this.changeBodyEvent.fire(bodyContent);
1578
            this.changeContentEvent.fire();
1579
        },
1580
1581
        /**
1582
        * Appends the passed element to the body. If no body is present, one 
1583
        * will be automatically created.
1584
        * @method appendToBody
1585
        * @param {HTMLElement | DocumentFragment} element The element to 
1586
        * append to the body. In the case of a document fragment, the
1587
        * children of the fragment will be appended to the body.
1588
        * 
1589
        */
1590
        appendToBody: function (element) {
1591
            var oBody = this.body || (this.body = createBody());
1592
        
1593
            oBody.appendChild(element);
1594
1595
            this.changeBodyEvent.fire(element);
1596
            this.changeContentEvent.fire();
1597
1598
        },
1599
        
1600
        /**
1601
        * Sets the Module's footer content to the HTML specified, or appends 
1602
        * the passed element to the footer. If no footer is present, one will 
1603
        * be automatically created. An empty string can be passed to the method
1604
        * to clear the contents of the footer.
1605
        * @method setFooter
1606
        * @param {String} footerContent The HTML used to set the footer 
1607
        * As a convenience, non HTMLElement objects can also be passed into 
1608
        * the method, and will be treated as strings, with the footer innerHTML
1609
        * set to their default toString implementations.
1610
        * <em>OR</em>
1611
        * @param {HTMLElement} footerContent The HTMLElement to append to 
1612
        * the footer
1613
        * <em>OR</em>
1614
        * @param {DocumentFragment} footerContent The document fragment containing 
1615
        * elements which are to be added to the footer
1616
        */
1617
        setFooter: function (footerContent) {
1618
1619
            var oFooter = this.footer || (this.footer = createFooter());
1620
1621
            if (footerContent.nodeName) {
1622
                oFooter.innerHTML = "";
1623
                oFooter.appendChild(footerContent);
1624
            } else {
1625
                oFooter.innerHTML = footerContent;
1626
            }
1627
1628
            if (this._rendered) {
1629
                this._renderFooter();
1630
            }
1631
1632
            this.changeFooterEvent.fire(footerContent);
1633
            this.changeContentEvent.fire();
1634
        },
1635
1636
        /**
1637
        * Appends the passed element to the footer. If no footer is present, 
1638
        * one will be automatically created.
1639
        * @method appendToFooter
1640
        * @param {HTMLElement | DocumentFragment} element The element to 
1641
        * append to the footer. In the case of a document fragment, the
1642
        * children of the fragment will be appended to the footer
1643
        */
1644
        appendToFooter: function (element) {
1645
1646
            var oFooter = this.footer || (this.footer = createFooter());
1647
1648
            oFooter.appendChild(element);
1649
1650
            this.changeFooterEvent.fire(element);
1651
            this.changeContentEvent.fire();
1652
1653
        },
1654
1655
        /**
1656
        * Renders the Module by inserting the elements that are not already 
1657
        * in the main Module into their correct places. Optionally appends 
1658
        * the Module to the specified node prior to the render's execution. 
1659
        * <p>
1660
        * For Modules without existing markup, the appendToNode argument 
1661
        * is REQUIRED. If this argument is ommitted and the current element is 
1662
        * not present in the document, the function will return false, 
1663
        * indicating that the render was a failure.
1664
        * </p>
1665
        * <p>
1666
        * NOTE: As of 2.3.1, if the appendToNode is the document's body element
1667
        * then the module is rendered as the first child of the body element, 
1668
        * and not appended to it, to avoid Operation Aborted errors in IE when 
1669
        * rendering the module before window's load event is fired. You can 
1670
        * use the appendtodocumentbody configuration property to change this 
1671
        * to append to document.body if required.
1672
        * </p>
1673
        * @method render
1674
        * @param {String} appendToNode The element id to which the Module 
1675
        * should be appended to prior to rendering <em>OR</em>
1676
        * @param {HTMLElement} appendToNode The element to which the Module 
1677
        * should be appended to prior to rendering
1678
        * @param {HTMLElement} moduleElement OPTIONAL. The element that 
1679
        * represents the actual Standard Module container.
1680
        * @return {Boolean} Success or failure of the render
1681
        */
1682
        render: function (appendToNode, moduleElement) {
1683
1684
            var me = this;
1685
1686
            function appendTo(parentNode) {
1687
                if (typeof parentNode == "string") {
1688
                    parentNode = document.getElementById(parentNode);
1689
                }
1690
1691
                if (parentNode) {
1692
                    me._addToParent(parentNode, me.element);
1693
                    me.appendEvent.fire();
1694
                }
1695
            }
1696
1697
            this.beforeRenderEvent.fire();
1698
1699
            if (! moduleElement) {
1700
                moduleElement = this.element;
1701
            }
1702
1703
            if (appendToNode) {
1704
                appendTo(appendToNode);
1705
            } else { 
1706
                // No node was passed in. If the element is not already in the Dom, this fails
1707
                if (! Dom.inDocument(this.element)) {
1708
                    return false;
1709
                }
1710
            }
1711
1712
            this._renderHeader(moduleElement);
1713
            this._renderBody(moduleElement);
1714
            this._renderFooter(moduleElement);
1715
1716
            this._rendered = true;
1717
1718
            this.renderEvent.fire();
1719
            return true;
1720
        },
1721
1722
        /**
1723
         * Renders the currently set header into it's proper position under the 
1724
         * module element. If the module element is not provided, "this.element" 
1725
         * is used.
1726
         * 
1727
         * @method _renderHeader
1728
         * @protected
1729
         * @param {HTMLElement} moduleElement Optional. A reference to the module element
1730
         */
1731
        _renderHeader: function(moduleElement){
1732
            moduleElement = moduleElement || this.element;
1733
1734
            // Need to get everything into the DOM if it isn't already
1735
            if (this.header && !Dom.inDocument(this.header)) {
1736
                // There is a header, but it's not in the DOM yet. Need to add it.
1737
                var firstChild = moduleElement.firstChild;
1738
                if (firstChild) {
1739
                    moduleElement.insertBefore(this.header, firstChild);
1740
                } else {
1741
                    moduleElement.appendChild(this.header);
1742
                }
1743
            }
1744
        },
1745
1746
        /**
1747
         * Renders the currently set body into it's proper position under the 
1748
         * module element. If the module element is not provided, "this.element" 
1749
         * is used.
1750
         * 
1751
         * @method _renderBody
1752
         * @protected
1753
         * @param {HTMLElement} moduleElement Optional. A reference to the module element.
1754
         */
1755
        _renderBody: function(moduleElement){
1756
            moduleElement = moduleElement || this.element;
1757
1758
            if (this.body && !Dom.inDocument(this.body)) {
1759
                // There is a body, but it's not in the DOM yet. Need to add it.
1760
                if (this.footer && Dom.isAncestor(moduleElement, this.footer)) {
1761
                    moduleElement.insertBefore(this.body, this.footer);
1762
                } else {
1763
                    moduleElement.appendChild(this.body);
1764
                }
1765
            }
1766
        },
1767
1768
        /**
1769
         * Renders the currently set footer into it's proper position under the 
1770
         * module element. If the module element is not provided, "this.element" 
1771
         * is used.
1772
         * 
1773
         * @method _renderFooter
1774
         * @protected
1775
         * @param {HTMLElement} moduleElement Optional. A reference to the module element
1776
         */
1777
        _renderFooter: function(moduleElement){
1778
            moduleElement = moduleElement || this.element;
1779
1780
            if (this.footer && !Dom.inDocument(this.footer)) {
1781
                // There is a footer, but it's not in the DOM yet. Need to add it.
1782
                moduleElement.appendChild(this.footer);
1783
            }
1784
        },
1785
1786
        /**
1787
        * Removes the Module element from the DOM and sets all child elements 
1788
        * to null.
1789
        * @method destroy
1790
        */
1791
        destroy: function () {
1792
1793
            var parent;
1794
1795
            if (this.element) {
1796
                Event.purgeElement(this.element, true);
1797
                parent = this.element.parentNode;
1798
            }
1799
1800
            if (parent) {
1801
                parent.removeChild(this.element);
1802
            }
1803
        
1804
            this.element = null;
1805
            this.header = null;
1806
            this.body = null;
1807
            this.footer = null;
1808
1809
            Module.textResizeEvent.unsubscribe(this.onDomResize, this);
1810
1811
            this.cfg.destroy();
1812
            this.cfg = null;
1813
1814
            this.destroyEvent.fire();
1815
        },
1816
1817
        /**
1818
        * Shows the Module element by setting the visible configuration 
1819
        * property to true. Also fires two events: beforeShowEvent prior to 
1820
        * the visibility change, and showEvent after.
1821
        * @method show
1822
        */
1823
        show: function () {
1824
            this.cfg.setProperty("visible", true);
1825
        },
1826
1827
        /**
1828
        * Hides the Module element by setting the visible configuration 
1829
        * property to false. Also fires two events: beforeHideEvent prior to 
1830
        * the visibility change, and hideEvent after.
1831
        * @method hide
1832
        */
1833
        hide: function () {
1834
            this.cfg.setProperty("visible", false);
1835
        },
1836
        
1837
        // BUILT-IN EVENT HANDLERS FOR MODULE //
1838
        /**
1839
        * Default event handler for changing the visibility property of a 
1840
        * Module. By default, this is achieved by switching the "display" style 
1841
        * between "block" and "none".
1842
        * This method is responsible for firing showEvent and hideEvent.
1843
        * @param {String} type The CustomEvent type (usually the property name)
1844
        * @param {Object[]} args The CustomEvent arguments. For configuration 
1845
        * handlers, args[0] will equal the newly applied value for the property.
1846
        * @param {Object} obj The scope object. For configuration handlers, 
1847
        * this will usually equal the owner.
1848
        * @method configVisible
1849
        */
1850
        configVisible: function (type, args, obj) {
1851
            var visible = args[0];
1852
            if (visible) {
1853
                this.beforeShowEvent.fire();
1854
                Dom.setStyle(this.element, "display", "block");
1855
                this.showEvent.fire();
1856
            } else {
1857
                this.beforeHideEvent.fire();
1858
                Dom.setStyle(this.element, "display", "none");
1859
                this.hideEvent.fire();
1860
            }
1861
        },
1862
1863
        /**
1864
        * Default event handler for the "monitorresize" configuration property
1865
        * @param {String} type The CustomEvent type (usually the property name)
1866
        * @param {Object[]} args The CustomEvent arguments. For configuration 
1867
        * handlers, args[0] will equal the newly applied value for the property.
1868
        * @param {Object} obj The scope object. For configuration handlers, 
1869
        * this will usually equal the owner.
1870
        * @method configMonitorResize
1871
        */
1872
        configMonitorResize: function (type, args, obj) {
1873
            var monitor = args[0];
1874
            if (monitor) {
1875
                this.initResizeMonitor();
1876
            } else {
1877
                Module.textResizeEvent.unsubscribe(this.onDomResize, this, true);
1878
                this.resizeMonitor = null;
1879
            }
1880
        },
1881
1882
        /**
1883
         * This method is a protected helper, used when constructing the DOM structure for the module 
1884
         * to account for situations which may cause Operation Aborted errors in IE. It should not 
1885
         * be used for general DOM construction.
1886
         * <p>
1887
         * If the parentNode is not document.body, the element is appended as the last element.
1888
         * </p>
1889
         * <p>
1890
         * If the parentNode is document.body the element is added as the first child to help
1891
         * prevent Operation Aborted errors in IE.
1892
         * </p>
1893
         *
1894
         * @param {parentNode} The HTML element to which the element will be added
1895
         * @param {element} The HTML element to be added to parentNode's children
1896
         * @method _addToParent
1897
         * @protected
1898
         */
1899
        _addToParent: function(parentNode, element) {
1900
            if (!this.cfg.getProperty("appendtodocumentbody") && parentNode === document.body && parentNode.firstChild) {
1901
                parentNode.insertBefore(element, parentNode.firstChild);
1902
            } else {
1903
                parentNode.appendChild(element);
1904
            }
1905
        },
1906
1907
        /**
1908
        * Returns a String representation of the Object.
1909
        * @method toString
1910
        * @return {String} The string representation of the Module
1911
        */
1912
        toString: function () {
1913
            return "Module " + this.id;
1914
        }
1915
    };
1916
1917
    YAHOO.lang.augmentProto(Module, YAHOO.util.EventProvider);
1918
1919
}());
1920
(function () {
1921
1922
    /**
1923
    * Overlay is a Module that is absolutely positioned above the page flow. It 
1924
    * has convenience methods for positioning and sizing, as well as options for 
1925
    * controlling zIndex and constraining the Overlay's position to the current 
1926
    * visible viewport. Overlay also contains a dynamicly generated IFRAME which 
1927
    * is placed beneath it for Internet Explorer 6 and 5.x so that it will be 
1928
    * properly rendered above SELECT elements.
1929
    * @namespace YAHOO.widget
1930
    * @class Overlay
1931
    * @extends YAHOO.widget.Module
1932
    * @param {String} el The element ID representing the Overlay <em>OR</em>
1933
    * @param {HTMLElement} el The element representing the Overlay
1934
    * @param {Object} userConfig The configuration object literal containing 
1935
    * the configuration that should be set for this Overlay. See configuration 
1936
    * documentation for more details.
1937
    * @constructor
1938
    */
1939
    YAHOO.widget.Overlay = function (el, userConfig) {
1940
        YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
1941
    };
1942
1943
    var Lang = YAHOO.lang,
1944
        CustomEvent = YAHOO.util.CustomEvent,
1945
        Module = YAHOO.widget.Module,
1946
        Event = YAHOO.util.Event,
1947
        Dom = YAHOO.util.Dom,
1948
        Config = YAHOO.util.Config,
1949
        UA = YAHOO.env.ua,
1950
        Overlay = YAHOO.widget.Overlay,
1951
1952
        _SUBSCRIBE = "subscribe",
1953
        _UNSUBSCRIBE = "unsubscribe",
1954
        _CONTAINED = "contained",
1955
1956
        m_oIFrameTemplate,
1957
1958
        /**
1959
        * Constant representing the name of the Overlay's events
1960
        * @property EVENT_TYPES
1961
        * @private
1962
        * @final
1963
        * @type Object
1964
        */
1965
        EVENT_TYPES = {
1966
            "BEFORE_MOVE": "beforeMove",
1967
            "MOVE": "move"
1968
        },
1969
1970
        /**
1971
        * Constant representing the Overlay's configuration properties
1972
        * @property DEFAULT_CONFIG
1973
        * @private
1974
        * @final
1975
        * @type Object
1976
        */
1977
        DEFAULT_CONFIG = {
1978
1979
            "X": { 
1980
                key: "x", 
1981
                validator: Lang.isNumber, 
1982
                suppressEvent: true, 
1983
                supercedes: ["iframe"]
1984
            },
1985
1986
            "Y": { 
1987
                key: "y", 
1988
                validator: Lang.isNumber, 
1989
                suppressEvent: true, 
1990
                supercedes: ["iframe"]
1991
            },
1992
1993
            "XY": { 
1994
                key: "xy", 
1995
                suppressEvent: true, 
1996
                supercedes: ["iframe"] 
1997
            },
1998
1999
            "CONTEXT": { 
2000
                key: "context", 
2001
                suppressEvent: true, 
2002
                supercedes: ["iframe"] 
2003
            },
2004
2005
            "FIXED_CENTER": { 
2006
                key: "fixedcenter", 
2007
                value: false, 
2008
                supercedes: ["iframe", "visible"] 
2009
            },
2010
2011
            "WIDTH": { 
2012
                key: "width",
2013
                suppressEvent: true,
2014
                supercedes: ["context", "fixedcenter", "iframe"]
2015
            }, 
2016
2017
            "HEIGHT": { 
2018
                key: "height", 
2019
                suppressEvent: true, 
2020
                supercedes: ["context", "fixedcenter", "iframe"] 
2021
            },
2022
2023
            "AUTO_FILL_HEIGHT" : {
2024
                key: "autofillheight",
2025
                supercedes: ["height"],
2026
                value:"body"
2027
            },
2028
2029
            "ZINDEX": { 
2030
                key: "zindex", 
2031
                value: null 
2032
            },
2033
2034
            "CONSTRAIN_TO_VIEWPORT": { 
2035
                key: "constraintoviewport", 
2036
                value: false, 
2037
                validator: Lang.isBoolean, 
2038
                supercedes: ["iframe", "x", "y", "xy"]
2039
            }, 
2040
2041
            "IFRAME": { 
2042
                key: "iframe", 
2043
                value: (UA.ie == 6 ? true : false), 
2044
                validator: Lang.isBoolean, 
2045
                supercedes: ["zindex"] 
2046
            },
2047
2048
            "PREVENT_CONTEXT_OVERLAP": {
2049
                key: "preventcontextoverlap",
2050
                value: false,
2051
                validator: Lang.isBoolean,  
2052
                supercedes: ["constraintoviewport"]
2053
            }
2054
2055
        };
2056
2057
    /**
2058
    * The URL that will be placed in the iframe
2059
    * @property YAHOO.widget.Overlay.IFRAME_SRC
2060
    * @static
2061
    * @final
2062
    * @type String
2063
    */
2064
    Overlay.IFRAME_SRC = "javascript:false;";
2065
2066
    /**
2067
    * Number representing how much the iframe shim should be offset from each 
2068
    * side of an Overlay instance, in pixels.
2069
    * @property YAHOO.widget.Overlay.IFRAME_SRC
2070
    * @default 3
2071
    * @static
2072
    * @final
2073
    * @type Number
2074
    */
2075
    Overlay.IFRAME_OFFSET = 3;
2076
2077
    /**
2078
    * Number representing the minimum distance an Overlay instance should be 
2079
    * positioned relative to the boundaries of the browser's viewport, in pixels.
2080
    * @property YAHOO.widget.Overlay.VIEWPORT_OFFSET
2081
    * @default 10
2082
    * @static
2083
    * @final
2084
    * @type Number
2085
    */
2086
    Overlay.VIEWPORT_OFFSET = 10;
2087
2088
    /**
2089
    * Constant representing the top left corner of an element, used for 
2090
    * configuring the context element alignment
2091
    * @property YAHOO.widget.Overlay.TOP_LEFT
2092
    * @static
2093
    * @final
2094
    * @type String
2095
    */
2096
    Overlay.TOP_LEFT = "tl";
2097
2098
    /**
2099
    * Constant representing the top right corner of an element, used for 
2100
    * configuring the context element alignment
2101
    * @property YAHOO.widget.Overlay.TOP_RIGHT
2102
    * @static
2103
    * @final
2104
    * @type String
2105
    */
2106
    Overlay.TOP_RIGHT = "tr";
2107
2108
    /**
2109
    * Constant representing the top bottom left corner of an element, used for 
2110
    * configuring the context element alignment
2111
    * @property YAHOO.widget.Overlay.BOTTOM_LEFT
2112
    * @static
2113
    * @final
2114
    * @type String
2115
    */
2116
    Overlay.BOTTOM_LEFT = "bl";
2117
2118
    /**
2119
    * Constant representing the bottom right corner of an element, used for 
2120
    * configuring the context element alignment
2121
    * @property YAHOO.widget.Overlay.BOTTOM_RIGHT
2122
    * @static
2123
    * @final
2124
    * @type String
2125
    */
2126
    Overlay.BOTTOM_RIGHT = "br";
2127
2128
    Overlay.PREVENT_OVERLAP_X = {
2129
        "tltr": true,
2130
        "blbr": true,
2131
        "brbl": true,
2132
        "trtl": true
2133
    };
2134
            
2135
    Overlay.PREVENT_OVERLAP_Y = {
2136
        "trbr": true,
2137
        "tlbl": true,
2138
        "bltl": true,
2139
        "brtr": true
2140
    };
2141
2142
    /**
2143
    * Constant representing the default CSS class used for an Overlay
2144
    * @property YAHOO.widget.Overlay.CSS_OVERLAY
2145
    * @static
2146
    * @final
2147
    * @type String
2148
    */
2149
    Overlay.CSS_OVERLAY = "yui-overlay";
2150
2151
    /**
2152
    * Constant representing the default hidden CSS class used for an Overlay. This class is 
2153
    * applied to the overlay's outer DIV whenever it's hidden.
2154
    *
2155
    * @property YAHOO.widget.Overlay.CSS_HIDDEN
2156
    * @static
2157
    * @final
2158
    * @type String
2159
    */
2160
    Overlay.CSS_HIDDEN = "yui-overlay-hidden";
2161
2162
    /**
2163
    * Constant representing the default CSS class used for an Overlay iframe shim.
2164
    * 
2165
    * @property YAHOO.widget.Overlay.CSS_IFRAME
2166
    * @static
2167
    * @final
2168
    * @type String
2169
    */
2170
    Overlay.CSS_IFRAME = "yui-overlay-iframe";
2171
2172
    /**
2173
     * Constant representing the names of the standard module elements
2174
     * used in the overlay.
2175
     * @property YAHOO.widget.Overlay.STD_MOD_RE
2176
     * @static
2177
     * @final
2178
     * @type RegExp
2179
     */
2180
    Overlay.STD_MOD_RE = /^\s*?(body|footer|header)\s*?$/i;
2181
2182
    /**
2183
    * A singleton CustomEvent used for reacting to the DOM event for 
2184
    * window scroll
2185
    * @event YAHOO.widget.Overlay.windowScrollEvent
2186
    */
2187
    Overlay.windowScrollEvent = new CustomEvent("windowScroll");
2188
2189
    /**
2190
    * A singleton CustomEvent used for reacting to the DOM event for
2191
    * window resize
2192
    * @event YAHOO.widget.Overlay.windowResizeEvent
2193
    */
2194
    Overlay.windowResizeEvent = new CustomEvent("windowResize");
2195
2196
    /**
2197
    * The DOM event handler used to fire the CustomEvent for window scroll
2198
    * @method YAHOO.widget.Overlay.windowScrollHandler
2199
    * @static
2200
    * @param {DOMEvent} e The DOM scroll event
2201
    */
2202
    Overlay.windowScrollHandler = function (e) {
2203
        var t = Event.getTarget(e);
2204
2205
        // - Webkit (Safari 2/3) and Opera 9.2x bubble scroll events from elements to window
2206
        // - FF2/3 and IE6/7, Opera 9.5x don't bubble scroll events from elements to window
2207
        // - IE doesn't recognize scroll registered on the document.
2208
        //
2209
        // Also, when document view is scrolled, IE doesn't provide a target, 
2210
        // rest of the browsers set target to window.document, apart from opera 
2211
        // which sets target to window.
2212
        if (!t || t === window || t === window.document) {
2213
            if (UA.ie) {
2214
2215
                if (! window.scrollEnd) {
2216
                    window.scrollEnd = -1;
2217
                }
2218
2219
                clearTimeout(window.scrollEnd);
2220
        
2221
                window.scrollEnd = setTimeout(function () { 
2222
                    Overlay.windowScrollEvent.fire(); 
2223
                }, 1);
2224
        
2225
            } else {
2226
                Overlay.windowScrollEvent.fire();
2227
            }
2228
        }
2229
    };
2230
2231
    /**
2232
    * The DOM event handler used to fire the CustomEvent for window resize
2233
    * @method YAHOO.widget.Overlay.windowResizeHandler
2234
    * @static
2235
    * @param {DOMEvent} e The DOM resize event
2236
    */
2237
    Overlay.windowResizeHandler = function (e) {
2238
2239
        if (UA.ie) {
2240
            if (! window.resizeEnd) {
2241
                window.resizeEnd = -1;
2242
            }
2243
2244
            clearTimeout(window.resizeEnd);
2245
2246
            window.resizeEnd = setTimeout(function () {
2247
                Overlay.windowResizeEvent.fire(); 
2248
            }, 100);
2249
        } else {
2250
            Overlay.windowResizeEvent.fire();
2251
        }
2252
    };
2253
2254
    /**
2255
    * A boolean that indicated whether the window resize and scroll events have 
2256
    * already been subscribed to.
2257
    * @property YAHOO.widget.Overlay._initialized
2258
    * @private
2259
    * @type Boolean
2260
    */
2261
    Overlay._initialized = null;
2262
2263
    if (Overlay._initialized === null) {
2264
        Event.on(window, "scroll", Overlay.windowScrollHandler);
2265
        Event.on(window, "resize", Overlay.windowResizeHandler);
2266
        Overlay._initialized = true;
2267
    }
2268
2269
    /**
2270
     * Internal map of special event types, which are provided
2271
     * by the instance. It maps the event type to the custom event 
2272
     * instance. Contains entries for the "windowScroll", "windowResize" and
2273
     * "textResize" static container events.
2274
     *
2275
     * @property YAHOO.widget.Overlay._TRIGGER_MAP
2276
     * @type Object
2277
     * @static
2278
     * @private
2279
     */
2280
    Overlay._TRIGGER_MAP = {
2281
        "windowScroll" : Overlay.windowScrollEvent,
2282
        "windowResize" : Overlay.windowResizeEvent,
2283
        "textResize"   : Module.textResizeEvent
2284
    };
2285
2286
    YAHOO.extend(Overlay, Module, {
2287
2288
        /**
2289
         * <p>
2290
         * Array of default event types which will trigger
2291
         * context alignment for the Overlay class.
2292
         * </p>
2293
         * <p>The array is empty by default for Overlay,
2294
         * but maybe populated in future releases, so classes extending
2295
         * Overlay which need to define their own set of CONTEXT_TRIGGERS
2296
         * should concatenate their super class's prototype.CONTEXT_TRIGGERS 
2297
         * value with their own array of values.
2298
         * </p>
2299
         * <p>
2300
         * E.g.:
2301
         * <code>CustomOverlay.prototype.CONTEXT_TRIGGERS = YAHOO.widget.Overlay.prototype.CONTEXT_TRIGGERS.concat(["windowScroll"]);</code>
2302
         * </p>
2303
         * 
2304
         * @property CONTEXT_TRIGGERS
2305
         * @type Array
2306
         * @final
2307
         */
2308
        CONTEXT_TRIGGERS : [],
2309
2310
        /**
2311
        * The Overlay initialization method, which is executed for Overlay and  
2312
        * all of its subclasses. This method is automatically called by the 
2313
        * constructor, and  sets up all DOM references for pre-existing markup, 
2314
        * and creates required markup if it is not already present.
2315
        * @method init
2316
        * @param {String} el The element ID representing the Overlay <em>OR</em>
2317
        * @param {HTMLElement} el The element representing the Overlay
2318
        * @param {Object} userConfig The configuration object literal 
2319
        * containing the configuration that should be set for this Overlay. 
2320
        * See configuration documentation for more details.
2321
        */
2322
        init: function (el, userConfig) {
2323
2324
            /*
2325
                 Note that we don't pass the user config in here yet because we
2326
                 only want it executed once, at the lowest subclass level
2327
            */
2328
2329
            Overlay.superclass.init.call(this, el/*, userConfig*/);
2330
2331
            this.beforeInitEvent.fire(Overlay);
2332
2333
            Dom.addClass(this.element, Overlay.CSS_OVERLAY);
2334
2335
            if (userConfig) {
2336
                this.cfg.applyConfig(userConfig, true);
2337
            }
2338
2339
            if (this.platform == "mac" && UA.gecko) {
2340
2341
                if (! Config.alreadySubscribed(this.showEvent,
2342
                    this.showMacGeckoScrollbars, this)) {
2343
2344
                    this.showEvent.subscribe(this.showMacGeckoScrollbars, 
2345
                        this, true);
2346
2347
                }
2348
2349
                if (! Config.alreadySubscribed(this.hideEvent, 
2350
                    this.hideMacGeckoScrollbars, this)) {
2351
2352
                    this.hideEvent.subscribe(this.hideMacGeckoScrollbars, 
2353
                        this, true);
2354
2355
                }
2356
            }
2357
2358
            this.initEvent.fire(Overlay);
2359
        },
2360
        
2361
        /**
2362
        * Initializes the custom events for Overlay which are fired  
2363
        * automatically at appropriate times by the Overlay class.
2364
        * @method initEvents
2365
        */
2366
        initEvents: function () {
2367
2368
            Overlay.superclass.initEvents.call(this);
2369
2370
            var SIGNATURE = CustomEvent.LIST;
2371
2372
            /**
2373
            * CustomEvent fired before the Overlay is moved.
2374
            * @event beforeMoveEvent
2375
            * @param {Number} x x coordinate
2376
            * @param {Number} y y coordinate
2377
            */
2378
            this.beforeMoveEvent = this.createEvent(EVENT_TYPES.BEFORE_MOVE);
2379
            this.beforeMoveEvent.signature = SIGNATURE;
2380
2381
            /**
2382
            * CustomEvent fired after the Overlay is moved.
2383
            * @event moveEvent
2384
            * @param {Number} x x coordinate
2385
            * @param {Number} y y coordinate
2386
            */
2387
            this.moveEvent = this.createEvent(EVENT_TYPES.MOVE);
2388
            this.moveEvent.signature = SIGNATURE;
2389
2390
        },
2391
        
2392
        /**
2393
        * Initializes the class's configurable properties which can be changed 
2394
        * using the Overlay's Config object (cfg).
2395
        * @method initDefaultConfig
2396
        */
2397
        initDefaultConfig: function () {
2398
    
2399
            Overlay.superclass.initDefaultConfig.call(this);
2400
2401
            var cfg = this.cfg;
2402
2403
            // Add overlay config properties //
2404
            
2405
            /**
2406
            * The absolute x-coordinate position of the Overlay
2407
            * @config x
2408
            * @type Number
2409
            * @default null
2410
            */
2411
            cfg.addProperty(DEFAULT_CONFIG.X.key, { 
2412
    
2413
                handler: this.configX, 
2414
                validator: DEFAULT_CONFIG.X.validator, 
2415
                suppressEvent: DEFAULT_CONFIG.X.suppressEvent, 
2416
                supercedes: DEFAULT_CONFIG.X.supercedes
2417
    
2418
            });
2419
2420
            /**
2421
            * The absolute y-coordinate position of the Overlay
2422
            * @config y
2423
            * @type Number
2424
            * @default null
2425
            */
2426
            cfg.addProperty(DEFAULT_CONFIG.Y.key, {
2427
2428
                handler: this.configY, 
2429
                validator: DEFAULT_CONFIG.Y.validator, 
2430
                suppressEvent: DEFAULT_CONFIG.Y.suppressEvent, 
2431
                supercedes: DEFAULT_CONFIG.Y.supercedes
2432
2433
            });
2434
2435
            /**
2436
            * An array with the absolute x and y positions of the Overlay
2437
            * @config xy
2438
            * @type Number[]
2439
            * @default null
2440
            */
2441
            cfg.addProperty(DEFAULT_CONFIG.XY.key, {
2442
                handler: this.configXY, 
2443
                suppressEvent: DEFAULT_CONFIG.XY.suppressEvent, 
2444
                supercedes: DEFAULT_CONFIG.XY.supercedes
2445
            });
2446
2447
            /**
2448
            * <p>
2449
            * The array of context arguments for context-sensitive positioning. 
2450
            * </p>
2451
            *
2452
            * <p>
2453
            * The format of the array is: <code>[contextElementOrId, overlayCorner, contextCorner, arrayOfTriggerEvents (optional), xyOffset (optional)]</code>, the
2454
            * the 5 array elements described in detail below:
2455
            * </p>
2456
            *
2457
            * <dl>
2458
            * <dt>contextElementOrId &#60;String|HTMLElement&#62;</dt>
2459
            * <dd>A reference to the context element to which the overlay should be aligned (or it's id).</dd>
2460
            * <dt>overlayCorner &#60;String&#62;</dt>
2461
            * <dd>The corner of the overlay which is to be used for alignment. This corner will be aligned to the 
2462
            * corner of the context element defined by the "contextCorner" entry which follows. Supported string values are: 
2463
            * "tr" (top right), "tl" (top left), "br" (bottom right), or "bl" (bottom left).</dd>
2464
            * <dt>contextCorner &#60;String&#62;</dt>
2465
            * <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>
2466
            * <dt>arrayOfTriggerEvents (optional) &#60;Array[String|CustomEvent]&#62;</dt>
2467
            * <dd>
2468
            * <p>
2469
            * 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> 
2470
            * 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. 
2471
            * This is useful in situations where the layout of the document may change, resulting in the context element's position being modified.
2472
            * </p>
2473
            * <p>
2474
            * The array can contain either event type strings for events the instance publishes (e.g. "beforeShow") or CustomEvent instances. Additionally the following
2475
            * 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).
2476
            * </p>
2477
            * </dd>
2478
            * <dt>xyOffset &#60;Number[]&#62;</dt>
2479
            * <dd>
2480
            * A 2 element Array specifying the X and Y pixel amounts by which the Overlay should be offset from the aligned corner. e.g. [5,0] offsets the Overlay 5 pixels to the left, <em>after</em> aligning the given context corners.
2481
            * NOTE: If using this property and no triggers need to be defined, the arrayOfTriggerEvents property should be set to null to maintain correct array positions for the arguments. 
2482
            * </dd>
2483
            * </dl>
2484
            *
2485
            * <p>
2486
            * For example, setting this property to <code>["img1", "tl", "bl"]</code> will 
2487
            * align the Overlay's top left corner to the bottom left corner of the
2488
            * context element with id "img1".
2489
            * </p>
2490
            * <p>
2491
            * Setting this property to <code>["img1", "tl", "bl", null, [0,5]</code> will 
2492
            * align the Overlay's top left corner to the bottom left corner of the
2493
            * context element with id "img1", and then offset it by 5 pixels on the Y axis (providing a 5 pixel gap between the bottom of the context element and top of the overlay).
2494
            * </p>
2495
            * <p>
2496
            * Adding the optional trigger values: <code>["img1", "tl", "bl", ["beforeShow", "windowResize"], [0,5]]</code>,
2497
            * will re-align the overlay position, whenever the "beforeShow" or "windowResize" events are fired.
2498
            * </p>
2499
            *
2500
            * @config context
2501
            * @type Array
2502
            * @default null
2503
            */
2504
            cfg.addProperty(DEFAULT_CONFIG.CONTEXT.key, {
2505
                handler: this.configContext, 
2506
                suppressEvent: DEFAULT_CONFIG.CONTEXT.suppressEvent, 
2507
                supercedes: DEFAULT_CONFIG.CONTEXT.supercedes
2508
            });
2509
2510
            /**
2511
            * Determines whether or not the Overlay should be anchored 
2512
            * to the center of the viewport.
2513
            * 
2514
            * <p>This property can be set to:</p>
2515
            * 
2516
            * <dl>
2517
            * <dt>true</dt>
2518
            * <dd>
2519
            * To enable fixed center positioning
2520
            * <p>
2521
            * When enabled, the overlay will 
2522
            * be positioned in the center of viewport when initially displayed, and 
2523
            * will remain in the center of the viewport whenever the window is 
2524
            * scrolled or resized.
2525
            * </p>
2526
            * <p>
2527
            * If the overlay is too big for the viewport, 
2528
            * it's top left corner will be aligned with the top left corner of the viewport.
2529
            * </p>
2530
            * </dd>
2531
            * <dt>false</dt>
2532
            * <dd>
2533
            * To disable fixed center positioning.
2534
            * <p>In this case the overlay can still be 
2535
            * centered as a one-off operation, by invoking the <code>center()</code> method,
2536
            * however it will not remain centered when the window is scrolled/resized.
2537
            * </dd>
2538
            * <dt>"contained"<dt>
2539
            * <dd>To enable fixed center positioning, as with the <code>true</code> option.
2540
            * <p>However, unlike setting the property to <code>true</code>, 
2541
            * when the property is set to <code>"contained"</code>, if the overlay is 
2542
            * too big for the viewport, it will not get automatically centered when the 
2543
            * user scrolls or resizes the window (until the window is large enough to contain the 
2544
            * overlay). This is useful in cases where the Overlay has both header and footer 
2545
            * UI controls which the user may need to access.
2546
            * </p>
2547
            * </dd>
2548
            * </dl>
2549
            *
2550
            * @config fixedcenter
2551
            * @type Boolean | String
2552
            * @default false
2553
            */
2554
            cfg.addProperty(DEFAULT_CONFIG.FIXED_CENTER.key, {
2555
                handler: this.configFixedCenter,
2556
                value: DEFAULT_CONFIG.FIXED_CENTER.value, 
2557
                validator: DEFAULT_CONFIG.FIXED_CENTER.validator, 
2558
                supercedes: DEFAULT_CONFIG.FIXED_CENTER.supercedes
2559
            });
2560
    
2561
            /**
2562
            * CSS width of the Overlay.
2563
            * @config width
2564
            * @type String
2565
            * @default null
2566
            */
2567
            cfg.addProperty(DEFAULT_CONFIG.WIDTH.key, {
2568
                handler: this.configWidth, 
2569
                suppressEvent: DEFAULT_CONFIG.WIDTH.suppressEvent, 
2570
                supercedes: DEFAULT_CONFIG.WIDTH.supercedes
2571
            });
2572
2573
            /**
2574
            * CSS height of the Overlay.
2575
            * @config height
2576
            * @type String
2577
            * @default null
2578
            */
2579
            cfg.addProperty(DEFAULT_CONFIG.HEIGHT.key, {
2580
                handler: this.configHeight, 
2581
                suppressEvent: DEFAULT_CONFIG.HEIGHT.suppressEvent, 
2582
                supercedes: DEFAULT_CONFIG.HEIGHT.supercedes
2583
            });
2584
2585
            /**
2586
            * Standard module element which should auto fill out the height of the Overlay if the height config property is set.
2587
            * Supported values are "header", "body", "footer".
2588
            *
2589
            * @config autofillheight
2590
            * @type String
2591
            * @default null
2592
            */
2593
            cfg.addProperty(DEFAULT_CONFIG.AUTO_FILL_HEIGHT.key, {
2594
                handler: this.configAutoFillHeight, 
2595
                value : DEFAULT_CONFIG.AUTO_FILL_HEIGHT.value,
2596
                validator : this._validateAutoFill,
2597
                supercedes: DEFAULT_CONFIG.AUTO_FILL_HEIGHT.supercedes
2598
            });
2599
2600
            /**
2601
            * CSS z-index of the Overlay.
2602
            * @config zIndex
2603
            * @type Number
2604
            * @default null
2605
            */
2606
            cfg.addProperty(DEFAULT_CONFIG.ZINDEX.key, {
2607
                handler: this.configzIndex,
2608
                value: DEFAULT_CONFIG.ZINDEX.value
2609
            });
2610
2611
            /**
2612
            * True if the Overlay should be prevented from being positioned 
2613
            * out of the viewport.
2614
            * @config constraintoviewport
2615
            * @type Boolean
2616
            * @default false
2617
            */
2618
            cfg.addProperty(DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.key, {
2619
2620
                handler: this.configConstrainToViewport, 
2621
                value: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.value, 
2622
                validator: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.validator, 
2623
                supercedes: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.supercedes
2624
2625
            });
2626
2627
            /**
2628
            * @config iframe
2629
            * @description Boolean indicating whether or not the Overlay should 
2630
            * have an IFRAME shim; used to prevent SELECT elements from 
2631
            * poking through an Overlay instance in IE6.  When set to "true", 
2632
            * the iframe shim is created when the Overlay instance is intially
2633
            * made visible.
2634
            * @type Boolean
2635
            * @default true for IE6 and below, false for all other browsers.
2636
            */
2637
            cfg.addProperty(DEFAULT_CONFIG.IFRAME.key, {
2638
2639
                handler: this.configIframe, 
2640
                value: DEFAULT_CONFIG.IFRAME.value, 
2641
                validator: DEFAULT_CONFIG.IFRAME.validator, 
2642
                supercedes: DEFAULT_CONFIG.IFRAME.supercedes
2643
2644
            });
2645
2646
            /**
2647
            * @config preventcontextoverlap
2648
            * @description Boolean indicating whether or not the Overlay should overlap its 
2649
            * context element (defined using the "context" configuration property) when the 
2650
            * "constraintoviewport" configuration property is set to "true".
2651
            * @type Boolean
2652
            * @default false
2653
            */
2654
            cfg.addProperty(DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.key, {
2655
                value: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.value, 
2656
                validator: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.validator, 
2657
                supercedes: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.supercedes
2658
            });
2659
        },
2660
2661
        /**
2662
        * Moves the Overlay to the specified position. This function is  
2663
        * identical to calling this.cfg.setProperty("xy", [x,y]);
2664
        * @method moveTo
2665
        * @param {Number} x The Overlay's new x position
2666
        * @param {Number} y The Overlay's new y position
2667
        */
2668
        moveTo: function (x, y) {
2669
            this.cfg.setProperty("xy", [x, y]);
2670
        },
2671
2672
        /**
2673
        * Adds a CSS class ("hide-scrollbars") and removes a CSS class 
2674
        * ("show-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
2675
        * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2676
        * @method hideMacGeckoScrollbars
2677
        */
2678
        hideMacGeckoScrollbars: function () {
2679
            Dom.replaceClass(this.element, "show-scrollbars", "hide-scrollbars");
2680
        },
2681
2682
        /**
2683
        * Adds a CSS class ("show-scrollbars") and removes a CSS class 
2684
        * ("hide-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
2685
        * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2686
        * @method showMacGeckoScrollbars
2687
        */
2688
        showMacGeckoScrollbars: function () {
2689
            Dom.replaceClass(this.element, "hide-scrollbars", "show-scrollbars");
2690
        },
2691
2692
        /**
2693
         * Internal implementation to set the visibility of the overlay in the DOM.
2694
         *
2695
         * @method _setDomVisibility
2696
         * @param {boolean} visible Whether to show or hide the Overlay's outer element
2697
         * @protected
2698
         */
2699
        _setDomVisibility : function(show) {
2700
            Dom.setStyle(this.element, "visibility", (show) ? "visible" : "hidden");
2701
            var hiddenClass = Overlay.CSS_HIDDEN;
2702
2703
            if (show) {
2704
                Dom.removeClass(this.element, hiddenClass);
2705
            } else {
2706
                Dom.addClass(this.element, hiddenClass);
2707
            }
2708
        },
2709
2710
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
2711
        /**
2712
        * The default event handler fired when the "visible" property is 
2713
        * changed.  This method is responsible for firing showEvent
2714
        * and hideEvent.
2715
        * @method configVisible
2716
        * @param {String} type The CustomEvent type (usually the property name)
2717
        * @param {Object[]} args The CustomEvent arguments. For configuration
2718
        * handlers, args[0] will equal the newly applied value for the property.
2719
        * @param {Object} obj The scope object. For configuration handlers, 
2720
        * this will usually equal the owner.
2721
        */
2722
        configVisible: function (type, args, obj) {
2723
2724
            var visible = args[0],
2725
                currentVis = Dom.getStyle(this.element, "visibility"),
2726
                effect = this.cfg.getProperty("effect"),
2727
                effectInstances = [],
2728
                isMacGecko = (this.platform == "mac" && UA.gecko),
2729
                alreadySubscribed = Config.alreadySubscribed,
2730
                eff, ei, e, i, j, k, h,
2731
                nEffects,
2732
                nEffectInstances;
2733
2734
            if (currentVis == "inherit") {
2735
                e = this.element.parentNode;
2736
2737
                while (e.nodeType != 9 && e.nodeType != 11) {
2738
                    currentVis = Dom.getStyle(e, "visibility");
2739
2740
                    if (currentVis != "inherit") {
2741
                        break;
2742
                    }
2743
2744
                    e = e.parentNode;
2745
                }
2746
2747
                if (currentVis == "inherit") {
2748
                    currentVis = "visible";
2749
                }
2750
            }
2751
2752
            if (effect) {
2753
                if (effect instanceof Array) {
2754
                    nEffects = effect.length;
2755
2756
                    for (i = 0; i < nEffects; i++) {
2757
                        eff = effect[i];
2758
                        effectInstances[effectInstances.length] = 
2759
                            eff.effect(this, eff.duration);
2760
2761
                    }
2762
                } else {
2763
                    effectInstances[effectInstances.length] = 
2764
                        effect.effect(this, effect.duration);
2765
                }
2766
            }
2767
2768
            if (visible) { // Show
2769
                if (isMacGecko) {
2770
                    this.showMacGeckoScrollbars();
2771
                }
2772
2773
                if (effect) { // Animate in
2774
                    if (visible) { // Animate in if not showing
2775
                        if (currentVis != "visible" || currentVis === "") {
2776
                            this.beforeShowEvent.fire();
2777
                            nEffectInstances = effectInstances.length;
2778
2779
                            for (j = 0; j < nEffectInstances; j++) {
2780
                                ei = effectInstances[j];
2781
                                if (j === 0 && !alreadySubscribed(
2782
                                        ei.animateInCompleteEvent, 
2783
                                        this.showEvent.fire, this.showEvent)) {
2784
2785
                                    /*
2786
                                         Delegate showEvent until end 
2787
                                         of animateInComplete
2788
                                    */
2789
2790
                                    ei.animateInCompleteEvent.subscribe(
2791
                                     this.showEvent.fire, this.showEvent, true);
2792
                                }
2793
                                ei.animateIn();
2794
                            }
2795
                        }
2796
                    }
2797
                } else { // Show
2798
                    if (currentVis != "visible" || currentVis === "") {
2799
                        this.beforeShowEvent.fire();
2800
2801
                        this._setDomVisibility(true);
2802
2803
                        this.cfg.refireEvent("iframe");
2804
                        this.showEvent.fire();
2805
                    } else {
2806
                        this._setDomVisibility(true);
2807
                    }
2808
                }
2809
            } else { // Hide
2810
2811
                if (isMacGecko) {
2812
                    this.hideMacGeckoScrollbars();
2813
                }
2814
2815
                if (effect) { // Animate out if showing
2816
                    if (currentVis == "visible") {
2817
                        this.beforeHideEvent.fire();
2818
2819
                        nEffectInstances = effectInstances.length;
2820
                        for (k = 0; k < nEffectInstances; k++) {
2821
                            h = effectInstances[k];
2822
    
2823
                            if (k === 0 && !alreadySubscribed(
2824
                                h.animateOutCompleteEvent, this.hideEvent.fire, 
2825
                                this.hideEvent)) {
2826
    
2827
                                /*
2828
                                     Delegate hideEvent until end 
2829
                                     of animateOutComplete
2830
                                */
2831
    
2832
                                h.animateOutCompleteEvent.subscribe(
2833
                                    this.hideEvent.fire, this.hideEvent, true);
2834
    
2835
                            }
2836
                            h.animateOut();
2837
                        }
2838
2839
                    } else if (currentVis === "") {
2840
                        this._setDomVisibility(false);
2841
                    }
2842
2843
                } else { // Simple hide
2844
2845
                    if (currentVis == "visible" || currentVis === "") {
2846
                        this.beforeHideEvent.fire();
2847
                        this._setDomVisibility(false);
2848
                        this.hideEvent.fire();
2849
                    } else {
2850
                        this._setDomVisibility(false);
2851
                    }
2852
                }
2853
            }
2854
        },
2855
2856
        /**
2857
        * Fixed center event handler used for centering on scroll/resize, but only if 
2858
        * the overlay is visible and, if "fixedcenter" is set to "contained", only if 
2859
        * the overlay fits within the viewport.
2860
        *
2861
        * @method doCenterOnDOMEvent
2862
        */
2863
        doCenterOnDOMEvent: function () {
2864
            var cfg = this.cfg,
2865
                fc = cfg.getProperty("fixedcenter");
2866
2867
            if (cfg.getProperty("visible")) {
2868
                if (fc && (fc !== _CONTAINED || this.fitsInViewport())) {
2869
                    this.center();
2870
                }
2871
            }
2872
        },
2873
2874
        /**
2875
         * Determines if the Overlay (including the offset value defined by Overlay.VIEWPORT_OFFSET) 
2876
         * will fit entirely inside the viewport, in both dimensions - width and height.
2877
         * 
2878
         * @method fitsInViewport
2879
         * @return boolean true if the Overlay will fit, false if not
2880
         */
2881
        fitsInViewport : function() {
2882
            var nViewportOffset = Overlay.VIEWPORT_OFFSET,
2883
                element = this.element,
2884
                elementWidth = element.offsetWidth,
2885
                elementHeight = element.offsetHeight,
2886
                viewportWidth = Dom.getViewportWidth(),
2887
                viewportHeight = Dom.getViewportHeight();
2888
2889
            return ((elementWidth + nViewportOffset < viewportWidth) && (elementHeight + nViewportOffset < viewportHeight));
2890
        },
2891
2892
        /**
2893
        * The default event handler fired when the "fixedcenter" property 
2894
        * is changed.
2895
        * @method configFixedCenter
2896
        * @param {String} type The CustomEvent type (usually the property name)
2897
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2898
        * handlers, args[0] will equal the newly applied value for the property.
2899
        * @param {Object} obj The scope object. For configuration handlers, 
2900
        * this will usually equal the owner.
2901
        */
2902
        configFixedCenter: function (type, args, obj) {
2903
2904
            var val = args[0],
2905
                alreadySubscribed = Config.alreadySubscribed,
2906
                windowResizeEvent = Overlay.windowResizeEvent,
2907
                windowScrollEvent = Overlay.windowScrollEvent;
2908
2909
            if (val) {
2910
                this.center();
2911
2912
                if (!alreadySubscribed(this.beforeShowEvent, this.center)) {
2913
                    this.beforeShowEvent.subscribe(this.center);
2914
                }
2915
2916
                if (!alreadySubscribed(windowResizeEvent, this.doCenterOnDOMEvent, this)) {
2917
                    windowResizeEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2918
                }
2919
2920
                if (!alreadySubscribed(windowScrollEvent, this.doCenterOnDOMEvent, this)) {
2921
                    windowScrollEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2922
                }
2923
2924
            } else {
2925
                this.beforeShowEvent.unsubscribe(this.center);
2926
2927
                windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2928
                windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2929
            }
2930
        },
2931
2932
        /**
2933
        * The default event handler fired when the "height" property is changed.
2934
        * @method configHeight
2935
        * @param {String} type The CustomEvent type (usually the property name)
2936
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2937
        * handlers, args[0] will equal the newly applied value for the property.
2938
        * @param {Object} obj The scope object. For configuration handlers, 
2939
        * this will usually equal the owner.
2940
        */
2941
        configHeight: function (type, args, obj) {
2942
2943
            var height = args[0],
2944
                el = this.element;
2945
2946
            Dom.setStyle(el, "height", height);
2947
            this.cfg.refireEvent("iframe");
2948
        },
2949
2950
        /**
2951
         * The default event handler fired when the "autofillheight" property is changed.
2952
         * @method configAutoFillHeight
2953
         *
2954
         * @param {String} type The CustomEvent type (usually the property name)
2955
         * @param {Object[]} args The CustomEvent arguments. For configuration 
2956
         * handlers, args[0] will equal the newly applied value for the property.
2957
         * @param {Object} obj The scope object. For configuration handlers, 
2958
         * this will usually equal the owner.
2959
         */
2960
        configAutoFillHeight: function (type, args, obj) {
2961
            var fillEl = args[0],
2962
                cfg = this.cfg,
2963
                autoFillHeight = "autofillheight",
2964
                height = "height",
2965
                currEl = cfg.getProperty(autoFillHeight),
2966
                autoFill = this._autoFillOnHeightChange;
2967
2968
            cfg.unsubscribeFromConfigEvent(height, autoFill);
2969
            Module.textResizeEvent.unsubscribe(autoFill);
2970
            this.changeContentEvent.unsubscribe(autoFill);
2971
2972
            if (currEl && fillEl !== currEl && this[currEl]) {
2973
                Dom.setStyle(this[currEl], height, "");
2974
            }
2975
2976
            if (fillEl) {
2977
                fillEl = Lang.trim(fillEl.toLowerCase());
2978
2979
                cfg.subscribeToConfigEvent(height, autoFill, this[fillEl], this);
2980
                Module.textResizeEvent.subscribe(autoFill, this[fillEl], this);
2981
                this.changeContentEvent.subscribe(autoFill, this[fillEl], this);
2982
2983
                cfg.setProperty(autoFillHeight, fillEl, true);
2984
            }
2985
        },
2986
2987
        /**
2988
        * The default event handler fired when the "width" property is changed.
2989
        * @method configWidth
2990
        * @param {String} type The CustomEvent type (usually the property name)
2991
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2992
        * handlers, args[0] will equal the newly applied value for the property.
2993
        * @param {Object} obj The scope object. For configuration handlers, 
2994
        * this will usually equal the owner.
2995
        */
2996
        configWidth: function (type, args, obj) {
2997
2998
            var width = args[0],
2999
                el = this.element;
3000
3001
            Dom.setStyle(el, "width", width);
3002
            this.cfg.refireEvent("iframe");
3003
        },
3004
3005
        /**
3006
        * The default event handler fired when the "zIndex" property is changed.
3007
        * @method configzIndex
3008
        * @param {String} type The CustomEvent type (usually the property name)
3009
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3010
        * handlers, args[0] will equal the newly applied value for the property.
3011
        * @param {Object} obj The scope object. For configuration handlers, 
3012
        * this will usually equal the owner.
3013
        */
3014
        configzIndex: function (type, args, obj) {
3015
3016
            var zIndex = args[0],
3017
                el = this.element;
3018
3019
            if (! zIndex) {
3020
                zIndex = Dom.getStyle(el, "zIndex");
3021
                if (! zIndex || isNaN(zIndex)) {
3022
                    zIndex = 0;
3023
                }
3024
            }
3025
3026
            if (this.iframe || this.cfg.getProperty("iframe") === true) {
3027
                if (zIndex <= 0) {
3028
                    zIndex = 1;
3029
                }
3030
            }
3031
3032
            Dom.setStyle(el, "zIndex", zIndex);
3033
            this.cfg.setProperty("zIndex", zIndex, true);
3034
3035
            if (this.iframe) {
3036
                this.stackIframe();
3037
            }
3038
        },
3039
3040
        /**
3041
        * The default event handler fired when the "xy" property is changed.
3042
        * @method configXY
3043
        * @param {String} type The CustomEvent type (usually the property name)
3044
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3045
        * handlers, args[0] will equal the newly applied value for the property.
3046
        * @param {Object} obj The scope object. For configuration handlers, 
3047
        * this will usually equal the owner.
3048
        */
3049
        configXY: function (type, args, obj) {
3050
3051
            var pos = args[0],
3052
                x = pos[0],
3053
                y = pos[1];
3054
3055
            this.cfg.setProperty("x", x);
3056
            this.cfg.setProperty("y", y);
3057
3058
            this.beforeMoveEvent.fire([x, y]);
3059
3060
            x = this.cfg.getProperty("x");
3061
            y = this.cfg.getProperty("y");
3062
3063
3064
            this.cfg.refireEvent("iframe");
3065
            this.moveEvent.fire([x, y]);
3066
        },
3067
3068
        /**
3069
        * The default event handler fired when the "x" property is changed.
3070
        * @method configX
3071
        * @param {String} type The CustomEvent type (usually the property name)
3072
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3073
        * handlers, args[0] will equal the newly applied value for the property.
3074
        * @param {Object} obj The scope object. For configuration handlers, 
3075
        * this will usually equal the owner.
3076
        */
3077
        configX: function (type, args, obj) {
3078
3079
            var x = args[0],
3080
                y = this.cfg.getProperty("y");
3081
3082
            this.cfg.setProperty("x", x, true);
3083
            this.cfg.setProperty("y", y, true);
3084
3085
            this.beforeMoveEvent.fire([x, y]);
3086
3087
            x = this.cfg.getProperty("x");
3088
            y = this.cfg.getProperty("y");
3089
3090
            Dom.setX(this.element, x, true);
3091
3092
            this.cfg.setProperty("xy", [x, y], true);
3093
3094
            this.cfg.refireEvent("iframe");
3095
            this.moveEvent.fire([x, y]);
3096
        },
3097
3098
        /**
3099
        * The default event handler fired when the "y" property is changed.
3100
        * @method configY
3101
        * @param {String} type The CustomEvent type (usually the property name)
3102
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3103
        * handlers, args[0] will equal the newly applied value for the property.
3104
        * @param {Object} obj The scope object. For configuration handlers, 
3105
        * this will usually equal the owner.
3106
        */
3107
        configY: function (type, args, obj) {
3108
3109
            var x = this.cfg.getProperty("x"),
3110
                y = args[0];
3111
3112
            this.cfg.setProperty("x", x, true);
3113
            this.cfg.setProperty("y", y, true);
3114
3115
            this.beforeMoveEvent.fire([x, y]);
3116
3117
            x = this.cfg.getProperty("x");
3118
            y = this.cfg.getProperty("y");
3119
3120
            Dom.setY(this.element, y, true);
3121
3122
            this.cfg.setProperty("xy", [x, y], true);
3123
3124
            this.cfg.refireEvent("iframe");
3125
            this.moveEvent.fire([x, y]);
3126
        },
3127
        
3128
        /**
3129
        * Shows the iframe shim, if it has been enabled.
3130
        * @method showIframe
3131
        */
3132
        showIframe: function () {
3133
3134
            var oIFrame = this.iframe,
3135
                oParentNode;
3136
3137
            if (oIFrame) {
3138
                oParentNode = this.element.parentNode;
3139
3140
                if (oParentNode != oIFrame.parentNode) {
3141
                    this._addToParent(oParentNode, oIFrame);
3142
                }
3143
                oIFrame.style.display = "block";
3144
            }
3145
        },
3146
3147
        /**
3148
        * Hides the iframe shim, if it has been enabled.
3149
        * @method hideIframe
3150
        */
3151
        hideIframe: function () {
3152
            if (this.iframe) {
3153
                this.iframe.style.display = "none";
3154
            }
3155
        },
3156
3157
        /**
3158
        * Syncronizes the size and position of iframe shim to that of its 
3159
        * corresponding Overlay instance.
3160
        * @method syncIframe
3161
        */
3162
        syncIframe: function () {
3163
3164
            var oIFrame = this.iframe,
3165
                oElement = this.element,
3166
                nOffset = Overlay.IFRAME_OFFSET,
3167
                nDimensionOffset = (nOffset * 2),
3168
                aXY;
3169
3170
            if (oIFrame) {
3171
                // Size <iframe>
3172
                oIFrame.style.width = (oElement.offsetWidth + nDimensionOffset + "px");
3173
                oIFrame.style.height = (oElement.offsetHeight + nDimensionOffset + "px");
3174
3175
                // Position <iframe>
3176
                aXY = this.cfg.getProperty("xy");
3177
3178
                if (!Lang.isArray(aXY) || (isNaN(aXY[0]) || isNaN(aXY[1]))) {
3179
                    this.syncPosition();
3180
                    aXY = this.cfg.getProperty("xy");
3181
                }
3182
                Dom.setXY(oIFrame, [(aXY[0] - nOffset), (aXY[1] - nOffset)]);
3183
            }
3184
        },
3185
3186
        /**
3187
         * Sets the zindex of the iframe shim, if it exists, based on the zindex of
3188
         * the Overlay element. The zindex of the iframe is set to be one less 
3189
         * than the Overlay element's zindex.
3190
         * 
3191
         * <p>NOTE: This method will not bump up the zindex of the Overlay element
3192
         * to ensure that the iframe shim has a non-negative zindex.
3193
         * If you require the iframe zindex to be 0 or higher, the zindex of 
3194
         * the Overlay element should be set to a value greater than 0, before 
3195
         * this method is called.
3196
         * </p>
3197
         * @method stackIframe
3198
         */
3199
        stackIframe: function () {
3200
            if (this.iframe) {
3201
                var overlayZ = Dom.getStyle(this.element, "zIndex");
3202
                if (!YAHOO.lang.isUndefined(overlayZ) && !isNaN(overlayZ)) {
3203
                    Dom.setStyle(this.iframe, "zIndex", (overlayZ - 1));
3204
                }
3205
            }
3206
        },
3207
3208
        /**
3209
        * The default event handler fired when the "iframe" property is changed.
3210
        * @method configIframe
3211
        * @param {String} type The CustomEvent type (usually the property name)
3212
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3213
        * handlers, args[0] will equal the newly applied value for the property.
3214
        * @param {Object} obj The scope object. For configuration handlers, 
3215
        * this will usually equal the owner.
3216
        */
3217
        configIframe: function (type, args, obj) {
3218
3219
            var bIFrame = args[0];
3220
3221
            function createIFrame() {
3222
3223
                var oIFrame = this.iframe,
3224
                    oElement = this.element,
3225
                    oParent;
3226
3227
                if (!oIFrame) {
3228
                    if (!m_oIFrameTemplate) {
3229
                        m_oIFrameTemplate = document.createElement("iframe");
3230
3231
                        if (this.isSecure) {
3232
                            m_oIFrameTemplate.src = Overlay.IFRAME_SRC;
3233
                        }
3234
3235
                        /*
3236
                            Set the opacity of the <iframe> to 0 so that it 
3237
                            doesn't modify the opacity of any transparent 
3238
                            elements that may be on top of it (like a shadow).
3239
                        */
3240
                        if (UA.ie) {
3241
                            m_oIFrameTemplate.style.filter = "alpha(opacity=0)";
3242
                            /*
3243
                                 Need to set the "frameBorder" property to 0 
3244
                                 supress the default <iframe> border in IE.  
3245
                                 Setting the CSS "border" property alone 
3246
                                 doesn't supress it.
3247
                            */
3248
                            m_oIFrameTemplate.frameBorder = 0;
3249
                        }
3250
                        else {
3251
                            m_oIFrameTemplate.style.opacity = "0";
3252
                        }
3253
3254
                        m_oIFrameTemplate.style.position = "absolute";
3255
                        m_oIFrameTemplate.style.border = "none";
3256
                        m_oIFrameTemplate.style.margin = "0";
3257
                        m_oIFrameTemplate.style.padding = "0";
3258
                        m_oIFrameTemplate.style.display = "none";
3259
                        m_oIFrameTemplate.tabIndex = -1;
3260
                        m_oIFrameTemplate.className = Overlay.CSS_IFRAME;
3261
                    }
3262
3263
                    oIFrame = m_oIFrameTemplate.cloneNode(false);
3264
                    oIFrame.id = this.id + "_f";
3265
                    oParent = oElement.parentNode;
3266
3267
                    var parentNode = oParent || document.body;
3268
3269
                    this._addToParent(parentNode, oIFrame);
3270
                    this.iframe = oIFrame;
3271
                }
3272
3273
                /*
3274
                     Show the <iframe> before positioning it since the "setXY" 
3275
                     method of DOM requires the element be in the document 
3276
                     and visible.
3277
                */
3278
                this.showIframe();
3279
3280
                /*
3281
                     Syncronize the size and position of the <iframe> to that 
3282
                     of the Overlay.
3283
                */
3284
                this.syncIframe();
3285
                this.stackIframe();
3286
3287
                // Add event listeners to update the <iframe> when necessary
3288
                if (!this._hasIframeEventListeners) {
3289
                    this.showEvent.subscribe(this.showIframe);
3290
                    this.hideEvent.subscribe(this.hideIframe);
3291
                    this.changeContentEvent.subscribe(this.syncIframe);
3292
3293
                    this._hasIframeEventListeners = true;
3294
                }
3295
            }
3296
3297
            function onBeforeShow() {
3298
                createIFrame.call(this);
3299
                this.beforeShowEvent.unsubscribe(onBeforeShow);
3300
                this._iframeDeferred = false;
3301
            }
3302
3303
            if (bIFrame) { // <iframe> shim is enabled
3304
3305
                if (this.cfg.getProperty("visible")) {
3306
                    createIFrame.call(this);
3307
                } else {
3308
                    if (!this._iframeDeferred) {
3309
                        this.beforeShowEvent.subscribe(onBeforeShow);
3310
                        this._iframeDeferred = true;
3311
                    }
3312
                }
3313
3314
            } else {    // <iframe> shim is disabled
3315
                this.hideIframe();
3316
3317
                if (this._hasIframeEventListeners) {
3318
                    this.showEvent.unsubscribe(this.showIframe);
3319
                    this.hideEvent.unsubscribe(this.hideIframe);
3320
                    this.changeContentEvent.unsubscribe(this.syncIframe);
3321
3322
                    this._hasIframeEventListeners = false;
3323
                }
3324
            }
3325
        },
3326
3327
        /**
3328
         * Set's the container's XY value from DOM if not already set.
3329
         * 
3330
         * Differs from syncPosition, in that the XY value is only sync'd with DOM if 
3331
         * not already set. The method also refire's the XY config property event, so any
3332
         * beforeMove, Move event listeners are invoked.
3333
         * 
3334
         * @method _primeXYFromDOM
3335
         * @protected
3336
         */
3337
        _primeXYFromDOM : function() {
3338
            if (YAHOO.lang.isUndefined(this.cfg.getProperty("xy"))) {
3339
                // Set CFG XY based on DOM XY
3340
                this.syncPosition();
3341
                // Account for XY being set silently in syncPosition (no moveTo fired/called)
3342
                this.cfg.refireEvent("xy");
3343
                this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
3344
            }
3345
        },
3346
3347
        /**
3348
        * The default event handler fired when the "constraintoviewport" 
3349
        * property is changed.
3350
        * @method configConstrainToViewport
3351
        * @param {String} type The CustomEvent type (usually the property name)
3352
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3353
        * handlers, args[0] will equal the newly applied value for 
3354
        * the property.
3355
        * @param {Object} obj The scope object. For configuration handlers, 
3356
        * this will usually equal the owner.
3357
        */
3358
        configConstrainToViewport: function (type, args, obj) {
3359
            var val = args[0];
3360
3361
            if (val) {
3362
                if (! Config.alreadySubscribed(this.beforeMoveEvent, this.enforceConstraints, this)) {
3363
                    this.beforeMoveEvent.subscribe(this.enforceConstraints, this, true);
3364
                }
3365
                if (! Config.alreadySubscribed(this.beforeShowEvent, this._primeXYFromDOM)) {
3366
                    this.beforeShowEvent.subscribe(this._primeXYFromDOM);
3367
                }
3368
            } else {
3369
                this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
3370
                this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
3371
            }
3372
        },
3373
3374
         /**
3375
        * The default event handler fired when the "context" property
3376
        * is changed.
3377
        *
3378
        * @method configContext
3379
        * @param {String} type The CustomEvent type (usually the property name)
3380
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3381
        * handlers, args[0] will equal the newly applied value for the property.
3382
        * @param {Object} obj The scope object. For configuration handlers, 
3383
        * this will usually equal the owner.
3384
        */
3385
        configContext: function (type, args, obj) {
3386
3387
            var contextArgs = args[0],
3388
                contextEl,
3389
                elementMagnetCorner,
3390
                contextMagnetCorner,
3391
                triggers,
3392
                offset,
3393
                defTriggers = this.CONTEXT_TRIGGERS;
3394
3395
            if (contextArgs) {
3396
3397
                contextEl = contextArgs[0];
3398
                elementMagnetCorner = contextArgs[1];
3399
                contextMagnetCorner = contextArgs[2];
3400
                triggers = contextArgs[3];
3401
                offset = contextArgs[4];
3402
3403
                if (defTriggers && defTriggers.length > 0) {
3404
                    triggers = (triggers || []).concat(defTriggers);
3405
                }
3406
3407
                if (contextEl) {
3408
                    if (typeof contextEl == "string") {
3409
                        this.cfg.setProperty("context", [
3410
                                document.getElementById(contextEl), 
3411
                                elementMagnetCorner,
3412
                                contextMagnetCorner,
3413
                                triggers,
3414
                                offset],
3415
                                true);
3416
                    }
3417
3418
                    if (elementMagnetCorner && contextMagnetCorner) {
3419
                        this.align(elementMagnetCorner, contextMagnetCorner, offset);
3420
                    }
3421
3422
                    if (this._contextTriggers) {
3423
                        // Unsubscribe Old Set
3424
                        this._processTriggers(this._contextTriggers, _UNSUBSCRIBE, this._alignOnTrigger);
3425
                    }
3426
3427
                    if (triggers) {
3428
                        // Subscribe New Set
3429
                        this._processTriggers(triggers, _SUBSCRIBE, this._alignOnTrigger);
3430
                        this._contextTriggers = triggers;
3431
                    }
3432
                }
3433
            }
3434
        },
3435
3436
        /**
3437
         * Custom Event handler for context alignment triggers. Invokes the align method
3438
         * 
3439
         * @method _alignOnTrigger
3440
         * @protected
3441
         * 
3442
         * @param {String} type The event type (not used by the default implementation)
3443
         * @param {Any[]} args The array of arguments for the trigger event (not used by the default implementation)
3444
         */
3445
        _alignOnTrigger: function(type, args) {
3446
            this.align();
3447
        },
3448
3449
        /**
3450
         * Helper method to locate the custom event instance for the event name string
3451
         * passed in. As a convenience measure, any custom events passed in are returned.
3452
         *
3453
         * @method _findTriggerCE
3454
         * @private
3455
         *
3456
         * @param {String|CustomEvent} t Either a CustomEvent, or event type (e.g. "windowScroll") for which a 
3457
         * custom event instance needs to be looked up from the Overlay._TRIGGER_MAP.
3458
         */
3459
        _findTriggerCE : function(t) {
3460
            var tce = null;
3461
            if (t instanceof CustomEvent) {
3462
                tce = t;
3463
            } else if (Overlay._TRIGGER_MAP[t]) {
3464
                tce = Overlay._TRIGGER_MAP[t];
3465
            }
3466
            return tce;
3467
        },
3468
3469
        /**
3470
         * Utility method that subscribes or unsubscribes the given 
3471
         * function from the list of trigger events provided.
3472
         *
3473
         * @method _processTriggers
3474
         * @protected 
3475
         *
3476
         * @param {Array[String|CustomEvent]} triggers An array of either CustomEvents, event type strings 
3477
         * (e.g. "beforeShow", "windowScroll") to/from which the provided function should be 
3478
         * subscribed/unsubscribed respectively.
3479
         *
3480
         * @param {String} mode Either "subscribe" or "unsubscribe", specifying whether or not
3481
         * we are subscribing or unsubscribing trigger listeners
3482
         * 
3483
         * @param {Function} fn The function to be subscribed/unsubscribed to/from the trigger event.
3484
         * Context is always set to the overlay instance, and no additional object argument 
3485
         * get passed to the subscribed function.
3486
         */
3487
        _processTriggers : function(triggers, mode, fn) {
3488
            var t, tce;
3489
3490
            for (var i = 0, l = triggers.length; i < l; ++i) {
3491
                t = triggers[i];
3492
                tce = this._findTriggerCE(t);
3493
                if (tce) {
3494
                    tce[mode](fn, this, true);
3495
                } else {
3496
                    this[mode](t, fn);
3497
                }
3498
            }
3499
        },
3500
3501
        // END BUILT-IN PROPERTY EVENT HANDLERS //
3502
        /**
3503
        * Aligns the Overlay to its context element using the specified corner 
3504
        * points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, 
3505
        * and BOTTOM_RIGHT.
3506
        * @method align
3507
        * @param {String} elementAlign  The String representing the corner of 
3508
        * the Overlay that should be aligned to the context element
3509
        * @param {String} contextAlign  The corner of the context element 
3510
        * that the elementAlign corner should stick to.
3511
        * @param {Number[]} xyOffset Optional. A 2 element array specifying the x and y pixel offsets which should be applied
3512
        * after aligning the element and context corners. For example, passing in [5, -10] for this value, would offset the 
3513
        * Overlay by 5 pixels along the X axis (horizontally) and -10 pixels along the Y axis (vertically) after aligning the specified corners.
3514
        */
3515
        align: function (elementAlign, contextAlign, xyOffset) {
3516
3517
            var contextArgs = this.cfg.getProperty("context"),
3518
                me = this,
3519
                context,
3520
                element,
3521
                contextRegion;
3522
3523
            function doAlign(v, h) {
3524
3525
                var alignX = null, alignY = null;
3526
3527
                switch (elementAlign) {
3528
    
3529
                    case Overlay.TOP_LEFT:
3530
                        alignX = h;
3531
                        alignY = v;
3532
                        break;
3533
        
3534
                    case Overlay.TOP_RIGHT:
3535
                        alignX = h - element.offsetWidth;
3536
                        alignY = v;
3537
                        break;
3538
        
3539
                    case Overlay.BOTTOM_LEFT:
3540
                        alignX = h;
3541
                        alignY = v - element.offsetHeight;
3542
                        break;
3543
        
3544
                    case Overlay.BOTTOM_RIGHT:
3545
                        alignX = h - element.offsetWidth; 
3546
                        alignY = v - element.offsetHeight;
3547
                        break;
3548
                }
3549
3550
                if (alignX !== null && alignY !== null) {
3551
                    if (xyOffset) {
3552
                        alignX += xyOffset[0];
3553
                        alignY += xyOffset[1];
3554
                    }
3555
                    me.moveTo(alignX, alignY);
3556
                }
3557
            }
3558
3559
            if (contextArgs) {
3560
                context = contextArgs[0];
3561
                element = this.element;
3562
                me = this;
3563
3564
                if (! elementAlign) {
3565
                    elementAlign = contextArgs[1];
3566
                }
3567
3568
                if (! contextAlign) {
3569
                    contextAlign = contextArgs[2];
3570
                }
3571
3572
                if (!xyOffset && contextArgs[4]) {
3573
                    xyOffset = contextArgs[4];
3574
                }
3575
3576
                if (element && context) {
3577
                    contextRegion = Dom.getRegion(context);
3578
3579
                    switch (contextAlign) {
3580
    
3581
                        case Overlay.TOP_LEFT:
3582
                            doAlign(contextRegion.top, contextRegion.left);
3583
                            break;
3584
        
3585
                        case Overlay.TOP_RIGHT:
3586
                            doAlign(contextRegion.top, contextRegion.right);
3587
                            break;
3588
        
3589
                        case Overlay.BOTTOM_LEFT:
3590
                            doAlign(contextRegion.bottom, contextRegion.left);
3591
                            break;
3592
        
3593
                        case Overlay.BOTTOM_RIGHT:
3594
                            doAlign(contextRegion.bottom, contextRegion.right);
3595
                            break;
3596
                    }
3597
                }
3598
            }
3599
        },
3600
3601
        /**
3602
        * The default event handler executed when the moveEvent is fired, if the 
3603
        * "constraintoviewport" is set to true.
3604
        * @method enforceConstraints
3605
        * @param {String} type The CustomEvent type (usually the property name)
3606
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3607
        * handlers, args[0] will equal the newly applied value for the property.
3608
        * @param {Object} obj The scope object. For configuration handlers, 
3609
        * this will usually equal the owner.
3610
        */
3611
        enforceConstraints: function (type, args, obj) {
3612
            var pos = args[0];
3613
3614
            var cXY = this.getConstrainedXY(pos[0], pos[1]);
3615
            this.cfg.setProperty("x", cXY[0], true);
3616
            this.cfg.setProperty("y", cXY[1], true);
3617
            this.cfg.setProperty("xy", cXY, true);
3618
        },
3619
3620
        /**
3621
         * Shared implementation method for getConstrainedX and getConstrainedY.
3622
         * 
3623
         * <p>
3624
         * Given a coordinate value, returns the calculated coordinate required to 
3625
         * position the Overlay if it is to be constrained to the viewport, based on the 
3626
         * current element size, viewport dimensions, scroll values and preventoverlap 
3627
         * settings
3628
         * </p>
3629
         *
3630
         * @method _getConstrainedPos
3631
         * @protected
3632
         * @param {String} pos The coordinate which needs to be constrained, either "x" or "y"
3633
         * @param {Number} The coordinate value which needs to be constrained
3634
         * @return {Number} The constrained coordinate value
3635
         */
3636
        _getConstrainedPos: function(pos, val) {
3637
3638
            var overlayEl = this.element,
3639
3640
                buffer = Overlay.VIEWPORT_OFFSET,
3641
3642
                x = (pos == "x"),
3643
3644
                overlaySize      = (x) ? overlayEl.offsetWidth : overlayEl.offsetHeight,
3645
                viewportSize     = (x) ? Dom.getViewportWidth() : Dom.getViewportHeight(),
3646
                docScroll        = (x) ? Dom.getDocumentScrollLeft() : Dom.getDocumentScrollTop(),
3647
                overlapPositions = (x) ? Overlay.PREVENT_OVERLAP_X : Overlay.PREVENT_OVERLAP_Y,
3648
3649
                context = this.cfg.getProperty("context"),
3650
3651
                bOverlayFitsInViewport = (overlaySize + buffer < viewportSize),
3652
                bPreventContextOverlap = this.cfg.getProperty("preventcontextoverlap") && context && overlapPositions[(context[1] + context[2])],
3653
3654
                minConstraint = docScroll + buffer,
3655
                maxConstraint = docScroll + viewportSize - overlaySize - buffer,
3656
3657
                constrainedVal = val;
3658
3659
            if (val < minConstraint || val > maxConstraint) {
3660
                if (bPreventContextOverlap) {
3661
                    constrainedVal = this._preventOverlap(pos, context[0], overlaySize, viewportSize, docScroll);
3662
                } else {
3663
                    if (bOverlayFitsInViewport) {
3664
                        if (val < minConstraint) {
3665
                            constrainedVal = minConstraint;
3666
                        } else if (val > maxConstraint) {
3667
                            constrainedVal = maxConstraint;
3668
                        }
3669
                    } else {
3670
                        constrainedVal = minConstraint;
3671
                    }
3672
                }
3673
            }
3674
3675
            return constrainedVal;
3676
        },
3677
3678
        /**
3679
         * Helper method, used to position the Overlap to prevent overlap with the 
3680
         * context element (used when preventcontextoverlap is enabled)
3681
         *
3682
         * @method _preventOverlap
3683
         * @protected
3684
         * @param {String} pos The coordinate to prevent overlap for, either "x" or "y".
3685
         * @param {HTMLElement} contextEl The context element
3686
         * @param {Number} overlaySize The related overlay dimension value (for "x", the width, for "y", the height)
3687
         * @param {Number} viewportSize The related viewport dimension value (for "x", the width, for "y", the height)
3688
         * @param {Object} docScroll  The related document scroll value (for "x", the scrollLeft, for "y", the scrollTop)
3689
         *
3690
         * @return {Number} The new coordinate value which was set to prevent overlap
3691
         */
3692
        _preventOverlap : function(pos, contextEl, overlaySize, viewportSize, docScroll) {
3693
            
3694
            var x = (pos == "x"),
3695
3696
                buffer = Overlay.VIEWPORT_OFFSET,
3697
3698
                overlay = this,
3699
3700
                contextElPos   = ((x) ? Dom.getX(contextEl) : Dom.getY(contextEl)) - docScroll,
3701
                contextElSize  = (x) ? contextEl.offsetWidth : contextEl.offsetHeight,
3702
3703
                minRegionSize = contextElPos - buffer,
3704
                maxRegionSize = (viewportSize - (contextElPos + contextElSize)) - buffer,
3705
3706
                bFlipped = false,
3707
3708
                flip = function () {
3709
                    var flippedVal;
3710
3711
                    if ((overlay.cfg.getProperty(pos) - docScroll) > contextElPos) {
3712
                        flippedVal = (contextElPos - overlaySize);
3713
                    } else {
3714
                        flippedVal = (contextElPos + contextElSize);
3715
                    }
3716
3717
                    overlay.cfg.setProperty(pos, (flippedVal + docScroll), true);
3718
3719
                    return flippedVal;
3720
                },
3721
3722
                setPosition = function () {
3723
3724
                    var displayRegionSize = ((overlay.cfg.getProperty(pos) - docScroll) > contextElPos) ? maxRegionSize : minRegionSize,
3725
                        position;
3726
3727
                    if (overlaySize > displayRegionSize) {
3728
                        if (bFlipped) {
3729
                            /*
3730
                                 All possible positions and values have been 
3731
                                 tried, but none were successful, so fall back 
3732
                                 to the original size and position.
3733
                            */
3734
                            flip();
3735
                        } else {
3736
                            flip();
3737
                            bFlipped = true;
3738
                            position = setPosition();
3739
                        }
3740
                    }
3741
3742
                    return position;
3743
                };
3744
3745
            setPosition();
3746
3747
            return this.cfg.getProperty(pos);
3748
        },
3749
3750
        /**
3751
         * Given x coordinate value, returns the calculated x coordinate required to 
3752
         * position the Overlay if it is to be constrained to the viewport, based on the 
3753
         * current element size, viewport dimensions and scroll values.
3754
         *
3755
         * @param {Number} x The X coordinate value to be constrained
3756
         * @return {Number} The constrained x coordinate
3757
         */		
3758
        getConstrainedX: function (x) {
3759
            return this._getConstrainedPos("x", x);
3760
        },
3761
3762
        /**
3763
         * Given y coordinate value, returns the calculated y coordinate required to 
3764
         * position the Overlay if it is to be constrained to the viewport, based on the 
3765
         * current element size, viewport dimensions and scroll values.
3766
         *
3767
         * @param {Number} y The Y coordinate value to be constrained
3768
         * @return {Number} The constrained y coordinate
3769
         */		
3770
        getConstrainedY : function (y) {
3771
            return this._getConstrainedPos("y", y);
3772
        },
3773
3774
        /**
3775
         * Given x, y coordinate values, returns the calculated coordinates required to 
3776
         * position the Overlay if it is to be constrained to the viewport, based on the 
3777
         * current element size, viewport dimensions and scroll values.
3778
         *
3779
         * @param {Number} x The X coordinate value to be constrained
3780
         * @param {Number} y The Y coordinate value to be constrained
3781
         * @return {Array} The constrained x and y coordinates at index 0 and 1 respectively;
3782
         */
3783
        getConstrainedXY: function(x, y) {
3784
            return [this.getConstrainedX(x), this.getConstrainedY(y)];
3785
        },
3786
3787
        /**
3788
        * Centers the container in the viewport.
3789
        * @method center
3790
        */
3791
        center: function () {
3792
3793
            var nViewportOffset = Overlay.VIEWPORT_OFFSET,
3794
                elementWidth = this.element.offsetWidth,
3795
                elementHeight = this.element.offsetHeight,
3796
                viewPortWidth = Dom.getViewportWidth(),
3797
                viewPortHeight = Dom.getViewportHeight(),
3798
                x,
3799
                y;
3800
3801
            if (elementWidth < viewPortWidth) {
3802
                x = (viewPortWidth / 2) - (elementWidth / 2) + Dom.getDocumentScrollLeft();
3803
            } else {
3804
                x = nViewportOffset + Dom.getDocumentScrollLeft();
3805
            }
3806
3807
            if (elementHeight < viewPortHeight) {
3808
                y = (viewPortHeight / 2) - (elementHeight / 2) + Dom.getDocumentScrollTop();
3809
            } else {
3810
                y = nViewportOffset + Dom.getDocumentScrollTop();
3811
            }
3812
3813
            this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
3814
            this.cfg.refireEvent("iframe");
3815
3816
            if (UA.webkit) {
3817
                this.forceContainerRedraw();
3818
            }
3819
        },
3820
3821
        /**
3822
        * Synchronizes the Panel's "xy", "x", and "y" properties with the 
3823
        * Panel's position in the DOM. This is primarily used to update  
3824
        * position information during drag & drop.
3825
        * @method syncPosition
3826
        */
3827
        syncPosition: function () {
3828
3829
            var pos = Dom.getXY(this.element);
3830
3831
            this.cfg.setProperty("x", pos[0], true);
3832
            this.cfg.setProperty("y", pos[1], true);
3833
            this.cfg.setProperty("xy", pos, true);
3834
3835
        },
3836
3837
        /**
3838
        * Event handler fired when the resize monitor element is resized.
3839
        * @method onDomResize
3840
        * @param {DOMEvent} e The resize DOM event
3841
        * @param {Object} obj The scope object
3842
        */
3843
        onDomResize: function (e, obj) {
3844
3845
            var me = this;
3846
3847
            Overlay.superclass.onDomResize.call(this, e, obj);
3848
3849
            setTimeout(function () {
3850
                me.syncPosition();
3851
                me.cfg.refireEvent("iframe");
3852
                me.cfg.refireEvent("context");
3853
            }, 0);
3854
        },
3855
3856
        /**
3857
         * Determines the content box height of the given element (height of the element, without padding or borders) in pixels.
3858
         *
3859
         * @method _getComputedHeight
3860
         * @private
3861
         * @param {HTMLElement} el The element for which the content height needs to be determined
3862
         * @return {Number} The content box height of the given element, or null if it could not be determined.
3863
         */
3864
        _getComputedHeight : (function() {
3865
3866
            if (document.defaultView && document.defaultView.getComputedStyle) {
3867
                return function(el) {
3868
                    var height = null;
3869
                    if (el.ownerDocument && el.ownerDocument.defaultView) {
3870
                        var computed = el.ownerDocument.defaultView.getComputedStyle(el, '');
3871
                        if (computed) {
3872
                            height = parseInt(computed.height, 10);
3873
                        }
3874
                    }
3875
                    return (Lang.isNumber(height)) ? height : null;
3876
                };
3877
            } else {
3878
                return function(el) {
3879
                    var height = null;
3880
                    if (el.style.pixelHeight) {
3881
                        height = el.style.pixelHeight;
3882
                    }
3883
                    return (Lang.isNumber(height)) ? height : null;
3884
                };
3885
            }
3886
        })(),
3887
3888
        /**
3889
         * autofillheight validator. Verifies that the autofill value is either null 
3890
         * or one of the strings : "body", "header" or "footer".
3891
         *
3892
         * @method _validateAutoFillHeight
3893
         * @protected
3894
         * @param {String} val
3895
         * @return true, if valid, false otherwise
3896
         */
3897
        _validateAutoFillHeight : function(val) {
3898
            return (!val) || (Lang.isString(val) && Overlay.STD_MOD_RE.test(val));
3899
        },
3900
3901
        /**
3902
         * The default custom event handler executed when the overlay's height is changed, 
3903
         * if the autofillheight property has been set.
3904
         *
3905
         * @method _autoFillOnHeightChange
3906
         * @protected
3907
         * @param {String} type The event type
3908
         * @param {Array} args The array of arguments passed to event subscribers
3909
         * @param {HTMLElement} el The header, body or footer element which is to be resized to fill
3910
         * out the containers height
3911
         */
3912
        _autoFillOnHeightChange : function(type, args, el) {
3913
            var height = this.cfg.getProperty("height");
3914
            if ((height && height !== "auto") || (height === 0)) {
3915
                this.fillHeight(el);
3916
            }
3917
        },
3918
3919
        /**
3920
         * Returns the sub-pixel height of the el, using getBoundingClientRect, if available,
3921
         * otherwise returns the offsetHeight
3922
         * @method _getPreciseHeight
3923
         * @private
3924
         * @param {HTMLElement} el
3925
         * @return {Float} The sub-pixel height if supported by the browser, else the rounded height.
3926
         */
3927
        _getPreciseHeight : function(el) {
3928
            var height = el.offsetHeight;
3929
3930
            if (el.getBoundingClientRect) {
3931
                var rect = el.getBoundingClientRect();
3932
                height = rect.bottom - rect.top;
3933
            }
3934
3935
            return height;
3936
        },
3937
3938
        /**
3939
         * <p>
3940
         * Sets the height on the provided header, body or footer element to 
3941
         * fill out the height of the container. It determines the height of the 
3942
         * containers content box, based on it's configured height value, and 
3943
         * sets the height of the autofillheight element to fill out any 
3944
         * space remaining after the other standard module element heights 
3945
         * have been accounted for.
3946
         * </p>
3947
         * <p><strong>NOTE:</strong> This method is not designed to work if an explicit 
3948
         * height has not been set on the container, since for an "auto" height container, 
3949
         * the heights of the header/body/footer will drive the height of the container.</p>
3950
         *
3951
         * @method fillHeight
3952
         * @param {HTMLElement} el The element which should be resized to fill out the height
3953
         * of the container element.
3954
         */
3955
        fillHeight : function(el) {
3956
            if (el) {
3957
                var container = this.innerElement || this.element,
3958
                    containerEls = [this.header, this.body, this.footer],
3959
                    containerEl,
3960
                    total = 0,
3961
                    filled = 0,
3962
                    remaining = 0,
3963
                    validEl = false;
3964
3965
                for (var i = 0, l = containerEls.length; i < l; i++) {
3966
                    containerEl = containerEls[i];
3967
                    if (containerEl) {
3968
                        if (el !== containerEl) {
3969
                            filled += this._getPreciseHeight(containerEl);
3970
                        } else {
3971
                            validEl = true;
3972
                        }
3973
                    }
3974
                }
3975
3976
                if (validEl) {
3977
3978
                    if (UA.ie || UA.opera) {
3979
                        // Need to set height to 0, to allow height to be reduced
3980
                        Dom.setStyle(el, 'height', 0 + 'px');
3981
                    }
3982
3983
                    total = this._getComputedHeight(container);
3984
3985
                    // Fallback, if we can't get computed value for content height
3986
                    if (total === null) {
3987
                        Dom.addClass(container, "yui-override-padding");
3988
                        total = container.clientHeight; // Content, No Border, 0 Padding (set by yui-override-padding)
3989
                        Dom.removeClass(container, "yui-override-padding");
3990
                    }
3991
    
3992
                    remaining = Math.max(total - filled, 0);
3993
    
3994
                    Dom.setStyle(el, "height", remaining + "px");
3995
    
3996
                    // Re-adjust height if required, to account for el padding and border
3997
                    if (el.offsetHeight != remaining) {
3998
                        remaining = Math.max(remaining - (el.offsetHeight - remaining), 0);
3999
                    }
4000
                    Dom.setStyle(el, "height", remaining + "px");
4001
                }
4002
            }
4003
        },
4004
4005
        /**
4006
        * Places the Overlay on top of all other instances of 
4007
        * YAHOO.widget.Overlay.
4008
        * @method bringToTop
4009
        */
4010
        bringToTop: function () {
4011
4012
            var aOverlays = [],
4013
                oElement = this.element;
4014
4015
            function compareZIndexDesc(p_oOverlay1, p_oOverlay2) {
4016
4017
                var sZIndex1 = Dom.getStyle(p_oOverlay1, "zIndex"),
4018
                    sZIndex2 = Dom.getStyle(p_oOverlay2, "zIndex"),
4019
4020
                    nZIndex1 = (!sZIndex1 || isNaN(sZIndex1)) ? 0 : parseInt(sZIndex1, 10),
4021
                    nZIndex2 = (!sZIndex2 || isNaN(sZIndex2)) ? 0 : parseInt(sZIndex2, 10);
4022
4023
                if (nZIndex1 > nZIndex2) {
4024
                    return -1;
4025
                } else if (nZIndex1 < nZIndex2) {
4026
                    return 1;
4027
                } else {
4028
                    return 0;
4029
                }
4030
            }
4031
4032
            function isOverlayElement(p_oElement) {
4033
4034
                var isOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY),
4035
                    Panel = YAHOO.widget.Panel;
4036
4037
                if (isOverlay && !Dom.isAncestor(oElement, p_oElement)) {
4038
                    if (Panel && Dom.hasClass(p_oElement, Panel.CSS_PANEL)) {
4039
                        aOverlays[aOverlays.length] = p_oElement.parentNode;
4040
                    } else {
4041
                        aOverlays[aOverlays.length] = p_oElement;
4042
                    }
4043
                }
4044
            }
4045
4046
            Dom.getElementsBy(isOverlayElement, "DIV", document.body);
4047
4048
            aOverlays.sort(compareZIndexDesc);
4049
4050
            var oTopOverlay = aOverlays[0],
4051
                nTopZIndex;
4052
4053
            if (oTopOverlay) {
4054
                nTopZIndex = Dom.getStyle(oTopOverlay, "zIndex");
4055
4056
                if (!isNaN(nTopZIndex)) {
4057
                    var bRequiresBump = false;
4058
4059
                    if (oTopOverlay != oElement) {
4060
                        bRequiresBump = true;
4061
                    } else if (aOverlays.length > 1) {
4062
                        var nNextZIndex = Dom.getStyle(aOverlays[1], "zIndex");
4063
                        // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
4064
                        if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
4065
                            bRequiresBump = true;
4066
                        }
4067
                    }
4068
                    if (bRequiresBump) {
4069
                        this.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
4070
                    }
4071
                }
4072
            }
4073
        },
4074
4075
        /**
4076
        * Removes the Overlay element from the DOM and sets all child 
4077
        * elements to null.
4078
        * @method destroy
4079
        */
4080
        destroy: function () {
4081
4082
            if (this.iframe) {
4083
                this.iframe.parentNode.removeChild(this.iframe);
4084
            }
4085
4086
            this.iframe = null;
4087
4088
            Overlay.windowResizeEvent.unsubscribe(
4089
                this.doCenterOnDOMEvent, this);
4090
    
4091
            Overlay.windowScrollEvent.unsubscribe(
4092
                this.doCenterOnDOMEvent, this);
4093
4094
            Module.textResizeEvent.unsubscribe(this._autoFillOnHeightChange);
4095
4096
            if (this._contextTriggers) {
4097
                // Unsubscribe context triggers - to cover context triggers which listen for global
4098
                // events such as windowResize and windowScroll. Easier just to unsubscribe all
4099
                this._processTriggers(this._contextTriggers, _UNSUBSCRIBE, this._alignOnTrigger);
4100
            }
4101
4102
            Overlay.superclass.destroy.call(this);
4103
        },
4104
4105
        /**
4106
         * Can be used to force the container to repaint/redraw it's contents.
4107
         * <p>
4108
         * By default applies and then removes a 1px bottom margin through the 
4109
         * application/removal of a "yui-force-redraw" class.
4110
         * </p>
4111
         * <p>
4112
         * It is currently used by Overlay to force a repaint for webkit 
4113
         * browsers, when centering.
4114
         * </p>
4115
         * @method forceContainerRedraw
4116
         */
4117
        forceContainerRedraw : function() {
4118
            var c = this;
4119
            Dom.addClass(c.element, "yui-force-redraw");
4120
            setTimeout(function() {
4121
                Dom.removeClass(c.element, "yui-force-redraw");
4122
            }, 0);
4123
        },
4124
4125
        /**
4126
        * Returns a String representation of the object.
4127
        * @method toString
4128
        * @return {String} The string representation of the Overlay.
4129
        */
4130
        toString: function () {
4131
            return "Overlay " + this.id;
4132
        }
4133
4134
    });
4135
}());
4136
(function () {
4137
4138
    /**
4139
    * OverlayManager is used for maintaining the focus status of 
4140
    * multiple Overlays.
4141
    * @namespace YAHOO.widget
4142
    * @namespace YAHOO.widget
4143
    * @class OverlayManager
4144
    * @constructor
4145
    * @param {Array} overlays Optional. A collection of Overlays to register 
4146
    * with the manager.
4147
    * @param {Object} userConfig  The object literal representing the user 
4148
    * configuration of the OverlayManager
4149
    */
4150
    YAHOO.widget.OverlayManager = function (userConfig) {
4151
        this.init(userConfig);
4152
    };
4153
4154
    var Overlay = YAHOO.widget.Overlay,
4155
        Event = YAHOO.util.Event,
4156
        Dom = YAHOO.util.Dom,
4157
        Config = YAHOO.util.Config,
4158
        CustomEvent = YAHOO.util.CustomEvent,
4159
        OverlayManager = YAHOO.widget.OverlayManager;
4160
4161
    /**
4162
    * The CSS class representing a focused Overlay
4163
    * @property OverlayManager.CSS_FOCUSED
4164
    * @static
4165
    * @final
4166
    * @type String
4167
    */
4168
    OverlayManager.CSS_FOCUSED = "focused";
4169
4170
    OverlayManager.prototype = {
4171
4172
        /**
4173
        * The class's constructor function
4174
        * @property contructor
4175
        * @type Function
4176
        */
4177
        constructor: OverlayManager,
4178
4179
        /**
4180
        * The array of Overlays that are currently registered
4181
        * @property overlays
4182
        * @type YAHOO.widget.Overlay[]
4183
        */
4184
        overlays: null,
4185
4186
        /**
4187
        * Initializes the default configuration of the OverlayManager
4188
        * @method initDefaultConfig
4189
        */
4190
        initDefaultConfig: function () {
4191
            /**
4192
            * The collection of registered Overlays in use by 
4193
            * the OverlayManager
4194
            * @config overlays
4195
            * @type YAHOO.widget.Overlay[]
4196
            * @default null
4197
            */
4198
            this.cfg.addProperty("overlays", { suppressEvent: true } );
4199
4200
            /**
4201
            * The default DOM event that should be used to focus an Overlay
4202
            * @config focusevent
4203
            * @type String
4204
            * @default "mousedown"
4205
            */
4206
            this.cfg.addProperty("focusevent", { value: "mousedown" } );
4207
        },
4208
4209
        /**
4210
        * Initializes the OverlayManager
4211
        * @method init
4212
        * @param {Overlay[]} overlays Optional. A collection of Overlays to 
4213
        * register with the manager.
4214
        * @param {Object} userConfig  The object literal representing the user 
4215
        * configuration of the OverlayManager
4216
        */
4217
        init: function (userConfig) {
4218
4219
            /**
4220
            * The OverlayManager's Config object used for monitoring 
4221
            * configuration properties.
4222
            * @property cfg
4223
            * @type Config
4224
            */
4225
            this.cfg = new Config(this);
4226
4227
            this.initDefaultConfig();
4228
4229
            if (userConfig) {
4230
                this.cfg.applyConfig(userConfig, true);
4231
            }
4232
            this.cfg.fireQueue();
4233
4234
            /**
4235
            * The currently activated Overlay
4236
            * @property activeOverlay
4237
            * @private
4238
            * @type YAHOO.widget.Overlay
4239
            */
4240
            var activeOverlay = null;
4241
4242
            /**
4243
            * Returns the currently focused Overlay
4244
            * @method getActive
4245
            * @return {Overlay} The currently focused Overlay
4246
            */
4247
            this.getActive = function () {
4248
                return activeOverlay;
4249
            };
4250
4251
            /**
4252
            * Focuses the specified Overlay
4253
            * @method focus
4254
            * @param {Overlay} overlay The Overlay to focus
4255
            * @param {String} overlay The id of the Overlay to focus
4256
            */
4257
            this.focus = function (overlay) {
4258
                var o = this.find(overlay);
4259
                if (o) {
4260
                    o.focus();
4261
                }
4262
            };
4263
4264
            /**
4265
            * Removes the specified Overlay from the manager
4266
            * @method remove
4267
            * @param {Overlay} overlay The Overlay to remove
4268
            * @param {String} overlay The id of the Overlay to remove
4269
            */
4270
            this.remove = function (overlay) {
4271
4272
                var o = this.find(overlay), 
4273
                        originalZ;
4274
4275
                if (o) {
4276
                    if (activeOverlay == o) {
4277
                        activeOverlay = null;
4278
                    }
4279
4280
                    var bDestroyed = (o.element === null && o.cfg === null) ? true : false;
4281
4282
                    if (!bDestroyed) {
4283
                        // Set it's zindex so that it's sorted to the end.
4284
                        originalZ = Dom.getStyle(o.element, "zIndex");
4285
                        o.cfg.setProperty("zIndex", -1000, true);
4286
                    }
4287
4288
                    this.overlays.sort(this.compareZIndexDesc);
4289
                    this.overlays = this.overlays.slice(0, (this.overlays.length - 1));
4290
4291
                    o.hideEvent.unsubscribe(o.blur);
4292
                    o.destroyEvent.unsubscribe(this._onOverlayDestroy, o);
4293
                    o.focusEvent.unsubscribe(this._onOverlayFocusHandler, o);
4294
                    o.blurEvent.unsubscribe(this._onOverlayBlurHandler, o);
4295
4296
                    if (!bDestroyed) {
4297
                        Event.removeListener(o.element, this.cfg.getProperty("focusevent"), this._onOverlayElementFocus);
4298
                        o.cfg.setProperty("zIndex", originalZ, true);
4299
                        o.cfg.setProperty("manager", null);
4300
                    }
4301
4302
                    /* _managed Flag for custom or existing. Don't want to remove existing */
4303
                    if (o.focusEvent._managed) { o.focusEvent = null; }
4304
                    if (o.blurEvent._managed) { o.blurEvent = null; }
4305
4306
                    if (o.focus._managed) { o.focus = null; }
4307
                    if (o.blur._managed) { o.blur = null; }
4308
                }
4309
            };
4310
4311
            /**
4312
            * Removes focus from all registered Overlays in the manager
4313
            * @method blurAll
4314
            */
4315
            this.blurAll = function () {
4316
4317
                var nOverlays = this.overlays.length,
4318
                    i;
4319
4320
                if (nOverlays > 0) {
4321
                    i = nOverlays - 1;
4322
                    do {
4323
                        this.overlays[i].blur();
4324
                    }
4325
                    while(i--);
4326
                }
4327
            };
4328
4329
            /**
4330
             * Updates the state of the OverlayManager and overlay, as a result of the overlay
4331
             * being blurred.
4332
             * 
4333
             * @method _manageBlur
4334
             * @param {Overlay} overlay The overlay instance which got blurred.
4335
             * @protected
4336
             */
4337
            this._manageBlur = function (overlay) {
4338
                var changed = false;
4339
                if (activeOverlay == overlay) {
4340
                    Dom.removeClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
4341
                    activeOverlay = null;
4342
                    changed = true;
4343
                }
4344
                return changed;
4345
            };
4346
4347
            /**
4348
             * Updates the state of the OverlayManager and overlay, as a result of the overlay 
4349
             * receiving focus.
4350
             *
4351
             * @method _manageFocus
4352
             * @param {Overlay} overlay The overlay instance which got focus.
4353
             * @protected
4354
             */
4355
            this._manageFocus = function(overlay) {
4356
                var changed = false;
4357
                if (activeOverlay != overlay) {
4358
                    if (activeOverlay) {
4359
                        activeOverlay.blur();
4360
                    }
4361
                    activeOverlay = overlay;
4362
                    this.bringToTop(activeOverlay);
4363
                    Dom.addClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
4364
                    changed = true;
4365
                }
4366
                return changed;
4367
            };
4368
4369
            var overlays = this.cfg.getProperty("overlays");
4370
4371
            if (! this.overlays) {
4372
                this.overlays = [];
4373
            }
4374
4375
            if (overlays) {
4376
                this.register(overlays);
4377
                this.overlays.sort(this.compareZIndexDesc);
4378
            }
4379
        },
4380
4381
        /**
4382
        * @method _onOverlayElementFocus
4383
        * @description Event handler for the DOM event that is used to focus 
4384
        * the Overlay instance as specified by the "focusevent" 
4385
        * configuration property.
4386
        * @private
4387
        * @param {Event} p_oEvent Object representing the DOM event 
4388
        * object passed back by the event utility (Event).
4389
        */
4390
        _onOverlayElementFocus: function (p_oEvent) {
4391
4392
            var oTarget = Event.getTarget(p_oEvent),
4393
                oClose = this.close;
4394
4395
            if (oClose && (oTarget == oClose || Dom.isAncestor(oClose, oTarget))) {
4396
                this.blur();
4397
            } else {
4398
                this.focus();
4399
            }
4400
        },
4401
4402
        /**
4403
        * @method _onOverlayDestroy
4404
        * @description "destroy" event handler for the Overlay.
4405
        * @private
4406
        * @param {String} p_sType String representing the name of the event  
4407
        * that was fired.
4408
        * @param {Array} p_aArgs Array of arguments sent when the event 
4409
        * was fired.
4410
        * @param {Overlay} p_oOverlay Object representing the overlay that 
4411
        * fired the event.
4412
        */
4413
        _onOverlayDestroy: function (p_sType, p_aArgs, p_oOverlay) {
4414
            this.remove(p_oOverlay);
4415
        },
4416
4417
        /**
4418
        * @method _onOverlayFocusHandler
4419
        *
4420
        * @description focusEvent Handler, used to delegate to _manageFocus with the correct arguments.
4421
        *
4422
        * @private
4423
        * @param {String} p_sType String representing the name of the event  
4424
        * that was fired.
4425
        * @param {Array} p_aArgs Array of arguments sent when the event 
4426
        * was fired.
4427
        * @param {Overlay} p_oOverlay Object representing the overlay that 
4428
        * fired the event.
4429
        */
4430
        _onOverlayFocusHandler: function(p_sType, p_aArgs, p_oOverlay) {
4431
            this._manageFocus(p_oOverlay);
4432
        },
4433
4434
        /**
4435
        * @method _onOverlayBlurHandler
4436
        * @description blurEvent Handler, used to delegate to _manageBlur with the correct arguments.
4437
        *
4438
        * @private
4439
        * @param {String} p_sType String representing the name of the event  
4440
        * that was fired.
4441
        * @param {Array} p_aArgs Array of arguments sent when the event 
4442
        * was fired.
4443
        * @param {Overlay} p_oOverlay Object representing the overlay that 
4444
        * fired the event.
4445
        */
4446
        _onOverlayBlurHandler: function(p_sType, p_aArgs, p_oOverlay) {
4447
            this._manageBlur(p_oOverlay);
4448
        },
4449
4450
        /**
4451
         * Subscribes to the Overlay based instance focusEvent, to allow the OverlayManager to
4452
         * monitor focus state.
4453
         * 
4454
         * If the instance already has a focusEvent (e.g. Menu), OverlayManager will subscribe 
4455
         * to the existing focusEvent, however if a focusEvent or focus method does not exist
4456
         * on the instance, the _bindFocus method will add them, and the focus method will 
4457
         * update the OverlayManager's state directly.
4458
         * 
4459
         * @method _bindFocus
4460
         * @param {Overlay} overlay The overlay for which focus needs to be managed
4461
         * @protected
4462
         */
4463
        _bindFocus : function(overlay) {
4464
            var mgr = this;
4465
4466
            if (!overlay.focusEvent) {
4467
                overlay.focusEvent = overlay.createEvent("focus");
4468
                overlay.focusEvent.signature = CustomEvent.LIST;
4469
                overlay.focusEvent._managed = true;
4470
            } else {
4471
                overlay.focusEvent.subscribe(mgr._onOverlayFocusHandler, overlay, mgr);
4472
            }
4473
4474
            if (!overlay.focus) {
4475
                Event.on(overlay.element, mgr.cfg.getProperty("focusevent"), mgr._onOverlayElementFocus, null, overlay);
4476
                overlay.focus = function () {
4477
                    if (mgr._manageFocus(this)) {
4478
                        // For Panel/Dialog
4479
                        if (this.cfg.getProperty("visible") && this.focusFirst) {
4480
                            this.focusFirst();
4481
                        }
4482
                        this.focusEvent.fire();
4483
                    }
4484
                };
4485
                overlay.focus._managed = true;
4486
            }
4487
        },
4488
4489
        /**
4490
         * Subscribes to the Overlay based instance's blurEvent to allow the OverlayManager to
4491
         * monitor blur state.
4492
         *
4493
         * If the instance already has a blurEvent (e.g. Menu), OverlayManager will subscribe 
4494
         * to the existing blurEvent, however if a blurEvent or blur method does not exist
4495
         * on the instance, the _bindBlur method will add them, and the blur method 
4496
         * update the OverlayManager's state directly.
4497
         *
4498
         * @method _bindBlur
4499
         * @param {Overlay} overlay The overlay for which blur needs to be managed
4500
         * @protected
4501
         */
4502
        _bindBlur : function(overlay) {
4503
            var mgr = this;
4504
4505
            if (!overlay.blurEvent) {
4506
                overlay.blurEvent = overlay.createEvent("blur");
4507
                overlay.blurEvent.signature = CustomEvent.LIST;
4508
                overlay.focusEvent._managed = true;
4509
            } else {
4510
                overlay.blurEvent.subscribe(mgr._onOverlayBlurHandler, overlay, mgr);
4511
            }
4512
4513
            if (!overlay.blur) {
4514
                overlay.blur = function () {
4515
                    if (mgr._manageBlur(this)) {
4516
                        this.blurEvent.fire();
4517
                    }
4518
                };
4519
                overlay.blur._managed = true;
4520
            }
4521
4522
            overlay.hideEvent.subscribe(overlay.blur);
4523
        },
4524
4525
        /**
4526
         * Subscribes to the Overlay based instance's destroyEvent, to allow the Overlay
4527
         * to be removed for the OverlayManager when destroyed.
4528
         * 
4529
         * @method _bindDestroy
4530
         * @param {Overlay} overlay The overlay instance being managed
4531
         * @protected
4532
         */
4533
        _bindDestroy : function(overlay) {
4534
            var mgr = this;
4535
            overlay.destroyEvent.subscribe(mgr._onOverlayDestroy, overlay, mgr);
4536
        },
4537
4538
        /**
4539
         * Ensures the zIndex configuration property on the managed overlay based instance
4540
         * is set to the computed zIndex value from the DOM (with "auto" translating to 0).
4541
         *
4542
         * @method _syncZIndex
4543
         * @param {Overlay} overlay The overlay instance being managed
4544
         * @protected
4545
         */
4546
        _syncZIndex : function(overlay) {
4547
            var zIndex = Dom.getStyle(overlay.element, "zIndex");
4548
            if (!isNaN(zIndex)) {
4549
                overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
4550
            } else {
4551
                overlay.cfg.setProperty("zIndex", 0);
4552
            }
4553
        },
4554
4555
        /**
4556
        * Registers an Overlay or an array of Overlays with the manager. Upon 
4557
        * registration, the Overlay receives functions for focus and blur, 
4558
        * along with CustomEvents for each.
4559
        *
4560
        * @method register
4561
        * @param {Overlay} overlay  An Overlay to register with the manager.
4562
        * @param {Overlay[]} overlay  An array of Overlays to register with 
4563
        * the manager.
4564
        * @return {boolean} true if any Overlays are registered.
4565
        */
4566
        register: function (overlay) {
4567
4568
            var registered = false,
4569
                i,
4570
                n;
4571
4572
            if (overlay instanceof Overlay) {
4573
4574
                overlay.cfg.addProperty("manager", { value: this } );
4575
4576
                this._bindFocus(overlay);
4577
                this._bindBlur(overlay);
4578
                this._bindDestroy(overlay);
4579
                this._syncZIndex(overlay);
4580
4581
                this.overlays.push(overlay);
4582
                this.bringToTop(overlay);
4583
4584
                registered = true;
4585
4586
            } else if (overlay instanceof Array) {
4587
4588
                for (i = 0, n = overlay.length; i < n; i++) {
4589
                    registered = this.register(overlay[i]) || registered;
4590
                }
4591
4592
            }
4593
4594
            return registered;
4595
        },
4596
4597
        /**
4598
        * Places the specified Overlay instance on top of all other 
4599
        * Overlay instances.
4600
        * @method bringToTop
4601
        * @param {YAHOO.widget.Overlay} p_oOverlay Object representing an 
4602
        * Overlay instance.
4603
        * @param {String} p_oOverlay String representing the id of an 
4604
        * Overlay instance.
4605
        */        
4606
        bringToTop: function (p_oOverlay) {
4607
4608
            var oOverlay = this.find(p_oOverlay),
4609
                nTopZIndex,
4610
                oTopOverlay,
4611
                aOverlays;
4612
4613
            if (oOverlay) {
4614
4615
                aOverlays = this.overlays;
4616
                aOverlays.sort(this.compareZIndexDesc);
4617
4618
                oTopOverlay = aOverlays[0];
4619
4620
                if (oTopOverlay) {
4621
                    nTopZIndex = Dom.getStyle(oTopOverlay.element, "zIndex");
4622
4623
                    if (!isNaN(nTopZIndex)) {
4624
4625
                        var bRequiresBump = false;
4626
4627
                        if (oTopOverlay !== oOverlay) {
4628
                            bRequiresBump = true;
4629
                        } else if (aOverlays.length > 1) {
4630
                            var nNextZIndex = Dom.getStyle(aOverlays[1].element, "zIndex");
4631
                            // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
4632
                            if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
4633
                                bRequiresBump = true;
4634
                            }
4635
                        }
4636
4637
                        if (bRequiresBump) {
4638
                            oOverlay.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
4639
                        }
4640
                    }
4641
                    aOverlays.sort(this.compareZIndexDesc);
4642
                }
4643
            }
4644
        },
4645
4646
        /**
4647
        * Attempts to locate an Overlay by instance or ID.
4648
        * @method find
4649
        * @param {Overlay} overlay  An Overlay to locate within the manager
4650
        * @param {String} overlay  An Overlay id to locate within the manager
4651
        * @return {Overlay} The requested Overlay, if found, or null if it 
4652
        * cannot be located.
4653
        */
4654
        find: function (overlay) {
4655
4656
            var isInstance = overlay instanceof Overlay,
4657
                overlays = this.overlays,
4658
                n = overlays.length,
4659
                found = null,
4660
                o,
4661
                i;
4662
4663
            if (isInstance || typeof overlay == "string") {
4664
                for (i = n-1; i >= 0; i--) {
4665
                    o = overlays[i];
4666
                    if ((isInstance && (o === overlay)) || (o.id == overlay)) {
4667
                        found = o;
4668
                        break;
4669
                    }
4670
                }
4671
            }
4672
4673
            return found;
4674
        },
4675
4676
        /**
4677
        * Used for sorting the manager's Overlays by z-index.
4678
        * @method compareZIndexDesc
4679
        * @private
4680
        * @return {Number} 0, 1, or -1, depending on where the Overlay should 
4681
        * fall in the stacking order.
4682
        */
4683
        compareZIndexDesc: function (o1, o2) {
4684
4685
            var zIndex1 = (o1.cfg) ? o1.cfg.getProperty("zIndex") : null, // Sort invalid (destroyed)
4686
                zIndex2 = (o2.cfg) ? o2.cfg.getProperty("zIndex") : null; // objects at bottom.
4687
4688
            if (zIndex1 === null && zIndex2 === null) {
4689
                return 0;
4690
            } else if (zIndex1 === null){
4691
                return 1;
4692
            } else if (zIndex2 === null) {
4693
                return -1;
4694
            } else if (zIndex1 > zIndex2) {
4695
                return -1;
4696
            } else if (zIndex1 < zIndex2) {
4697
                return 1;
4698
            } else {
4699
                return 0;
4700
            }
4701
        },
4702
4703
        /**
4704
        * Shows all Overlays in the manager.
4705
        * @method showAll
4706
        */
4707
        showAll: function () {
4708
            var overlays = this.overlays,
4709
                n = overlays.length,
4710
                i;
4711
4712
            for (i = n - 1; i >= 0; i--) {
4713
                overlays[i].show();
4714
            }
4715
        },
4716
4717
        /**
4718
        * Hides all Overlays in the manager.
4719
        * @method hideAll
4720
        */
4721
        hideAll: function () {
4722
            var overlays = this.overlays,
4723
                n = overlays.length,
4724
                i;
4725
4726
            for (i = n - 1; i >= 0; i--) {
4727
                overlays[i].hide();
4728
            }
4729
        },
4730
4731
        /**
4732
        * Returns a string representation of the object.
4733
        * @method toString
4734
        * @return {String} The string representation of the OverlayManager
4735
        */
4736
        toString: function () {
4737
            return "OverlayManager";
4738
        }
4739
    };
4740
}());
4741
(function () {
4742
4743
    /**
4744
    * ContainerEffect encapsulates animation transitions that are executed when 
4745
    * an Overlay is shown or hidden.
4746
    * @namespace YAHOO.widget
4747
    * @class ContainerEffect
4748
    * @constructor
4749
    * @param {YAHOO.widget.Overlay} overlay The Overlay that the animation 
4750
    * should be associated with
4751
    * @param {Object} attrIn The object literal representing the animation 
4752
    * arguments to be used for the animate-in transition. The arguments for 
4753
    * this literal are: attributes(object, see YAHOO.util.Anim for description), 
4754
    * duration(Number), and method(i.e. Easing.easeIn).
4755
    * @param {Object} attrOut The object literal representing the animation 
4756
    * arguments to be used for the animate-out transition. The arguments for  
4757
    * this literal are: attributes(object, see YAHOO.util.Anim for description), 
4758
    * duration(Number), and method(i.e. Easing.easeIn).
4759
    * @param {HTMLElement} targetElement Optional. The target element that  
4760
    * should be animated during the transition. Defaults to overlay.element.
4761
    * @param {class} Optional. The animation class to instantiate. Defaults to 
4762
    * YAHOO.util.Anim. Other options include YAHOO.util.Motion.
4763
    */
4764
    YAHOO.widget.ContainerEffect = function (overlay, attrIn, attrOut, targetElement, animClass) {
4765
4766
        if (!animClass) {
4767
            animClass = YAHOO.util.Anim;
4768
        }
4769
4770
        /**
4771
        * The overlay to animate
4772
        * @property overlay
4773
        * @type YAHOO.widget.Overlay
4774
        */
4775
        this.overlay = overlay;
4776
    
4777
        /**
4778
        * The animation attributes to use when transitioning into view
4779
        * @property attrIn
4780
        * @type Object
4781
        */
4782
        this.attrIn = attrIn;
4783
    
4784
        /**
4785
        * The animation attributes to use when transitioning out of view
4786
        * @property attrOut
4787
        * @type Object
4788
        */
4789
        this.attrOut = attrOut;
4790
    
4791
        /**
4792
        * The target element to be animated
4793
        * @property targetElement
4794
        * @type HTMLElement
4795
        */
4796
        this.targetElement = targetElement || overlay.element;
4797
    
4798
        /**
4799
        * The animation class to use for animating the overlay
4800
        * @property animClass
4801
        * @type class
4802
        */
4803
        this.animClass = animClass;
4804
    
4805
    };
4806
4807
4808
    var Dom = YAHOO.util.Dom,
4809
        CustomEvent = YAHOO.util.CustomEvent,
4810
        ContainerEffect = YAHOO.widget.ContainerEffect;
4811
4812
4813
    /**
4814
    * A pre-configured ContainerEffect instance that can be used for fading 
4815
    * an overlay in and out.
4816
    * @method FADE
4817
    * @static
4818
    * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
4819
    * @param {Number} dur The duration of the animation
4820
    * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
4821
    */
4822
    ContainerEffect.FADE = function (overlay, dur) {
4823
4824
        var Easing = YAHOO.util.Easing,
4825
            fin = {
4826
                attributes: {opacity:{from:0, to:1}},
4827
                duration: dur,
4828
                method: Easing.easeIn
4829
            },
4830
            fout = {
4831
                attributes: {opacity:{to:0}},
4832
                duration: dur,
4833
                method: Easing.easeOut
4834
            },
4835
            fade = new ContainerEffect(overlay, fin, fout, overlay.element);
4836
4837
        fade.handleUnderlayStart = function() {
4838
            var underlay = this.overlay.underlay;
4839
            if (underlay && YAHOO.env.ua.ie) {
4840
                var hasFilters = (underlay.filters && underlay.filters.length > 0);
4841
                if(hasFilters) {
4842
                    Dom.addClass(overlay.element, "yui-effect-fade");
4843
                }
4844
            }
4845
        };
4846
4847
        fade.handleUnderlayComplete = function() {
4848
            var underlay = this.overlay.underlay;
4849
            if (underlay && YAHOO.env.ua.ie) {
4850
                Dom.removeClass(overlay.element, "yui-effect-fade");
4851
            }
4852
        };
4853
4854
        fade.handleStartAnimateIn = function (type, args, obj) {
4855
            Dom.addClass(obj.overlay.element, "hide-select");
4856
4857
            if (!obj.overlay.underlay) {
4858
                obj.overlay.cfg.refireEvent("underlay");
4859
            }
4860
4861
            obj.handleUnderlayStart();
4862
4863
            obj.overlay._setDomVisibility(true);
4864
            Dom.setStyle(obj.overlay.element, "opacity", 0);
4865
        };
4866
4867
        fade.handleCompleteAnimateIn = function (type,args,obj) {
4868
            Dom.removeClass(obj.overlay.element, "hide-select");
4869
4870
            if (obj.overlay.element.style.filter) {
4871
                obj.overlay.element.style.filter = null;
4872
            }
4873
4874
            obj.handleUnderlayComplete();
4875
4876
            obj.overlay.cfg.refireEvent("iframe");
4877
            obj.animateInCompleteEvent.fire();
4878
        };
4879
4880
        fade.handleStartAnimateOut = function (type, args, obj) {
4881
            Dom.addClass(obj.overlay.element, "hide-select");
4882
            obj.handleUnderlayStart();
4883
        };
4884
4885
        fade.handleCompleteAnimateOut =  function (type, args, obj) {
4886
            Dom.removeClass(obj.overlay.element, "hide-select");
4887
            if (obj.overlay.element.style.filter) {
4888
                obj.overlay.element.style.filter = null;
4889
            }
4890
            obj.overlay._setDomVisibility(false);
4891
            Dom.setStyle(obj.overlay.element, "opacity", 1);
4892
4893
            obj.handleUnderlayComplete();
4894
4895
            obj.overlay.cfg.refireEvent("iframe");
4896
            obj.animateOutCompleteEvent.fire();
4897
        };
4898
4899
        fade.init();
4900
        return fade;
4901
    };
4902
    
4903
    
4904
    /**
4905
    * A pre-configured ContainerEffect instance that can be used for sliding an 
4906
    * overlay in and out.
4907
    * @method SLIDE
4908
    * @static
4909
    * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
4910
    * @param {Number} dur The duration of the animation
4911
    * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
4912
    */
4913
    ContainerEffect.SLIDE = function (overlay, dur) {
4914
        var Easing = YAHOO.util.Easing,
4915
4916
            x = overlay.cfg.getProperty("x") || Dom.getX(overlay.element),
4917
            y = overlay.cfg.getProperty("y") || Dom.getY(overlay.element),
4918
            clientWidth = Dom.getClientWidth(),
4919
            offsetWidth = overlay.element.offsetWidth,
4920
4921
            sin =  { 
4922
                attributes: { points: { to: [x, y] } },
4923
                duration: dur,
4924
                method: Easing.easeIn 
4925
            },
4926
4927
            sout = {
4928
                attributes: { points: { to: [(clientWidth + 25), y] } },
4929
                duration: dur,
4930
                method: Easing.easeOut 
4931
            },
4932
4933
            slide = new ContainerEffect(overlay, sin, sout, overlay.element, YAHOO.util.Motion);
4934
4935
        slide.handleStartAnimateIn = function (type,args,obj) {
4936
            obj.overlay.element.style.left = ((-25) - offsetWidth) + "px";
4937
            obj.overlay.element.style.top  = y + "px";
4938
        };
4939
4940
        slide.handleTweenAnimateIn = function (type, args, obj) {
4941
        
4942
            var pos = Dom.getXY(obj.overlay.element),
4943
                currentX = pos[0],
4944
                currentY = pos[1];
4945
        
4946
            if (Dom.getStyle(obj.overlay.element, "visibility") == 
4947
                "hidden" && currentX < x) {
4948
4949
                obj.overlay._setDomVisibility(true);
4950
4951
            }
4952
        
4953
            obj.overlay.cfg.setProperty("xy", [currentX, currentY], true);
4954
            obj.overlay.cfg.refireEvent("iframe");
4955
        };
4956
        
4957
        slide.handleCompleteAnimateIn = function (type, args, obj) {
4958
            obj.overlay.cfg.setProperty("xy", [x, y], true);
4959
            obj.startX = x;
4960
            obj.startY = y;
4961
            obj.overlay.cfg.refireEvent("iframe");
4962
            obj.animateInCompleteEvent.fire();
4963
        };
4964
        
4965
        slide.handleStartAnimateOut = function (type, args, obj) {
4966
    
4967
            var vw = Dom.getViewportWidth(),
4968
                pos = Dom.getXY(obj.overlay.element),
4969
                yso = pos[1];
4970
    
4971
            obj.animOut.attributes.points.to = [(vw + 25), yso];
4972
        };
4973
        
4974
        slide.handleTweenAnimateOut = function (type, args, obj) {
4975
    
4976
            var pos = Dom.getXY(obj.overlay.element),
4977
                xto = pos[0],
4978
                yto = pos[1];
4979
        
4980
            obj.overlay.cfg.setProperty("xy", [xto, yto], true);
4981
            obj.overlay.cfg.refireEvent("iframe");
4982
        };
4983
        
4984
        slide.handleCompleteAnimateOut = function (type, args, obj) {
4985
            obj.overlay._setDomVisibility(false);
4986
4987
            obj.overlay.cfg.setProperty("xy", [x, y]);
4988
            obj.animateOutCompleteEvent.fire();
4989
        };
4990
4991
        slide.init();
4992
        return slide;
4993
    };
4994
4995
    ContainerEffect.prototype = {
4996
4997
        /**
4998
        * Initializes the animation classes and events.
4999
        * @method init
5000
        */
5001
        init: function () {
5002
5003
            this.beforeAnimateInEvent = this.createEvent("beforeAnimateIn");
5004
            this.beforeAnimateInEvent.signature = CustomEvent.LIST;
5005
            
5006
            this.beforeAnimateOutEvent = this.createEvent("beforeAnimateOut");
5007
            this.beforeAnimateOutEvent.signature = CustomEvent.LIST;
5008
        
5009
            this.animateInCompleteEvent = this.createEvent("animateInComplete");
5010
            this.animateInCompleteEvent.signature = CustomEvent.LIST;
5011
        
5012
            this.animateOutCompleteEvent = 
5013
                this.createEvent("animateOutComplete");
5014
            this.animateOutCompleteEvent.signature = CustomEvent.LIST;
5015
        
5016
            this.animIn = new this.animClass(this.targetElement, 
5017
                this.attrIn.attributes, this.attrIn.duration, 
5018
                this.attrIn.method);
5019
5020
            this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
5021
            this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
5022
5023
            this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn, 
5024
                this);
5025
        
5026
            this.animOut = new this.animClass(this.targetElement, 
5027
                this.attrOut.attributes, this.attrOut.duration, 
5028
                this.attrOut.method);
5029
5030
            this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
5031
            this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
5032
            this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut, 
5033
                this);
5034
5035
        },
5036
        
5037
        /**
5038
        * Triggers the in-animation.
5039
        * @method animateIn
5040
        */
5041
        animateIn: function () {
5042
            this.beforeAnimateInEvent.fire();
5043
            this.animIn.animate();
5044
        },
5045
5046
        /**
5047
        * Triggers the out-animation.
5048
        * @method animateOut
5049
        */
5050
        animateOut: function () {
5051
            this.beforeAnimateOutEvent.fire();
5052
            this.animOut.animate();
5053
        },
5054
5055
        /**
5056
        * The default onStart handler for the in-animation.
5057
        * @method handleStartAnimateIn
5058
        * @param {String} type The CustomEvent type
5059
        * @param {Object[]} args The CustomEvent arguments
5060
        * @param {Object} obj The scope object
5061
        */
5062
        handleStartAnimateIn: function (type, args, obj) { },
5063
5064
        /**
5065
        * The default onTween handler for the in-animation.
5066
        * @method handleTweenAnimateIn
5067
        * @param {String} type The CustomEvent type
5068
        * @param {Object[]} args The CustomEvent arguments
5069
        * @param {Object} obj The scope object
5070
        */
5071
        handleTweenAnimateIn: function (type, args, obj) { },
5072
5073
        /**
5074
        * The default onComplete handler for the in-animation.
5075
        * @method handleCompleteAnimateIn
5076
        * @param {String} type The CustomEvent type
5077
        * @param {Object[]} args The CustomEvent arguments
5078
        * @param {Object} obj The scope object
5079
        */
5080
        handleCompleteAnimateIn: function (type, args, obj) { },
5081
5082
        /**
5083
        * The default onStart handler for the out-animation.
5084
        * @method handleStartAnimateOut
5085
        * @param {String} type The CustomEvent type
5086
        * @param {Object[]} args The CustomEvent arguments
5087
        * @param {Object} obj The scope object
5088
        */
5089
        handleStartAnimateOut: function (type, args, obj) { },
5090
5091
        /**
5092
        * The default onTween handler for the out-animation.
5093
        * @method handleTweenAnimateOut
5094
        * @param {String} type The CustomEvent type
5095
        * @param {Object[]} args The CustomEvent arguments
5096
        * @param {Object} obj The scope object
5097
        */
5098
        handleTweenAnimateOut: function (type, args, obj) { },
5099
5100
        /**
5101
        * The default onComplete handler for the out-animation.
5102
        * @method handleCompleteAnimateOut
5103
        * @param {String} type The CustomEvent type
5104
        * @param {Object[]} args The CustomEvent arguments
5105
        * @param {Object} obj The scope object
5106
        */
5107
        handleCompleteAnimateOut: function (type, args, obj) { },
5108
        
5109
        /**
5110
        * Returns a string representation of the object.
5111
        * @method toString
5112
        * @return {String} The string representation of the ContainerEffect
5113
        */
5114
        toString: function () {
5115
            var output = "ContainerEffect";
5116
            if (this.overlay) {
5117
                output += " [" + this.overlay.toString() + "]";
5118
            }
5119
            return output;
5120
        }
5121
    };
5122
5123
    YAHOO.lang.augmentProto(ContainerEffect, YAHOO.util.EventProvider);
5124
5125
})();
5126
YAHOO.register("containercore", YAHOO.widget.Module, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/dragdrop/dragdrop-debug.js (-3710 lines)
Lines 1-3710 Link Here
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.8.0r4
6
*/
7
/**
8
 * The drag and drop utility provides a framework for building drag and drop
9
 * applications.  In addition to enabling drag and drop for specific elements,
10
 * the drag and drop elements are tracked by the manager class, and the
11
 * interactions between the various elements are tracked during the drag and
12
 * the implementing code is notified about these important moments.
13
 * @module dragdrop
14
 * @title Drag and Drop
15
 * @requires yahoo,dom,event
16
 * @namespace YAHOO.util
17
 */
18
19
// Only load the library once.  Rewriting the manager class would orphan 
20
// existing drag and drop instances.
21
if (!YAHOO.util.DragDropMgr) {
22
23
/**
24
 * DragDropMgr is a singleton that tracks the element interaction for 
25
 * all DragDrop items in the window.  Generally, you will not call 
26
 * this class directly, but it does have helper methods that could 
27
 * be useful in your DragDrop implementations.
28
 * @class DragDropMgr
29
 * @static
30
 */
31
YAHOO.util.DragDropMgr = function() {
32
33
    var Event = YAHOO.util.Event,
34
        Dom = YAHOO.util.Dom;
35
36
    return {
37
        /**
38
        * This property is used to turn on global use of the shim element on all DragDrop instances, defaults to false for backcompat. (Use: YAHOO.util.DDM.useShim = true)
39
        * @property useShim
40
        * @type Boolean
41
        * @static
42
        */
43
        useShim: false,
44
        /**
45
        * This property is used to determine if the shim is active over the screen, default false.
46
        * @private
47
        * @property _shimActive
48
        * @type Boolean
49
        * @static
50
        */
51
        _shimActive: false,
52
        /**
53
        * This property is used when useShim is set on a DragDrop object to store the current state of DDM.useShim so it can be reset when a drag operation is done.
54
        * @private
55
        * @property _shimState
56
        * @type Boolean
57
        * @static
58
        */
59
        _shimState: false,
60
        /**
61
        * This property is used when useShim is set to true, it will set the opacity on the shim to .5 for debugging. Use: (YAHOO.util.DDM._debugShim = true;)
62
        * @private
63
        * @property _debugShim
64
        * @type Boolean
65
        * @static
66
        */
67
        _debugShim: false,
68
        /**
69
        * This method will create a shim element (giving it the id of yui-ddm-shim), it also attaches the mousemove and mouseup listeners to it and attaches a scroll listener on the window
70
        * @private
71
        * @method _sizeShim
72
        * @static
73
        */
74
        _createShim: function() {
75
            YAHOO.log('Creating Shim Element', 'info', 'DragDropMgr');
76
            var s = document.createElement('div');
77
            s.id = 'yui-ddm-shim';
78
            if (document.body.firstChild) {
79
                document.body.insertBefore(s, document.body.firstChild);
80
            } else {
81
                document.body.appendChild(s);
82
            }
83
            s.style.display = 'none';
84
            s.style.backgroundColor = 'red';
85
            s.style.position = 'absolute';
86
            s.style.zIndex = '99999';
87
            Dom.setStyle(s, 'opacity', '0');
88
            this._shim = s;
89
            Event.on(s, "mouseup",   this.handleMouseUp, this, true);
90
            Event.on(s, "mousemove", this.handleMouseMove, this, true);
91
            Event.on(window, 'scroll', this._sizeShim, this, true);
92
        },
93
        /**
94
        * This method will size the shim, called from activate and on window scroll event
95
        * @private
96
        * @method _sizeShim
97
        * @static
98
        */
99
        _sizeShim: function() {
100
            if (this._shimActive) {
101
                YAHOO.log('Sizing Shim', 'info', 'DragDropMgr');
102
                var s = this._shim;
103
                s.style.height = Dom.getDocumentHeight() + 'px';
104
                s.style.width = Dom.getDocumentWidth() + 'px';
105
                s.style.top = '0';
106
                s.style.left = '0';
107
            }
108
        },
109
        /**
110
        * This method will create the shim element if needed, then show the shim element, size the element and set the _shimActive property to true
111
        * @private
112
        * @method _activateShim
113
        * @static
114
        */
115
        _activateShim: function() {
116
            if (this.useShim) {
117
                YAHOO.log('Activating Shim', 'info', 'DragDropMgr');
118
                if (!this._shim) {
119
                    this._createShim();
120
                }
121
                this._shimActive = true;
122
                var s = this._shim,
123
                    o = '0';
124
                if (this._debugShim) {
125
                    o = '.5';
126
                }
127
                Dom.setStyle(s, 'opacity', o);
128
                this._sizeShim();
129
                s.style.display = 'block';
130
            }
131
        },
132
        /**
133
        * This method will hide the shim element and set the _shimActive property to false
134
        * @private
135
        * @method _deactivateShim
136
        * @static
137
        */
138
        _deactivateShim: function() {
139
            YAHOO.log('Deactivating Shim', 'info', 'DragDropMgr');
140
            this._shim.style.display = 'none';
141
            this._shimActive = false;
142
        },
143
        /**
144
        * The HTML element created to use as a shim over the document to track mouse movements
145
        * @private
146
        * @property _shim
147
        * @type HTMLElement
148
        * @static
149
        */
150
        _shim: null,
151
        /**
152
         * Two dimensional Array of registered DragDrop objects.  The first 
153
         * dimension is the DragDrop item group, the second the DragDrop 
154
         * object.
155
         * @property ids
156
         * @type {string: string}
157
         * @private
158
         * @static
159
         */
160
        ids: {},
161
162
        /**
163
         * Array of element ids defined as drag handles.  Used to determine 
164
         * if the element that generated the mousedown event is actually the 
165
         * handle and not the html element itself.
166
         * @property handleIds
167
         * @type {string: string}
168
         * @private
169
         * @static
170
         */
171
        handleIds: {},
172
173
        /**
174
         * the DragDrop object that is currently being dragged
175
         * @property dragCurrent
176
         * @type DragDrop
177
         * @private
178
         * @static
179
         **/
180
        dragCurrent: null,
181
182
        /**
183
         * the DragDrop object(s) that are being hovered over
184
         * @property dragOvers
185
         * @type Array
186
         * @private
187
         * @static
188
         */
189
        dragOvers: {},
190
191
        /**
192
         * the X distance between the cursor and the object being dragged
193
         * @property deltaX
194
         * @type int
195
         * @private
196
         * @static
197
         */
198
        deltaX: 0,
199
200
        /**
201
         * the Y distance between the cursor and the object being dragged
202
         * @property deltaY
203
         * @type int
204
         * @private
205
         * @static
206
         */
207
        deltaY: 0,
208
209
        /**
210
         * Flag to determine if we should prevent the default behavior of the
211
         * events we define. By default this is true, but this can be set to 
212
         * false if you need the default behavior (not recommended)
213
         * @property preventDefault
214
         * @type boolean
215
         * @static
216
         */
217
        preventDefault: true,
218
219
        /**
220
         * Flag to determine if we should stop the propagation of the events 
221
         * we generate. This is true by default but you may want to set it to
222
         * false if the html element contains other features that require the
223
         * mouse click.
224
         * @property stopPropagation
225
         * @type boolean
226
         * @static
227
         */
228
        stopPropagation: true,
229
230
        /**
231
         * Internal flag that is set to true when drag and drop has been
232
         * initialized
233
         * @property initialized
234
         * @private
235
         * @static
236
         */
237
        initialized: false,
238
239
        /**
240
         * All drag and drop can be disabled.
241
         * @property locked
242
         * @private
243
         * @static
244
         */
245
        locked: false,
246
247
        /**
248
         * Provides additional information about the current set of
249
         * interactions.  Can be accessed from the event handlers. It
250
         * contains the following properties:
251
         *
252
         *       out:       onDragOut interactions
253
         *       enter:     onDragEnter interactions
254
         *       over:      onDragOver interactions
255
         *       drop:      onDragDrop interactions
256
         *       point:     The location of the cursor
257
         *       draggedRegion: The location of dragged element at the time
258
         *                      of the interaction
259
         *       sourceRegion: The location of the source elemtn at the time
260
         *                     of the interaction
261
         *       validDrop: boolean
262
         * @property interactionInfo
263
         * @type object
264
         * @static
265
         */
266
        interactionInfo: null,
267
268
        /**
269
         * Called the first time an element is registered.
270
         * @method init
271
         * @private
272
         * @static
273
         */
274
        init: function() {
275
            this.initialized = true;
276
        },
277
278
        /**
279
         * In point mode, drag and drop interaction is defined by the 
280
         * location of the cursor during the drag/drop
281
         * @property POINT
282
         * @type int
283
         * @static
284
         * @final
285
         */
286
        POINT: 0,
287
288
        /**
289
         * In intersect mode, drag and drop interaction is defined by the 
290
         * cursor position or the amount of overlap of two or more drag and 
291
         * drop objects.
292
         * @property INTERSECT
293
         * @type int
294
         * @static
295
         * @final
296
         */
297
        INTERSECT: 1,
298
299
        /**
300
         * In intersect mode, drag and drop interaction is defined only by the 
301
         * overlap of two or more drag and drop objects.
302
         * @property STRICT_INTERSECT
303
         * @type int
304
         * @static
305
         * @final
306
         */
307
        STRICT_INTERSECT: 2,
308
309
        /**
310
         * The current drag and drop mode.  Default: POINT
311
         * @property mode
312
         * @type int
313
         * @static
314
         */
315
        mode: 0,
316
317
        /**
318
         * Runs method on all drag and drop objects
319
         * @method _execOnAll
320
         * @private
321
         * @static
322
         */
323
        _execOnAll: function(sMethod, args) {
324
            for (var i in this.ids) {
325
                for (var j in this.ids[i]) {
326
                    var oDD = this.ids[i][j];
327
                    if (! this.isTypeOfDD(oDD)) {
328
                        continue;
329
                    }
330
                    oDD[sMethod].apply(oDD, args);
331
                }
332
            }
333
        },
334
335
        /**
336
         * Drag and drop initialization.  Sets up the global event handlers
337
         * @method _onLoad
338
         * @private
339
         * @static
340
         */
341
        _onLoad: function() {
342
343
            this.init();
344
345
            YAHOO.log("DragDropMgr onload", "info", "DragDropMgr");
346
            Event.on(document, "mouseup",   this.handleMouseUp, this, true);
347
            Event.on(document, "mousemove", this.handleMouseMove, this, true);
348
            Event.on(window,   "unload",    this._onUnload, this, true);
349
            Event.on(window,   "resize",    this._onResize, this, true);
350
            // Event.on(window,   "mouseout",    this._test);
351
352
        },
353
354
        /**
355
         * Reset constraints on all drag and drop objs
356
         * @method _onResize
357
         * @private
358
         * @static
359
         */
360
        _onResize: function(e) {
361
            YAHOO.log("window resize", "info", "DragDropMgr");
362
            this._execOnAll("resetConstraints", []);
363
        },
364
365
        /**
366
         * Lock all drag and drop functionality
367
         * @method lock
368
         * @static
369
         */
370
        lock: function() { this.locked = true; },
371
372
        /**
373
         * Unlock all drag and drop functionality
374
         * @method unlock
375
         * @static
376
         */
377
        unlock: function() { this.locked = false; },
378
379
        /**
380
         * Is drag and drop locked?
381
         * @method isLocked
382
         * @return {boolean} True if drag and drop is locked, false otherwise.
383
         * @static
384
         */
385
        isLocked: function() { return this.locked; },
386
387
        /**
388
         * Location cache that is set for all drag drop objects when a drag is
389
         * initiated, cleared when the drag is finished.
390
         * @property locationCache
391
         * @private
392
         * @static
393
         */
394
        locationCache: {},
395
396
        /**
397
         * Set useCache to false if you want to force object the lookup of each
398
         * drag and drop linked element constantly during a drag.
399
         * @property useCache
400
         * @type boolean
401
         * @static
402
         */
403
        useCache: true,
404
405
        /**
406
         * The number of pixels that the mouse needs to move after the 
407
         * mousedown before the drag is initiated.  Default=3;
408
         * @property clickPixelThresh
409
         * @type int
410
         * @static
411
         */
412
        clickPixelThresh: 3,
413
414
        /**
415
         * The number of milliseconds after the mousedown event to initiate the
416
         * drag if we don't get a mouseup event. Default=1000
417
         * @property clickTimeThresh
418
         * @type int
419
         * @static
420
         */
421
        clickTimeThresh: 1000,
422
423
        /**
424
         * Flag that indicates that either the drag pixel threshold or the 
425
         * mousdown time threshold has been met
426
         * @property dragThreshMet
427
         * @type boolean
428
         * @private
429
         * @static
430
         */
431
        dragThreshMet: false,
432
433
        /**
434
         * Timeout used for the click time threshold
435
         * @property clickTimeout
436
         * @type Object
437
         * @private
438
         * @static
439
         */
440
        clickTimeout: null,
441
442
        /**
443
         * The X position of the mousedown event stored for later use when a 
444
         * drag threshold is met.
445
         * @property startX
446
         * @type int
447
         * @private
448
         * @static
449
         */
450
        startX: 0,
451
452
        /**
453
         * The Y position of the mousedown event stored for later use when a 
454
         * drag threshold is met.
455
         * @property startY
456
         * @type int
457
         * @private
458
         * @static
459
         */
460
        startY: 0,
461
462
        /**
463
         * Flag to determine if the drag event was fired from the click timeout and
464
         * not the mouse move threshold.
465
         * @property fromTimeout
466
         * @type boolean
467
         * @private
468
         * @static
469
         */
470
        fromTimeout: false,
471
472
        /**
473
         * Each DragDrop instance must be registered with the DragDropMgr.  
474
         * This is executed in DragDrop.init()
475
         * @method regDragDrop
476
         * @param {DragDrop} oDD the DragDrop object to register
477
         * @param {String} sGroup the name of the group this element belongs to
478
         * @static
479
         */
480
        regDragDrop: function(oDD, sGroup) {
481
            if (!this.initialized) { this.init(); }
482
            
483
            if (!this.ids[sGroup]) {
484
                this.ids[sGroup] = {};
485
            }
486
            this.ids[sGroup][oDD.id] = oDD;
487
        },
488
489
        /**
490
         * Removes the supplied dd instance from the supplied group. Executed
491
         * by DragDrop.removeFromGroup, so don't call this function directly.
492
         * @method removeDDFromGroup
493
         * @private
494
         * @static
495
         */
496
        removeDDFromGroup: function(oDD, sGroup) {
497
            if (!this.ids[sGroup]) {
498
                this.ids[sGroup] = {};
499
            }
500
501
            var obj = this.ids[sGroup];
502
            if (obj && obj[oDD.id]) {
503
                delete obj[oDD.id];
504
            }
505
        },
506
507
        /**
508
         * Unregisters a drag and drop item.  This is executed in 
509
         * DragDrop.unreg, use that method instead of calling this directly.
510
         * @method _remove
511
         * @private
512
         * @static
513
         */
514
        _remove: function(oDD) {
515
            for (var g in oDD.groups) {
516
                if (g) {
517
                    var item = this.ids[g];
518
                    if (item && item[oDD.id]) {
519
                        delete item[oDD.id];
520
                    }
521
                }
522
                
523
            }
524
            delete this.handleIds[oDD.id];
525
        },
526
527
        /**
528
         * Each DragDrop handle element must be registered.  This is done
529
         * automatically when executing DragDrop.setHandleElId()
530
         * @method regHandle
531
         * @param {String} sDDId the DragDrop id this element is a handle for
532
         * @param {String} sHandleId the id of the element that is the drag 
533
         * handle
534
         * @static
535
         */
536
        regHandle: function(sDDId, sHandleId) {
537
            if (!this.handleIds[sDDId]) {
538
                this.handleIds[sDDId] = {};
539
            }
540
            this.handleIds[sDDId][sHandleId] = sHandleId;
541
        },
542
543
        /**
544
         * Utility function to determine if a given element has been 
545
         * registered as a drag drop item.
546
         * @method isDragDrop
547
         * @param {String} id the element id to check
548
         * @return {boolean} true if this element is a DragDrop item, 
549
         * false otherwise
550
         * @static
551
         */
552
        isDragDrop: function(id) {
553
            return ( this.getDDById(id) ) ? true : false;
554
        },
555
556
        /**
557
         * Returns the drag and drop instances that are in all groups the
558
         * passed in instance belongs to.
559
         * @method getRelated
560
         * @param {DragDrop} p_oDD the obj to get related data for
561
         * @param {boolean} bTargetsOnly if true, only return targetable objs
562
         * @return {DragDrop[]} the related instances
563
         * @static
564
         */
565
        getRelated: function(p_oDD, bTargetsOnly) {
566
            var oDDs = [];
567
            for (var i in p_oDD.groups) {
568
                for (var j in this.ids[i]) {
569
                    var dd = this.ids[i][j];
570
                    if (! this.isTypeOfDD(dd)) {
571
                        continue;
572
                    }
573
                    if (!bTargetsOnly || dd.isTarget) {
574
                        oDDs[oDDs.length] = dd;
575
                    }
576
                }
577
            }
578
579
            return oDDs;
580
        },
581
582
        /**
583
         * Returns true if the specified dd target is a legal target for 
584
         * the specifice drag obj
585
         * @method isLegalTarget
586
         * @param {DragDrop} the drag obj
587
         * @param {DragDrop} the target
588
         * @return {boolean} true if the target is a legal target for the 
589
         * dd obj
590
         * @static
591
         */
592
        isLegalTarget: function (oDD, oTargetDD) {
593
            var targets = this.getRelated(oDD, true);
594
            for (var i=0, len=targets.length;i<len;++i) {
595
                if (targets[i].id == oTargetDD.id) {
596
                    return true;
597
                }
598
            }
599
600
            return false;
601
        },
602
603
        /**
604
         * My goal is to be able to transparently determine if an object is
605
         * typeof DragDrop, and the exact subclass of DragDrop.  typeof 
606
         * returns "object", oDD.constructor.toString() always returns
607
         * "DragDrop" and not the name of the subclass.  So for now it just
608
         * evaluates a well-known variable in DragDrop.
609
         * @method isTypeOfDD
610
         * @param {Object} the object to evaluate
611
         * @return {boolean} true if typeof oDD = DragDrop
612
         * @static
613
         */
614
        isTypeOfDD: function (oDD) {
615
            return (oDD && oDD.__ygDragDrop);
616
        },
617
618
        /**
619
         * Utility function to determine if a given element has been 
620
         * registered as a drag drop handle for the given Drag Drop object.
621
         * @method isHandle
622
         * @param {String} id the element id to check
623
         * @return {boolean} true if this element is a DragDrop handle, false 
624
         * otherwise
625
         * @static
626
         */
627
        isHandle: function(sDDId, sHandleId) {
628
            return ( this.handleIds[sDDId] && 
629
                            this.handleIds[sDDId][sHandleId] );
630
        },
631
632
        /**
633
         * Returns the DragDrop instance for a given id
634
         * @method getDDById
635
         * @param {String} id the id of the DragDrop object
636
         * @return {DragDrop} the drag drop object, null if it is not found
637
         * @static
638
         */
639
        getDDById: function(id) {
640
            for (var i in this.ids) {
641
                if (this.ids[i][id]) {
642
                    return this.ids[i][id];
643
                }
644
            }
645
            return null;
646
        },
647
648
        /**
649
         * Fired after a registered DragDrop object gets the mousedown event.
650
         * Sets up the events required to track the object being dragged
651
         * @method handleMouseDown
652
         * @param {Event} e the event
653
         * @param oDD the DragDrop object being dragged
654
         * @private
655
         * @static
656
         */
657
        handleMouseDown: function(e, oDD) {
658
            //this._activateShim();
659
660
            this.currentTarget = YAHOO.util.Event.getTarget(e);
661
662
            this.dragCurrent = oDD;
663
664
            var el = oDD.getEl();
665
666
            // track start position
667
            this.startX = YAHOO.util.Event.getPageX(e);
668
            this.startY = YAHOO.util.Event.getPageY(e);
669
670
            this.deltaX = this.startX - el.offsetLeft;
671
            this.deltaY = this.startY - el.offsetTop;
672
673
            this.dragThreshMet = false;
674
675
            this.clickTimeout = setTimeout( 
676
                    function() { 
677
                        var DDM = YAHOO.util.DDM;
678
                        DDM.startDrag(DDM.startX, DDM.startY);
679
                        DDM.fromTimeout = true;
680
                    }, 
681
                    this.clickTimeThresh );
682
        },
683
684
        /**
685
         * Fired when either the drag pixel threshold or the mousedown hold 
686
         * time threshold has been met.
687
         * @method startDrag
688
         * @param x {int} the X position of the original mousedown
689
         * @param y {int} the Y position of the original mousedown
690
         * @static
691
         */
692
        startDrag: function(x, y) {
693
            if (this.dragCurrent && this.dragCurrent.useShim) {
694
                this._shimState = this.useShim;
695
                this.useShim = true;
696
            }
697
            this._activateShim();
698
            YAHOO.log("firing drag start events", "info", "DragDropMgr");
699
            clearTimeout(this.clickTimeout);
700
            var dc = this.dragCurrent;
701
            if (dc && dc.events.b4StartDrag) {
702
                dc.b4StartDrag(x, y);
703
                dc.fireEvent('b4StartDragEvent', { x: x, y: y });
704
            }
705
            if (dc && dc.events.startDrag) {
706
                dc.startDrag(x, y);
707
                dc.fireEvent('startDragEvent', { x: x, y: y });
708
            }
709
            this.dragThreshMet = true;
710
        },
711
712
        /**
713
         * Internal function to handle the mouseup event.  Will be invoked 
714
         * from the context of the document.
715
         * @method handleMouseUp
716
         * @param {Event} e the event
717
         * @private
718
         * @static
719
         */
720
        handleMouseUp: function(e) {
721
            if (this.dragCurrent) {
722
                clearTimeout(this.clickTimeout);
723
724
                if (this.dragThreshMet) {
725
                    YAHOO.log("mouseup detected - completing drag", "info", "DragDropMgr");
726
                    if (this.fromTimeout) {
727
                        YAHOO.log('fromTimeout is true (mouse didn\'t move), call handleMouseMove so we can get the dragOver event', 'info', 'DragDropMgr');
728
                        this.fromTimeout = false;
729
                        this.handleMouseMove(e);
730
                    }
731
                    this.fromTimeout = false;
732
                    this.fireEvents(e, true);
733
                } else {
734
                    YAHOO.log("drag threshold not met", "info", "DragDropMgr");
735
                }
736
737
                this.stopDrag(e);
738
739
                this.stopEvent(e);
740
            }
741
        },
742
743
        /**
744
         * Utility to stop event propagation and event default, if these 
745
         * features are turned on.
746
         * @method stopEvent
747
         * @param {Event} e the event as returned by this.getEvent()
748
         * @static
749
         */
750
        stopEvent: function(e) {
751
            if (this.stopPropagation) {
752
                YAHOO.util.Event.stopPropagation(e);
753
            }
754
755
            if (this.preventDefault) {
756
                YAHOO.util.Event.preventDefault(e);
757
            }
758
        },
759
760
        /** 
761
         * Ends the current drag, cleans up the state, and fires the endDrag
762
         * and mouseUp events.  Called internally when a mouseup is detected
763
         * during the drag.  Can be fired manually during the drag by passing
764
         * either another event (such as the mousemove event received in onDrag)
765
         * or a fake event with pageX and pageY defined (so that endDrag and
766
         * onMouseUp have usable position data.).  Alternatively, pass true
767
         * for the silent parameter so that the endDrag and onMouseUp events
768
         * are skipped (so no event data is needed.)
769
         *
770
         * @method stopDrag
771
         * @param {Event} e the mouseup event, another event (or a fake event) 
772
         *                  with pageX and pageY defined, or nothing if the 
773
         *                  silent parameter is true
774
         * @param {boolean} silent skips the enddrag and mouseup events if true
775
         * @static
776
         */
777
        stopDrag: function(e, silent) {
778
            // YAHOO.log("mouseup - removing event handlers");
779
            var dc = this.dragCurrent;
780
            // Fire the drag end event for the item that was dragged
781
            if (dc && !silent) {
782
                if (this.dragThreshMet) {
783
                    YAHOO.log("firing endDrag events", "info", "DragDropMgr");
784
                    if (dc.events.b4EndDrag) {
785
                        dc.b4EndDrag(e);
786
                        dc.fireEvent('b4EndDragEvent', { e: e });
787
                    }
788
                    if (dc.events.endDrag) {
789
                        dc.endDrag(e);
790
                        dc.fireEvent('endDragEvent', { e: e });
791
                    }
792
                }
793
                if (dc.events.mouseUp) {
794
                    YAHOO.log("firing dragdrop onMouseUp event", "info", "DragDropMgr");
795
                    dc.onMouseUp(e);
796
                    dc.fireEvent('mouseUpEvent', { e: e });
797
                }
798
            }
799
800
            if (this._shimActive) {
801
                this._deactivateShim();
802
                if (this.dragCurrent && this.dragCurrent.useShim) {
803
                    this.useShim = this._shimState;
804
                    this._shimState = false;
805
                }
806
            }
807
808
            this.dragCurrent = null;
809
            this.dragOvers = {};
810
        },
811
812
        /** 
813
         * Internal function to handle the mousemove event.  Will be invoked 
814
         * from the context of the html element.
815
         *
816
         * @TODO figure out what we can do about mouse events lost when the 
817
         * user drags objects beyond the window boundary.  Currently we can 
818
         * detect this in internet explorer by verifying that the mouse is 
819
         * down during the mousemove event.  Firefox doesn't give us the 
820
         * button state on the mousemove event.
821
         * @method handleMouseMove
822
         * @param {Event} e the event
823
         * @private
824
         * @static
825
         */
826
        handleMouseMove: function(e) {
827
            //YAHOO.log("handlemousemove");
828
829
            var dc = this.dragCurrent;
830
            if (dc) {
831
                // YAHOO.log("no current drag obj");
832
833
                // var button = e.which || e.button;
834
                // YAHOO.log("which: " + e.which + ", button: "+ e.button);
835
836
                // check for IE mouseup outside of page boundary
837
                if (YAHOO.util.Event.isIE && !e.button) {
838
                    YAHOO.log("button failure", "info", "DragDropMgr");
839
                    this.stopEvent(e);
840
                    return this.handleMouseUp(e);
841
                } else {
842
                    if (e.clientX < 0 || e.clientY < 0) {
843
                        //This will stop the element from leaving the viewport in FF, Opera & Safari
844
                        //Not turned on yet
845
                        //YAHOO.log("Either clientX or clientY is negative, stop the event.", "info", "DragDropMgr");
846
                        //this.stopEvent(e);
847
                        //return false;
848
                    }
849
                }
850
851
                if (!this.dragThreshMet) {
852
                    var diffX = Math.abs(this.startX - YAHOO.util.Event.getPageX(e));
853
                    var diffY = Math.abs(this.startY - YAHOO.util.Event.getPageY(e));
854
                    // YAHOO.log("diffX: " + diffX + "diffY: " + diffY);
855
                    if (diffX > this.clickPixelThresh || 
856
                                diffY > this.clickPixelThresh) {
857
                        YAHOO.log("pixel threshold met", "info", "DragDropMgr");
858
                        this.startDrag(this.startX, this.startY);
859
                    }
860
                }
861
862
                if (this.dragThreshMet) {
863
                    if (dc && dc.events.b4Drag) {
864
                        dc.b4Drag(e);
865
                        dc.fireEvent('b4DragEvent', { e: e});
866
                    }
867
                    if (dc && dc.events.drag) {
868
                        dc.onDrag(e);
869
                        dc.fireEvent('dragEvent', { e: e});
870
                    }
871
                    if (dc) {
872
                        this.fireEvents(e, false);
873
                    }
874
                }
875
876
                this.stopEvent(e);
877
            }
878
        },
879
        
880
        /**
881
         * Iterates over all of the DragDrop elements to find ones we are 
882
         * hovering over or dropping on
883
         * @method fireEvents
884
         * @param {Event} e the event
885
         * @param {boolean} isDrop is this a drop op or a mouseover op?
886
         * @private
887
         * @static
888
         */
889
        fireEvents: function(e, isDrop) {
890
            var dc = this.dragCurrent;
891
892
            // If the user did the mouse up outside of the window, we could 
893
            // get here even though we have ended the drag.
894
            // If the config option dragOnly is true, bail out and don't fire the events
895
            if (!dc || dc.isLocked() || dc.dragOnly) {
896
                return;
897
            }
898
899
            var x = YAHOO.util.Event.getPageX(e),
900
                y = YAHOO.util.Event.getPageY(e),
901
                pt = new YAHOO.util.Point(x,y),
902
                pos = dc.getTargetCoord(pt.x, pt.y),
903
                el = dc.getDragEl(),
904
                events = ['out', 'over', 'drop', 'enter'],
905
                curRegion = new YAHOO.util.Region( pos.y, 
906
                                               pos.x + el.offsetWidth,
907
                                               pos.y + el.offsetHeight, 
908
                                               pos.x ),
909
            
910
                oldOvers = [], // cache the previous dragOver array
911
                inGroupsObj  = {},
912
                inGroups  = [],
913
                data = {
914
                    outEvts: [],
915
                    overEvts: [],
916
                    dropEvts: [],
917
                    enterEvts: []
918
                };
919
920
921
            // Check to see if the object(s) we were hovering over is no longer 
922
            // being hovered over so we can fire the onDragOut event
923
            for (var i in this.dragOvers) {
924
925
                var ddo = this.dragOvers[i];
926
927
                if (! this.isTypeOfDD(ddo)) {
928
                    continue;
929
                }
930
                if (! this.isOverTarget(pt, ddo, this.mode, curRegion)) {
931
                    data.outEvts.push( ddo );
932
                }
933
934
                oldOvers[i] = true;
935
                delete this.dragOvers[i];
936
            }
937
938
            for (var sGroup in dc.groups) {
939
                // YAHOO.log("Processing group " + sGroup);
940
                
941
                if ("string" != typeof sGroup) {
942
                    continue;
943
                }
944
945
                for (i in this.ids[sGroup]) {
946
                    var oDD = this.ids[sGroup][i];
947
                    if (! this.isTypeOfDD(oDD)) {
948
                        continue;
949
                    }
950
951
                    if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
952
                        if (this.isOverTarget(pt, oDD, this.mode, curRegion)) {
953
                            inGroupsObj[sGroup] = true;
954
                            // look for drop interactions
955
                            if (isDrop) {
956
                                data.dropEvts.push( oDD );
957
                            // look for drag enter and drag over interactions
958
                            } else {
959
960
                                // initial drag over: dragEnter fires
961
                                if (!oldOvers[oDD.id]) {
962
                                    data.enterEvts.push( oDD );
963
                                // subsequent drag overs: dragOver fires
964
                                } else {
965
                                    data.overEvts.push( oDD );
966
                                }
967
968
                                this.dragOvers[oDD.id] = oDD;
969
                            }
970
                        }
971
                    }
972
                }
973
            }
974
975
            this.interactionInfo = {
976
                out:       data.outEvts,
977
                enter:     data.enterEvts,
978
                over:      data.overEvts,
979
                drop:      data.dropEvts,
980
                point:     pt,
981
                draggedRegion:    curRegion,
982
                sourceRegion: this.locationCache[dc.id],
983
                validDrop: isDrop
984
            };
985
986
            
987
            for (var inG in inGroupsObj) {
988
                inGroups.push(inG);
989
            }
990
991
            // notify about a drop that did not find a target
992
            if (isDrop && !data.dropEvts.length) {
993
                YAHOO.log(dc.id + " dropped, but not on a target", "info", "DragDropMgr");
994
                this.interactionInfo.validDrop = false;
995
                if (dc.events.invalidDrop) {
996
                    dc.onInvalidDrop(e);
997
                    dc.fireEvent('invalidDropEvent', { e: e });
998
                }
999
            }
1000
            for (i = 0; i < events.length; i++) {
1001
                var tmp = null;
1002
                if (data[events[i] + 'Evts']) {
1003
                    tmp = data[events[i] + 'Evts'];
1004
                }
1005
                if (tmp && tmp.length) {
1006
                    var type = events[i].charAt(0).toUpperCase() + events[i].substr(1),
1007
                        ev = 'onDrag' + type,
1008
                        b4 = 'b4Drag' + type,
1009
                        cev = 'drag' + type + 'Event',
1010
                        check = 'drag' + type;
1011
                    if (this.mode) {
1012
                        YAHOO.log(dc.id + ' ' + ev + ': ' + tmp, "info", "DragDropMgr");
1013
                        if (dc.events[b4]) {
1014
                            dc[b4](e, tmp, inGroups);
1015
                            dc.fireEvent(b4 + 'Event', { event: e, info: tmp, group: inGroups });
1016
                            
1017
                        }
1018
                        if (dc.events[check]) {
1019
                            dc[ev](e, tmp, inGroups);
1020
                            dc.fireEvent(cev, { event: e, info: tmp, group: inGroups });
1021
                        }
1022
                    } else {
1023
                        for (var b = 0, len = tmp.length; b < len; ++b) {
1024
                            YAHOO.log(dc.id + ' ' + ev + ': ' + tmp[b].id, "info", "DragDropMgr");
1025
                            if (dc.events[b4]) {
1026
                                dc[b4](e, tmp[b].id, inGroups[0]);
1027
                                dc.fireEvent(b4 + 'Event', { event: e, info: tmp[b].id, group: inGroups[0] });
1028
                            }
1029
                            if (dc.events[check]) {
1030
                                dc[ev](e, tmp[b].id, inGroups[0]);
1031
                                dc.fireEvent(cev, { event: e, info: tmp[b].id, group: inGroups[0] });
1032
                            }
1033
                        }
1034
                    }
1035
                }
1036
            }
1037
        },
1038
1039
        /**
1040
         * Helper function for getting the best match from the list of drag 
1041
         * and drop objects returned by the drag and drop events when we are 
1042
         * in INTERSECT mode.  It returns either the first object that the 
1043
         * cursor is over, or the object that has the greatest overlap with 
1044
         * the dragged element.
1045
         * @method getBestMatch
1046
         * @param  {DragDrop[]} dds The array of drag and drop objects 
1047
         * targeted
1048
         * @return {DragDrop}       The best single match
1049
         * @static
1050
         */
1051
        getBestMatch: function(dds) {
1052
            var winner = null;
1053
1054
            var len = dds.length;
1055
1056
            if (len == 1) {
1057
                winner = dds[0];
1058
            } else {
1059
                // Loop through the targeted items
1060
                for (var i=0; i<len; ++i) {
1061
                    var dd = dds[i];
1062
                    // If the cursor is over the object, it wins.  If the 
1063
                    // cursor is over multiple matches, the first one we come
1064
                    // to wins.
1065
                    if (this.mode == this.INTERSECT && dd.cursorIsOver) {
1066
                        winner = dd;
1067
                        break;
1068
                    // Otherwise the object with the most overlap wins
1069
                    } else {
1070
                        if (!winner || !winner.overlap || (dd.overlap &&
1071
                            winner.overlap.getArea() < dd.overlap.getArea())) {
1072
                            winner = dd;
1073
                        }
1074
                    }
1075
                }
1076
            }
1077
1078
            return winner;
1079
        },
1080
1081
        /**
1082
         * Refreshes the cache of the top-left and bottom-right points of the 
1083
         * drag and drop objects in the specified group(s).  This is in the
1084
         * format that is stored in the drag and drop instance, so typical 
1085
         * usage is:
1086
         * <code>
1087
         * YAHOO.util.DragDropMgr.refreshCache(ddinstance.groups);
1088
         * </code>
1089
         * Alternatively:
1090
         * <code>
1091
         * YAHOO.util.DragDropMgr.refreshCache({group1:true, group2:true});
1092
         * </code>
1093
         * @TODO this really should be an indexed array.  Alternatively this
1094
         * method could accept both.
1095
         * @method refreshCache
1096
         * @param {Object} groups an associative array of groups to refresh
1097
         * @static
1098
         */
1099
        refreshCache: function(groups) {
1100
            YAHOO.log("refreshing element location cache", "info", "DragDropMgr");
1101
1102
            // refresh everything if group array is not provided
1103
            var g = groups || this.ids;
1104
1105
            for (var sGroup in g) {
1106
                if ("string" != typeof sGroup) {
1107
                    continue;
1108
                }
1109
                for (var i in this.ids[sGroup]) {
1110
                    var oDD = this.ids[sGroup][i];
1111
1112
                    if (this.isTypeOfDD(oDD)) {
1113
                        var loc = this.getLocation(oDD);
1114
                        if (loc) {
1115
                            this.locationCache[oDD.id] = loc;
1116
                        } else {
1117
                            delete this.locationCache[oDD.id];
1118
YAHOO.log("Could not get the loc for " + oDD.id, "warn", "DragDropMgr");
1119
                        }
1120
                    }
1121
                }
1122
            }
1123
        },
1124
1125
        /**
1126
         * This checks to make sure an element exists and is in the DOM.  The
1127
         * main purpose is to handle cases where innerHTML is used to remove
1128
         * drag and drop objects from the DOM.  IE provides an 'unspecified
1129
         * error' when trying to access the offsetParent of such an element
1130
         * @method verifyEl
1131
         * @param {HTMLElement} el the element to check
1132
         * @return {boolean} true if the element looks usable
1133
         * @static
1134
         */
1135
        verifyEl: function(el) {
1136
            try {
1137
                if (el) {
1138
                    var parent = el.offsetParent;
1139
                    if (parent) {
1140
                        return true;
1141
                    }
1142
                }
1143
            } catch(e) {
1144
                YAHOO.log("detected problem with an element", "info", "DragDropMgr");
1145
            }
1146
1147
            return false;
1148
        },
1149
        
1150
        /**
1151
         * Returns a Region object containing the drag and drop element's position
1152
         * and size, including the padding configured for it
1153
         * @method getLocation
1154
         * @param {DragDrop} oDD the drag and drop object to get the 
1155
         *                       location for
1156
         * @return {YAHOO.util.Region} a Region object representing the total area
1157
         *                             the element occupies, including any padding
1158
         *                             the instance is configured for.
1159
         * @static
1160
         */
1161
        getLocation: function(oDD) {
1162
            if (! this.isTypeOfDD(oDD)) {
1163
                YAHOO.log(oDD + " is not a DD obj", "info", "DragDropMgr");
1164
                return null;
1165
            }
1166
1167
            var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
1168
1169
            try {
1170
                pos= YAHOO.util.Dom.getXY(el);
1171
            } catch (e) { }
1172
1173
            if (!pos) {
1174
                YAHOO.log("getXY failed", "info", "DragDropMgr");
1175
                return null;
1176
            }
1177
1178
            x1 = pos[0];
1179
            x2 = x1 + el.offsetWidth;
1180
            y1 = pos[1];
1181
            y2 = y1 + el.offsetHeight;
1182
1183
            t = y1 - oDD.padding[0];
1184
            r = x2 + oDD.padding[1];
1185
            b = y2 + oDD.padding[2];
1186
            l = x1 - oDD.padding[3];
1187
1188
            return new YAHOO.util.Region( t, r, b, l );
1189
        },
1190
1191
        /**
1192
         * Checks the cursor location to see if it over the target
1193
         * @method isOverTarget
1194
         * @param {YAHOO.util.Point} pt The point to evaluate
1195
         * @param {DragDrop} oTarget the DragDrop object we are inspecting
1196
         * @param {boolean} intersect true if we are in intersect mode
1197
         * @param {YAHOO.util.Region} pre-cached location of the dragged element
1198
         * @return {boolean} true if the mouse is over the target
1199
         * @private
1200
         * @static
1201
         */
1202
        isOverTarget: function(pt, oTarget, intersect, curRegion) {
1203
            // use cache if available
1204
            var loc = this.locationCache[oTarget.id];
1205
            if (!loc || !this.useCache) {
1206
                YAHOO.log("cache not populated", "info", "DragDropMgr");
1207
                loc = this.getLocation(oTarget);
1208
                this.locationCache[oTarget.id] = loc;
1209
1210
                YAHOO.log("cache: " + loc, "info", "DragDropMgr");
1211
            }
1212
1213
            if (!loc) {
1214
                YAHOO.log("could not get the location of the element", "info", "DragDropMgr");
1215
                return false;
1216
            }
1217
1218
            //YAHOO.log("loc: " + loc + ", pt: " + pt);
1219
            oTarget.cursorIsOver = loc.contains( pt );
1220
1221
            // DragDrop is using this as a sanity check for the initial mousedown
1222
            // in this case we are done.  In POINT mode, if the drag obj has no
1223
            // contraints, we are done. Otherwise we need to evaluate the 
1224
            // region the target as occupies to determine if the dragged element
1225
            // overlaps with it.
1226
            
1227
            var dc = this.dragCurrent;
1228
            if (!dc || (!intersect && !dc.constrainX && !dc.constrainY)) {
1229
1230
                //if (oTarget.cursorIsOver) {
1231
                    //YAHOO.log("over " + oTarget + ", " + loc + ", " + pt, "warn");
1232
                //}
1233
                return oTarget.cursorIsOver;
1234
            }
1235
1236
            oTarget.overlap = null;
1237
1238
1239
            // Get the current location of the drag element, this is the
1240
            // location of the mouse event less the delta that represents
1241
            // where the original mousedown happened on the element.  We
1242
            // need to consider constraints and ticks as well.
1243
1244
            if (!curRegion) {
1245
                var pos = dc.getTargetCoord(pt.x, pt.y);
1246
                var el = dc.getDragEl();
1247
                curRegion = new YAHOO.util.Region( pos.y, 
1248
                                                   pos.x + el.offsetWidth,
1249
                                                   pos.y + el.offsetHeight, 
1250
                                                   pos.x );
1251
            }
1252
1253
            var overlap = curRegion.intersect(loc);
1254
1255
            if (overlap) {
1256
                oTarget.overlap = overlap;
1257
                return (intersect) ? true : oTarget.cursorIsOver;
1258
            } else {
1259
                return false;
1260
            }
1261
        },
1262
1263
        /**
1264
         * unload event handler
1265
         * @method _onUnload
1266
         * @private
1267
         * @static
1268
         */
1269
        _onUnload: function(e, me) {
1270
            this.unregAll();
1271
        },
1272
1273
        /**
1274
         * Cleans up the drag and drop events and objects.
1275
         * @method unregAll
1276
         * @private
1277
         * @static
1278
         */
1279
        unregAll: function() {
1280
            YAHOO.log("unregister all", "info", "DragDropMgr");
1281
1282
            if (this.dragCurrent) {
1283
                this.stopDrag();
1284
                this.dragCurrent = null;
1285
            }
1286
1287
            this._execOnAll("unreg", []);
1288
1289
            //for (var i in this.elementCache) {
1290
                //delete this.elementCache[i];
1291
            //}
1292
            //this.elementCache = {};
1293
1294
            this.ids = {};
1295
        },
1296
1297
        /**
1298
         * A cache of DOM elements
1299
         * @property elementCache
1300
         * @private
1301
         * @static
1302
         * @deprecated elements are not cached now
1303
         */
1304
        elementCache: {},
1305
        
1306
        /**
1307
         * Get the wrapper for the DOM element specified
1308
         * @method getElWrapper
1309
         * @param {String} id the id of the element to get
1310
         * @return {YAHOO.util.DDM.ElementWrapper} the wrapped element
1311
         * @private
1312
         * @deprecated This wrapper isn't that useful
1313
         * @static
1314
         */
1315
        getElWrapper: function(id) {
1316
            var oWrapper = this.elementCache[id];
1317
            if (!oWrapper || !oWrapper.el) {
1318
                oWrapper = this.elementCache[id] = 
1319
                    new this.ElementWrapper(YAHOO.util.Dom.get(id));
1320
            }
1321
            return oWrapper;
1322
        },
1323
1324
        /**
1325
         * Returns the actual DOM element
1326
         * @method getElement
1327
         * @param {String} id the id of the elment to get
1328
         * @return {Object} The element
1329
         * @deprecated use YAHOO.util.Dom.get instead
1330
         * @static
1331
         */
1332
        getElement: function(id) {
1333
            return YAHOO.util.Dom.get(id);
1334
        },
1335
        
1336
        /**
1337
         * Returns the style property for the DOM element (i.e., 
1338
         * document.getElById(id).style)
1339
         * @method getCss
1340
         * @param {String} id the id of the elment to get
1341
         * @return {Object} The style property of the element
1342
         * @deprecated use YAHOO.util.Dom instead
1343
         * @static
1344
         */
1345
        getCss: function(id) {
1346
            var el = YAHOO.util.Dom.get(id);
1347
            return (el) ? el.style : null;
1348
        },
1349
1350
        /**
1351
         * Inner class for cached elements
1352
         * @class DragDropMgr.ElementWrapper
1353
         * @for DragDropMgr
1354
         * @private
1355
         * @deprecated
1356
         */
1357
        ElementWrapper: function(el) {
1358
                /**
1359
                 * The element
1360
                 * @property el
1361
                 */
1362
                this.el = el || null;
1363
                /**
1364
                 * The element id
1365
                 * @property id
1366
                 */
1367
                this.id = this.el && el.id;
1368
                /**
1369
                 * A reference to the style property
1370
                 * @property css
1371
                 */
1372
                this.css = this.el && el.style;
1373
            },
1374
1375
        /**
1376
         * Returns the X position of an html element
1377
         * @method getPosX
1378
         * @param el the element for which to get the position
1379
         * @return {int} the X coordinate
1380
         * @for DragDropMgr
1381
         * @deprecated use YAHOO.util.Dom.getX instead
1382
         * @static
1383
         */
1384
        getPosX: function(el) {
1385
            return YAHOO.util.Dom.getX(el);
1386
        },
1387
1388
        /**
1389
         * Returns the Y position of an html element
1390
         * @method getPosY
1391
         * @param el the element for which to get the position
1392
         * @return {int} the Y coordinate
1393
         * @deprecated use YAHOO.util.Dom.getY instead
1394
         * @static
1395
         */
1396
        getPosY: function(el) {
1397
            return YAHOO.util.Dom.getY(el); 
1398
        },
1399
1400
        /**
1401
         * Swap two nodes.  In IE, we use the native method, for others we 
1402
         * emulate the IE behavior
1403
         * @method swapNode
1404
         * @param n1 the first node to swap
1405
         * @param n2 the other node to swap
1406
         * @static
1407
         */
1408
        swapNode: function(n1, n2) {
1409
            if (n1.swapNode) {
1410
                n1.swapNode(n2);
1411
            } else {
1412
                var p = n2.parentNode;
1413
                var s = n2.nextSibling;
1414
1415
                if (s == n1) {
1416
                    p.insertBefore(n1, n2);
1417
                } else if (n2 == n1.nextSibling) {
1418
                    p.insertBefore(n2, n1);
1419
                } else {
1420
                    n1.parentNode.replaceChild(n2, n1);
1421
                    p.insertBefore(n1, s);
1422
                }
1423
            }
1424
        },
1425
1426
        /**
1427
         * Returns the current scroll position
1428
         * @method getScroll
1429
         * @private
1430
         * @static
1431
         */
1432
        getScroll: function () {
1433
            var t, l, dde=document.documentElement, db=document.body;
1434
            if (dde && (dde.scrollTop || dde.scrollLeft)) {
1435
                t = dde.scrollTop;
1436
                l = dde.scrollLeft;
1437
            } else if (db) {
1438
                t = db.scrollTop;
1439
                l = db.scrollLeft;
1440
            } else {
1441
                YAHOO.log("could not get scroll property", "info", "DragDropMgr");
1442
            }
1443
            return { top: t, left: l };
1444
        },
1445
1446
        /**
1447
         * Returns the specified element style property
1448
         * @method getStyle
1449
         * @param {HTMLElement} el          the element
1450
         * @param {string}      styleProp   the style property
1451
         * @return {string} The value of the style property
1452
         * @deprecated use YAHOO.util.Dom.getStyle
1453
         * @static
1454
         */
1455
        getStyle: function(el, styleProp) {
1456
            return YAHOO.util.Dom.getStyle(el, styleProp);
1457
        },
1458
1459
        /**
1460
         * Gets the scrollTop
1461
         * @method getScrollTop
1462
         * @return {int} the document's scrollTop
1463
         * @static
1464
         */
1465
        getScrollTop: function () { return this.getScroll().top; },
1466
1467
        /**
1468
         * Gets the scrollLeft
1469
         * @method getScrollLeft
1470
         * @return {int} the document's scrollTop
1471
         * @static
1472
         */
1473
        getScrollLeft: function () { return this.getScroll().left; },
1474
1475
        /**
1476
         * Sets the x/y position of an element to the location of the
1477
         * target element.
1478
         * @method moveToEl
1479
         * @param {HTMLElement} moveEl      The element to move
1480
         * @param {HTMLElement} targetEl    The position reference element
1481
         * @static
1482
         */
1483
        moveToEl: function (moveEl, targetEl) {
1484
            var aCoord = YAHOO.util.Dom.getXY(targetEl);
1485
            YAHOO.log("moveToEl: " + aCoord, "info", "DragDropMgr");
1486
            YAHOO.util.Dom.setXY(moveEl, aCoord);
1487
        },
1488
1489
        /**
1490
         * Gets the client height
1491
         * @method getClientHeight
1492
         * @return {int} client height in px
1493
         * @deprecated use YAHOO.util.Dom.getViewportHeight instead
1494
         * @static
1495
         */
1496
        getClientHeight: function() {
1497
            return YAHOO.util.Dom.getViewportHeight();
1498
        },
1499
1500
        /**
1501
         * Gets the client width
1502
         * @method getClientWidth
1503
         * @return {int} client width in px
1504
         * @deprecated use YAHOO.util.Dom.getViewportWidth instead
1505
         * @static
1506
         */
1507
        getClientWidth: function() {
1508
            return YAHOO.util.Dom.getViewportWidth();
1509
        },
1510
1511
        /**
1512
         * Numeric array sort function
1513
         * @method numericSort
1514
         * @static
1515
         */
1516
        numericSort: function(a, b) { return (a - b); },
1517
1518
        /**
1519
         * Internal counter
1520
         * @property _timeoutCount
1521
         * @private
1522
         * @static
1523
         */
1524
        _timeoutCount: 0,
1525
1526
        /**
1527
         * Trying to make the load order less important.  Without this we get
1528
         * an error if this file is loaded before the Event Utility.
1529
         * @method _addListeners
1530
         * @private
1531
         * @static
1532
         */
1533
        _addListeners: function() {
1534
            var DDM = YAHOO.util.DDM;
1535
            if ( YAHOO.util.Event && document ) {
1536
                DDM._onLoad();
1537
            } else {
1538
                if (DDM._timeoutCount > 2000) {
1539
                    YAHOO.log("DragDrop requires the Event Utility", "error", "DragDropMgr");
1540
                } else {
1541
                    setTimeout(DDM._addListeners, 10);
1542
                    if (document && document.body) {
1543
                        DDM._timeoutCount += 1;
1544
                    }
1545
                }
1546
            }
1547
        },
1548
1549
        /**
1550
         * Recursively searches the immediate parent and all child nodes for 
1551
         * the handle element in order to determine wheter or not it was 
1552
         * clicked.
1553
         * @method handleWasClicked
1554
         * @param node the html element to inspect
1555
         * @static
1556
         */
1557
        handleWasClicked: function(node, id) {
1558
            if (this.isHandle(id, node.id)) {
1559
                YAHOO.log("clicked node is a handle", "info", "DragDropMgr");
1560
                return true;
1561
            } else {
1562
                // check to see if this is a text node child of the one we want
1563
                var p = node.parentNode;
1564
                // YAHOO.log("p: " + p);
1565
1566
                while (p) {
1567
                    if (this.isHandle(id, p.id)) {
1568
                        return true;
1569
                    } else {
1570
                        YAHOO.log(p.id + " is not a handle", "info", "DragDropMgr");
1571
                        p = p.parentNode;
1572
                    }
1573
                }
1574
            }
1575
1576
            return false;
1577
        }
1578
1579
    };
1580
1581
}();
1582
1583
// shorter alias, save a few bytes
1584
YAHOO.util.DDM = YAHOO.util.DragDropMgr;
1585
YAHOO.util.DDM._addListeners();
1586
1587
}
1588
1589
(function() {
1590
1591
var Event=YAHOO.util.Event; 
1592
var Dom=YAHOO.util.Dom;
1593
1594
/**
1595
 * Defines the interface and base operation of items that that can be 
1596
 * dragged or can be drop targets.  It was designed to be extended, overriding
1597
 * the event handlers for startDrag, onDrag, onDragOver, onDragOut.
1598
 * Up to three html elements can be associated with a DragDrop instance:
1599
 * <ul>
1600
 * <li>linked element: the element that is passed into the constructor.
1601
 * This is the element which defines the boundaries for interaction with 
1602
 * other DragDrop objects.</li>
1603
 * <li>handle element(s): The drag operation only occurs if the element that 
1604
 * was clicked matches a handle element.  By default this is the linked 
1605
 * element, but there are times that you will want only a portion of the 
1606
 * linked element to initiate the drag operation, and the setHandleElId() 
1607
 * method provides a way to define this.</li>
1608
 * <li>drag element: this represents an the element that would be moved along
1609
 * with the cursor during a drag operation.  By default, this is the linked
1610
 * element itself as in {@link YAHOO.util.DD}.  setDragElId() lets you define
1611
 * a separate element that would be moved, as in {@link YAHOO.util.DDProxy}
1612
 * </li>
1613
 * </ul>
1614
 * This class should not be instantiated until the onload event to ensure that
1615
 * the associated elements are available.
1616
 * The following would define a DragDrop obj that would interact with any 
1617
 * other DragDrop obj in the "group1" group:
1618
 * <pre>
1619
 *  dd = new YAHOO.util.DragDrop("div1", "group1");
1620
 * </pre>
1621
 * Since none of the event handlers have been implemented, nothing would 
1622
 * actually happen if you were to run the code above.  Normally you would 
1623
 * override this class or one of the default implementations, but you can 
1624
 * also override the methods you want on an instance of the class...
1625
 * <pre>
1626
 *  dd.onDragDrop = function(e, id) {
1627
 *  &nbsp;&nbsp;alert("dd was dropped on " + id);
1628
 *  }
1629
 * </pre>
1630
 * @namespace YAHOO.util
1631
 * @class DragDrop
1632
 * @constructor
1633
 * @param {String} id of the element that is linked to this instance
1634
 * @param {String} sGroup the group of related DragDrop objects
1635
 * @param {object} config an object containing configurable attributes
1636
 *                Valid properties for DragDrop: 
1637
 *                    padding, isTarget, maintainOffset, primaryButtonOnly,
1638
 */
1639
YAHOO.util.DragDrop = function(id, sGroup, config) {
1640
    if (id) {
1641
        this.init(id, sGroup, config); 
1642
    }
1643
};
1644
1645
YAHOO.util.DragDrop.prototype = {
1646
    /**
1647
     * An Object Literal containing the events that we will be using: mouseDown, b4MouseDown, mouseUp, b4StartDrag, startDrag, b4EndDrag, endDrag, mouseUp, drag, b4Drag, invalidDrop, b4DragOut, dragOut, dragEnter, b4DragOver, dragOver, b4DragDrop, dragDrop
1648
     * By setting any of these to false, then event will not be fired.
1649
     * @property events
1650
     * @type object
1651
     */
1652
    events: null,
1653
    /**
1654
    * @method on
1655
    * @description Shortcut for EventProvider.subscribe, see <a href="YAHOO.util.EventProvider.html#subscribe">YAHOO.util.EventProvider.subscribe</a>
1656
    */
1657
    on: function() {
1658
        this.subscribe.apply(this, arguments);
1659
    },
1660
    /**
1661
     * The id of the element associated with this object.  This is what we 
1662
     * refer to as the "linked element" because the size and position of 
1663
     * this element is used to determine when the drag and drop objects have 
1664
     * interacted.
1665
     * @property id
1666
     * @type String
1667
     */
1668
    id: null,
1669
1670
    /**
1671
     * Configuration attributes passed into the constructor
1672
     * @property config
1673
     * @type object
1674
     */
1675
    config: null,
1676
1677
    /**
1678
     * The id of the element that will be dragged.  By default this is same 
1679
     * as the linked element , but could be changed to another element. Ex: 
1680
     * YAHOO.util.DDProxy
1681
     * @property dragElId
1682
     * @type String
1683
     * @private
1684
     */
1685
    dragElId: null, 
1686
1687
    /**
1688
     * the id of the element that initiates the drag operation.  By default 
1689
     * this is the linked element, but could be changed to be a child of this
1690
     * element.  This lets us do things like only starting the drag when the 
1691
     * header element within the linked html element is clicked.
1692
     * @property handleElId
1693
     * @type String
1694
     * @private
1695
     */
1696
    handleElId: null, 
1697
1698
    /**
1699
     * An associative array of HTML tags that will be ignored if clicked.
1700
     * @property invalidHandleTypes
1701
     * @type {string: string}
1702
     */
1703
    invalidHandleTypes: null, 
1704
1705
    /**
1706
     * An associative array of ids for elements that will be ignored if clicked
1707
     * @property invalidHandleIds
1708
     * @type {string: string}
1709
     */
1710
    invalidHandleIds: null, 
1711
1712
    /**
1713
     * An indexted array of css class names for elements that will be ignored
1714
     * if clicked.
1715
     * @property invalidHandleClasses
1716
     * @type string[]
1717
     */
1718
    invalidHandleClasses: null, 
1719
1720
    /**
1721
     * The linked element's absolute X position at the time the drag was 
1722
     * started
1723
     * @property startPageX
1724
     * @type int
1725
     * @private
1726
     */
1727
    startPageX: 0,
1728
1729
    /**
1730
     * The linked element's absolute X position at the time the drag was 
1731
     * started
1732
     * @property startPageY
1733
     * @type int
1734
     * @private
1735
     */
1736
    startPageY: 0,
1737
1738
    /**
1739
     * The group defines a logical collection of DragDrop objects that are 
1740
     * related.  Instances only get events when interacting with other 
1741
     * DragDrop object in the same group.  This lets us define multiple 
1742
     * groups using a single DragDrop subclass if we want.
1743
     * @property groups
1744
     * @type {string: string}
1745
     */
1746
    groups: null,
1747
1748
    /**
1749
     * Individual drag/drop instances can be locked.  This will prevent 
1750
     * onmousedown start drag.
1751
     * @property locked
1752
     * @type boolean
1753
     * @private
1754
     */
1755
    locked: false,
1756
1757
    /**
1758
     * Lock this instance
1759
     * @method lock
1760
     */
1761
    lock: function() { this.locked = true; },
1762
1763
    /**
1764
     * Unlock this instace
1765
     * @method unlock
1766
     */
1767
    unlock: function() { this.locked = false; },
1768
1769
    /**
1770
     * By default, all instances can be a drop target.  This can be disabled by
1771
     * setting isTarget to false.
1772
     * @property isTarget
1773
     * @type boolean
1774
     */
1775
    isTarget: true,
1776
1777
    /**
1778
     * The padding configured for this drag and drop object for calculating
1779
     * the drop zone intersection with this object.
1780
     * @property padding
1781
     * @type int[]
1782
     */
1783
    padding: null,
1784
    /**
1785
     * If this flag is true, do not fire drop events. The element is a drag only element (for movement not dropping)
1786
     * @property dragOnly
1787
     * @type Boolean
1788
     */
1789
    dragOnly: false,
1790
1791
    /**
1792
     * If this flag is true, a shim will be placed over the screen/viewable area to track mouse events. Should help with dragging elements over iframes and other controls.
1793
     * @property useShim
1794
     * @type Boolean
1795
     */
1796
    useShim: false,
1797
1798
    /**
1799
     * Cached reference to the linked element
1800
     * @property _domRef
1801
     * @private
1802
     */
1803
    _domRef: null,
1804
1805
    /**
1806
     * Internal typeof flag
1807
     * @property __ygDragDrop
1808
     * @private
1809
     */
1810
    __ygDragDrop: true,
1811
1812
    /**
1813
     * Set to true when horizontal contraints are applied
1814
     * @property constrainX
1815
     * @type boolean
1816
     * @private
1817
     */
1818
    constrainX: false,
1819
1820
    /**
1821
     * Set to true when vertical contraints are applied
1822
     * @property constrainY
1823
     * @type boolean
1824
     * @private
1825
     */
1826
    constrainY: false,
1827
1828
    /**
1829
     * The left constraint
1830
     * @property minX
1831
     * @type int
1832
     * @private
1833
     */
1834
    minX: 0,
1835
1836
    /**
1837
     * The right constraint
1838
     * @property maxX
1839
     * @type int
1840
     * @private
1841
     */
1842
    maxX: 0,
1843
1844
    /**
1845
     * The up constraint 
1846
     * @property minY
1847
     * @type int
1848
     * @type int
1849
     * @private
1850
     */
1851
    minY: 0,
1852
1853
    /**
1854
     * The down constraint 
1855
     * @property maxY
1856
     * @type int
1857
     * @private
1858
     */
1859
    maxY: 0,
1860
1861
    /**
1862
     * The difference between the click position and the source element's location
1863
     * @property deltaX
1864
     * @type int
1865
     * @private
1866
     */
1867
    deltaX: 0,
1868
1869
    /**
1870
     * The difference between the click position and the source element's location
1871
     * @property deltaY
1872
     * @type int
1873
     * @private
1874
     */
1875
    deltaY: 0,
1876
1877
    /**
1878
     * Maintain offsets when we resetconstraints.  Set to true when you want
1879
     * the position of the element relative to its parent to stay the same
1880
     * when the page changes
1881
     *
1882
     * @property maintainOffset
1883
     * @type boolean
1884
     */
1885
    maintainOffset: false,
1886
1887
    /**
1888
     * Array of pixel locations the element will snap to if we specified a 
1889
     * horizontal graduation/interval.  This array is generated automatically
1890
     * when you define a tick interval.
1891
     * @property xTicks
1892
     * @type int[]
1893
     */
1894
    xTicks: null,
1895
1896
    /**
1897
     * Array of pixel locations the element will snap to if we specified a 
1898
     * vertical graduation/interval.  This array is generated automatically 
1899
     * when you define a tick interval.
1900
     * @property yTicks
1901
     * @type int[]
1902
     */
1903
    yTicks: null,
1904
1905
    /**
1906
     * By default the drag and drop instance will only respond to the primary
1907
     * button click (left button for a right-handed mouse).  Set to true to
1908
     * allow drag and drop to start with any mouse click that is propogated
1909
     * by the browser
1910
     * @property primaryButtonOnly
1911
     * @type boolean
1912
     */
1913
    primaryButtonOnly: true,
1914
1915
    /**
1916
     * The availabe property is false until the linked dom element is accessible.
1917
     * @property available
1918
     * @type boolean
1919
     */
1920
    available: false,
1921
1922
    /**
1923
     * By default, drags can only be initiated if the mousedown occurs in the
1924
     * region the linked element is.  This is done in part to work around a
1925
     * bug in some browsers that mis-report the mousedown if the previous
1926
     * mouseup happened outside of the window.  This property is set to true
1927
     * if outer handles are defined.
1928
     *
1929
     * @property hasOuterHandles
1930
     * @type boolean
1931
     * @default false
1932
     */
1933
    hasOuterHandles: false,
1934
1935
    /**
1936
     * Property that is assigned to a drag and drop object when testing to
1937
     * see if it is being targeted by another dd object.  This property
1938
     * can be used in intersect mode to help determine the focus of
1939
     * the mouse interaction.  DDM.getBestMatch uses this property first to
1940
     * determine the closest match in INTERSECT mode when multiple targets
1941
     * are part of the same interaction.
1942
     * @property cursorIsOver
1943
     * @type boolean
1944
     */
1945
    cursorIsOver: false,
1946
1947
    /**
1948
     * Property that is assigned to a drag and drop object when testing to
1949
     * see if it is being targeted by another dd object.  This is a region
1950
     * that represents the area the draggable element overlaps this target.
1951
     * DDM.getBestMatch uses this property to compare the size of the overlap
1952
     * to that of other targets in order to determine the closest match in
1953
     * INTERSECT mode when multiple targets are part of the same interaction.
1954
     * @property overlap 
1955
     * @type YAHOO.util.Region
1956
     */
1957
    overlap: null,
1958
1959
    /**
1960
     * Code that executes immediately before the startDrag event
1961
     * @method b4StartDrag
1962
     * @private
1963
     */
1964
    b4StartDrag: function(x, y) { },
1965
1966
    /**
1967
     * Abstract method called after a drag/drop object is clicked
1968
     * and the drag or mousedown time thresholds have beeen met.
1969
     * @method startDrag
1970
     * @param {int} X click location
1971
     * @param {int} Y click location
1972
     */
1973
    startDrag: function(x, y) { /* override this */ },
1974
1975
    /**
1976
     * Code that executes immediately before the onDrag event
1977
     * @method b4Drag
1978
     * @private
1979
     */
1980
    b4Drag: function(e) { },
1981
1982
    /**
1983
     * Abstract method called during the onMouseMove event while dragging an 
1984
     * object.
1985
     * @method onDrag
1986
     * @param {Event} e the mousemove event
1987
     */
1988
    onDrag: function(e) { /* override this */ },
1989
1990
    /**
1991
     * Abstract method called when this element fist begins hovering over 
1992
     * another DragDrop obj
1993
     * @method onDragEnter
1994
     * @param {Event} e the mousemove event
1995
     * @param {String|DragDrop[]} id In POINT mode, the element
1996
     * id this is hovering over.  In INTERSECT mode, an array of one or more 
1997
     * dragdrop items being hovered over.
1998
     */
1999
    onDragEnter: function(e, id) { /* override this */ },
2000
2001
    /**
2002
     * Code that executes immediately before the onDragOver event
2003
     * @method b4DragOver
2004
     * @private
2005
     */
2006
    b4DragOver: function(e) { },
2007
2008
    /**
2009
     * Abstract method called when this element is hovering over another 
2010
     * DragDrop obj
2011
     * @method onDragOver
2012
     * @param {Event} e the mousemove event
2013
     * @param {String|DragDrop[]} id In POINT mode, the element
2014
     * id this is hovering over.  In INTERSECT mode, an array of dd items 
2015
     * being hovered over.
2016
     */
2017
    onDragOver: function(e, id) { /* override this */ },
2018
2019
    /**
2020
     * Code that executes immediately before the onDragOut event
2021
     * @method b4DragOut
2022
     * @private
2023
     */
2024
    b4DragOut: function(e) { },
2025
2026
    /**
2027
     * Abstract method called when we are no longer hovering over an element
2028
     * @method onDragOut
2029
     * @param {Event} e the mousemove event
2030
     * @param {String|DragDrop[]} id In POINT mode, the element
2031
     * id this was hovering over.  In INTERSECT mode, an array of dd items 
2032
     * that the mouse is no longer over.
2033
     */
2034
    onDragOut: function(e, id) { /* override this */ },
2035
2036
    /**
2037
     * Code that executes immediately before the onDragDrop event
2038
     * @method b4DragDrop
2039
     * @private
2040
     */
2041
    b4DragDrop: function(e) { },
2042
2043
    /**
2044
     * Abstract method called when this item is dropped on another DragDrop 
2045
     * obj
2046
     * @method onDragDrop
2047
     * @param {Event} e the mouseup event
2048
     * @param {String|DragDrop[]} id In POINT mode, the element
2049
     * id this was dropped on.  In INTERSECT mode, an array of dd items this 
2050
     * was dropped on.
2051
     */
2052
    onDragDrop: function(e, id) { /* override this */ },
2053
2054
    /**
2055
     * Abstract method called when this item is dropped on an area with no
2056
     * drop target
2057
     * @method onInvalidDrop
2058
     * @param {Event} e the mouseup event
2059
     */
2060
    onInvalidDrop: function(e) { /* override this */ },
2061
2062
    /**
2063
     * Code that executes immediately before the endDrag event
2064
     * @method b4EndDrag
2065
     * @private
2066
     */
2067
    b4EndDrag: function(e) { },
2068
2069
    /**
2070
     * Fired when we are done dragging the object
2071
     * @method endDrag
2072
     * @param {Event} e the mouseup event
2073
     */
2074
    endDrag: function(e) { /* override this */ },
2075
2076
    /**
2077
     * Code executed immediately before the onMouseDown event
2078
     * @method b4MouseDown
2079
     * @param {Event} e the mousedown event
2080
     * @private
2081
     */
2082
    b4MouseDown: function(e) {  },
2083
2084
    /**
2085
     * Event handler that fires when a drag/drop obj gets a mousedown
2086
     * @method onMouseDown
2087
     * @param {Event} e the mousedown event
2088
     */
2089
    onMouseDown: function(e) { /* override this */ },
2090
2091
    /**
2092
     * Event handler that fires when a drag/drop obj gets a mouseup
2093
     * @method onMouseUp
2094
     * @param {Event} e the mouseup event
2095
     */
2096
    onMouseUp: function(e) { /* override this */ },
2097
   
2098
    /**
2099
     * Override the onAvailable method to do what is needed after the initial
2100
     * position was determined.
2101
     * @method onAvailable
2102
     */
2103
    onAvailable: function () { 
2104
        //this.logger.log("onAvailable (base)"); 
2105
    },
2106
2107
    /**
2108
     * Returns a reference to the linked element
2109
     * @method getEl
2110
     * @return {HTMLElement} the html element 
2111
     */
2112
    getEl: function() { 
2113
        if (!this._domRef) {
2114
            this._domRef = Dom.get(this.id); 
2115
        }
2116
2117
        return this._domRef;
2118
    },
2119
2120
    /**
2121
     * Returns a reference to the actual element to drag.  By default this is
2122
     * the same as the html element, but it can be assigned to another 
2123
     * element. An example of this can be found in YAHOO.util.DDProxy
2124
     * @method getDragEl
2125
     * @return {HTMLElement} the html element 
2126
     */
2127
    getDragEl: function() {
2128
        return Dom.get(this.dragElId);
2129
    },
2130
2131
    /**
2132
     * Sets up the DragDrop object.  Must be called in the constructor of any
2133
     * YAHOO.util.DragDrop subclass
2134
     * @method init
2135
     * @param id the id of the linked element
2136
     * @param {String} sGroup the group of related items
2137
     * @param {object} config configuration attributes
2138
     */
2139
    init: function(id, sGroup, config) {
2140
        this.initTarget(id, sGroup, config);
2141
        Event.on(this._domRef || this.id, "mousedown", 
2142
                        this.handleMouseDown, this, true);
2143
2144
        // Event.on(this.id, "selectstart", Event.preventDefault);
2145
        for (var i in this.events) {
2146
            this.createEvent(i + 'Event');
2147
        }
2148
        
2149
    },
2150
2151
    /**
2152
     * Initializes Targeting functionality only... the object does not
2153
     * get a mousedown handler.
2154
     * @method initTarget
2155
     * @param id the id of the linked element
2156
     * @param {String} sGroup the group of related items
2157
     * @param {object} config configuration attributes
2158
     */
2159
    initTarget: function(id, sGroup, config) {
2160
2161
        // configuration attributes 
2162
        this.config = config || {};
2163
2164
        this.events = {};
2165
2166
        // create a local reference to the drag and drop manager
2167
        this.DDM = YAHOO.util.DDM;
2168
2169
        // initialize the groups object
2170
        this.groups = {};
2171
2172
        // assume that we have an element reference instead of an id if the
2173
        // parameter is not a string
2174
        if (typeof id !== "string") {
2175
            YAHOO.log("id is not a string, assuming it is an HTMLElement");
2176
            this._domRef = id;
2177
            id = Dom.generateId(id);
2178
        }
2179
2180
        // set the id
2181
        this.id = id;
2182
2183
        // add to an interaction group
2184
        this.addToGroup((sGroup) ? sGroup : "default");
2185
2186
        // We don't want to register this as the handle with the manager
2187
        // so we just set the id rather than calling the setter.
2188
        this.handleElId = id;
2189
2190
        Event.onAvailable(id, this.handleOnAvailable, this, true);
2191
2192
        // create a logger instance
2193
        this.logger = (YAHOO.widget.LogWriter) ? 
2194
                new YAHOO.widget.LogWriter(this.toString()) : YAHOO;
2195
2196
        // the linked element is the element that gets dragged by default
2197
        this.setDragElId(id); 
2198
2199
        // by default, clicked anchors will not start drag operations. 
2200
        // @TODO what else should be here?  Probably form fields.
2201
        this.invalidHandleTypes = { A: "A" };
2202
        this.invalidHandleIds = {};
2203
        this.invalidHandleClasses = [];
2204
2205
        this.applyConfig();
2206
    },
2207
2208
    /**
2209
     * Applies the configuration parameters that were passed into the constructor.
2210
     * This is supposed to happen at each level through the inheritance chain.  So
2211
     * a DDProxy implentation will execute apply config on DDProxy, DD, and 
2212
     * DragDrop in order to get all of the parameters that are available in
2213
     * each object.
2214
     * @method applyConfig
2215
     */
2216
    applyConfig: function() {
2217
        this.events = {
2218
            mouseDown: true,
2219
            b4MouseDown: true,
2220
            mouseUp: true,
2221
            b4StartDrag: true,
2222
            startDrag: true,
2223
            b4EndDrag: true,
2224
            endDrag: true,
2225
            drag: true,
2226
            b4Drag: true,
2227
            invalidDrop: true,
2228
            b4DragOut: true,
2229
            dragOut: true,
2230
            dragEnter: true,
2231
            b4DragOver: true,
2232
            dragOver: true,
2233
            b4DragDrop: true,
2234
            dragDrop: true
2235
        };
2236
        
2237
        if (this.config.events) {
2238
            for (var i in this.config.events) {
2239
                if (this.config.events[i] === false) {
2240
                    this.events[i] = false;
2241
                }
2242
            }
2243
        }
2244
2245
2246
        // configurable properties: 
2247
        //    padding, isTarget, maintainOffset, primaryButtonOnly
2248
        this.padding           = this.config.padding || [0, 0, 0, 0];
2249
        this.isTarget          = (this.config.isTarget !== false);
2250
        this.maintainOffset    = (this.config.maintainOffset);
2251
        this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
2252
        this.dragOnly = ((this.config.dragOnly === true) ? true : false);
2253
        this.useShim = ((this.config.useShim === true) ? true : false);
2254
    },
2255
2256
    /**
2257
     * Executed when the linked element is available
2258
     * @method handleOnAvailable
2259
     * @private
2260
     */
2261
    handleOnAvailable: function() {
2262
        //this.logger.log("handleOnAvailable");
2263
        this.available = true;
2264
        this.resetConstraints();
2265
        this.onAvailable();
2266
    },
2267
2268
     /**
2269
     * Configures the padding for the target zone in px.  Effectively expands
2270
     * (or reduces) the virtual object size for targeting calculations.  
2271
     * Supports css-style shorthand; if only one parameter is passed, all sides
2272
     * will have that padding, and if only two are passed, the top and bottom
2273
     * will have the first param, the left and right the second.
2274
     * @method setPadding
2275
     * @param {int} iTop    Top pad
2276
     * @param {int} iRight  Right pad
2277
     * @param {int} iBot    Bot pad
2278
     * @param {int} iLeft   Left pad
2279
     */
2280
    setPadding: function(iTop, iRight, iBot, iLeft) {
2281
        // this.padding = [iLeft, iRight, iTop, iBot];
2282
        if (!iRight && 0 !== iRight) {
2283
            this.padding = [iTop, iTop, iTop, iTop];
2284
        } else if (!iBot && 0 !== iBot) {
2285
            this.padding = [iTop, iRight, iTop, iRight];
2286
        } else {
2287
            this.padding = [iTop, iRight, iBot, iLeft];
2288
        }
2289
    },
2290
2291
    /**
2292
     * Stores the initial placement of the linked element.
2293
     * @method setInitialPosition
2294
     * @param {int} diffX   the X offset, default 0
2295
     * @param {int} diffY   the Y offset, default 0
2296
     * @private
2297
     */
2298
    setInitPosition: function(diffX, diffY) {
2299
        var el = this.getEl();
2300
2301
        if (!this.DDM.verifyEl(el)) {
2302
            if (el && el.style && (el.style.display == 'none')) {
2303
                this.logger.log(this.id + " can not get initial position, element style is display: none");
2304
            } else {
2305
                this.logger.log(this.id + " element is broken");
2306
            }
2307
            return;
2308
        }
2309
2310
        var dx = diffX || 0;
2311
        var dy = diffY || 0;
2312
2313
        var p = Dom.getXY( el );
2314
2315
        this.initPageX = p[0] - dx;
2316
        this.initPageY = p[1] - dy;
2317
2318
        this.lastPageX = p[0];
2319
        this.lastPageY = p[1];
2320
2321
        this.logger.log(this.id + " initial position: " + this.initPageX + 
2322
                ", " + this.initPageY);
2323
2324
2325
        this.setStartPosition(p);
2326
    },
2327
2328
    /**
2329
     * Sets the start position of the element.  This is set when the obj
2330
     * is initialized, the reset when a drag is started.
2331
     * @method setStartPosition
2332
     * @param pos current position (from previous lookup)
2333
     * @private
2334
     */
2335
    setStartPosition: function(pos) {
2336
        var p = pos || Dom.getXY(this.getEl());
2337
2338
        this.deltaSetXY = null;
2339
2340
        this.startPageX = p[0];
2341
        this.startPageY = p[1];
2342
    },
2343
2344
    /**
2345
     * Add this instance to a group of related drag/drop objects.  All 
2346
     * instances belong to at least one group, and can belong to as many 
2347
     * groups as needed.
2348
     * @method addToGroup
2349
     * @param sGroup {string} the name of the group
2350
     */
2351
    addToGroup: function(sGroup) {
2352
        this.groups[sGroup] = true;
2353
        this.DDM.regDragDrop(this, sGroup);
2354
    },
2355
2356
    /**
2357
     * Remove's this instance from the supplied interaction group
2358
     * @method removeFromGroup
2359
     * @param {string}  sGroup  The group to drop
2360
     */
2361
    removeFromGroup: function(sGroup) {
2362
        this.logger.log("Removing from group: " + sGroup);
2363
        if (this.groups[sGroup]) {
2364
            delete this.groups[sGroup];
2365
        }
2366
2367
        this.DDM.removeDDFromGroup(this, sGroup);
2368
    },
2369
2370
    /**
2371
     * Allows you to specify that an element other than the linked element 
2372
     * will be moved with the cursor during a drag
2373
     * @method setDragElId
2374
     * @param id {string} the id of the element that will be used to initiate the drag
2375
     */
2376
    setDragElId: function(id) {
2377
        this.dragElId = id;
2378
    },
2379
2380
    /**
2381
     * Allows you to specify a child of the linked element that should be 
2382
     * used to initiate the drag operation.  An example of this would be if 
2383
     * you have a content div with text and links.  Clicking anywhere in the 
2384
     * content area would normally start the drag operation.  Use this method
2385
     * to specify that an element inside of the content div is the element 
2386
     * that starts the drag operation.
2387
     * @method setHandleElId
2388
     * @param id {string} the id of the element that will be used to 
2389
     * initiate the drag.
2390
     */
2391
    setHandleElId: function(id) {
2392
        if (typeof id !== "string") {
2393
            YAHOO.log("id is not a string, assuming it is an HTMLElement");
2394
            id = Dom.generateId(id);
2395
        }
2396
        this.handleElId = id;
2397
        this.DDM.regHandle(this.id, id);
2398
    },
2399
2400
    /**
2401
     * Allows you to set an element outside of the linked element as a drag 
2402
     * handle
2403
     * @method setOuterHandleElId
2404
     * @param id the id of the element that will be used to initiate the drag
2405
     */
2406
    setOuterHandleElId: function(id) {
2407
        if (typeof id !== "string") {
2408
            YAHOO.log("id is not a string, assuming it is an HTMLElement");
2409
            id = Dom.generateId(id);
2410
        }
2411
        this.logger.log("Adding outer handle event: " + id);
2412
        Event.on(id, "mousedown", 
2413
                this.handleMouseDown, this, true);
2414
        this.setHandleElId(id);
2415
2416
        this.hasOuterHandles = true;
2417
    },
2418
2419
    /**
2420
     * Remove all drag and drop hooks for this element
2421
     * @method unreg
2422
     */
2423
    unreg: function() {
2424
        this.logger.log("DragDrop obj cleanup " + this.id);
2425
        Event.removeListener(this.id, "mousedown", 
2426
                this.handleMouseDown);
2427
        this._domRef = null;
2428
        this.DDM._remove(this);
2429
    },
2430
2431
    /**
2432
     * Returns true if this instance is locked, or the drag drop mgr is locked
2433
     * (meaning that all drag/drop is disabled on the page.)
2434
     * @method isLocked
2435
     * @return {boolean} true if this obj or all drag/drop is locked, else 
2436
     * false
2437
     */
2438
    isLocked: function() {
2439
        return (this.DDM.isLocked() || this.locked);
2440
    },
2441
2442
    /**
2443
     * Fired when this object is clicked
2444
     * @method handleMouseDown
2445
     * @param {Event} e 
2446
     * @param {YAHOO.util.DragDrop} oDD the clicked dd object (this dd obj)
2447
     * @private
2448
     */
2449
    handleMouseDown: function(e, oDD) {
2450
2451
        var button = e.which || e.button;
2452
        this.logger.log("button: " + button);
2453
2454
        if (this.primaryButtonOnly && button > 1) {
2455
            this.logger.log("Mousedown was not produced by the primary button");
2456
            return;
2457
        }
2458
2459
        if (this.isLocked()) {
2460
            this.logger.log("Drag and drop is disabled, aborting");
2461
            return;
2462
        }
2463
2464
        this.logger.log("mousedown " + this.id);
2465
2466
        this.logger.log("firing onMouseDown events");
2467
2468
        // firing the mousedown events prior to calculating positions
2469
        var b4Return = this.b4MouseDown(e),
2470
        b4Return2 = true;
2471
2472
        if (this.events.b4MouseDown) {
2473
            b4Return2 = this.fireEvent('b4MouseDownEvent', e);
2474
        }
2475
        var mDownReturn = this.onMouseDown(e),
2476
            mDownReturn2 = true;
2477
        if (this.events.mouseDown) {
2478
            mDownReturn2 = this.fireEvent('mouseDownEvent', e);
2479
        }
2480
2481
        if ((b4Return === false) || (mDownReturn === false) || (b4Return2 === false) || (mDownReturn2 === false)) {
2482
            this.logger.log('b4MouseDown or onMouseDown returned false, exiting drag');
2483
            return;
2484
        }
2485
2486
        this.DDM.refreshCache(this.groups);
2487
        // var self = this;
2488
        // setTimeout( function() { self.DDM.refreshCache(self.groups); }, 0);
2489
2490
        // Only process the event if we really clicked within the linked 
2491
        // element.  The reason we make this check is that in the case that 
2492
        // another element was moved between the clicked element and the 
2493
        // cursor in the time between the mousedown and mouseup events. When 
2494
        // this happens, the element gets the next mousedown event 
2495
        // regardless of where on the screen it happened.  
2496
        var pt = new YAHOO.util.Point(Event.getPageX(e), Event.getPageY(e));
2497
        if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {
2498
                this.logger.log("Click was not over the element: " + this.id);
2499
        } else {
2500
            if (this.clickValidator(e)) {
2501
2502
                this.logger.log("click was a valid handle");
2503
2504
                // set the initial element position
2505
                this.setStartPosition();
2506
2507
                // start tracking mousemove distance and mousedown time to
2508
                // determine when to start the actual drag
2509
                this.DDM.handleMouseDown(e, this);
2510
2511
                // this mousedown is mine
2512
                this.DDM.stopEvent(e);
2513
            } else {
2514
2515
this.logger.log("clickValidator returned false, drag not initiated");
2516
2517
            }
2518
        }
2519
    },
2520
2521
    /**
2522
     * @method clickValidator
2523
     * @description Method validates that the clicked element
2524
     * was indeed the handle or a valid child of the handle
2525
     * @param {Event} e 
2526
     */
2527
    clickValidator: function(e) {
2528
        var target = YAHOO.util.Event.getTarget(e);
2529
        return ( this.isValidHandleChild(target) &&
2530
                    (this.id == this.handleElId || 
2531
                        this.DDM.handleWasClicked(target, this.id)) );
2532
    },
2533
2534
    /**
2535
     * Finds the location the element should be placed if we want to move
2536
     * it to where the mouse location less the click offset would place us.
2537
     * @method getTargetCoord
2538
     * @param {int} iPageX the X coordinate of the click
2539
     * @param {int} iPageY the Y coordinate of the click
2540
     * @return an object that contains the coordinates (Object.x and Object.y)
2541
     * @private
2542
     */
2543
    getTargetCoord: function(iPageX, iPageY) {
2544
2545
        // this.logger.log("getTargetCoord: " + iPageX + ", " + iPageY);
2546
2547
        var x = iPageX - this.deltaX;
2548
        var y = iPageY - this.deltaY;
2549
2550
        if (this.constrainX) {
2551
            if (x < this.minX) { x = this.minX; }
2552
            if (x > this.maxX) { x = this.maxX; }
2553
        }
2554
2555
        if (this.constrainY) {
2556
            if (y < this.minY) { y = this.minY; }
2557
            if (y > this.maxY) { y = this.maxY; }
2558
        }
2559
2560
        x = this.getTick(x, this.xTicks);
2561
        y = this.getTick(y, this.yTicks);
2562
2563
        // this.logger.log("getTargetCoord " + 
2564
                // " iPageX: " + iPageX +
2565
                // " iPageY: " + iPageY +
2566
                // " x: " + x + ", y: " + y);
2567
2568
        return {x:x, y:y};
2569
    },
2570
2571
    /**
2572
     * Allows you to specify a tag name that should not start a drag operation
2573
     * when clicked.  This is designed to facilitate embedding links within a
2574
     * drag handle that do something other than start the drag.
2575
     * @method addInvalidHandleType
2576
     * @param {string} tagName the type of element to exclude
2577
     */
2578
    addInvalidHandleType: function(tagName) {
2579
        var type = tagName.toUpperCase();
2580
        this.invalidHandleTypes[type] = type;
2581
    },
2582
2583
    /**
2584
     * Lets you to specify an element id for a child of a drag handle
2585
     * that should not initiate a drag
2586
     * @method addInvalidHandleId
2587
     * @param {string} id the element id of the element you wish to ignore
2588
     */
2589
    addInvalidHandleId: function(id) {
2590
        if (typeof id !== "string") {
2591
            YAHOO.log("id is not a string, assuming it is an HTMLElement");
2592
            id = Dom.generateId(id);
2593
        }
2594
        this.invalidHandleIds[id] = id;
2595
    },
2596
2597
2598
    /**
2599
     * Lets you specify a css class of elements that will not initiate a drag
2600
     * @method addInvalidHandleClass
2601
     * @param {string} cssClass the class of the elements you wish to ignore
2602
     */
2603
    addInvalidHandleClass: function(cssClass) {
2604
        this.invalidHandleClasses.push(cssClass);
2605
    },
2606
2607
    /**
2608
     * Unsets an excluded tag name set by addInvalidHandleType
2609
     * @method removeInvalidHandleType
2610
     * @param {string} tagName the type of element to unexclude
2611
     */
2612
    removeInvalidHandleType: function(tagName) {
2613
        var type = tagName.toUpperCase();
2614
        // this.invalidHandleTypes[type] = null;
2615
        delete this.invalidHandleTypes[type];
2616
    },
2617
    
2618
    /**
2619
     * Unsets an invalid handle id
2620
     * @method removeInvalidHandleId
2621
     * @param {string} id the id of the element to re-enable
2622
     */
2623
    removeInvalidHandleId: function(id) {
2624
        if (typeof id !== "string") {
2625
            YAHOO.log("id is not a string, assuming it is an HTMLElement");
2626
            id = Dom.generateId(id);
2627
        }
2628
        delete this.invalidHandleIds[id];
2629
    },
2630
2631
    /**
2632
     * Unsets an invalid css class
2633
     * @method removeInvalidHandleClass
2634
     * @param {string} cssClass the class of the element(s) you wish to 
2635
     * re-enable
2636
     */
2637
    removeInvalidHandleClass: function(cssClass) {
2638
        for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
2639
            if (this.invalidHandleClasses[i] == cssClass) {
2640
                delete this.invalidHandleClasses[i];
2641
            }
2642
        }
2643
    },
2644
2645
    /**
2646
     * Checks the tag exclusion list to see if this click should be ignored
2647
     * @method isValidHandleChild
2648
     * @param {HTMLElement} node the HTMLElement to evaluate
2649
     * @return {boolean} true if this is a valid tag type, false if not
2650
     */
2651
    isValidHandleChild: function(node) {
2652
2653
        var valid = true;
2654
        // var n = (node.nodeName == "#text") ? node.parentNode : node;
2655
        var nodeName;
2656
        try {
2657
            nodeName = node.nodeName.toUpperCase();
2658
        } catch(e) {
2659
            nodeName = node.nodeName;
2660
        }
2661
        valid = valid && !this.invalidHandleTypes[nodeName];
2662
        valid = valid && !this.invalidHandleIds[node.id];
2663
2664
        for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
2665
            valid = !Dom.hasClass(node, this.invalidHandleClasses[i]);
2666
        }
2667
2668
        this.logger.log("Valid handle? ... " + valid);
2669
2670
        return valid;
2671
2672
    },
2673
2674
    /**
2675
     * Create the array of horizontal tick marks if an interval was specified
2676
     * in setXConstraint().
2677
     * @method setXTicks
2678
     * @private
2679
     */
2680
    setXTicks: function(iStartX, iTickSize) {
2681
        this.xTicks = [];
2682
        this.xTickSize = iTickSize;
2683
        
2684
        var tickMap = {};
2685
2686
        for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
2687
            if (!tickMap[i]) {
2688
                this.xTicks[this.xTicks.length] = i;
2689
                tickMap[i] = true;
2690
            }
2691
        }
2692
2693
        for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
2694
            if (!tickMap[i]) {
2695
                this.xTicks[this.xTicks.length] = i;
2696
                tickMap[i] = true;
2697
            }
2698
        }
2699
2700
        this.xTicks.sort(this.DDM.numericSort) ;
2701
        this.logger.log("xTicks: " + this.xTicks.join());
2702
    },
2703
2704
    /**
2705
     * Create the array of vertical tick marks if an interval was specified in 
2706
     * setYConstraint().
2707
     * @method setYTicks
2708
     * @private
2709
     */
2710
    setYTicks: function(iStartY, iTickSize) {
2711
        // this.logger.log("setYTicks: " + iStartY + ", " + iTickSize
2712
               // + ", " + this.initPageY + ", " + this.minY + ", " + this.maxY );
2713
        this.yTicks = [];
2714
        this.yTickSize = iTickSize;
2715
2716
        var tickMap = {};
2717
2718
        for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
2719
            if (!tickMap[i]) {
2720
                this.yTicks[this.yTicks.length] = i;
2721
                tickMap[i] = true;
2722
            }
2723
        }
2724
2725
        for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
2726
            if (!tickMap[i]) {
2727
                this.yTicks[this.yTicks.length] = i;
2728
                tickMap[i] = true;
2729
            }
2730
        }
2731
2732
        this.yTicks.sort(this.DDM.numericSort) ;
2733
        this.logger.log("yTicks: " + this.yTicks.join());
2734
    },
2735
2736
    /**
2737
     * By default, the element can be dragged any place on the screen.  Use 
2738
     * this method to limit the horizontal travel of the element.  Pass in 
2739
     * 0,0 for the parameters if you want to lock the drag to the y axis.
2740
     * @method setXConstraint
2741
     * @param {int} iLeft the number of pixels the element can move to the left
2742
     * @param {int} iRight the number of pixels the element can move to the 
2743
     * right
2744
     * @param {int} iTickSize optional parameter for specifying that the 
2745
     * element
2746
     * should move iTickSize pixels at a time.
2747
     */
2748
    setXConstraint: function(iLeft, iRight, iTickSize) {
2749
        this.leftConstraint = parseInt(iLeft, 10);
2750
        this.rightConstraint = parseInt(iRight, 10);
2751
2752
        this.minX = this.initPageX - this.leftConstraint;
2753
        this.maxX = this.initPageX + this.rightConstraint;
2754
        if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
2755
2756
        this.constrainX = true;
2757
        this.logger.log("initPageX:" + this.initPageX + " minX:" + this.minX + 
2758
                " maxX:" + this.maxX);
2759
    },
2760
2761
    /**
2762
     * Clears any constraints applied to this instance.  Also clears ticks
2763
     * since they can't exist independent of a constraint at this time.
2764
     * @method clearConstraints
2765
     */
2766
    clearConstraints: function() {
2767
        this.logger.log("Clearing constraints");
2768
        this.constrainX = false;
2769
        this.constrainY = false;
2770
        this.clearTicks();
2771
    },
2772
2773
    /**
2774
     * Clears any tick interval defined for this instance
2775
     * @method clearTicks
2776
     */
2777
    clearTicks: function() {
2778
        this.logger.log("Clearing ticks");
2779
        this.xTicks = null;
2780
        this.yTicks = null;
2781
        this.xTickSize = 0;
2782
        this.yTickSize = 0;
2783
    },
2784
2785
    /**
2786
     * By default, the element can be dragged any place on the screen.  Set 
2787
     * this to limit the vertical travel of the element.  Pass in 0,0 for the
2788
     * parameters if you want to lock the drag to the x axis.
2789
     * @method setYConstraint
2790
     * @param {int} iUp the number of pixels the element can move up
2791
     * @param {int} iDown the number of pixels the element can move down
2792
     * @param {int} iTickSize optional parameter for specifying that the 
2793
     * element should move iTickSize pixels at a time.
2794
     */
2795
    setYConstraint: function(iUp, iDown, iTickSize) {
2796
        this.logger.log("setYConstraint: " + iUp + "," + iDown + "," + iTickSize);
2797
        this.topConstraint = parseInt(iUp, 10);
2798
        this.bottomConstraint = parseInt(iDown, 10);
2799
2800
        this.minY = this.initPageY - this.topConstraint;
2801
        this.maxY = this.initPageY + this.bottomConstraint;
2802
        if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
2803
2804
        this.constrainY = true;
2805
        
2806
        this.logger.log("initPageY:" + this.initPageY + " minY:" + this.minY + 
2807
                " maxY:" + this.maxY);
2808
    },
2809
2810
    /**
2811
     * resetConstraints must be called if you manually reposition a dd element.
2812
     * @method resetConstraints
2813
     */
2814
    resetConstraints: function() {
2815
2816
        //this.logger.log("resetConstraints");
2817
2818
        // Maintain offsets if necessary
2819
        if (this.initPageX || this.initPageX === 0) {
2820
            //this.logger.log("init pagexy: " + this.initPageX + ", " + 
2821
                               //this.initPageY);
2822
            //this.logger.log("last pagexy: " + this.lastPageX + ", " + 
2823
                               //this.lastPageY);
2824
            // figure out how much this thing has moved
2825
            var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
2826
            var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
2827
2828
            this.setInitPosition(dx, dy);
2829
2830
        // This is the first time we have detected the element's position
2831
        } else {
2832
            this.setInitPosition();
2833
        }
2834
2835
        if (this.constrainX) {
2836
            this.setXConstraint( this.leftConstraint, 
2837
                                 this.rightConstraint, 
2838
                                 this.xTickSize        );
2839
        }
2840
2841
        if (this.constrainY) {
2842
            this.setYConstraint( this.topConstraint, 
2843
                                 this.bottomConstraint, 
2844
                                 this.yTickSize         );
2845
        }
2846
    },
2847
2848
    /**
2849
     * Normally the drag element is moved pixel by pixel, but we can specify 
2850
     * that it move a number of pixels at a time.  This method resolves the 
2851
     * location when we have it set up like this.
2852
     * @method getTick
2853
     * @param {int} val where we want to place the object
2854
     * @param {int[]} tickArray sorted array of valid points
2855
     * @return {int} the closest tick
2856
     * @private
2857
     */
2858
    getTick: function(val, tickArray) {
2859
2860
        if (!tickArray) {
2861
            // If tick interval is not defined, it is effectively 1 pixel, 
2862
            // so we return the value passed to us.
2863
            return val; 
2864
        } else if (tickArray[0] >= val) {
2865
            // The value is lower than the first tick, so we return the first
2866
            // tick.
2867
            return tickArray[0];
2868
        } else {
2869
            for (var i=0, len=tickArray.length; i<len; ++i) {
2870
                var next = i + 1;
2871
                if (tickArray[next] && tickArray[next] >= val) {
2872
                    var diff1 = val - tickArray[i];
2873
                    var diff2 = tickArray[next] - val;
2874
                    return (diff2 > diff1) ? tickArray[i] : tickArray[next];
2875
                }
2876
            }
2877
2878
            // The value is larger than the last tick, so we return the last
2879
            // tick.
2880
            return tickArray[tickArray.length - 1];
2881
        }
2882
    },
2883
2884
    /**
2885
     * toString method
2886
     * @method toString
2887
     * @return {string} string representation of the dd obj
2888
     */
2889
    toString: function() {
2890
        return ("DragDrop " + this.id);
2891
    }
2892
2893
};
2894
YAHOO.augment(YAHOO.util.DragDrop, YAHOO.util.EventProvider);
2895
2896
/**
2897
* @event mouseDownEvent
2898
* @description Provides access to the mousedown event. The mousedown does not always result in a drag operation.
2899
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2900
*/
2901
2902
/**
2903
* @event b4MouseDownEvent
2904
* @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag.
2905
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2906
*/
2907
2908
/**
2909
* @event mouseUpEvent
2910
* @description Fired from inside DragDropMgr when the drag operation is finished.
2911
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2912
*/
2913
2914
/**
2915
* @event b4StartDragEvent
2916
* @description Fires before the startDragEvent, returning false will cancel the startDrag Event.
2917
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2918
*/
2919
2920
/**
2921
* @event startDragEvent
2922
* @description Occurs after a mouse down and the drag threshold has been met. The drag threshold default is either 3 pixels of mouse movement or 1 full second of holding the mousedown. 
2923
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2924
*/
2925
2926
/**
2927
* @event b4EndDragEvent
2928
* @description Fires before the endDragEvent. Returning false will cancel.
2929
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2930
*/
2931
2932
/**
2933
* @event endDragEvent
2934
* @description Fires on the mouseup event after a drag has been initiated (startDrag fired).
2935
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2936
*/
2937
2938
/**
2939
* @event dragEvent
2940
* @description Occurs every mousemove event while dragging.
2941
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2942
*/
2943
/**
2944
* @event b4DragEvent
2945
* @description Fires before the dragEvent.
2946
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2947
*/
2948
/**
2949
* @event invalidDropEvent
2950
* @description Fires when the dragged objects is dropped in a location that contains no drop targets.
2951
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2952
*/
2953
/**
2954
* @event b4DragOutEvent
2955
* @description Fires before the dragOutEvent
2956
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2957
*/
2958
/**
2959
* @event dragOutEvent
2960
* @description Fires when a dragged object is no longer over an object that had the onDragEnter fire. 
2961
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2962
*/
2963
/**
2964
* @event dragEnterEvent
2965
* @description Occurs when the dragged object first interacts with another targettable drag and drop object.
2966
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2967
*/
2968
/**
2969
* @event b4DragOverEvent
2970
* @description Fires before the dragOverEvent.
2971
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2972
*/
2973
/**
2974
* @event dragOverEvent
2975
* @description Fires every mousemove event while over a drag and drop object.
2976
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2977
*/
2978
/**
2979
* @event b4DragDropEvent 
2980
* @description Fires before the dragDropEvent
2981
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2982
*/
2983
/**
2984
* @event dragDropEvent
2985
* @description Fires when the dragged objects is dropped on another.
2986
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2987
*/
2988
})();
2989
/**
2990
 * A DragDrop implementation where the linked element follows the 
2991
 * mouse cursor during a drag.
2992
 * @class DD
2993
 * @extends YAHOO.util.DragDrop
2994
 * @constructor
2995
 * @param {String} id the id of the linked element 
2996
 * @param {String} sGroup the group of related DragDrop items
2997
 * @param {object} config an object containing configurable attributes
2998
 *                Valid properties for DD: 
2999
 *                    scroll
3000
 */
3001
YAHOO.util.DD = function(id, sGroup, config) {
3002
    if (id) {
3003
        this.init(id, sGroup, config);
3004
    }
3005
};
3006
3007
YAHOO.extend(YAHOO.util.DD, YAHOO.util.DragDrop, {
3008
3009
    /**
3010
     * When set to true, the utility automatically tries to scroll the browser
3011
     * window when a drag and drop element is dragged near the viewport boundary.
3012
     * Defaults to true.
3013
     * @property scroll
3014
     * @type boolean
3015
     */
3016
    scroll: true, 
3017
3018
    /**
3019
     * Sets the pointer offset to the distance between the linked element's top 
3020
     * left corner and the location the element was clicked
3021
     * @method autoOffset
3022
     * @param {int} iPageX the X coordinate of the click
3023
     * @param {int} iPageY the Y coordinate of the click
3024
     */
3025
    autoOffset: function(iPageX, iPageY) {
3026
        var x = iPageX - this.startPageX;
3027
        var y = iPageY - this.startPageY;
3028
        this.setDelta(x, y);
3029
        // this.logger.log("autoOffset el pos: " + aCoord + ", delta: " + x + "," + y);
3030
    },
3031
3032
    /** 
3033
     * Sets the pointer offset.  You can call this directly to force the 
3034
     * offset to be in a particular location (e.g., pass in 0,0 to set it 
3035
     * to the center of the object, as done in YAHOO.widget.Slider)
3036
     * @method setDelta
3037
     * @param {int} iDeltaX the distance from the left
3038
     * @param {int} iDeltaY the distance from the top
3039
     */
3040
    setDelta: function(iDeltaX, iDeltaY) {
3041
        this.deltaX = iDeltaX;
3042
        this.deltaY = iDeltaY;
3043
        this.logger.log("deltaX:" + this.deltaX + ", deltaY:" + this.deltaY);
3044
    },
3045
3046
    /**
3047
     * Sets the drag element to the location of the mousedown or click event, 
3048
     * maintaining the cursor location relative to the location on the element 
3049
     * that was clicked.  Override this if you want to place the element in a 
3050
     * location other than where the cursor is.
3051
     * @method setDragElPos
3052
     * @param {int} iPageX the X coordinate of the mousedown or drag event
3053
     * @param {int} iPageY the Y coordinate of the mousedown or drag event
3054
     */
3055
    setDragElPos: function(iPageX, iPageY) {
3056
        // the first time we do this, we are going to check to make sure
3057
        // the element has css positioning
3058
3059
        var el = this.getDragEl();
3060
        this.alignElWithMouse(el, iPageX, iPageY);
3061
    },
3062
3063
    /**
3064
     * Sets the element to the location of the mousedown or click event, 
3065
     * maintaining the cursor location relative to the location on the element 
3066
     * that was clicked.  Override this if you want to place the element in a 
3067
     * location other than where the cursor is.
3068
     * @method alignElWithMouse
3069
     * @param {HTMLElement} el the element to move
3070
     * @param {int} iPageX the X coordinate of the mousedown or drag event
3071
     * @param {int} iPageY the Y coordinate of the mousedown or drag event
3072
     */
3073
    alignElWithMouse: function(el, iPageX, iPageY) {
3074
        var oCoord = this.getTargetCoord(iPageX, iPageY);
3075
        // this.logger.log("****alignElWithMouse : " + el.id + ", " + aCoord + ", " + el.style.display);
3076
3077
        if (!this.deltaSetXY) {
3078
            var aCoord = [oCoord.x, oCoord.y];
3079
            YAHOO.util.Dom.setXY(el, aCoord);
3080
3081
            var newLeft = parseInt( YAHOO.util.Dom.getStyle(el, "left"), 10 );
3082
            var newTop  = parseInt( YAHOO.util.Dom.getStyle(el, "top" ), 10 );
3083
3084
            this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
3085
        } else {
3086
            YAHOO.util.Dom.setStyle(el, "left", (oCoord.x + this.deltaSetXY[0]) + "px");
3087
            YAHOO.util.Dom.setStyle(el, "top",  (oCoord.y + this.deltaSetXY[1]) + "px");
3088
        }
3089
        
3090
        this.cachePosition(oCoord.x, oCoord.y);
3091
        var self = this;
3092
        setTimeout(function() {
3093
            self.autoScroll.call(self, oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
3094
        }, 0);
3095
    },
3096
3097
    /**
3098
     * Saves the most recent position so that we can reset the constraints and
3099
     * tick marks on-demand.  We need to know this so that we can calculate the
3100
     * number of pixels the element is offset from its original position.
3101
     * @method cachePosition
3102
     * @param iPageX the current x position (optional, this just makes it so we
3103
     * don't have to look it up again)
3104
     * @param iPageY the current y position (optional, this just makes it so we
3105
     * don't have to look it up again)
3106
     */
3107
    cachePosition: function(iPageX, iPageY) {
3108
        if (iPageX) {
3109
            this.lastPageX = iPageX;
3110
            this.lastPageY = iPageY;
3111
        } else {
3112
            var aCoord = YAHOO.util.Dom.getXY(this.getEl());
3113
            this.lastPageX = aCoord[0];
3114
            this.lastPageY = aCoord[1];
3115
        }
3116
    },
3117
3118
    /**
3119
     * Auto-scroll the window if the dragged object has been moved beyond the 
3120
     * visible window boundary.
3121
     * @method autoScroll
3122
     * @param {int} x the drag element's x position
3123
     * @param {int} y the drag element's y position
3124
     * @param {int} h the height of the drag element
3125
     * @param {int} w the width of the drag element
3126
     * @private
3127
     */
3128
    autoScroll: function(x, y, h, w) {
3129
3130
        if (this.scroll) {
3131
            // The client height
3132
            var clientH = this.DDM.getClientHeight();
3133
3134
            // The client width
3135
            var clientW = this.DDM.getClientWidth();
3136
3137
            // The amt scrolled down
3138
            var st = this.DDM.getScrollTop();
3139
3140
            // The amt scrolled right
3141
            var sl = this.DDM.getScrollLeft();
3142
3143
            // Location of the bottom of the element
3144
            var bot = h + y;
3145
3146
            // Location of the right of the element
3147
            var right = w + x;
3148
3149
            // The distance from the cursor to the bottom of the visible area, 
3150
            // adjusted so that we don't scroll if the cursor is beyond the
3151
            // element drag constraints
3152
            var toBot = (clientH + st - y - this.deltaY);
3153
3154
            // The distance from the cursor to the right of the visible area
3155
            var toRight = (clientW + sl - x - this.deltaX);
3156
3157
            // this.logger.log( " x: " + x + " y: " + y + " h: " + h + 
3158
            // " clientH: " + clientH + " clientW: " + clientW + 
3159
            // " st: " + st + " sl: " + sl + " bot: " + bot + 
3160
            // " right: " + right + " toBot: " + toBot + " toRight: " + toRight);
3161
3162
            // How close to the edge the cursor must be before we scroll
3163
            // var thresh = (document.all) ? 100 : 40;
3164
            var thresh = 40;
3165
3166
            // How many pixels to scroll per autoscroll op.  This helps to reduce 
3167
            // clunky scrolling. IE is more sensitive about this ... it needs this 
3168
            // value to be higher.
3169
            var scrAmt = (document.all) ? 80 : 30;
3170
3171
            // Scroll down if we are near the bottom of the visible page and the 
3172
            // obj extends below the crease
3173
            if ( bot > clientH && toBot < thresh ) { 
3174
                window.scrollTo(sl, st + scrAmt); 
3175
            }
3176
3177
            // Scroll up if the window is scrolled down and the top of the object
3178
            // goes above the top border
3179
            if ( y < st && st > 0 && y - st < thresh ) { 
3180
                window.scrollTo(sl, st - scrAmt); 
3181
            }
3182
3183
            // Scroll right if the obj is beyond the right border and the cursor is
3184
            // near the border.
3185
            if ( right > clientW && toRight < thresh ) { 
3186
                window.scrollTo(sl + scrAmt, st); 
3187
            }
3188
3189
            // Scroll left if the window has been scrolled to the right and the obj
3190
            // extends past the left border
3191
            if ( x < sl && sl > 0 && x - sl < thresh ) { 
3192
                window.scrollTo(sl - scrAmt, st);
3193
            }
3194
        }
3195
    },
3196
3197
    /*
3198
     * Sets up config options specific to this class. Overrides
3199
     * YAHOO.util.DragDrop, but all versions of this method through the 
3200
     * inheritance chain are called
3201
     */
3202
    applyConfig: function() {
3203
        YAHOO.util.DD.superclass.applyConfig.call(this);
3204
        this.scroll = (this.config.scroll !== false);
3205
    },
3206
3207
    /*
3208
     * Event that fires prior to the onMouseDown event.  Overrides 
3209
     * YAHOO.util.DragDrop.
3210
     */
3211
    b4MouseDown: function(e) {
3212
        this.setStartPosition();
3213
        // this.resetConstraints();
3214
        this.autoOffset(YAHOO.util.Event.getPageX(e), 
3215
                            YAHOO.util.Event.getPageY(e));
3216
    },
3217
3218
    /*
3219
     * Event that fires prior to the onDrag event.  Overrides 
3220
     * YAHOO.util.DragDrop.
3221
     */
3222
    b4Drag: function(e) {
3223
        this.setDragElPos(YAHOO.util.Event.getPageX(e), 
3224
                            YAHOO.util.Event.getPageY(e));
3225
    },
3226
3227
    toString: function() {
3228
        return ("DD " + this.id);
3229
    }
3230
3231
    //////////////////////////////////////////////////////////////////////////
3232
    // Debugging ygDragDrop events that can be overridden
3233
    //////////////////////////////////////////////////////////////////////////
3234
    /*
3235
    startDrag: function(x, y) {
3236
        this.logger.log(this.id.toString()  + " startDrag");
3237
    },
3238
3239
    onDrag: function(e) {
3240
        this.logger.log(this.id.toString() + " onDrag");
3241
    },
3242
3243
    onDragEnter: function(e, id) {
3244
        this.logger.log(this.id.toString() + " onDragEnter: " + id);
3245
    },
3246
3247
    onDragOver: function(e, id) {
3248
        this.logger.log(this.id.toString() + " onDragOver: " + id);
3249
    },
3250
3251
    onDragOut: function(e, id) {
3252
        this.logger.log(this.id.toString() + " onDragOut: " + id);
3253
    },
3254
3255
    onDragDrop: function(e, id) {
3256
        this.logger.log(this.id.toString() + " onDragDrop: " + id);
3257
    },
3258
3259
    endDrag: function(e) {
3260
        this.logger.log(this.id.toString() + " endDrag");
3261
    }
3262
3263
    */
3264
3265
/**
3266
* @event mouseDownEvent
3267
* @description Provides access to the mousedown event. The mousedown does not always result in a drag operation.
3268
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3269
*/
3270
3271
/**
3272
* @event b4MouseDownEvent
3273
* @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag.
3274
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3275
*/
3276
3277
/**
3278
* @event mouseUpEvent
3279
* @description Fired from inside DragDropMgr when the drag operation is finished.
3280
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3281
*/
3282
3283
/**
3284
* @event b4StartDragEvent
3285
* @description Fires before the startDragEvent, returning false will cancel the startDrag Event.
3286
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3287
*/
3288
3289
/**
3290
* @event startDragEvent
3291
* @description Occurs after a mouse down and the drag threshold has been met. The drag threshold default is either 3 pixels of mouse movement or 1 full second of holding the mousedown. 
3292
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3293
*/
3294
3295
/**
3296
* @event b4EndDragEvent
3297
* @description Fires before the endDragEvent. Returning false will cancel.
3298
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3299
*/
3300
3301
/**
3302
* @event endDragEvent
3303
* @description Fires on the mouseup event after a drag has been initiated (startDrag fired).
3304
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3305
*/
3306
3307
/**
3308
* @event dragEvent
3309
* @description Occurs every mousemove event while dragging.
3310
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3311
*/
3312
/**
3313
* @event b4DragEvent
3314
* @description Fires before the dragEvent.
3315
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3316
*/
3317
/**
3318
* @event invalidDropEvent
3319
* @description Fires when the dragged objects is dropped in a location that contains no drop targets.
3320
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3321
*/
3322
/**
3323
* @event b4DragOutEvent
3324
* @description Fires before the dragOutEvent
3325
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3326
*/
3327
/**
3328
* @event dragOutEvent
3329
* @description Fires when a dragged object is no longer over an object that had the onDragEnter fire. 
3330
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3331
*/
3332
/**
3333
* @event dragEnterEvent
3334
* @description Occurs when the dragged object first interacts with another targettable drag and drop object.
3335
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3336
*/
3337
/**
3338
* @event b4DragOverEvent
3339
* @description Fires before the dragOverEvent.
3340
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3341
*/
3342
/**
3343
* @event dragOverEvent
3344
* @description Fires every mousemove event while over a drag and drop object.
3345
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3346
*/
3347
/**
3348
* @event b4DragDropEvent 
3349
* @description Fires before the dragDropEvent
3350
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3351
*/
3352
/**
3353
* @event dragDropEvent
3354
* @description Fires when the dragged objects is dropped on another.
3355
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3356
*/
3357
});
3358
/**
3359
 * A DragDrop implementation that inserts an empty, bordered div into
3360
 * the document that follows the cursor during drag operations.  At the time of
3361
 * the click, the frame div is resized to the dimensions of the linked html
3362
 * element, and moved to the exact location of the linked element.
3363
 *
3364
 * References to the "frame" element refer to the single proxy element that
3365
 * was created to be dragged in place of all DDProxy elements on the
3366
 * page.
3367
 *
3368
 * @class DDProxy
3369
 * @extends YAHOO.util.DD
3370
 * @constructor
3371
 * @param {String} id the id of the linked html element
3372
 * @param {String} sGroup the group of related DragDrop objects
3373
 * @param {object} config an object containing configurable attributes
3374
 *                Valid properties for DDProxy in addition to those in DragDrop: 
3375
 *                   resizeFrame, centerFrame, dragElId
3376
 */
3377
YAHOO.util.DDProxy = function(id, sGroup, config) {
3378
    if (id) {
3379
        this.init(id, sGroup, config);
3380
        this.initFrame(); 
3381
    }
3382
};
3383
3384
/**
3385
 * The default drag frame div id
3386
 * @property YAHOO.util.DDProxy.dragElId
3387
 * @type String
3388
 * @static
3389
 */
3390
YAHOO.util.DDProxy.dragElId = "ygddfdiv";
3391
3392
YAHOO.extend(YAHOO.util.DDProxy, YAHOO.util.DD, {
3393
3394
    /**
3395
     * By default we resize the drag frame to be the same size as the element
3396
     * we want to drag (this is to get the frame effect).  We can turn it off
3397
     * if we want a different behavior.
3398
     * @property resizeFrame
3399
     * @type boolean
3400
     */
3401
    resizeFrame: true,
3402
3403
    /**
3404
     * By default the frame is positioned exactly where the drag element is, so
3405
     * we use the cursor offset provided by YAHOO.util.DD.  Another option that works only if
3406
     * you do not have constraints on the obj is to have the drag frame centered
3407
     * around the cursor.  Set centerFrame to true for this effect.
3408
     * @property centerFrame
3409
     * @type boolean
3410
     */
3411
    centerFrame: false,
3412
3413
    /**
3414
     * Creates the proxy element if it does not yet exist
3415
     * @method createFrame
3416
     */
3417
    createFrame: function() {
3418
        var self=this, body=document.body;
3419
3420
        if (!body || !body.firstChild) {
3421
            setTimeout( function() { self.createFrame(); }, 50 );
3422
            return;
3423
        }
3424
3425
        var div=this.getDragEl(), Dom=YAHOO.util.Dom;
3426
3427
        if (!div) {
3428
            div    = document.createElement("div");
3429
            div.id = this.dragElId;
3430
            var s  = div.style;
3431
3432
            s.position   = "absolute";
3433
            s.visibility = "hidden";
3434
            s.cursor     = "move";
3435
            s.border     = "2px solid #aaa";
3436
            s.zIndex     = 999;
3437
            s.height     = "25px";
3438
            s.width      = "25px";
3439
3440
            var _data = document.createElement('div');
3441
            Dom.setStyle(_data, 'height', '100%');
3442
            Dom.setStyle(_data, 'width', '100%');
3443
            /**
3444
            * If the proxy element has no background-color, then it is considered to the "transparent" by Internet Explorer.
3445
            * Since it is "transparent" then the events pass through it to the iframe below.
3446
            * So creating a "fake" div inside the proxy element and giving it a background-color, then setting it to an
3447
            * opacity of 0, it appears to not be there, however IE still thinks that it is so the events never pass through.
3448
            */
3449
            Dom.setStyle(_data, 'background-color', '#ccc');
3450
            Dom.setStyle(_data, 'opacity', '0');
3451
            div.appendChild(_data);
3452
3453
            // appendChild can blow up IE if invoked prior to the window load event
3454
            // while rendering a table.  It is possible there are other scenarios 
3455
            // that would cause this to happen as well.
3456
            body.insertBefore(div, body.firstChild);
3457
        }
3458
    },
3459
3460
    /**
3461
     * Initialization for the drag frame element.  Must be called in the
3462
     * constructor of all subclasses
3463
     * @method initFrame
3464
     */
3465
    initFrame: function() {
3466
        this.createFrame();
3467
    },
3468
3469
    applyConfig: function() {
3470
        //this.logger.log("DDProxy applyConfig");
3471
        YAHOO.util.DDProxy.superclass.applyConfig.call(this);
3472
3473
        this.resizeFrame = (this.config.resizeFrame !== false);
3474
        this.centerFrame = (this.config.centerFrame);
3475
        this.setDragElId(this.config.dragElId || YAHOO.util.DDProxy.dragElId);
3476
    },
3477
3478
    /**
3479
     * Resizes the drag frame to the dimensions of the clicked object, positions 
3480
     * it over the object, and finally displays it
3481
     * @method showFrame
3482
     * @param {int} iPageX X click position
3483
     * @param {int} iPageY Y click position
3484
     * @private
3485
     */
3486
    showFrame: function(iPageX, iPageY) {
3487
        var el = this.getEl();
3488
        var dragEl = this.getDragEl();
3489
        var s = dragEl.style;
3490
3491
        this._resizeProxy();
3492
3493
        if (this.centerFrame) {
3494
            this.setDelta( Math.round(parseInt(s.width,  10)/2), 
3495
                           Math.round(parseInt(s.height, 10)/2) );
3496
        }
3497
3498
        this.setDragElPos(iPageX, iPageY);
3499
3500
        YAHOO.util.Dom.setStyle(dragEl, "visibility", "visible"); 
3501
    },
3502
3503
    /**
3504
     * The proxy is automatically resized to the dimensions of the linked
3505
     * element when a drag is initiated, unless resizeFrame is set to false
3506
     * @method _resizeProxy
3507
     * @private
3508
     */
3509
    _resizeProxy: function() {
3510
        if (this.resizeFrame) {
3511
            var DOM    = YAHOO.util.Dom;
3512
            var el     = this.getEl();
3513
            var dragEl = this.getDragEl();
3514
3515
            var bt = parseInt( DOM.getStyle(dragEl, "borderTopWidth"    ), 10);
3516
            var br = parseInt( DOM.getStyle(dragEl, "borderRightWidth"  ), 10);
3517
            var bb = parseInt( DOM.getStyle(dragEl, "borderBottomWidth" ), 10);
3518
            var bl = parseInt( DOM.getStyle(dragEl, "borderLeftWidth"   ), 10);
3519
3520
            if (isNaN(bt)) { bt = 0; }
3521
            if (isNaN(br)) { br = 0; }
3522
            if (isNaN(bb)) { bb = 0; }
3523
            if (isNaN(bl)) { bl = 0; }
3524
3525
            this.logger.log("proxy size: " + bt + "  " + br + " " + bb + " " + bl);
3526
3527
            var newWidth  = Math.max(0, el.offsetWidth  - br - bl);                                                                                           
3528
            var newHeight = Math.max(0, el.offsetHeight - bt - bb);
3529
3530
            this.logger.log("Resizing proxy element");
3531
3532
            DOM.setStyle( dragEl, "width",  newWidth  + "px" );
3533
            DOM.setStyle( dragEl, "height", newHeight + "px" );
3534
        }
3535
    },
3536
3537
    // overrides YAHOO.util.DragDrop
3538
    b4MouseDown: function(e) {
3539
        this.setStartPosition();
3540
        var x = YAHOO.util.Event.getPageX(e);
3541
        var y = YAHOO.util.Event.getPageY(e);
3542
        this.autoOffset(x, y);
3543
3544
        // This causes the autoscroll code to kick off, which means autoscroll can
3545
        // happen prior to the check for a valid drag handle.
3546
        // this.setDragElPos(x, y);
3547
    },
3548
3549
    // overrides YAHOO.util.DragDrop
3550
    b4StartDrag: function(x, y) {
3551
        // show the drag frame
3552
        this.logger.log("start drag show frame, x: " + x + ", y: " + y);
3553
        this.showFrame(x, y);
3554
    },
3555
3556
    // overrides YAHOO.util.DragDrop
3557
    b4EndDrag: function(e) {
3558
        this.logger.log(this.id + " b4EndDrag");
3559
        YAHOO.util.Dom.setStyle(this.getDragEl(), "visibility", "hidden"); 
3560
    },
3561
3562
    // overrides YAHOO.util.DragDrop
3563
    // By default we try to move the element to the last location of the frame.  
3564
    // This is so that the default behavior mirrors that of YAHOO.util.DD.  
3565
    endDrag: function(e) {
3566
        var DOM = YAHOO.util.Dom;
3567
        this.logger.log(this.id + " endDrag");
3568
        var lel = this.getEl();
3569
        var del = this.getDragEl();
3570
3571
        // Show the drag frame briefly so we can get its position
3572
        // del.style.visibility = "";
3573
        DOM.setStyle(del, "visibility", ""); 
3574
3575
        // Hide the linked element before the move to get around a Safari 
3576
        // rendering bug.
3577
        //lel.style.visibility = "hidden";
3578
        DOM.setStyle(lel, "visibility", "hidden"); 
3579
        YAHOO.util.DDM.moveToEl(lel, del);
3580
        //del.style.visibility = "hidden";
3581
        DOM.setStyle(del, "visibility", "hidden"); 
3582
        //lel.style.visibility = "";
3583
        DOM.setStyle(lel, "visibility", ""); 
3584
    },
3585
3586
    toString: function() {
3587
        return ("DDProxy " + this.id);
3588
    }
3589
/**
3590
* @event mouseDownEvent
3591
* @description Provides access to the mousedown event. The mousedown does not always result in a drag operation.
3592
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3593
*/
3594
3595
/**
3596
* @event b4MouseDownEvent
3597
* @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag.
3598
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3599
*/
3600
3601
/**
3602
* @event mouseUpEvent
3603
* @description Fired from inside DragDropMgr when the drag operation is finished.
3604
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3605
*/
3606
3607
/**
3608
* @event b4StartDragEvent
3609
* @description Fires before the startDragEvent, returning false will cancel the startDrag Event.
3610
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3611
*/
3612
3613
/**
3614
* @event startDragEvent
3615
* @description Occurs after a mouse down and the drag threshold has been met. The drag threshold default is either 3 pixels of mouse movement or 1 full second of holding the mousedown. 
3616
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3617
*/
3618
3619
/**
3620
* @event b4EndDragEvent
3621
* @description Fires before the endDragEvent. Returning false will cancel.
3622
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3623
*/
3624
3625
/**
3626
* @event endDragEvent
3627
* @description Fires on the mouseup event after a drag has been initiated (startDrag fired).
3628
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3629
*/
3630
3631
/**
3632
* @event dragEvent
3633
* @description Occurs every mousemove event while dragging.
3634
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3635
*/
3636
/**
3637
* @event b4DragEvent
3638
* @description Fires before the dragEvent.
3639
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3640
*/
3641
/**
3642
* @event invalidDropEvent
3643
* @description Fires when the dragged objects is dropped in a location that contains no drop targets.
3644
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3645
*/
3646
/**
3647
* @event b4DragOutEvent
3648
* @description Fires before the dragOutEvent
3649
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3650
*/
3651
/**
3652
* @event dragOutEvent
3653
* @description Fires when a dragged object is no longer over an object that had the onDragEnter fire. 
3654
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3655
*/
3656
/**
3657
* @event dragEnterEvent
3658
* @description Occurs when the dragged object first interacts with another targettable drag and drop object.
3659
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3660
*/
3661
/**
3662
* @event b4DragOverEvent
3663
* @description Fires before the dragOverEvent.
3664
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3665
*/
3666
/**
3667
* @event dragOverEvent
3668
* @description Fires every mousemove event while over a drag and drop object.
3669
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3670
*/
3671
/**
3672
* @event b4DragDropEvent 
3673
* @description Fires before the dragDropEvent
3674
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3675
*/
3676
/**
3677
* @event dragDropEvent
3678
* @description Fires when the dragged objects is dropped on another.
3679
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3680
*/
3681
3682
});
3683
/**
3684
 * A DragDrop implementation that does not move, but can be a drop 
3685
 * target.  You would get the same result by simply omitting implementation 
3686
 * for the event callbacks, but this way we reduce the processing cost of the 
3687
 * event listener and the callbacks.
3688
 * @class DDTarget
3689
 * @extends YAHOO.util.DragDrop 
3690
 * @constructor
3691
 * @param {String} id the id of the element that is a drop target
3692
 * @param {String} sGroup the group of related DragDrop objects
3693
 * @param {object} config an object containing configurable attributes
3694
 *                 Valid properties for DDTarget in addition to those in 
3695
 *                 DragDrop: 
3696
 *                    none
3697
 */
3698
YAHOO.util.DDTarget = function(id, sGroup, config) {
3699
    if (id) {
3700
        this.initTarget(id, sGroup, config);
3701
    }
3702
};
3703
3704
// YAHOO.util.DDTarget.prototype = new YAHOO.util.DragDrop();
3705
YAHOO.extend(YAHOO.util.DDTarget, YAHOO.util.DragDrop, {
3706
    toString: function() {
3707
        return ("DDTarget " + this.id);
3708
    }
3709
});
3710
YAHOO.register("dragdrop", YAHOO.util.DragDropMgr, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/dragdrop/dragdrop-min.js (-10 lines)
Lines 1-10 Link Here
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.8.0r4
6
*/
7
if(!YAHOO.util.DragDropMgr){YAHOO.util.DragDropMgr=function(){var A=YAHOO.util.Event,B=YAHOO.util.Dom;return{useShim:false,_shimActive:false,_shimState:false,_debugShim:false,_createShim:function(){var C=document.createElement("div");C.id="yui-ddm-shim";if(document.body.firstChild){document.body.insertBefore(C,document.body.firstChild);}else{document.body.appendChild(C);}C.style.display="none";C.style.backgroundColor="red";C.style.position="absolute";C.style.zIndex="99999";B.setStyle(C,"opacity","0");this._shim=C;A.on(C,"mouseup",this.handleMouseUp,this,true);A.on(C,"mousemove",this.handleMouseMove,this,true);A.on(window,"scroll",this._sizeShim,this,true);},_sizeShim:function(){if(this._shimActive){var C=this._shim;C.style.height=B.getDocumentHeight()+"px";C.style.width=B.getDocumentWidth()+"px";C.style.top="0";C.style.left="0";}},_activateShim:function(){if(this.useShim){if(!this._shim){this._createShim();}this._shimActive=true;var C=this._shim,D="0";if(this._debugShim){D=".5";}B.setStyle(C,"opacity",D);this._sizeShim();C.style.display="block";}},_deactivateShim:function(){this._shim.style.display="none";this._shimActive=false;},_shim:null,ids:{},handleIds:{},dragCurrent:null,dragOvers:{},deltaX:0,deltaY:0,preventDefault:true,stopPropagation:true,initialized:false,locked:false,interactionInfo:null,init:function(){this.initialized=true;},POINT:0,INTERSECT:1,STRICT_INTERSECT:2,mode:0,_execOnAll:function(E,D){for(var F in this.ids){for(var C in this.ids[F]){var G=this.ids[F][C];if(!this.isTypeOfDD(G)){continue;}G[E].apply(G,D);}}},_onLoad:function(){this.init();A.on(document,"mouseup",this.handleMouseUp,this,true);A.on(document,"mousemove",this.handleMouseMove,this,true);A.on(window,"unload",this._onUnload,this,true);A.on(window,"resize",this._onResize,this,true);},_onResize:function(C){this._execOnAll("resetConstraints",[]);},lock:function(){this.locked=true;},unlock:function(){this.locked=false;},isLocked:function(){return this.locked;},locationCache:{},useCache:true,clickPixelThresh:3,clickTimeThresh:1000,dragThreshMet:false,clickTimeout:null,startX:0,startY:0,fromTimeout:false,regDragDrop:function(D,C){if(!this.initialized){this.init();}if(!this.ids[C]){this.ids[C]={};}this.ids[C][D.id]=D;},removeDDFromGroup:function(E,C){if(!this.ids[C]){this.ids[C]={};}var D=this.ids[C];if(D&&D[E.id]){delete D[E.id];}},_remove:function(E){for(var D in E.groups){if(D){var C=this.ids[D];if(C&&C[E.id]){delete C[E.id];}}}delete this.handleIds[E.id];},regHandle:function(D,C){if(!this.handleIds[D]){this.handleIds[D]={};}this.handleIds[D][C]=C;},isDragDrop:function(C){return(this.getDDById(C))?true:false;},getRelated:function(H,D){var G=[];for(var F in H.groups){for(var E in this.ids[F]){var C=this.ids[F][E];if(!this.isTypeOfDD(C)){continue;}if(!D||C.isTarget){G[G.length]=C;}}}return G;},isLegalTarget:function(G,F){var D=this.getRelated(G,true);for(var E=0,C=D.length;E<C;++E){if(D[E].id==F.id){return true;}}return false;},isTypeOfDD:function(C){return(C&&C.__ygDragDrop);},isHandle:function(D,C){return(this.handleIds[D]&&this.handleIds[D][C]);},getDDById:function(D){for(var C in this.ids){if(this.ids[C][D]){return this.ids[C][D];}}return null;},handleMouseDown:function(E,D){this.currentTarget=YAHOO.util.Event.getTarget(E);this.dragCurrent=D;var C=D.getEl();this.startX=YAHOO.util.Event.getPageX(E);this.startY=YAHOO.util.Event.getPageY(E);this.deltaX=this.startX-C.offsetLeft;this.deltaY=this.startY-C.offsetTop;this.dragThreshMet=false;this.clickTimeout=setTimeout(function(){var F=YAHOO.util.DDM;F.startDrag(F.startX,F.startY);F.fromTimeout=true;},this.clickTimeThresh);},startDrag:function(C,E){if(this.dragCurrent&&this.dragCurrent.useShim){this._shimState=this.useShim;this.useShim=true;}this._activateShim();clearTimeout(this.clickTimeout);var D=this.dragCurrent;if(D&&D.events.b4StartDrag){D.b4StartDrag(C,E);D.fireEvent("b4StartDragEvent",{x:C,y:E});}if(D&&D.events.startDrag){D.startDrag(C,E);D.fireEvent("startDragEvent",{x:C,y:E});}this.dragThreshMet=true;},handleMouseUp:function(C){if(this.dragCurrent){clearTimeout(this.clickTimeout);if(this.dragThreshMet){if(this.fromTimeout){this.fromTimeout=false;this.handleMouseMove(C);}this.fromTimeout=false;this.fireEvents(C,true);}else{}this.stopDrag(C);this.stopEvent(C);}},stopEvent:function(C){if(this.stopPropagation){YAHOO.util.Event.stopPropagation(C);}if(this.preventDefault){YAHOO.util.Event.preventDefault(C);}},stopDrag:function(E,D){var C=this.dragCurrent;if(C&&!D){if(this.dragThreshMet){if(C.events.b4EndDrag){C.b4EndDrag(E);C.fireEvent("b4EndDragEvent",{e:E});}if(C.events.endDrag){C.endDrag(E);C.fireEvent("endDragEvent",{e:E});}}if(C.events.mouseUp){C.onMouseUp(E);C.fireEvent("mouseUpEvent",{e:E});}}if(this._shimActive){this._deactivateShim();if(this.dragCurrent&&this.dragCurrent.useShim){this.useShim=this._shimState;this._shimState=false;}}this.dragCurrent=null;this.dragOvers={};},handleMouseMove:function(F){var C=this.dragCurrent;if(C){if(YAHOO.util.Event.isIE&&!F.button){this.stopEvent(F);return this.handleMouseUp(F);}else{if(F.clientX<0||F.clientY<0){}}if(!this.dragThreshMet){var E=Math.abs(this.startX-YAHOO.util.Event.getPageX(F));var D=Math.abs(this.startY-YAHOO.util.Event.getPageY(F));if(E>this.clickPixelThresh||D>this.clickPixelThresh){this.startDrag(this.startX,this.startY);}}if(this.dragThreshMet){if(C&&C.events.b4Drag){C.b4Drag(F);C.fireEvent("b4DragEvent",{e:F});}if(C&&C.events.drag){C.onDrag(F);C.fireEvent("dragEvent",{e:F});}if(C){this.fireEvents(F,false);}}this.stopEvent(F);}},fireEvents:function(V,L){var a=this.dragCurrent;if(!a||a.isLocked()||a.dragOnly){return;}var N=YAHOO.util.Event.getPageX(V),M=YAHOO.util.Event.getPageY(V),P=new YAHOO.util.Point(N,M),K=a.getTargetCoord(P.x,P.y),F=a.getDragEl(),E=["out","over","drop","enter"],U=new YAHOO.util.Region(K.y,K.x+F.offsetWidth,K.y+F.offsetHeight,K.x),I=[],D={},Q=[],c={outEvts:[],overEvts:[],dropEvts:[],enterEvts:[]};for(var S in this.dragOvers){var d=this.dragOvers[S];if(!this.isTypeOfDD(d)){continue;
8
}if(!this.isOverTarget(P,d,this.mode,U)){c.outEvts.push(d);}I[S]=true;delete this.dragOvers[S];}for(var R in a.groups){if("string"!=typeof R){continue;}for(S in this.ids[R]){var G=this.ids[R][S];if(!this.isTypeOfDD(G)){continue;}if(G.isTarget&&!G.isLocked()&&G!=a){if(this.isOverTarget(P,G,this.mode,U)){D[R]=true;if(L){c.dropEvts.push(G);}else{if(!I[G.id]){c.enterEvts.push(G);}else{c.overEvts.push(G);}this.dragOvers[G.id]=G;}}}}}this.interactionInfo={out:c.outEvts,enter:c.enterEvts,over:c.overEvts,drop:c.dropEvts,point:P,draggedRegion:U,sourceRegion:this.locationCache[a.id],validDrop:L};for(var C in D){Q.push(C);}if(L&&!c.dropEvts.length){this.interactionInfo.validDrop=false;if(a.events.invalidDrop){a.onInvalidDrop(V);a.fireEvent("invalidDropEvent",{e:V});}}for(S=0;S<E.length;S++){var Y=null;if(c[E[S]+"Evts"]){Y=c[E[S]+"Evts"];}if(Y&&Y.length){var H=E[S].charAt(0).toUpperCase()+E[S].substr(1),X="onDrag"+H,J="b4Drag"+H,O="drag"+H+"Event",W="drag"+H;if(this.mode){if(a.events[J]){a[J](V,Y,Q);a.fireEvent(J+"Event",{event:V,info:Y,group:Q});}if(a.events[W]){a[X](V,Y,Q);a.fireEvent(O,{event:V,info:Y,group:Q});}}else{for(var Z=0,T=Y.length;Z<T;++Z){if(a.events[J]){a[J](V,Y[Z].id,Q[0]);a.fireEvent(J+"Event",{event:V,info:Y[Z].id,group:Q[0]});}if(a.events[W]){a[X](V,Y[Z].id,Q[0]);a.fireEvent(O,{event:V,info:Y[Z].id,group:Q[0]});}}}}}},getBestMatch:function(E){var G=null;var D=E.length;if(D==1){G=E[0];}else{for(var F=0;F<D;++F){var C=E[F];if(this.mode==this.INTERSECT&&C.cursorIsOver){G=C;break;}else{if(!G||!G.overlap||(C.overlap&&G.overlap.getArea()<C.overlap.getArea())){G=C;}}}}return G;},refreshCache:function(D){var F=D||this.ids;for(var C in F){if("string"!=typeof C){continue;}for(var E in this.ids[C]){var G=this.ids[C][E];if(this.isTypeOfDD(G)){var H=this.getLocation(G);if(H){this.locationCache[G.id]=H;}else{delete this.locationCache[G.id];}}}}},verifyEl:function(D){try{if(D){var C=D.offsetParent;if(C){return true;}}}catch(E){}return false;},getLocation:function(H){if(!this.isTypeOfDD(H)){return null;}var F=H.getEl(),K,E,D,M,L,N,C,J,G;try{K=YAHOO.util.Dom.getXY(F);}catch(I){}if(!K){return null;}E=K[0];D=E+F.offsetWidth;M=K[1];L=M+F.offsetHeight;N=M-H.padding[0];C=D+H.padding[1];J=L+H.padding[2];G=E-H.padding[3];return new YAHOO.util.Region(N,C,J,G);},isOverTarget:function(K,C,E,F){var G=this.locationCache[C.id];if(!G||!this.useCache){G=this.getLocation(C);this.locationCache[C.id]=G;}if(!G){return false;}C.cursorIsOver=G.contains(K);var J=this.dragCurrent;if(!J||(!E&&!J.constrainX&&!J.constrainY)){return C.cursorIsOver;}C.overlap=null;if(!F){var H=J.getTargetCoord(K.x,K.y);var D=J.getDragEl();F=new YAHOO.util.Region(H.y,H.x+D.offsetWidth,H.y+D.offsetHeight,H.x);}var I=F.intersect(G);if(I){C.overlap=I;return(E)?true:C.cursorIsOver;}else{return false;}},_onUnload:function(D,C){this.unregAll();},unregAll:function(){if(this.dragCurrent){this.stopDrag();this.dragCurrent=null;}this._execOnAll("unreg",[]);this.ids={};},elementCache:{},getElWrapper:function(D){var C=this.elementCache[D];if(!C||!C.el){C=this.elementCache[D]=new this.ElementWrapper(YAHOO.util.Dom.get(D));}return C;},getElement:function(C){return YAHOO.util.Dom.get(C);},getCss:function(D){var C=YAHOO.util.Dom.get(D);return(C)?C.style:null;},ElementWrapper:function(C){this.el=C||null;this.id=this.el&&C.id;this.css=this.el&&C.style;},getPosX:function(C){return YAHOO.util.Dom.getX(C);},getPosY:function(C){return YAHOO.util.Dom.getY(C);},swapNode:function(E,C){if(E.swapNode){E.swapNode(C);}else{var F=C.parentNode;var D=C.nextSibling;if(D==E){F.insertBefore(E,C);}else{if(C==E.nextSibling){F.insertBefore(C,E);}else{E.parentNode.replaceChild(C,E);F.insertBefore(E,D);}}}},getScroll:function(){var E,C,F=document.documentElement,D=document.body;if(F&&(F.scrollTop||F.scrollLeft)){E=F.scrollTop;C=F.scrollLeft;}else{if(D){E=D.scrollTop;C=D.scrollLeft;}else{}}return{top:E,left:C};},getStyle:function(D,C){return YAHOO.util.Dom.getStyle(D,C);},getScrollTop:function(){return this.getScroll().top;},getScrollLeft:function(){return this.getScroll().left;},moveToEl:function(C,E){var D=YAHOO.util.Dom.getXY(E);YAHOO.util.Dom.setXY(C,D);},getClientHeight:function(){return YAHOO.util.Dom.getViewportHeight();},getClientWidth:function(){return YAHOO.util.Dom.getViewportWidth();},numericSort:function(D,C){return(D-C);},_timeoutCount:0,_addListeners:function(){var C=YAHOO.util.DDM;if(YAHOO.util.Event&&document){C._onLoad();}else{if(C._timeoutCount>2000){}else{setTimeout(C._addListeners,10);if(document&&document.body){C._timeoutCount+=1;}}}},handleWasClicked:function(C,E){if(this.isHandle(E,C.id)){return true;}else{var D=C.parentNode;while(D){if(this.isHandle(E,D.id)){return true;}else{D=D.parentNode;}}}return false;}};}();YAHOO.util.DDM=YAHOO.util.DragDropMgr;YAHOO.util.DDM._addListeners();}(function(){var A=YAHOO.util.Event;var B=YAHOO.util.Dom;YAHOO.util.DragDrop=function(E,C,D){if(E){this.init(E,C,D);}};YAHOO.util.DragDrop.prototype={events:null,on:function(){this.subscribe.apply(this,arguments);},id:null,config:null,dragElId:null,handleElId:null,invalidHandleTypes:null,invalidHandleIds:null,invalidHandleClasses:null,startPageX:0,startPageY:0,groups:null,locked:false,lock:function(){this.locked=true;},unlock:function(){this.locked=false;},isTarget:true,padding:null,dragOnly:false,useShim:false,_domRef:null,__ygDragDrop:true,constrainX:false,constrainY:false,minX:0,maxX:0,minY:0,maxY:0,deltaX:0,deltaY:0,maintainOffset:false,xTicks:null,yTicks:null,primaryButtonOnly:true,available:false,hasOuterHandles:false,cursorIsOver:false,overlap:null,b4StartDrag:function(C,D){},startDrag:function(C,D){},b4Drag:function(C){},onDrag:function(C){},onDragEnter:function(C,D){},b4DragOver:function(C){},onDragOver:function(C,D){},b4DragOut:function(C){},onDragOut:function(C,D){},b4DragDrop:function(C){},onDragDrop:function(C,D){},onInvalidDrop:function(C){},b4EndDrag:function(C){},endDrag:function(C){},b4MouseDown:function(C){},onMouseDown:function(C){},onMouseUp:function(C){},onAvailable:function(){},getEl:function(){if(!this._domRef){this._domRef=B.get(this.id);
9
}return this._domRef;},getDragEl:function(){return B.get(this.dragElId);},init:function(F,C,D){this.initTarget(F,C,D);A.on(this._domRef||this.id,"mousedown",this.handleMouseDown,this,true);for(var E in this.events){this.createEvent(E+"Event");}},initTarget:function(E,C,D){this.config=D||{};this.events={};this.DDM=YAHOO.util.DDM;this.groups={};if(typeof E!=="string"){this._domRef=E;E=B.generateId(E);}this.id=E;this.addToGroup((C)?C:"default");this.handleElId=E;A.onAvailable(E,this.handleOnAvailable,this,true);this.setDragElId(E);this.invalidHandleTypes={A:"A"};this.invalidHandleIds={};this.invalidHandleClasses=[];this.applyConfig();},applyConfig:function(){this.events={mouseDown:true,b4MouseDown:true,mouseUp:true,b4StartDrag:true,startDrag:true,b4EndDrag:true,endDrag:true,drag:true,b4Drag:true,invalidDrop:true,b4DragOut:true,dragOut:true,dragEnter:true,b4DragOver:true,dragOver:true,b4DragDrop:true,dragDrop:true};if(this.config.events){for(var C in this.config.events){if(this.config.events[C]===false){this.events[C]=false;}}}this.padding=this.config.padding||[0,0,0,0];this.isTarget=(this.config.isTarget!==false);this.maintainOffset=(this.config.maintainOffset);this.primaryButtonOnly=(this.config.primaryButtonOnly!==false);this.dragOnly=((this.config.dragOnly===true)?true:false);this.useShim=((this.config.useShim===true)?true:false);},handleOnAvailable:function(){this.available=true;this.resetConstraints();this.onAvailable();},setPadding:function(E,C,F,D){if(!C&&0!==C){this.padding=[E,E,E,E];}else{if(!F&&0!==F){this.padding=[E,C,E,C];}else{this.padding=[E,C,F,D];}}},setInitPosition:function(F,E){var G=this.getEl();if(!this.DDM.verifyEl(G)){if(G&&G.style&&(G.style.display=="none")){}else{}return;}var D=F||0;var C=E||0;var H=B.getXY(G);this.initPageX=H[0]-D;this.initPageY=H[1]-C;this.lastPageX=H[0];this.lastPageY=H[1];this.setStartPosition(H);},setStartPosition:function(D){var C=D||B.getXY(this.getEl());this.deltaSetXY=null;this.startPageX=C[0];this.startPageY=C[1];},addToGroup:function(C){this.groups[C]=true;this.DDM.regDragDrop(this,C);},removeFromGroup:function(C){if(this.groups[C]){delete this.groups[C];}this.DDM.removeDDFromGroup(this,C);},setDragElId:function(C){this.dragElId=C;},setHandleElId:function(C){if(typeof C!=="string"){C=B.generateId(C);}this.handleElId=C;this.DDM.regHandle(this.id,C);},setOuterHandleElId:function(C){if(typeof C!=="string"){C=B.generateId(C);}A.on(C,"mousedown",this.handleMouseDown,this,true);this.setHandleElId(C);this.hasOuterHandles=true;},unreg:function(){A.removeListener(this.id,"mousedown",this.handleMouseDown);this._domRef=null;this.DDM._remove(this);},isLocked:function(){return(this.DDM.isLocked()||this.locked);},handleMouseDown:function(J,I){var D=J.which||J.button;if(this.primaryButtonOnly&&D>1){return;}if(this.isLocked()){return;}var C=this.b4MouseDown(J),F=true;if(this.events.b4MouseDown){F=this.fireEvent("b4MouseDownEvent",J);}var E=this.onMouseDown(J),H=true;if(this.events.mouseDown){H=this.fireEvent("mouseDownEvent",J);}if((C===false)||(E===false)||(F===false)||(H===false)){return;}this.DDM.refreshCache(this.groups);var G=new YAHOO.util.Point(A.getPageX(J),A.getPageY(J));if(!this.hasOuterHandles&&!this.DDM.isOverTarget(G,this)){}else{if(this.clickValidator(J)){this.setStartPosition();this.DDM.handleMouseDown(J,this);this.DDM.stopEvent(J);}else{}}},clickValidator:function(D){var C=YAHOO.util.Event.getTarget(D);return(this.isValidHandleChild(C)&&(this.id==this.handleElId||this.DDM.handleWasClicked(C,this.id)));},getTargetCoord:function(E,D){var C=E-this.deltaX;var F=D-this.deltaY;if(this.constrainX){if(C<this.minX){C=this.minX;}if(C>this.maxX){C=this.maxX;}}if(this.constrainY){if(F<this.minY){F=this.minY;}if(F>this.maxY){F=this.maxY;}}C=this.getTick(C,this.xTicks);F=this.getTick(F,this.yTicks);return{x:C,y:F};},addInvalidHandleType:function(C){var D=C.toUpperCase();this.invalidHandleTypes[D]=D;},addInvalidHandleId:function(C){if(typeof C!=="string"){C=B.generateId(C);}this.invalidHandleIds[C]=C;},addInvalidHandleClass:function(C){this.invalidHandleClasses.push(C);},removeInvalidHandleType:function(C){var D=C.toUpperCase();delete this.invalidHandleTypes[D];},removeInvalidHandleId:function(C){if(typeof C!=="string"){C=B.generateId(C);}delete this.invalidHandleIds[C];},removeInvalidHandleClass:function(D){for(var E=0,C=this.invalidHandleClasses.length;E<C;++E){if(this.invalidHandleClasses[E]==D){delete this.invalidHandleClasses[E];}}},isValidHandleChild:function(F){var E=true;var H;try{H=F.nodeName.toUpperCase();}catch(G){H=F.nodeName;}E=E&&!this.invalidHandleTypes[H];E=E&&!this.invalidHandleIds[F.id];for(var D=0,C=this.invalidHandleClasses.length;E&&D<C;++D){E=!B.hasClass(F,this.invalidHandleClasses[D]);}return E;},setXTicks:function(F,C){this.xTicks=[];this.xTickSize=C;var E={};for(var D=this.initPageX;D>=this.minX;D=D-C){if(!E[D]){this.xTicks[this.xTicks.length]=D;E[D]=true;}}for(D=this.initPageX;D<=this.maxX;D=D+C){if(!E[D]){this.xTicks[this.xTicks.length]=D;E[D]=true;}}this.xTicks.sort(this.DDM.numericSort);},setYTicks:function(F,C){this.yTicks=[];this.yTickSize=C;var E={};for(var D=this.initPageY;D>=this.minY;D=D-C){if(!E[D]){this.yTicks[this.yTicks.length]=D;E[D]=true;}}for(D=this.initPageY;D<=this.maxY;D=D+C){if(!E[D]){this.yTicks[this.yTicks.length]=D;E[D]=true;}}this.yTicks.sort(this.DDM.numericSort);},setXConstraint:function(E,D,C){this.leftConstraint=parseInt(E,10);this.rightConstraint=parseInt(D,10);this.minX=this.initPageX-this.leftConstraint;this.maxX=this.initPageX+this.rightConstraint;if(C){this.setXTicks(this.initPageX,C);}this.constrainX=true;},clearConstraints:function(){this.constrainX=false;this.constrainY=false;this.clearTicks();},clearTicks:function(){this.xTicks=null;this.yTicks=null;this.xTickSize=0;this.yTickSize=0;},setYConstraint:function(C,E,D){this.topConstraint=parseInt(C,10);this.bottomConstraint=parseInt(E,10);this.minY=this.initPageY-this.topConstraint;this.maxY=this.initPageY+this.bottomConstraint;if(D){this.setYTicks(this.initPageY,D);
10
}this.constrainY=true;},resetConstraints:function(){if(this.initPageX||this.initPageX===0){var D=(this.maintainOffset)?this.lastPageX-this.initPageX:0;var C=(this.maintainOffset)?this.lastPageY-this.initPageY:0;this.setInitPosition(D,C);}else{this.setInitPosition();}if(this.constrainX){this.setXConstraint(this.leftConstraint,this.rightConstraint,this.xTickSize);}if(this.constrainY){this.setYConstraint(this.topConstraint,this.bottomConstraint,this.yTickSize);}},getTick:function(I,F){if(!F){return I;}else{if(F[0]>=I){return F[0];}else{for(var D=0,C=F.length;D<C;++D){var E=D+1;if(F[E]&&F[E]>=I){var H=I-F[D];var G=F[E]-I;return(G>H)?F[D]:F[E];}}return F[F.length-1];}}},toString:function(){return("DragDrop "+this.id);}};YAHOO.augment(YAHOO.util.DragDrop,YAHOO.util.EventProvider);})();YAHOO.util.DD=function(C,A,B){if(C){this.init(C,A,B);}};YAHOO.extend(YAHOO.util.DD,YAHOO.util.DragDrop,{scroll:true,autoOffset:function(C,B){var A=C-this.startPageX;var D=B-this.startPageY;this.setDelta(A,D);},setDelta:function(B,A){this.deltaX=B;this.deltaY=A;},setDragElPos:function(C,B){var A=this.getDragEl();this.alignElWithMouse(A,C,B);},alignElWithMouse:function(C,G,F){var E=this.getTargetCoord(G,F);if(!this.deltaSetXY){var H=[E.x,E.y];YAHOO.util.Dom.setXY(C,H);var D=parseInt(YAHOO.util.Dom.getStyle(C,"left"),10);var B=parseInt(YAHOO.util.Dom.getStyle(C,"top"),10);this.deltaSetXY=[D-E.x,B-E.y];}else{YAHOO.util.Dom.setStyle(C,"left",(E.x+this.deltaSetXY[0])+"px");YAHOO.util.Dom.setStyle(C,"top",(E.y+this.deltaSetXY[1])+"px");}this.cachePosition(E.x,E.y);var A=this;setTimeout(function(){A.autoScroll.call(A,E.x,E.y,C.offsetHeight,C.offsetWidth);},0);},cachePosition:function(B,A){if(B){this.lastPageX=B;this.lastPageY=A;}else{var C=YAHOO.util.Dom.getXY(this.getEl());this.lastPageX=C[0];this.lastPageY=C[1];}},autoScroll:function(J,I,E,K){if(this.scroll){var L=this.DDM.getClientHeight();var B=this.DDM.getClientWidth();var N=this.DDM.getScrollTop();var D=this.DDM.getScrollLeft();var H=E+I;var M=K+J;var G=(L+N-I-this.deltaY);var F=(B+D-J-this.deltaX);var C=40;var A=(document.all)?80:30;if(H>L&&G<C){window.scrollTo(D,N+A);}if(I<N&&N>0&&I-N<C){window.scrollTo(D,N-A);}if(M>B&&F<C){window.scrollTo(D+A,N);}if(J<D&&D>0&&J-D<C){window.scrollTo(D-A,N);}}},applyConfig:function(){YAHOO.util.DD.superclass.applyConfig.call(this);this.scroll=(this.config.scroll!==false);},b4MouseDown:function(A){this.setStartPosition();this.autoOffset(YAHOO.util.Event.getPageX(A),YAHOO.util.Event.getPageY(A));},b4Drag:function(A){this.setDragElPos(YAHOO.util.Event.getPageX(A),YAHOO.util.Event.getPageY(A));},toString:function(){return("DD "+this.id);}});YAHOO.util.DDProxy=function(C,A,B){if(C){this.init(C,A,B);this.initFrame();}};YAHOO.util.DDProxy.dragElId="ygddfdiv";YAHOO.extend(YAHOO.util.DDProxy,YAHOO.util.DD,{resizeFrame:true,centerFrame:false,createFrame:function(){var B=this,A=document.body;if(!A||!A.firstChild){setTimeout(function(){B.createFrame();},50);return;}var F=this.getDragEl(),E=YAHOO.util.Dom;if(!F){F=document.createElement("div");F.id=this.dragElId;var D=F.style;D.position="absolute";D.visibility="hidden";D.cursor="move";D.border="2px solid #aaa";D.zIndex=999;D.height="25px";D.width="25px";var C=document.createElement("div");E.setStyle(C,"height","100%");E.setStyle(C,"width","100%");E.setStyle(C,"background-color","#ccc");E.setStyle(C,"opacity","0");F.appendChild(C);A.insertBefore(F,A.firstChild);}},initFrame:function(){this.createFrame();},applyConfig:function(){YAHOO.util.DDProxy.superclass.applyConfig.call(this);this.resizeFrame=(this.config.resizeFrame!==false);this.centerFrame=(this.config.centerFrame);this.setDragElId(this.config.dragElId||YAHOO.util.DDProxy.dragElId);},showFrame:function(E,D){var C=this.getEl();var A=this.getDragEl();var B=A.style;this._resizeProxy();if(this.centerFrame){this.setDelta(Math.round(parseInt(B.width,10)/2),Math.round(parseInt(B.height,10)/2));}this.setDragElPos(E,D);YAHOO.util.Dom.setStyle(A,"visibility","visible");},_resizeProxy:function(){if(this.resizeFrame){var H=YAHOO.util.Dom;var B=this.getEl();var C=this.getDragEl();var G=parseInt(H.getStyle(C,"borderTopWidth"),10);var I=parseInt(H.getStyle(C,"borderRightWidth"),10);var F=parseInt(H.getStyle(C,"borderBottomWidth"),10);var D=parseInt(H.getStyle(C,"borderLeftWidth"),10);if(isNaN(G)){G=0;}if(isNaN(I)){I=0;}if(isNaN(F)){F=0;}if(isNaN(D)){D=0;}var E=Math.max(0,B.offsetWidth-I-D);var A=Math.max(0,B.offsetHeight-G-F);H.setStyle(C,"width",E+"px");H.setStyle(C,"height",A+"px");}},b4MouseDown:function(B){this.setStartPosition();var A=YAHOO.util.Event.getPageX(B);var C=YAHOO.util.Event.getPageY(B);this.autoOffset(A,C);},b4StartDrag:function(A,B){this.showFrame(A,B);},b4EndDrag:function(A){YAHOO.util.Dom.setStyle(this.getDragEl(),"visibility","hidden");},endDrag:function(D){var C=YAHOO.util.Dom;var B=this.getEl();var A=this.getDragEl();C.setStyle(A,"visibility","");C.setStyle(B,"visibility","hidden");YAHOO.util.DDM.moveToEl(B,A);C.setStyle(A,"visibility","hidden");C.setStyle(B,"visibility","");},toString:function(){return("DDProxy "+this.id);}});YAHOO.util.DDTarget=function(C,A,B){if(C){this.initTarget(C,A,B);}};YAHOO.extend(YAHOO.util.DDTarget,YAHOO.util.DragDrop,{toString:function(){return("DDTarget "+this.id);}});YAHOO.register("dragdrop",YAHOO.util.DragDropMgr,{version:"2.8.0r4",build:"2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/dragdrop/dragdrop.js (-3601 lines)
Lines 1-3601 Link Here
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.8.0r4
6
*/
7
/**
8
 * The drag and drop utility provides a framework for building drag and drop
9
 * applications.  In addition to enabling drag and drop for specific elements,
10
 * the drag and drop elements are tracked by the manager class, and the
11
 * interactions between the various elements are tracked during the drag and
12
 * the implementing code is notified about these important moments.
13
 * @module dragdrop
14
 * @title Drag and Drop
15
 * @requires yahoo,dom,event
16
 * @namespace YAHOO.util
17
 */
18
19
// Only load the library once.  Rewriting the manager class would orphan 
20
// existing drag and drop instances.
21
if (!YAHOO.util.DragDropMgr) {
22
23
/**
24
 * DragDropMgr is a singleton that tracks the element interaction for 
25
 * all DragDrop items in the window.  Generally, you will not call 
26
 * this class directly, but it does have helper methods that could 
27
 * be useful in your DragDrop implementations.
28
 * @class DragDropMgr
29
 * @static
30
 */
31
YAHOO.util.DragDropMgr = function() {
32
33
    var Event = YAHOO.util.Event,
34
        Dom = YAHOO.util.Dom;
35
36
    return {
37
        /**
38
        * This property is used to turn on global use of the shim element on all DragDrop instances, defaults to false for backcompat. (Use: YAHOO.util.DDM.useShim = true)
39
        * @property useShim
40
        * @type Boolean
41
        * @static
42
        */
43
        useShim: false,
44
        /**
45
        * This property is used to determine if the shim is active over the screen, default false.
46
        * @private
47
        * @property _shimActive
48
        * @type Boolean
49
        * @static
50
        */
51
        _shimActive: false,
52
        /**
53
        * This property is used when useShim is set on a DragDrop object to store the current state of DDM.useShim so it can be reset when a drag operation is done.
54
        * @private
55
        * @property _shimState
56
        * @type Boolean
57
        * @static
58
        */
59
        _shimState: false,
60
        /**
61
        * This property is used when useShim is set to true, it will set the opacity on the shim to .5 for debugging. Use: (YAHOO.util.DDM._debugShim = true;)
62
        * @private
63
        * @property _debugShim
64
        * @type Boolean
65
        * @static
66
        */
67
        _debugShim: false,
68
        /**
69
        * This method will create a shim element (giving it the id of yui-ddm-shim), it also attaches the mousemove and mouseup listeners to it and attaches a scroll listener on the window
70
        * @private
71
        * @method _sizeShim
72
        * @static
73
        */
74
        _createShim: function() {
75
            var s = document.createElement('div');
76
            s.id = 'yui-ddm-shim';
77
            if (document.body.firstChild) {
78
                document.body.insertBefore(s, document.body.firstChild);
79
            } else {
80
                document.body.appendChild(s);
81
            }
82
            s.style.display = 'none';
83
            s.style.backgroundColor = 'red';
84
            s.style.position = 'absolute';
85
            s.style.zIndex = '99999';
86
            Dom.setStyle(s, 'opacity', '0');
87
            this._shim = s;
88
            Event.on(s, "mouseup",   this.handleMouseUp, this, true);
89
            Event.on(s, "mousemove", this.handleMouseMove, this, true);
90
            Event.on(window, 'scroll', this._sizeShim, this, true);
91
        },
92
        /**
93
        * This method will size the shim, called from activate and on window scroll event
94
        * @private
95
        * @method _sizeShim
96
        * @static
97
        */
98
        _sizeShim: function() {
99
            if (this._shimActive) {
100
                var s = this._shim;
101
                s.style.height = Dom.getDocumentHeight() + 'px';
102
                s.style.width = Dom.getDocumentWidth() + 'px';
103
                s.style.top = '0';
104
                s.style.left = '0';
105
            }
106
        },
107
        /**
108
        * This method will create the shim element if needed, then show the shim element, size the element and set the _shimActive property to true
109
        * @private
110
        * @method _activateShim
111
        * @static
112
        */
113
        _activateShim: function() {
114
            if (this.useShim) {
115
                if (!this._shim) {
116
                    this._createShim();
117
                }
118
                this._shimActive = true;
119
                var s = this._shim,
120
                    o = '0';
121
                if (this._debugShim) {
122
                    o = '.5';
123
                }
124
                Dom.setStyle(s, 'opacity', o);
125
                this._sizeShim();
126
                s.style.display = 'block';
127
            }
128
        },
129
        /**
130
        * This method will hide the shim element and set the _shimActive property to false
131
        * @private
132
        * @method _deactivateShim
133
        * @static
134
        */
135
        _deactivateShim: function() {
136
            this._shim.style.display = 'none';
137
            this._shimActive = false;
138
        },
139
        /**
140
        * The HTML element created to use as a shim over the document to track mouse movements
141
        * @private
142
        * @property _shim
143
        * @type HTMLElement
144
        * @static
145
        */
146
        _shim: null,
147
        /**
148
         * Two dimensional Array of registered DragDrop objects.  The first 
149
         * dimension is the DragDrop item group, the second the DragDrop 
150
         * object.
151
         * @property ids
152
         * @type {string: string}
153
         * @private
154
         * @static
155
         */
156
        ids: {},
157
158
        /**
159
         * Array of element ids defined as drag handles.  Used to determine 
160
         * if the element that generated the mousedown event is actually the 
161
         * handle and not the html element itself.
162
         * @property handleIds
163
         * @type {string: string}
164
         * @private
165
         * @static
166
         */
167
        handleIds: {},
168
169
        /**
170
         * the DragDrop object that is currently being dragged
171
         * @property dragCurrent
172
         * @type DragDrop
173
         * @private
174
         * @static
175
         **/
176
        dragCurrent: null,
177
178
        /**
179
         * the DragDrop object(s) that are being hovered over
180
         * @property dragOvers
181
         * @type Array
182
         * @private
183
         * @static
184
         */
185
        dragOvers: {},
186
187
        /**
188
         * the X distance between the cursor and the object being dragged
189
         * @property deltaX
190
         * @type int
191
         * @private
192
         * @static
193
         */
194
        deltaX: 0,
195
196
        /**
197
         * the Y distance between the cursor and the object being dragged
198
         * @property deltaY
199
         * @type int
200
         * @private
201
         * @static
202
         */
203
        deltaY: 0,
204
205
        /**
206
         * Flag to determine if we should prevent the default behavior of the
207
         * events we define. By default this is true, but this can be set to 
208
         * false if you need the default behavior (not recommended)
209
         * @property preventDefault
210
         * @type boolean
211
         * @static
212
         */
213
        preventDefault: true,
214
215
        /**
216
         * Flag to determine if we should stop the propagation of the events 
217
         * we generate. This is true by default but you may want to set it to
218
         * false if the html element contains other features that require the
219
         * mouse click.
220
         * @property stopPropagation
221
         * @type boolean
222
         * @static
223
         */
224
        stopPropagation: true,
225
226
        /**
227
         * Internal flag that is set to true when drag and drop has been
228
         * initialized
229
         * @property initialized
230
         * @private
231
         * @static
232
         */
233
        initialized: false,
234
235
        /**
236
         * All drag and drop can be disabled.
237
         * @property locked
238
         * @private
239
         * @static
240
         */
241
        locked: false,
242
243
        /**
244
         * Provides additional information about the current set of
245
         * interactions.  Can be accessed from the event handlers. It
246
         * contains the following properties:
247
         *
248
         *       out:       onDragOut interactions
249
         *       enter:     onDragEnter interactions
250
         *       over:      onDragOver interactions
251
         *       drop:      onDragDrop interactions
252
         *       point:     The location of the cursor
253
         *       draggedRegion: The location of dragged element at the time
254
         *                      of the interaction
255
         *       sourceRegion: The location of the source elemtn at the time
256
         *                     of the interaction
257
         *       validDrop: boolean
258
         * @property interactionInfo
259
         * @type object
260
         * @static
261
         */
262
        interactionInfo: null,
263
264
        /**
265
         * Called the first time an element is registered.
266
         * @method init
267
         * @private
268
         * @static
269
         */
270
        init: function() {
271
            this.initialized = true;
272
        },
273
274
        /**
275
         * In point mode, drag and drop interaction is defined by the 
276
         * location of the cursor during the drag/drop
277
         * @property POINT
278
         * @type int
279
         * @static
280
         * @final
281
         */
282
        POINT: 0,
283
284
        /**
285
         * In intersect mode, drag and drop interaction is defined by the 
286
         * cursor position or the amount of overlap of two or more drag and 
287
         * drop objects.
288
         * @property INTERSECT
289
         * @type int
290
         * @static
291
         * @final
292
         */
293
        INTERSECT: 1,
294
295
        /**
296
         * In intersect mode, drag and drop interaction is defined only by the 
297
         * overlap of two or more drag and drop objects.
298
         * @property STRICT_INTERSECT
299
         * @type int
300
         * @static
301
         * @final
302
         */
303
        STRICT_INTERSECT: 2,
304
305
        /**
306
         * The current drag and drop mode.  Default: POINT
307
         * @property mode
308
         * @type int
309
         * @static
310
         */
311
        mode: 0,
312
313
        /**
314
         * Runs method on all drag and drop objects
315
         * @method _execOnAll
316
         * @private
317
         * @static
318
         */
319
        _execOnAll: function(sMethod, args) {
320
            for (var i in this.ids) {
321
                for (var j in this.ids[i]) {
322
                    var oDD = this.ids[i][j];
323
                    if (! this.isTypeOfDD(oDD)) {
324
                        continue;
325
                    }
326
                    oDD[sMethod].apply(oDD, args);
327
                }
328
            }
329
        },
330
331
        /**
332
         * Drag and drop initialization.  Sets up the global event handlers
333
         * @method _onLoad
334
         * @private
335
         * @static
336
         */
337
        _onLoad: function() {
338
339
            this.init();
340
341
            Event.on(document, "mouseup",   this.handleMouseUp, this, true);
342
            Event.on(document, "mousemove", this.handleMouseMove, this, true);
343
            Event.on(window,   "unload",    this._onUnload, this, true);
344
            Event.on(window,   "resize",    this._onResize, this, true);
345
            // Event.on(window,   "mouseout",    this._test);
346
347
        },
348
349
        /**
350
         * Reset constraints on all drag and drop objs
351
         * @method _onResize
352
         * @private
353
         * @static
354
         */
355
        _onResize: function(e) {
356
            this._execOnAll("resetConstraints", []);
357
        },
358
359
        /**
360
         * Lock all drag and drop functionality
361
         * @method lock
362
         * @static
363
         */
364
        lock: function() { this.locked = true; },
365
366
        /**
367
         * Unlock all drag and drop functionality
368
         * @method unlock
369
         * @static
370
         */
371
        unlock: function() { this.locked = false; },
372
373
        /**
374
         * Is drag and drop locked?
375
         * @method isLocked
376
         * @return {boolean} True if drag and drop is locked, false otherwise.
377
         * @static
378
         */
379
        isLocked: function() { return this.locked; },
380
381
        /**
382
         * Location cache that is set for all drag drop objects when a drag is
383
         * initiated, cleared when the drag is finished.
384
         * @property locationCache
385
         * @private
386
         * @static
387
         */
388
        locationCache: {},
389
390
        /**
391
         * Set useCache to false if you want to force object the lookup of each
392
         * drag and drop linked element constantly during a drag.
393
         * @property useCache
394
         * @type boolean
395
         * @static
396
         */
397
        useCache: true,
398
399
        /**
400
         * The number of pixels that the mouse needs to move after the 
401
         * mousedown before the drag is initiated.  Default=3;
402
         * @property clickPixelThresh
403
         * @type int
404
         * @static
405
         */
406
        clickPixelThresh: 3,
407
408
        /**
409
         * The number of milliseconds after the mousedown event to initiate the
410
         * drag if we don't get a mouseup event. Default=1000
411
         * @property clickTimeThresh
412
         * @type int
413
         * @static
414
         */
415
        clickTimeThresh: 1000,
416
417
        /**
418
         * Flag that indicates that either the drag pixel threshold or the 
419
         * mousdown time threshold has been met
420
         * @property dragThreshMet
421
         * @type boolean
422
         * @private
423
         * @static
424
         */
425
        dragThreshMet: false,
426
427
        /**
428
         * Timeout used for the click time threshold
429
         * @property clickTimeout
430
         * @type Object
431
         * @private
432
         * @static
433
         */
434
        clickTimeout: null,
435
436
        /**
437
         * The X position of the mousedown event stored for later use when a 
438
         * drag threshold is met.
439
         * @property startX
440
         * @type int
441
         * @private
442
         * @static
443
         */
444
        startX: 0,
445
446
        /**
447
         * The Y position of the mousedown event stored for later use when a 
448
         * drag threshold is met.
449
         * @property startY
450
         * @type int
451
         * @private
452
         * @static
453
         */
454
        startY: 0,
455
456
        /**
457
         * Flag to determine if the drag event was fired from the click timeout and
458
         * not the mouse move threshold.
459
         * @property fromTimeout
460
         * @type boolean
461
         * @private
462
         * @static
463
         */
464
        fromTimeout: false,
465
466
        /**
467
         * Each DragDrop instance must be registered with the DragDropMgr.  
468
         * This is executed in DragDrop.init()
469
         * @method regDragDrop
470
         * @param {DragDrop} oDD the DragDrop object to register
471
         * @param {String} sGroup the name of the group this element belongs to
472
         * @static
473
         */
474
        regDragDrop: function(oDD, sGroup) {
475
            if (!this.initialized) { this.init(); }
476
            
477
            if (!this.ids[sGroup]) {
478
                this.ids[sGroup] = {};
479
            }
480
            this.ids[sGroup][oDD.id] = oDD;
481
        },
482
483
        /**
484
         * Removes the supplied dd instance from the supplied group. Executed
485
         * by DragDrop.removeFromGroup, so don't call this function directly.
486
         * @method removeDDFromGroup
487
         * @private
488
         * @static
489
         */
490
        removeDDFromGroup: function(oDD, sGroup) {
491
            if (!this.ids[sGroup]) {
492
                this.ids[sGroup] = {};
493
            }
494
495
            var obj = this.ids[sGroup];
496
            if (obj && obj[oDD.id]) {
497
                delete obj[oDD.id];
498
            }
499
        },
500
501
        /**
502
         * Unregisters a drag and drop item.  This is executed in 
503
         * DragDrop.unreg, use that method instead of calling this directly.
504
         * @method _remove
505
         * @private
506
         * @static
507
         */
508
        _remove: function(oDD) {
509
            for (var g in oDD.groups) {
510
                if (g) {
511
                    var item = this.ids[g];
512
                    if (item && item[oDD.id]) {
513
                        delete item[oDD.id];
514
                    }
515
                }
516
                
517
            }
518
            delete this.handleIds[oDD.id];
519
        },
520
521
        /**
522
         * Each DragDrop handle element must be registered.  This is done
523
         * automatically when executing DragDrop.setHandleElId()
524
         * @method regHandle
525
         * @param {String} sDDId the DragDrop id this element is a handle for
526
         * @param {String} sHandleId the id of the element that is the drag 
527
         * handle
528
         * @static
529
         */
530
        regHandle: function(sDDId, sHandleId) {
531
            if (!this.handleIds[sDDId]) {
532
                this.handleIds[sDDId] = {};
533
            }
534
            this.handleIds[sDDId][sHandleId] = sHandleId;
535
        },
536
537
        /**
538
         * Utility function to determine if a given element has been 
539
         * registered as a drag drop item.
540
         * @method isDragDrop
541
         * @param {String} id the element id to check
542
         * @return {boolean} true if this element is a DragDrop item, 
543
         * false otherwise
544
         * @static
545
         */
546
        isDragDrop: function(id) {
547
            return ( this.getDDById(id) ) ? true : false;
548
        },
549
550
        /**
551
         * Returns the drag and drop instances that are in all groups the
552
         * passed in instance belongs to.
553
         * @method getRelated
554
         * @param {DragDrop} p_oDD the obj to get related data for
555
         * @param {boolean} bTargetsOnly if true, only return targetable objs
556
         * @return {DragDrop[]} the related instances
557
         * @static
558
         */
559
        getRelated: function(p_oDD, bTargetsOnly) {
560
            var oDDs = [];
561
            for (var i in p_oDD.groups) {
562
                for (var j in this.ids[i]) {
563
                    var dd = this.ids[i][j];
564
                    if (! this.isTypeOfDD(dd)) {
565
                        continue;
566
                    }
567
                    if (!bTargetsOnly || dd.isTarget) {
568
                        oDDs[oDDs.length] = dd;
569
                    }
570
                }
571
            }
572
573
            return oDDs;
574
        },
575
576
        /**
577
         * Returns true if the specified dd target is a legal target for 
578
         * the specifice drag obj
579
         * @method isLegalTarget
580
         * @param {DragDrop} the drag obj
581
         * @param {DragDrop} the target
582
         * @return {boolean} true if the target is a legal target for the 
583
         * dd obj
584
         * @static
585
         */
586
        isLegalTarget: function (oDD, oTargetDD) {
587
            var targets = this.getRelated(oDD, true);
588
            for (var i=0, len=targets.length;i<len;++i) {
589
                if (targets[i].id == oTargetDD.id) {
590
                    return true;
591
                }
592
            }
593
594
            return false;
595
        },
596
597
        /**
598
         * My goal is to be able to transparently determine if an object is
599
         * typeof DragDrop, and the exact subclass of DragDrop.  typeof 
600
         * returns "object", oDD.constructor.toString() always returns
601
         * "DragDrop" and not the name of the subclass.  So for now it just
602
         * evaluates a well-known variable in DragDrop.
603
         * @method isTypeOfDD
604
         * @param {Object} the object to evaluate
605
         * @return {boolean} true if typeof oDD = DragDrop
606
         * @static
607
         */
608
        isTypeOfDD: function (oDD) {
609
            return (oDD && oDD.__ygDragDrop);
610
        },
611
612
        /**
613
         * Utility function to determine if a given element has been 
614
         * registered as a drag drop handle for the given Drag Drop object.
615
         * @method isHandle
616
         * @param {String} id the element id to check
617
         * @return {boolean} true if this element is a DragDrop handle, false 
618
         * otherwise
619
         * @static
620
         */
621
        isHandle: function(sDDId, sHandleId) {
622
            return ( this.handleIds[sDDId] && 
623
                            this.handleIds[sDDId][sHandleId] );
624
        },
625
626
        /**
627
         * Returns the DragDrop instance for a given id
628
         * @method getDDById
629
         * @param {String} id the id of the DragDrop object
630
         * @return {DragDrop} the drag drop object, null if it is not found
631
         * @static
632
         */
633
        getDDById: function(id) {
634
            for (var i in this.ids) {
635
                if (this.ids[i][id]) {
636
                    return this.ids[i][id];
637
                }
638
            }
639
            return null;
640
        },
641
642
        /**
643
         * Fired after a registered DragDrop object gets the mousedown event.
644
         * Sets up the events required to track the object being dragged
645
         * @method handleMouseDown
646
         * @param {Event} e the event
647
         * @param oDD the DragDrop object being dragged
648
         * @private
649
         * @static
650
         */
651
        handleMouseDown: function(e, oDD) {
652
            //this._activateShim();
653
654
            this.currentTarget = YAHOO.util.Event.getTarget(e);
655
656
            this.dragCurrent = oDD;
657
658
            var el = oDD.getEl();
659
660
            // track start position
661
            this.startX = YAHOO.util.Event.getPageX(e);
662
            this.startY = YAHOO.util.Event.getPageY(e);
663
664
            this.deltaX = this.startX - el.offsetLeft;
665
            this.deltaY = this.startY - el.offsetTop;
666
667
            this.dragThreshMet = false;
668
669
            this.clickTimeout = setTimeout( 
670
                    function() { 
671
                        var DDM = YAHOO.util.DDM;
672
                        DDM.startDrag(DDM.startX, DDM.startY);
673
                        DDM.fromTimeout = true;
674
                    }, 
675
                    this.clickTimeThresh );
676
        },
677
678
        /**
679
         * Fired when either the drag pixel threshold or the mousedown hold 
680
         * time threshold has been met.
681
         * @method startDrag
682
         * @param x {int} the X position of the original mousedown
683
         * @param y {int} the Y position of the original mousedown
684
         * @static
685
         */
686
        startDrag: function(x, y) {
687
            if (this.dragCurrent && this.dragCurrent.useShim) {
688
                this._shimState = this.useShim;
689
                this.useShim = true;
690
            }
691
            this._activateShim();
692
            clearTimeout(this.clickTimeout);
693
            var dc = this.dragCurrent;
694
            if (dc && dc.events.b4StartDrag) {
695
                dc.b4StartDrag(x, y);
696
                dc.fireEvent('b4StartDragEvent', { x: x, y: y });
697
            }
698
            if (dc && dc.events.startDrag) {
699
                dc.startDrag(x, y);
700
                dc.fireEvent('startDragEvent', { x: x, y: y });
701
            }
702
            this.dragThreshMet = true;
703
        },
704
705
        /**
706
         * Internal function to handle the mouseup event.  Will be invoked 
707
         * from the context of the document.
708
         * @method handleMouseUp
709
         * @param {Event} e the event
710
         * @private
711
         * @static
712
         */
713
        handleMouseUp: function(e) {
714
            if (this.dragCurrent) {
715
                clearTimeout(this.clickTimeout);
716
717
                if (this.dragThreshMet) {
718
                    if (this.fromTimeout) {
719
                        this.fromTimeout = false;
720
                        this.handleMouseMove(e);
721
                    }
722
                    this.fromTimeout = false;
723
                    this.fireEvents(e, true);
724
                } else {
725
                }
726
727
                this.stopDrag(e);
728
729
                this.stopEvent(e);
730
            }
731
        },
732
733
        /**
734
         * Utility to stop event propagation and event default, if these 
735
         * features are turned on.
736
         * @method stopEvent
737
         * @param {Event} e the event as returned by this.getEvent()
738
         * @static
739
         */
740
        stopEvent: function(e) {
741
            if (this.stopPropagation) {
742
                YAHOO.util.Event.stopPropagation(e);
743
            }
744
745
            if (this.preventDefault) {
746
                YAHOO.util.Event.preventDefault(e);
747
            }
748
        },
749
750
        /** 
751
         * Ends the current drag, cleans up the state, and fires the endDrag
752
         * and mouseUp events.  Called internally when a mouseup is detected
753
         * during the drag.  Can be fired manually during the drag by passing
754
         * either another event (such as the mousemove event received in onDrag)
755
         * or a fake event with pageX and pageY defined (so that endDrag and
756
         * onMouseUp have usable position data.).  Alternatively, pass true
757
         * for the silent parameter so that the endDrag and onMouseUp events
758
         * are skipped (so no event data is needed.)
759
         *
760
         * @method stopDrag
761
         * @param {Event} e the mouseup event, another event (or a fake event) 
762
         *                  with pageX and pageY defined, or nothing if the 
763
         *                  silent parameter is true
764
         * @param {boolean} silent skips the enddrag and mouseup events if true
765
         * @static
766
         */
767
        stopDrag: function(e, silent) {
768
            var dc = this.dragCurrent;
769
            // Fire the drag end event for the item that was dragged
770
            if (dc && !silent) {
771
                if (this.dragThreshMet) {
772
                    if (dc.events.b4EndDrag) {
773
                        dc.b4EndDrag(e);
774
                        dc.fireEvent('b4EndDragEvent', { e: e });
775
                    }
776
                    if (dc.events.endDrag) {
777
                        dc.endDrag(e);
778
                        dc.fireEvent('endDragEvent', { e: e });
779
                    }
780
                }
781
                if (dc.events.mouseUp) {
782
                    dc.onMouseUp(e);
783
                    dc.fireEvent('mouseUpEvent', { e: e });
784
                }
785
            }
786
787
            if (this._shimActive) {
788
                this._deactivateShim();
789
                if (this.dragCurrent && this.dragCurrent.useShim) {
790
                    this.useShim = this._shimState;
791
                    this._shimState = false;
792
                }
793
            }
794
795
            this.dragCurrent = null;
796
            this.dragOvers = {};
797
        },
798
799
        /** 
800
         * Internal function to handle the mousemove event.  Will be invoked 
801
         * from the context of the html element.
802
         *
803
         * @TODO figure out what we can do about mouse events lost when the 
804
         * user drags objects beyond the window boundary.  Currently we can 
805
         * detect this in internet explorer by verifying that the mouse is 
806
         * down during the mousemove event.  Firefox doesn't give us the 
807
         * button state on the mousemove event.
808
         * @method handleMouseMove
809
         * @param {Event} e the event
810
         * @private
811
         * @static
812
         */
813
        handleMouseMove: function(e) {
814
815
            var dc = this.dragCurrent;
816
            if (dc) {
817
818
                // var button = e.which || e.button;
819
820
                // check for IE mouseup outside of page boundary
821
                if (YAHOO.util.Event.isIE && !e.button) {
822
                    this.stopEvent(e);
823
                    return this.handleMouseUp(e);
824
                } else {
825
                    if (e.clientX < 0 || e.clientY < 0) {
826
                        //This will stop the element from leaving the viewport in FF, Opera & Safari
827
                        //Not turned on yet
828
                        //this.stopEvent(e);
829
                        //return false;
830
                    }
831
                }
832
833
                if (!this.dragThreshMet) {
834
                    var diffX = Math.abs(this.startX - YAHOO.util.Event.getPageX(e));
835
                    var diffY = Math.abs(this.startY - YAHOO.util.Event.getPageY(e));
836
                    if (diffX > this.clickPixelThresh || 
837
                                diffY > this.clickPixelThresh) {
838
                        this.startDrag(this.startX, this.startY);
839
                    }
840
                }
841
842
                if (this.dragThreshMet) {
843
                    if (dc && dc.events.b4Drag) {
844
                        dc.b4Drag(e);
845
                        dc.fireEvent('b4DragEvent', { e: e});
846
                    }
847
                    if (dc && dc.events.drag) {
848
                        dc.onDrag(e);
849
                        dc.fireEvent('dragEvent', { e: e});
850
                    }
851
                    if (dc) {
852
                        this.fireEvents(e, false);
853
                    }
854
                }
855
856
                this.stopEvent(e);
857
            }
858
        },
859
        
860
        /**
861
         * Iterates over all of the DragDrop elements to find ones we are 
862
         * hovering over or dropping on
863
         * @method fireEvents
864
         * @param {Event} e the event
865
         * @param {boolean} isDrop is this a drop op or a mouseover op?
866
         * @private
867
         * @static
868
         */
869
        fireEvents: function(e, isDrop) {
870
            var dc = this.dragCurrent;
871
872
            // If the user did the mouse up outside of the window, we could 
873
            // get here even though we have ended the drag.
874
            // If the config option dragOnly is true, bail out and don't fire the events
875
            if (!dc || dc.isLocked() || dc.dragOnly) {
876
                return;
877
            }
878
879
            var x = YAHOO.util.Event.getPageX(e),
880
                y = YAHOO.util.Event.getPageY(e),
881
                pt = new YAHOO.util.Point(x,y),
882
                pos = dc.getTargetCoord(pt.x, pt.y),
883
                el = dc.getDragEl(),
884
                events = ['out', 'over', 'drop', 'enter'],
885
                curRegion = new YAHOO.util.Region( pos.y, 
886
                                               pos.x + el.offsetWidth,
887
                                               pos.y + el.offsetHeight, 
888
                                               pos.x ),
889
            
890
                oldOvers = [], // cache the previous dragOver array
891
                inGroupsObj  = {},
892
                inGroups  = [],
893
                data = {
894
                    outEvts: [],
895
                    overEvts: [],
896
                    dropEvts: [],
897
                    enterEvts: []
898
                };
899
900
901
            // Check to see if the object(s) we were hovering over is no longer 
902
            // being hovered over so we can fire the onDragOut event
903
            for (var i in this.dragOvers) {
904
905
                var ddo = this.dragOvers[i];
906
907
                if (! this.isTypeOfDD(ddo)) {
908
                    continue;
909
                }
910
                if (! this.isOverTarget(pt, ddo, this.mode, curRegion)) {
911
                    data.outEvts.push( ddo );
912
                }
913
914
                oldOvers[i] = true;
915
                delete this.dragOvers[i];
916
            }
917
918
            for (var sGroup in dc.groups) {
919
                
920
                if ("string" != typeof sGroup) {
921
                    continue;
922
                }
923
924
                for (i in this.ids[sGroup]) {
925
                    var oDD = this.ids[sGroup][i];
926
                    if (! this.isTypeOfDD(oDD)) {
927
                        continue;
928
                    }
929
930
                    if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
931
                        if (this.isOverTarget(pt, oDD, this.mode, curRegion)) {
932
                            inGroupsObj[sGroup] = true;
933
                            // look for drop interactions
934
                            if (isDrop) {
935
                                data.dropEvts.push( oDD );
936
                            // look for drag enter and drag over interactions
937
                            } else {
938
939
                                // initial drag over: dragEnter fires
940
                                if (!oldOvers[oDD.id]) {
941
                                    data.enterEvts.push( oDD );
942
                                // subsequent drag overs: dragOver fires
943
                                } else {
944
                                    data.overEvts.push( oDD );
945
                                }
946
947
                                this.dragOvers[oDD.id] = oDD;
948
                            }
949
                        }
950
                    }
951
                }
952
            }
953
954
            this.interactionInfo = {
955
                out:       data.outEvts,
956
                enter:     data.enterEvts,
957
                over:      data.overEvts,
958
                drop:      data.dropEvts,
959
                point:     pt,
960
                draggedRegion:    curRegion,
961
                sourceRegion: this.locationCache[dc.id],
962
                validDrop: isDrop
963
            };
964
965
            
966
            for (var inG in inGroupsObj) {
967
                inGroups.push(inG);
968
            }
969
970
            // notify about a drop that did not find a target
971
            if (isDrop && !data.dropEvts.length) {
972
                this.interactionInfo.validDrop = false;
973
                if (dc.events.invalidDrop) {
974
                    dc.onInvalidDrop(e);
975
                    dc.fireEvent('invalidDropEvent', { e: e });
976
                }
977
            }
978
            for (i = 0; i < events.length; i++) {
979
                var tmp = null;
980
                if (data[events[i] + 'Evts']) {
981
                    tmp = data[events[i] + 'Evts'];
982
                }
983
                if (tmp && tmp.length) {
984
                    var type = events[i].charAt(0).toUpperCase() + events[i].substr(1),
985
                        ev = 'onDrag' + type,
986
                        b4 = 'b4Drag' + type,
987
                        cev = 'drag' + type + 'Event',
988
                        check = 'drag' + type;
989
                    if (this.mode) {
990
                        if (dc.events[b4]) {
991
                            dc[b4](e, tmp, inGroups);
992
                            dc.fireEvent(b4 + 'Event', { event: e, info: tmp, group: inGroups });
993
                            
994
                        }
995
                        if (dc.events[check]) {
996
                            dc[ev](e, tmp, inGroups);
997
                            dc.fireEvent(cev, { event: e, info: tmp, group: inGroups });
998
                        }
999
                    } else {
1000
                        for (var b = 0, len = tmp.length; b < len; ++b) {
1001
                            if (dc.events[b4]) {
1002
                                dc[b4](e, tmp[b].id, inGroups[0]);
1003
                                dc.fireEvent(b4 + 'Event', { event: e, info: tmp[b].id, group: inGroups[0] });
1004
                            }
1005
                            if (dc.events[check]) {
1006
                                dc[ev](e, tmp[b].id, inGroups[0]);
1007
                                dc.fireEvent(cev, { event: e, info: tmp[b].id, group: inGroups[0] });
1008
                            }
1009
                        }
1010
                    }
1011
                }
1012
            }
1013
        },
1014
1015
        /**
1016
         * Helper function for getting the best match from the list of drag 
1017
         * and drop objects returned by the drag and drop events when we are 
1018
         * in INTERSECT mode.  It returns either the first object that the 
1019
         * cursor is over, or the object that has the greatest overlap with 
1020
         * the dragged element.
1021
         * @method getBestMatch
1022
         * @param  {DragDrop[]} dds The array of drag and drop objects 
1023
         * targeted
1024
         * @return {DragDrop}       The best single match
1025
         * @static
1026
         */
1027
        getBestMatch: function(dds) {
1028
            var winner = null;
1029
1030
            var len = dds.length;
1031
1032
            if (len == 1) {
1033
                winner = dds[0];
1034
            } else {
1035
                // Loop through the targeted items
1036
                for (var i=0; i<len; ++i) {
1037
                    var dd = dds[i];
1038
                    // If the cursor is over the object, it wins.  If the 
1039
                    // cursor is over multiple matches, the first one we come
1040
                    // to wins.
1041
                    if (this.mode == this.INTERSECT && dd.cursorIsOver) {
1042
                        winner = dd;
1043
                        break;
1044
                    // Otherwise the object with the most overlap wins
1045
                    } else {
1046
                        if (!winner || !winner.overlap || (dd.overlap &&
1047
                            winner.overlap.getArea() < dd.overlap.getArea())) {
1048
                            winner = dd;
1049
                        }
1050
                    }
1051
                }
1052
            }
1053
1054
            return winner;
1055
        },
1056
1057
        /**
1058
         * Refreshes the cache of the top-left and bottom-right points of the 
1059
         * drag and drop objects in the specified group(s).  This is in the
1060
         * format that is stored in the drag and drop instance, so typical 
1061
         * usage is:
1062
         * <code>
1063
         * YAHOO.util.DragDropMgr.refreshCache(ddinstance.groups);
1064
         * </code>
1065
         * Alternatively:
1066
         * <code>
1067
         * YAHOO.util.DragDropMgr.refreshCache({group1:true, group2:true});
1068
         * </code>
1069
         * @TODO this really should be an indexed array.  Alternatively this
1070
         * method could accept both.
1071
         * @method refreshCache
1072
         * @param {Object} groups an associative array of groups to refresh
1073
         * @static
1074
         */
1075
        refreshCache: function(groups) {
1076
1077
            // refresh everything if group array is not provided
1078
            var g = groups || this.ids;
1079
1080
            for (var sGroup in g) {
1081
                if ("string" != typeof sGroup) {
1082
                    continue;
1083
                }
1084
                for (var i in this.ids[sGroup]) {
1085
                    var oDD = this.ids[sGroup][i];
1086
1087
                    if (this.isTypeOfDD(oDD)) {
1088
                        var loc = this.getLocation(oDD);
1089
                        if (loc) {
1090
                            this.locationCache[oDD.id] = loc;
1091
                        } else {
1092
                            delete this.locationCache[oDD.id];
1093
                        }
1094
                    }
1095
                }
1096
            }
1097
        },
1098
1099
        /**
1100
         * This checks to make sure an element exists and is in the DOM.  The
1101
         * main purpose is to handle cases where innerHTML is used to remove
1102
         * drag and drop objects from the DOM.  IE provides an 'unspecified
1103
         * error' when trying to access the offsetParent of such an element
1104
         * @method verifyEl
1105
         * @param {HTMLElement} el the element to check
1106
         * @return {boolean} true if the element looks usable
1107
         * @static
1108
         */
1109
        verifyEl: function(el) {
1110
            try {
1111
                if (el) {
1112
                    var parent = el.offsetParent;
1113
                    if (parent) {
1114
                        return true;
1115
                    }
1116
                }
1117
            } catch(e) {
1118
            }
1119
1120
            return false;
1121
        },
1122
        
1123
        /**
1124
         * Returns a Region object containing the drag and drop element's position
1125
         * and size, including the padding configured for it
1126
         * @method getLocation
1127
         * @param {DragDrop} oDD the drag and drop object to get the 
1128
         *                       location for
1129
         * @return {YAHOO.util.Region} a Region object representing the total area
1130
         *                             the element occupies, including any padding
1131
         *                             the instance is configured for.
1132
         * @static
1133
         */
1134
        getLocation: function(oDD) {
1135
            if (! this.isTypeOfDD(oDD)) {
1136
                return null;
1137
            }
1138
1139
            var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
1140
1141
            try {
1142
                pos= YAHOO.util.Dom.getXY(el);
1143
            } catch (e) { }
1144
1145
            if (!pos) {
1146
                return null;
1147
            }
1148
1149
            x1 = pos[0];
1150
            x2 = x1 + el.offsetWidth;
1151
            y1 = pos[1];
1152
            y2 = y1 + el.offsetHeight;
1153
1154
            t = y1 - oDD.padding[0];
1155
            r = x2 + oDD.padding[1];
1156
            b = y2 + oDD.padding[2];
1157
            l = x1 - oDD.padding[3];
1158
1159
            return new YAHOO.util.Region( t, r, b, l );
1160
        },
1161
1162
        /**
1163
         * Checks the cursor location to see if it over the target
1164
         * @method isOverTarget
1165
         * @param {YAHOO.util.Point} pt The point to evaluate
1166
         * @param {DragDrop} oTarget the DragDrop object we are inspecting
1167
         * @param {boolean} intersect true if we are in intersect mode
1168
         * @param {YAHOO.util.Region} pre-cached location of the dragged element
1169
         * @return {boolean} true if the mouse is over the target
1170
         * @private
1171
         * @static
1172
         */
1173
        isOverTarget: function(pt, oTarget, intersect, curRegion) {
1174
            // use cache if available
1175
            var loc = this.locationCache[oTarget.id];
1176
            if (!loc || !this.useCache) {
1177
                loc = this.getLocation(oTarget);
1178
                this.locationCache[oTarget.id] = loc;
1179
1180
            }
1181
1182
            if (!loc) {
1183
                return false;
1184
            }
1185
1186
            oTarget.cursorIsOver = loc.contains( pt );
1187
1188
            // DragDrop is using this as a sanity check for the initial mousedown
1189
            // in this case we are done.  In POINT mode, if the drag obj has no
1190
            // contraints, we are done. Otherwise we need to evaluate the 
1191
            // region the target as occupies to determine if the dragged element
1192
            // overlaps with it.
1193
            
1194
            var dc = this.dragCurrent;
1195
            if (!dc || (!intersect && !dc.constrainX && !dc.constrainY)) {
1196
1197
                //if (oTarget.cursorIsOver) {
1198
                //}
1199
                return oTarget.cursorIsOver;
1200
            }
1201
1202
            oTarget.overlap = null;
1203
1204
1205
            // Get the current location of the drag element, this is the
1206
            // location of the mouse event less the delta that represents
1207
            // where the original mousedown happened on the element.  We
1208
            // need to consider constraints and ticks as well.
1209
1210
            if (!curRegion) {
1211
                var pos = dc.getTargetCoord(pt.x, pt.y);
1212
                var el = dc.getDragEl();
1213
                curRegion = new YAHOO.util.Region( pos.y, 
1214
                                                   pos.x + el.offsetWidth,
1215
                                                   pos.y + el.offsetHeight, 
1216
                                                   pos.x );
1217
            }
1218
1219
            var overlap = curRegion.intersect(loc);
1220
1221
            if (overlap) {
1222
                oTarget.overlap = overlap;
1223
                return (intersect) ? true : oTarget.cursorIsOver;
1224
            } else {
1225
                return false;
1226
            }
1227
        },
1228
1229
        /**
1230
         * unload event handler
1231
         * @method _onUnload
1232
         * @private
1233
         * @static
1234
         */
1235
        _onUnload: function(e, me) {
1236
            this.unregAll();
1237
        },
1238
1239
        /**
1240
         * Cleans up the drag and drop events and objects.
1241
         * @method unregAll
1242
         * @private
1243
         * @static
1244
         */
1245
        unregAll: function() {
1246
1247
            if (this.dragCurrent) {
1248
                this.stopDrag();
1249
                this.dragCurrent = null;
1250
            }
1251
1252
            this._execOnAll("unreg", []);
1253
1254
            //for (var i in this.elementCache) {
1255
                //delete this.elementCache[i];
1256
            //}
1257
            //this.elementCache = {};
1258
1259
            this.ids = {};
1260
        },
1261
1262
        /**
1263
         * A cache of DOM elements
1264
         * @property elementCache
1265
         * @private
1266
         * @static
1267
         * @deprecated elements are not cached now
1268
         */
1269
        elementCache: {},
1270
        
1271
        /**
1272
         * Get the wrapper for the DOM element specified
1273
         * @method getElWrapper
1274
         * @param {String} id the id of the element to get
1275
         * @return {YAHOO.util.DDM.ElementWrapper} the wrapped element
1276
         * @private
1277
         * @deprecated This wrapper isn't that useful
1278
         * @static
1279
         */
1280
        getElWrapper: function(id) {
1281
            var oWrapper = this.elementCache[id];
1282
            if (!oWrapper || !oWrapper.el) {
1283
                oWrapper = this.elementCache[id] = 
1284
                    new this.ElementWrapper(YAHOO.util.Dom.get(id));
1285
            }
1286
            return oWrapper;
1287
        },
1288
1289
        /**
1290
         * Returns the actual DOM element
1291
         * @method getElement
1292
         * @param {String} id the id of the elment to get
1293
         * @return {Object} The element
1294
         * @deprecated use YAHOO.util.Dom.get instead
1295
         * @static
1296
         */
1297
        getElement: function(id) {
1298
            return YAHOO.util.Dom.get(id);
1299
        },
1300
        
1301
        /**
1302
         * Returns the style property for the DOM element (i.e., 
1303
         * document.getElById(id).style)
1304
         * @method getCss
1305
         * @param {String} id the id of the elment to get
1306
         * @return {Object} The style property of the element
1307
         * @deprecated use YAHOO.util.Dom instead
1308
         * @static
1309
         */
1310
        getCss: function(id) {
1311
            var el = YAHOO.util.Dom.get(id);
1312
            return (el) ? el.style : null;
1313
        },
1314
1315
        /**
1316
         * Inner class for cached elements
1317
         * @class DragDropMgr.ElementWrapper
1318
         * @for DragDropMgr
1319
         * @private
1320
         * @deprecated
1321
         */
1322
        ElementWrapper: function(el) {
1323
                /**
1324
                 * The element
1325
                 * @property el
1326
                 */
1327
                this.el = el || null;
1328
                /**
1329
                 * The element id
1330
                 * @property id
1331
                 */
1332
                this.id = this.el && el.id;
1333
                /**
1334
                 * A reference to the style property
1335
                 * @property css
1336
                 */
1337
                this.css = this.el && el.style;
1338
            },
1339
1340
        /**
1341
         * Returns the X position of an html element
1342
         * @method getPosX
1343
         * @param el the element for which to get the position
1344
         * @return {int} the X coordinate
1345
         * @for DragDropMgr
1346
         * @deprecated use YAHOO.util.Dom.getX instead
1347
         * @static
1348
         */
1349
        getPosX: function(el) {
1350
            return YAHOO.util.Dom.getX(el);
1351
        },
1352
1353
        /**
1354
         * Returns the Y position of an html element
1355
         * @method getPosY
1356
         * @param el the element for which to get the position
1357
         * @return {int} the Y coordinate
1358
         * @deprecated use YAHOO.util.Dom.getY instead
1359
         * @static
1360
         */
1361
        getPosY: function(el) {
1362
            return YAHOO.util.Dom.getY(el); 
1363
        },
1364
1365
        /**
1366
         * Swap two nodes.  In IE, we use the native method, for others we 
1367
         * emulate the IE behavior
1368
         * @method swapNode
1369
         * @param n1 the first node to swap
1370
         * @param n2 the other node to swap
1371
         * @static
1372
         */
1373
        swapNode: function(n1, n2) {
1374
            if (n1.swapNode) {
1375
                n1.swapNode(n2);
1376
            } else {
1377
                var p = n2.parentNode;
1378
                var s = n2.nextSibling;
1379
1380
                if (s == n1) {
1381
                    p.insertBefore(n1, n2);
1382
                } else if (n2 == n1.nextSibling) {
1383
                    p.insertBefore(n2, n1);
1384
                } else {
1385
                    n1.parentNode.replaceChild(n2, n1);
1386
                    p.insertBefore(n1, s);
1387
                }
1388
            }
1389
        },
1390
1391
        /**
1392
         * Returns the current scroll position
1393
         * @method getScroll
1394
         * @private
1395
         * @static
1396
         */
1397
        getScroll: function () {
1398
            var t, l, dde=document.documentElement, db=document.body;
1399
            if (dde && (dde.scrollTop || dde.scrollLeft)) {
1400
                t = dde.scrollTop;
1401
                l = dde.scrollLeft;
1402
            } else if (db) {
1403
                t = db.scrollTop;
1404
                l = db.scrollLeft;
1405
            } else {
1406
            }
1407
            return { top: t, left: l };
1408
        },
1409
1410
        /**
1411
         * Returns the specified element style property
1412
         * @method getStyle
1413
         * @param {HTMLElement} el          the element
1414
         * @param {string}      styleProp   the style property
1415
         * @return {string} The value of the style property
1416
         * @deprecated use YAHOO.util.Dom.getStyle
1417
         * @static
1418
         */
1419
        getStyle: function(el, styleProp) {
1420
            return YAHOO.util.Dom.getStyle(el, styleProp);
1421
        },
1422
1423
        /**
1424
         * Gets the scrollTop
1425
         * @method getScrollTop
1426
         * @return {int} the document's scrollTop
1427
         * @static
1428
         */
1429
        getScrollTop: function () { return this.getScroll().top; },
1430
1431
        /**
1432
         * Gets the scrollLeft
1433
         * @method getScrollLeft
1434
         * @return {int} the document's scrollTop
1435
         * @static
1436
         */
1437
        getScrollLeft: function () { return this.getScroll().left; },
1438
1439
        /**
1440
         * Sets the x/y position of an element to the location of the
1441
         * target element.
1442
         * @method moveToEl
1443
         * @param {HTMLElement} moveEl      The element to move
1444
         * @param {HTMLElement} targetEl    The position reference element
1445
         * @static
1446
         */
1447
        moveToEl: function (moveEl, targetEl) {
1448
            var aCoord = YAHOO.util.Dom.getXY(targetEl);
1449
            YAHOO.util.Dom.setXY(moveEl, aCoord);
1450
        },
1451
1452
        /**
1453
         * Gets the client height
1454
         * @method getClientHeight
1455
         * @return {int} client height in px
1456
         * @deprecated use YAHOO.util.Dom.getViewportHeight instead
1457
         * @static
1458
         */
1459
        getClientHeight: function() {
1460
            return YAHOO.util.Dom.getViewportHeight();
1461
        },
1462
1463
        /**
1464
         * Gets the client width
1465
         * @method getClientWidth
1466
         * @return {int} client width in px
1467
         * @deprecated use YAHOO.util.Dom.getViewportWidth instead
1468
         * @static
1469
         */
1470
        getClientWidth: function() {
1471
            return YAHOO.util.Dom.getViewportWidth();
1472
        },
1473
1474
        /**
1475
         * Numeric array sort function
1476
         * @method numericSort
1477
         * @static
1478
         */
1479
        numericSort: function(a, b) { return (a - b); },
1480
1481
        /**
1482
         * Internal counter
1483
         * @property _timeoutCount
1484
         * @private
1485
         * @static
1486
         */
1487
        _timeoutCount: 0,
1488
1489
        /**
1490
         * Trying to make the load order less important.  Without this we get
1491
         * an error if this file is loaded before the Event Utility.
1492
         * @method _addListeners
1493
         * @private
1494
         * @static
1495
         */
1496
        _addListeners: function() {
1497
            var DDM = YAHOO.util.DDM;
1498
            if ( YAHOO.util.Event && document ) {
1499
                DDM._onLoad();
1500
            } else {
1501
                if (DDM._timeoutCount > 2000) {
1502
                } else {
1503
                    setTimeout(DDM._addListeners, 10);
1504
                    if (document && document.body) {
1505
                        DDM._timeoutCount += 1;
1506
                    }
1507
                }
1508
            }
1509
        },
1510
1511
        /**
1512
         * Recursively searches the immediate parent and all child nodes for 
1513
         * the handle element in order to determine wheter or not it was 
1514
         * clicked.
1515
         * @method handleWasClicked
1516
         * @param node the html element to inspect
1517
         * @static
1518
         */
1519
        handleWasClicked: function(node, id) {
1520
            if (this.isHandle(id, node.id)) {
1521
                return true;
1522
            } else {
1523
                // check to see if this is a text node child of the one we want
1524
                var p = node.parentNode;
1525
1526
                while (p) {
1527
                    if (this.isHandle(id, p.id)) {
1528
                        return true;
1529
                    } else {
1530
                        p = p.parentNode;
1531
                    }
1532
                }
1533
            }
1534
1535
            return false;
1536
        }
1537
1538
    };
1539
1540
}();
1541
1542
// shorter alias, save a few bytes
1543
YAHOO.util.DDM = YAHOO.util.DragDropMgr;
1544
YAHOO.util.DDM._addListeners();
1545
1546
}
1547
1548
(function() {
1549
1550
var Event=YAHOO.util.Event; 
1551
var Dom=YAHOO.util.Dom;
1552
1553
/**
1554
 * Defines the interface and base operation of items that that can be 
1555
 * dragged or can be drop targets.  It was designed to be extended, overriding
1556
 * the event handlers for startDrag, onDrag, onDragOver, onDragOut.
1557
 * Up to three html elements can be associated with a DragDrop instance:
1558
 * <ul>
1559
 * <li>linked element: the element that is passed into the constructor.
1560
 * This is the element which defines the boundaries for interaction with 
1561
 * other DragDrop objects.</li>
1562
 * <li>handle element(s): The drag operation only occurs if the element that 
1563
 * was clicked matches a handle element.  By default this is the linked 
1564
 * element, but there are times that you will want only a portion of the 
1565
 * linked element to initiate the drag operation, and the setHandleElId() 
1566
 * method provides a way to define this.</li>
1567
 * <li>drag element: this represents an the element that would be moved along
1568
 * with the cursor during a drag operation.  By default, this is the linked
1569
 * element itself as in {@link YAHOO.util.DD}.  setDragElId() lets you define
1570
 * a separate element that would be moved, as in {@link YAHOO.util.DDProxy}
1571
 * </li>
1572
 * </ul>
1573
 * This class should not be instantiated until the onload event to ensure that
1574
 * the associated elements are available.
1575
 * The following would define a DragDrop obj that would interact with any 
1576
 * other DragDrop obj in the "group1" group:
1577
 * <pre>
1578
 *  dd = new YAHOO.util.DragDrop("div1", "group1");
1579
 * </pre>
1580
 * Since none of the event handlers have been implemented, nothing would 
1581
 * actually happen if you were to run the code above.  Normally you would 
1582
 * override this class or one of the default implementations, but you can 
1583
 * also override the methods you want on an instance of the class...
1584
 * <pre>
1585
 *  dd.onDragDrop = function(e, id) {
1586
 *  &nbsp;&nbsp;alert("dd was dropped on " + id);
1587
 *  }
1588
 * </pre>
1589
 * @namespace YAHOO.util
1590
 * @class DragDrop
1591
 * @constructor
1592
 * @param {String} id of the element that is linked to this instance
1593
 * @param {String} sGroup the group of related DragDrop objects
1594
 * @param {object} config an object containing configurable attributes
1595
 *                Valid properties for DragDrop: 
1596
 *                    padding, isTarget, maintainOffset, primaryButtonOnly,
1597
 */
1598
YAHOO.util.DragDrop = function(id, sGroup, config) {
1599
    if (id) {
1600
        this.init(id, sGroup, config); 
1601
    }
1602
};
1603
1604
YAHOO.util.DragDrop.prototype = {
1605
    /**
1606
     * An Object Literal containing the events that we will be using: mouseDown, b4MouseDown, mouseUp, b4StartDrag, startDrag, b4EndDrag, endDrag, mouseUp, drag, b4Drag, invalidDrop, b4DragOut, dragOut, dragEnter, b4DragOver, dragOver, b4DragDrop, dragDrop
1607
     * By setting any of these to false, then event will not be fired.
1608
     * @property events
1609
     * @type object
1610
     */
1611
    events: null,
1612
    /**
1613
    * @method on
1614
    * @description Shortcut for EventProvider.subscribe, see <a href="YAHOO.util.EventProvider.html#subscribe">YAHOO.util.EventProvider.subscribe</a>
1615
    */
1616
    on: function() {
1617
        this.subscribe.apply(this, arguments);
1618
    },
1619
    /**
1620
     * The id of the element associated with this object.  This is what we 
1621
     * refer to as the "linked element" because the size and position of 
1622
     * this element is used to determine when the drag and drop objects have 
1623
     * interacted.
1624
     * @property id
1625
     * @type String
1626
     */
1627
    id: null,
1628
1629
    /**
1630
     * Configuration attributes passed into the constructor
1631
     * @property config
1632
     * @type object
1633
     */
1634
    config: null,
1635
1636
    /**
1637
     * The id of the element that will be dragged.  By default this is same 
1638
     * as the linked element , but could be changed to another element. Ex: 
1639
     * YAHOO.util.DDProxy
1640
     * @property dragElId
1641
     * @type String
1642
     * @private
1643
     */
1644
    dragElId: null, 
1645
1646
    /**
1647
     * the id of the element that initiates the drag operation.  By default 
1648
     * this is the linked element, but could be changed to be a child of this
1649
     * element.  This lets us do things like only starting the drag when the 
1650
     * header element within the linked html element is clicked.
1651
     * @property handleElId
1652
     * @type String
1653
     * @private
1654
     */
1655
    handleElId: null, 
1656
1657
    /**
1658
     * An associative array of HTML tags that will be ignored if clicked.
1659
     * @property invalidHandleTypes
1660
     * @type {string: string}
1661
     */
1662
    invalidHandleTypes: null, 
1663
1664
    /**
1665
     * An associative array of ids for elements that will be ignored if clicked
1666
     * @property invalidHandleIds
1667
     * @type {string: string}
1668
     */
1669
    invalidHandleIds: null, 
1670
1671
    /**
1672
     * An indexted array of css class names for elements that will be ignored
1673
     * if clicked.
1674
     * @property invalidHandleClasses
1675
     * @type string[]
1676
     */
1677
    invalidHandleClasses: null, 
1678
1679
    /**
1680
     * The linked element's absolute X position at the time the drag was 
1681
     * started
1682
     * @property startPageX
1683
     * @type int
1684
     * @private
1685
     */
1686
    startPageX: 0,
1687
1688
    /**
1689
     * The linked element's absolute X position at the time the drag was 
1690
     * started
1691
     * @property startPageY
1692
     * @type int
1693
     * @private
1694
     */
1695
    startPageY: 0,
1696
1697
    /**
1698
     * The group defines a logical collection of DragDrop objects that are 
1699
     * related.  Instances only get events when interacting with other 
1700
     * DragDrop object in the same group.  This lets us define multiple 
1701
     * groups using a single DragDrop subclass if we want.
1702
     * @property groups
1703
     * @type {string: string}
1704
     */
1705
    groups: null,
1706
1707
    /**
1708
     * Individual drag/drop instances can be locked.  This will prevent 
1709
     * onmousedown start drag.
1710
     * @property locked
1711
     * @type boolean
1712
     * @private
1713
     */
1714
    locked: false,
1715
1716
    /**
1717
     * Lock this instance
1718
     * @method lock
1719
     */
1720
    lock: function() { this.locked = true; },
1721
1722
    /**
1723
     * Unlock this instace
1724
     * @method unlock
1725
     */
1726
    unlock: function() { this.locked = false; },
1727
1728
    /**
1729
     * By default, all instances can be a drop target.  This can be disabled by
1730
     * setting isTarget to false.
1731
     * @property isTarget
1732
     * @type boolean
1733
     */
1734
    isTarget: true,
1735
1736
    /**
1737
     * The padding configured for this drag and drop object for calculating
1738
     * the drop zone intersection with this object.
1739
     * @property padding
1740
     * @type int[]
1741
     */
1742
    padding: null,
1743
    /**
1744
     * If this flag is true, do not fire drop events. The element is a drag only element (for movement not dropping)
1745
     * @property dragOnly
1746
     * @type Boolean
1747
     */
1748
    dragOnly: false,
1749
1750
    /**
1751
     * If this flag is true, a shim will be placed over the screen/viewable area to track mouse events. Should help with dragging elements over iframes and other controls.
1752
     * @property useShim
1753
     * @type Boolean
1754
     */
1755
    useShim: false,
1756
1757
    /**
1758
     * Cached reference to the linked element
1759
     * @property _domRef
1760
     * @private
1761
     */
1762
    _domRef: null,
1763
1764
    /**
1765
     * Internal typeof flag
1766
     * @property __ygDragDrop
1767
     * @private
1768
     */
1769
    __ygDragDrop: true,
1770
1771
    /**
1772
     * Set to true when horizontal contraints are applied
1773
     * @property constrainX
1774
     * @type boolean
1775
     * @private
1776
     */
1777
    constrainX: false,
1778
1779
    /**
1780
     * Set to true when vertical contraints are applied
1781
     * @property constrainY
1782
     * @type boolean
1783
     * @private
1784
     */
1785
    constrainY: false,
1786
1787
    /**
1788
     * The left constraint
1789
     * @property minX
1790
     * @type int
1791
     * @private
1792
     */
1793
    minX: 0,
1794
1795
    /**
1796
     * The right constraint
1797
     * @property maxX
1798
     * @type int
1799
     * @private
1800
     */
1801
    maxX: 0,
1802
1803
    /**
1804
     * The up constraint 
1805
     * @property minY
1806
     * @type int
1807
     * @type int
1808
     * @private
1809
     */
1810
    minY: 0,
1811
1812
    /**
1813
     * The down constraint 
1814
     * @property maxY
1815
     * @type int
1816
     * @private
1817
     */
1818
    maxY: 0,
1819
1820
    /**
1821
     * The difference between the click position and the source element's location
1822
     * @property deltaX
1823
     * @type int
1824
     * @private
1825
     */
1826
    deltaX: 0,
1827
1828
    /**
1829
     * The difference between the click position and the source element's location
1830
     * @property deltaY
1831
     * @type int
1832
     * @private
1833
     */
1834
    deltaY: 0,
1835
1836
    /**
1837
     * Maintain offsets when we resetconstraints.  Set to true when you want
1838
     * the position of the element relative to its parent to stay the same
1839
     * when the page changes
1840
     *
1841
     * @property maintainOffset
1842
     * @type boolean
1843
     */
1844
    maintainOffset: false,
1845
1846
    /**
1847
     * Array of pixel locations the element will snap to if we specified a 
1848
     * horizontal graduation/interval.  This array is generated automatically
1849
     * when you define a tick interval.
1850
     * @property xTicks
1851
     * @type int[]
1852
     */
1853
    xTicks: null,
1854
1855
    /**
1856
     * Array of pixel locations the element will snap to if we specified a 
1857
     * vertical graduation/interval.  This array is generated automatically 
1858
     * when you define a tick interval.
1859
     * @property yTicks
1860
     * @type int[]
1861
     */
1862
    yTicks: null,
1863
1864
    /**
1865
     * By default the drag and drop instance will only respond to the primary
1866
     * button click (left button for a right-handed mouse).  Set to true to
1867
     * allow drag and drop to start with any mouse click that is propogated
1868
     * by the browser
1869
     * @property primaryButtonOnly
1870
     * @type boolean
1871
     */
1872
    primaryButtonOnly: true,
1873
1874
    /**
1875
     * The availabe property is false until the linked dom element is accessible.
1876
     * @property available
1877
     * @type boolean
1878
     */
1879
    available: false,
1880
1881
    /**
1882
     * By default, drags can only be initiated if the mousedown occurs in the
1883
     * region the linked element is.  This is done in part to work around a
1884
     * bug in some browsers that mis-report the mousedown if the previous
1885
     * mouseup happened outside of the window.  This property is set to true
1886
     * if outer handles are defined.
1887
     *
1888
     * @property hasOuterHandles
1889
     * @type boolean
1890
     * @default false
1891
     */
1892
    hasOuterHandles: false,
1893
1894
    /**
1895
     * Property that is assigned to a drag and drop object when testing to
1896
     * see if it is being targeted by another dd object.  This property
1897
     * can be used in intersect mode to help determine the focus of
1898
     * the mouse interaction.  DDM.getBestMatch uses this property first to
1899
     * determine the closest match in INTERSECT mode when multiple targets
1900
     * are part of the same interaction.
1901
     * @property cursorIsOver
1902
     * @type boolean
1903
     */
1904
    cursorIsOver: false,
1905
1906
    /**
1907
     * Property that is assigned to a drag and drop object when testing to
1908
     * see if it is being targeted by another dd object.  This is a region
1909
     * that represents the area the draggable element overlaps this target.
1910
     * DDM.getBestMatch uses this property to compare the size of the overlap
1911
     * to that of other targets in order to determine the closest match in
1912
     * INTERSECT mode when multiple targets are part of the same interaction.
1913
     * @property overlap 
1914
     * @type YAHOO.util.Region
1915
     */
1916
    overlap: null,
1917
1918
    /**
1919
     * Code that executes immediately before the startDrag event
1920
     * @method b4StartDrag
1921
     * @private
1922
     */
1923
    b4StartDrag: function(x, y) { },
1924
1925
    /**
1926
     * Abstract method called after a drag/drop object is clicked
1927
     * and the drag or mousedown time thresholds have beeen met.
1928
     * @method startDrag
1929
     * @param {int} X click location
1930
     * @param {int} Y click location
1931
     */
1932
    startDrag: function(x, y) { /* override this */ },
1933
1934
    /**
1935
     * Code that executes immediately before the onDrag event
1936
     * @method b4Drag
1937
     * @private
1938
     */
1939
    b4Drag: function(e) { },
1940
1941
    /**
1942
     * Abstract method called during the onMouseMove event while dragging an 
1943
     * object.
1944
     * @method onDrag
1945
     * @param {Event} e the mousemove event
1946
     */
1947
    onDrag: function(e) { /* override this */ },
1948
1949
    /**
1950
     * Abstract method called when this element fist begins hovering over 
1951
     * another DragDrop obj
1952
     * @method onDragEnter
1953
     * @param {Event} e the mousemove event
1954
     * @param {String|DragDrop[]} id In POINT mode, the element
1955
     * id this is hovering over.  In INTERSECT mode, an array of one or more 
1956
     * dragdrop items being hovered over.
1957
     */
1958
    onDragEnter: function(e, id) { /* override this */ },
1959
1960
    /**
1961
     * Code that executes immediately before the onDragOver event
1962
     * @method b4DragOver
1963
     * @private
1964
     */
1965
    b4DragOver: function(e) { },
1966
1967
    /**
1968
     * Abstract method called when this element is hovering over another 
1969
     * DragDrop obj
1970
     * @method onDragOver
1971
     * @param {Event} e the mousemove event
1972
     * @param {String|DragDrop[]} id In POINT mode, the element
1973
     * id this is hovering over.  In INTERSECT mode, an array of dd items 
1974
     * being hovered over.
1975
     */
1976
    onDragOver: function(e, id) { /* override this */ },
1977
1978
    /**
1979
     * Code that executes immediately before the onDragOut event
1980
     * @method b4DragOut
1981
     * @private
1982
     */
1983
    b4DragOut: function(e) { },
1984
1985
    /**
1986
     * Abstract method called when we are no longer hovering over an element
1987
     * @method onDragOut
1988
     * @param {Event} e the mousemove event
1989
     * @param {String|DragDrop[]} id In POINT mode, the element
1990
     * id this was hovering over.  In INTERSECT mode, an array of dd items 
1991
     * that the mouse is no longer over.
1992
     */
1993
    onDragOut: function(e, id) { /* override this */ },
1994
1995
    /**
1996
     * Code that executes immediately before the onDragDrop event
1997
     * @method b4DragDrop
1998
     * @private
1999
     */
2000
    b4DragDrop: function(e) { },
2001
2002
    /**
2003
     * Abstract method called when this item is dropped on another DragDrop 
2004
     * obj
2005
     * @method onDragDrop
2006
     * @param {Event} e the mouseup event
2007
     * @param {String|DragDrop[]} id In POINT mode, the element
2008
     * id this was dropped on.  In INTERSECT mode, an array of dd items this 
2009
     * was dropped on.
2010
     */
2011
    onDragDrop: function(e, id) { /* override this */ },
2012
2013
    /**
2014
     * Abstract method called when this item is dropped on an area with no
2015
     * drop target
2016
     * @method onInvalidDrop
2017
     * @param {Event} e the mouseup event
2018
     */
2019
    onInvalidDrop: function(e) { /* override this */ },
2020
2021
    /**
2022
     * Code that executes immediately before the endDrag event
2023
     * @method b4EndDrag
2024
     * @private
2025
     */
2026
    b4EndDrag: function(e) { },
2027
2028
    /**
2029
     * Fired when we are done dragging the object
2030
     * @method endDrag
2031
     * @param {Event} e the mouseup event
2032
     */
2033
    endDrag: function(e) { /* override this */ },
2034
2035
    /**
2036
     * Code executed immediately before the onMouseDown event
2037
     * @method b4MouseDown
2038
     * @param {Event} e the mousedown event
2039
     * @private
2040
     */
2041
    b4MouseDown: function(e) {  },
2042
2043
    /**
2044
     * Event handler that fires when a drag/drop obj gets a mousedown
2045
     * @method onMouseDown
2046
     * @param {Event} e the mousedown event
2047
     */
2048
    onMouseDown: function(e) { /* override this */ },
2049
2050
    /**
2051
     * Event handler that fires when a drag/drop obj gets a mouseup
2052
     * @method onMouseUp
2053
     * @param {Event} e the mouseup event
2054
     */
2055
    onMouseUp: function(e) { /* override this */ },
2056
   
2057
    /**
2058
     * Override the onAvailable method to do what is needed after the initial
2059
     * position was determined.
2060
     * @method onAvailable
2061
     */
2062
    onAvailable: function () { 
2063
    },
2064
2065
    /**
2066
     * Returns a reference to the linked element
2067
     * @method getEl
2068
     * @return {HTMLElement} the html element 
2069
     */
2070
    getEl: function() { 
2071
        if (!this._domRef) {
2072
            this._domRef = Dom.get(this.id); 
2073
        }
2074
2075
        return this._domRef;
2076
    },
2077
2078
    /**
2079
     * Returns a reference to the actual element to drag.  By default this is
2080
     * the same as the html element, but it can be assigned to another 
2081
     * element. An example of this can be found in YAHOO.util.DDProxy
2082
     * @method getDragEl
2083
     * @return {HTMLElement} the html element 
2084
     */
2085
    getDragEl: function() {
2086
        return Dom.get(this.dragElId);
2087
    },
2088
2089
    /**
2090
     * Sets up the DragDrop object.  Must be called in the constructor of any
2091
     * YAHOO.util.DragDrop subclass
2092
     * @method init
2093
     * @param id the id of the linked element
2094
     * @param {String} sGroup the group of related items
2095
     * @param {object} config configuration attributes
2096
     */
2097
    init: function(id, sGroup, config) {
2098
        this.initTarget(id, sGroup, config);
2099
        Event.on(this._domRef || this.id, "mousedown", 
2100
                        this.handleMouseDown, this, true);
2101
2102
        // Event.on(this.id, "selectstart", Event.preventDefault);
2103
        for (var i in this.events) {
2104
            this.createEvent(i + 'Event');
2105
        }
2106
        
2107
    },
2108
2109
    /**
2110
     * Initializes Targeting functionality only... the object does not
2111
     * get a mousedown handler.
2112
     * @method initTarget
2113
     * @param id the id of the linked element
2114
     * @param {String} sGroup the group of related items
2115
     * @param {object} config configuration attributes
2116
     */
2117
    initTarget: function(id, sGroup, config) {
2118
2119
        // configuration attributes 
2120
        this.config = config || {};
2121
2122
        this.events = {};
2123
2124
        // create a local reference to the drag and drop manager
2125
        this.DDM = YAHOO.util.DDM;
2126
2127
        // initialize the groups object
2128
        this.groups = {};
2129
2130
        // assume that we have an element reference instead of an id if the
2131
        // parameter is not a string
2132
        if (typeof id !== "string") {
2133
            this._domRef = id;
2134
            id = Dom.generateId(id);
2135
        }
2136
2137
        // set the id
2138
        this.id = id;
2139
2140
        // add to an interaction group
2141
        this.addToGroup((sGroup) ? sGroup : "default");
2142
2143
        // We don't want to register this as the handle with the manager
2144
        // so we just set the id rather than calling the setter.
2145
        this.handleElId = id;
2146
2147
        Event.onAvailable(id, this.handleOnAvailable, this, true);
2148
2149
2150
        // the linked element is the element that gets dragged by default
2151
        this.setDragElId(id); 
2152
2153
        // by default, clicked anchors will not start drag operations. 
2154
        // @TODO what else should be here?  Probably form fields.
2155
        this.invalidHandleTypes = { A: "A" };
2156
        this.invalidHandleIds = {};
2157
        this.invalidHandleClasses = [];
2158
2159
        this.applyConfig();
2160
    },
2161
2162
    /**
2163
     * Applies the configuration parameters that were passed into the constructor.
2164
     * This is supposed to happen at each level through the inheritance chain.  So
2165
     * a DDProxy implentation will execute apply config on DDProxy, DD, and 
2166
     * DragDrop in order to get all of the parameters that are available in
2167
     * each object.
2168
     * @method applyConfig
2169
     */
2170
    applyConfig: function() {
2171
        this.events = {
2172
            mouseDown: true,
2173
            b4MouseDown: true,
2174
            mouseUp: true,
2175
            b4StartDrag: true,
2176
            startDrag: true,
2177
            b4EndDrag: true,
2178
            endDrag: true,
2179
            drag: true,
2180
            b4Drag: true,
2181
            invalidDrop: true,
2182
            b4DragOut: true,
2183
            dragOut: true,
2184
            dragEnter: true,
2185
            b4DragOver: true,
2186
            dragOver: true,
2187
            b4DragDrop: true,
2188
            dragDrop: true
2189
        };
2190
        
2191
        if (this.config.events) {
2192
            for (var i in this.config.events) {
2193
                if (this.config.events[i] === false) {
2194
                    this.events[i] = false;
2195
                }
2196
            }
2197
        }
2198
2199
2200
        // configurable properties: 
2201
        //    padding, isTarget, maintainOffset, primaryButtonOnly
2202
        this.padding           = this.config.padding || [0, 0, 0, 0];
2203
        this.isTarget          = (this.config.isTarget !== false);
2204
        this.maintainOffset    = (this.config.maintainOffset);
2205
        this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
2206
        this.dragOnly = ((this.config.dragOnly === true) ? true : false);
2207
        this.useShim = ((this.config.useShim === true) ? true : false);
2208
    },
2209
2210
    /**
2211
     * Executed when the linked element is available
2212
     * @method handleOnAvailable
2213
     * @private
2214
     */
2215
    handleOnAvailable: function() {
2216
        this.available = true;
2217
        this.resetConstraints();
2218
        this.onAvailable();
2219
    },
2220
2221
     /**
2222
     * Configures the padding for the target zone in px.  Effectively expands
2223
     * (or reduces) the virtual object size for targeting calculations.  
2224
     * Supports css-style shorthand; if only one parameter is passed, all sides
2225
     * will have that padding, and if only two are passed, the top and bottom
2226
     * will have the first param, the left and right the second.
2227
     * @method setPadding
2228
     * @param {int} iTop    Top pad
2229
     * @param {int} iRight  Right pad
2230
     * @param {int} iBot    Bot pad
2231
     * @param {int} iLeft   Left pad
2232
     */
2233
    setPadding: function(iTop, iRight, iBot, iLeft) {
2234
        // this.padding = [iLeft, iRight, iTop, iBot];
2235
        if (!iRight && 0 !== iRight) {
2236
            this.padding = [iTop, iTop, iTop, iTop];
2237
        } else if (!iBot && 0 !== iBot) {
2238
            this.padding = [iTop, iRight, iTop, iRight];
2239
        } else {
2240
            this.padding = [iTop, iRight, iBot, iLeft];
2241
        }
2242
    },
2243
2244
    /**
2245
     * Stores the initial placement of the linked element.
2246
     * @method setInitialPosition
2247
     * @param {int} diffX   the X offset, default 0
2248
     * @param {int} diffY   the Y offset, default 0
2249
     * @private
2250
     */
2251
    setInitPosition: function(diffX, diffY) {
2252
        var el = this.getEl();
2253
2254
        if (!this.DDM.verifyEl(el)) {
2255
            if (el && el.style && (el.style.display == 'none')) {
2256
            } else {
2257
            }
2258
            return;
2259
        }
2260
2261
        var dx = diffX || 0;
2262
        var dy = diffY || 0;
2263
2264
        var p = Dom.getXY( el );
2265
2266
        this.initPageX = p[0] - dx;
2267
        this.initPageY = p[1] - dy;
2268
2269
        this.lastPageX = p[0];
2270
        this.lastPageY = p[1];
2271
2272
2273
2274
        this.setStartPosition(p);
2275
    },
2276
2277
    /**
2278
     * Sets the start position of the element.  This is set when the obj
2279
     * is initialized, the reset when a drag is started.
2280
     * @method setStartPosition
2281
     * @param pos current position (from previous lookup)
2282
     * @private
2283
     */
2284
    setStartPosition: function(pos) {
2285
        var p = pos || Dom.getXY(this.getEl());
2286
2287
        this.deltaSetXY = null;
2288
2289
        this.startPageX = p[0];
2290
        this.startPageY = p[1];
2291
    },
2292
2293
    /**
2294
     * Add this instance to a group of related drag/drop objects.  All 
2295
     * instances belong to at least one group, and can belong to as many 
2296
     * groups as needed.
2297
     * @method addToGroup
2298
     * @param sGroup {string} the name of the group
2299
     */
2300
    addToGroup: function(sGroup) {
2301
        this.groups[sGroup] = true;
2302
        this.DDM.regDragDrop(this, sGroup);
2303
    },
2304
2305
    /**
2306
     * Remove's this instance from the supplied interaction group
2307
     * @method removeFromGroup
2308
     * @param {string}  sGroup  The group to drop
2309
     */
2310
    removeFromGroup: function(sGroup) {
2311
        if (this.groups[sGroup]) {
2312
            delete this.groups[sGroup];
2313
        }
2314
2315
        this.DDM.removeDDFromGroup(this, sGroup);
2316
    },
2317
2318
    /**
2319
     * Allows you to specify that an element other than the linked element 
2320
     * will be moved with the cursor during a drag
2321
     * @method setDragElId
2322
     * @param id {string} the id of the element that will be used to initiate the drag
2323
     */
2324
    setDragElId: function(id) {
2325
        this.dragElId = id;
2326
    },
2327
2328
    /**
2329
     * Allows you to specify a child of the linked element that should be 
2330
     * used to initiate the drag operation.  An example of this would be if 
2331
     * you have a content div with text and links.  Clicking anywhere in the 
2332
     * content area would normally start the drag operation.  Use this method
2333
     * to specify that an element inside of the content div is the element 
2334
     * that starts the drag operation.
2335
     * @method setHandleElId
2336
     * @param id {string} the id of the element that will be used to 
2337
     * initiate the drag.
2338
     */
2339
    setHandleElId: function(id) {
2340
        if (typeof id !== "string") {
2341
            id = Dom.generateId(id);
2342
        }
2343
        this.handleElId = id;
2344
        this.DDM.regHandle(this.id, id);
2345
    },
2346
2347
    /**
2348
     * Allows you to set an element outside of the linked element as a drag 
2349
     * handle
2350
     * @method setOuterHandleElId
2351
     * @param id the id of the element that will be used to initiate the drag
2352
     */
2353
    setOuterHandleElId: function(id) {
2354
        if (typeof id !== "string") {
2355
            id = Dom.generateId(id);
2356
        }
2357
        Event.on(id, "mousedown", 
2358
                this.handleMouseDown, this, true);
2359
        this.setHandleElId(id);
2360
2361
        this.hasOuterHandles = true;
2362
    },
2363
2364
    /**
2365
     * Remove all drag and drop hooks for this element
2366
     * @method unreg
2367
     */
2368
    unreg: function() {
2369
        Event.removeListener(this.id, "mousedown", 
2370
                this.handleMouseDown);
2371
        this._domRef = null;
2372
        this.DDM._remove(this);
2373
    },
2374
2375
    /**
2376
     * Returns true if this instance is locked, or the drag drop mgr is locked
2377
     * (meaning that all drag/drop is disabled on the page.)
2378
     * @method isLocked
2379
     * @return {boolean} true if this obj or all drag/drop is locked, else 
2380
     * false
2381
     */
2382
    isLocked: function() {
2383
        return (this.DDM.isLocked() || this.locked);
2384
    },
2385
2386
    /**
2387
     * Fired when this object is clicked
2388
     * @method handleMouseDown
2389
     * @param {Event} e 
2390
     * @param {YAHOO.util.DragDrop} oDD the clicked dd object (this dd obj)
2391
     * @private
2392
     */
2393
    handleMouseDown: function(e, oDD) {
2394
2395
        var button = e.which || e.button;
2396
2397
        if (this.primaryButtonOnly && button > 1) {
2398
            return;
2399
        }
2400
2401
        if (this.isLocked()) {
2402
            return;
2403
        }
2404
2405
2406
2407
        // firing the mousedown events prior to calculating positions
2408
        var b4Return = this.b4MouseDown(e),
2409
        b4Return2 = true;
2410
2411
        if (this.events.b4MouseDown) {
2412
            b4Return2 = this.fireEvent('b4MouseDownEvent', e);
2413
        }
2414
        var mDownReturn = this.onMouseDown(e),
2415
            mDownReturn2 = true;
2416
        if (this.events.mouseDown) {
2417
            mDownReturn2 = this.fireEvent('mouseDownEvent', e);
2418
        }
2419
2420
        if ((b4Return === false) || (mDownReturn === false) || (b4Return2 === false) || (mDownReturn2 === false)) {
2421
            return;
2422
        }
2423
2424
        this.DDM.refreshCache(this.groups);
2425
        // var self = this;
2426
        // setTimeout( function() { self.DDM.refreshCache(self.groups); }, 0);
2427
2428
        // Only process the event if we really clicked within the linked 
2429
        // element.  The reason we make this check is that in the case that 
2430
        // another element was moved between the clicked element and the 
2431
        // cursor in the time between the mousedown and mouseup events. When 
2432
        // this happens, the element gets the next mousedown event 
2433
        // regardless of where on the screen it happened.  
2434
        var pt = new YAHOO.util.Point(Event.getPageX(e), Event.getPageY(e));
2435
        if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {
2436
        } else {
2437
            if (this.clickValidator(e)) {
2438
2439
2440
                // set the initial element position
2441
                this.setStartPosition();
2442
2443
                // start tracking mousemove distance and mousedown time to
2444
                // determine when to start the actual drag
2445
                this.DDM.handleMouseDown(e, this);
2446
2447
                // this mousedown is mine
2448
                this.DDM.stopEvent(e);
2449
            } else {
2450
2451
2452
            }
2453
        }
2454
    },
2455
2456
    /**
2457
     * @method clickValidator
2458
     * @description Method validates that the clicked element
2459
     * was indeed the handle or a valid child of the handle
2460
     * @param {Event} e 
2461
     */
2462
    clickValidator: function(e) {
2463
        var target = YAHOO.util.Event.getTarget(e);
2464
        return ( this.isValidHandleChild(target) &&
2465
                    (this.id == this.handleElId || 
2466
                        this.DDM.handleWasClicked(target, this.id)) );
2467
    },
2468
2469
    /**
2470
     * Finds the location the element should be placed if we want to move
2471
     * it to where the mouse location less the click offset would place us.
2472
     * @method getTargetCoord
2473
     * @param {int} iPageX the X coordinate of the click
2474
     * @param {int} iPageY the Y coordinate of the click
2475
     * @return an object that contains the coordinates (Object.x and Object.y)
2476
     * @private
2477
     */
2478
    getTargetCoord: function(iPageX, iPageY) {
2479
2480
2481
        var x = iPageX - this.deltaX;
2482
        var y = iPageY - this.deltaY;
2483
2484
        if (this.constrainX) {
2485
            if (x < this.minX) { x = this.minX; }
2486
            if (x > this.maxX) { x = this.maxX; }
2487
        }
2488
2489
        if (this.constrainY) {
2490
            if (y < this.minY) { y = this.minY; }
2491
            if (y > this.maxY) { y = this.maxY; }
2492
        }
2493
2494
        x = this.getTick(x, this.xTicks);
2495
        y = this.getTick(y, this.yTicks);
2496
2497
2498
        return {x:x, y:y};
2499
    },
2500
2501
    /**
2502
     * Allows you to specify a tag name that should not start a drag operation
2503
     * when clicked.  This is designed to facilitate embedding links within a
2504
     * drag handle that do something other than start the drag.
2505
     * @method addInvalidHandleType
2506
     * @param {string} tagName the type of element to exclude
2507
     */
2508
    addInvalidHandleType: function(tagName) {
2509
        var type = tagName.toUpperCase();
2510
        this.invalidHandleTypes[type] = type;
2511
    },
2512
2513
    /**
2514
     * Lets you to specify an element id for a child of a drag handle
2515
     * that should not initiate a drag
2516
     * @method addInvalidHandleId
2517
     * @param {string} id the element id of the element you wish to ignore
2518
     */
2519
    addInvalidHandleId: function(id) {
2520
        if (typeof id !== "string") {
2521
            id = Dom.generateId(id);
2522
        }
2523
        this.invalidHandleIds[id] = id;
2524
    },
2525
2526
2527
    /**
2528
     * Lets you specify a css class of elements that will not initiate a drag
2529
     * @method addInvalidHandleClass
2530
     * @param {string} cssClass the class of the elements you wish to ignore
2531
     */
2532
    addInvalidHandleClass: function(cssClass) {
2533
        this.invalidHandleClasses.push(cssClass);
2534
    },
2535
2536
    /**
2537
     * Unsets an excluded tag name set by addInvalidHandleType
2538
     * @method removeInvalidHandleType
2539
     * @param {string} tagName the type of element to unexclude
2540
     */
2541
    removeInvalidHandleType: function(tagName) {
2542
        var type = tagName.toUpperCase();
2543
        // this.invalidHandleTypes[type] = null;
2544
        delete this.invalidHandleTypes[type];
2545
    },
2546
    
2547
    /**
2548
     * Unsets an invalid handle id
2549
     * @method removeInvalidHandleId
2550
     * @param {string} id the id of the element to re-enable
2551
     */
2552
    removeInvalidHandleId: function(id) {
2553
        if (typeof id !== "string") {
2554
            id = Dom.generateId(id);
2555
        }
2556
        delete this.invalidHandleIds[id];
2557
    },
2558
2559
    /**
2560
     * Unsets an invalid css class
2561
     * @method removeInvalidHandleClass
2562
     * @param {string} cssClass the class of the element(s) you wish to 
2563
     * re-enable
2564
     */
2565
    removeInvalidHandleClass: function(cssClass) {
2566
        for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
2567
            if (this.invalidHandleClasses[i] == cssClass) {
2568
                delete this.invalidHandleClasses[i];
2569
            }
2570
        }
2571
    },
2572
2573
    /**
2574
     * Checks the tag exclusion list to see if this click should be ignored
2575
     * @method isValidHandleChild
2576
     * @param {HTMLElement} node the HTMLElement to evaluate
2577
     * @return {boolean} true if this is a valid tag type, false if not
2578
     */
2579
    isValidHandleChild: function(node) {
2580
2581
        var valid = true;
2582
        // var n = (node.nodeName == "#text") ? node.parentNode : node;
2583
        var nodeName;
2584
        try {
2585
            nodeName = node.nodeName.toUpperCase();
2586
        } catch(e) {
2587
            nodeName = node.nodeName;
2588
        }
2589
        valid = valid && !this.invalidHandleTypes[nodeName];
2590
        valid = valid && !this.invalidHandleIds[node.id];
2591
2592
        for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
2593
            valid = !Dom.hasClass(node, this.invalidHandleClasses[i]);
2594
        }
2595
2596
2597
        return valid;
2598
2599
    },
2600
2601
    /**
2602
     * Create the array of horizontal tick marks if an interval was specified
2603
     * in setXConstraint().
2604
     * @method setXTicks
2605
     * @private
2606
     */
2607
    setXTicks: function(iStartX, iTickSize) {
2608
        this.xTicks = [];
2609
        this.xTickSize = iTickSize;
2610
        
2611
        var tickMap = {};
2612
2613
        for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
2614
            if (!tickMap[i]) {
2615
                this.xTicks[this.xTicks.length] = i;
2616
                tickMap[i] = true;
2617
            }
2618
        }
2619
2620
        for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
2621
            if (!tickMap[i]) {
2622
                this.xTicks[this.xTicks.length] = i;
2623
                tickMap[i] = true;
2624
            }
2625
        }
2626
2627
        this.xTicks.sort(this.DDM.numericSort) ;
2628
    },
2629
2630
    /**
2631
     * Create the array of vertical tick marks if an interval was specified in 
2632
     * setYConstraint().
2633
     * @method setYTicks
2634
     * @private
2635
     */
2636
    setYTicks: function(iStartY, iTickSize) {
2637
        this.yTicks = [];
2638
        this.yTickSize = iTickSize;
2639
2640
        var tickMap = {};
2641
2642
        for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
2643
            if (!tickMap[i]) {
2644
                this.yTicks[this.yTicks.length] = i;
2645
                tickMap[i] = true;
2646
            }
2647
        }
2648
2649
        for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
2650
            if (!tickMap[i]) {
2651
                this.yTicks[this.yTicks.length] = i;
2652
                tickMap[i] = true;
2653
            }
2654
        }
2655
2656
        this.yTicks.sort(this.DDM.numericSort) ;
2657
    },
2658
2659
    /**
2660
     * By default, the element can be dragged any place on the screen.  Use 
2661
     * this method to limit the horizontal travel of the element.  Pass in 
2662
     * 0,0 for the parameters if you want to lock the drag to the y axis.
2663
     * @method setXConstraint
2664
     * @param {int} iLeft the number of pixels the element can move to the left
2665
     * @param {int} iRight the number of pixels the element can move to the 
2666
     * right
2667
     * @param {int} iTickSize optional parameter for specifying that the 
2668
     * element
2669
     * should move iTickSize pixels at a time.
2670
     */
2671
    setXConstraint: function(iLeft, iRight, iTickSize) {
2672
        this.leftConstraint = parseInt(iLeft, 10);
2673
        this.rightConstraint = parseInt(iRight, 10);
2674
2675
        this.minX = this.initPageX - this.leftConstraint;
2676
        this.maxX = this.initPageX + this.rightConstraint;
2677
        if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
2678
2679
        this.constrainX = true;
2680
    },
2681
2682
    /**
2683
     * Clears any constraints applied to this instance.  Also clears ticks
2684
     * since they can't exist independent of a constraint at this time.
2685
     * @method clearConstraints
2686
     */
2687
    clearConstraints: function() {
2688
        this.constrainX = false;
2689
        this.constrainY = false;
2690
        this.clearTicks();
2691
    },
2692
2693
    /**
2694
     * Clears any tick interval defined for this instance
2695
     * @method clearTicks
2696
     */
2697
    clearTicks: function() {
2698
        this.xTicks = null;
2699
        this.yTicks = null;
2700
        this.xTickSize = 0;
2701
        this.yTickSize = 0;
2702
    },
2703
2704
    /**
2705
     * By default, the element can be dragged any place on the screen.  Set 
2706
     * this to limit the vertical travel of the element.  Pass in 0,0 for the
2707
     * parameters if you want to lock the drag to the x axis.
2708
     * @method setYConstraint
2709
     * @param {int} iUp the number of pixels the element can move up
2710
     * @param {int} iDown the number of pixels the element can move down
2711
     * @param {int} iTickSize optional parameter for specifying that the 
2712
     * element should move iTickSize pixels at a time.
2713
     */
2714
    setYConstraint: function(iUp, iDown, iTickSize) {
2715
        this.topConstraint = parseInt(iUp, 10);
2716
        this.bottomConstraint = parseInt(iDown, 10);
2717
2718
        this.minY = this.initPageY - this.topConstraint;
2719
        this.maxY = this.initPageY + this.bottomConstraint;
2720
        if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
2721
2722
        this.constrainY = true;
2723
        
2724
    },
2725
2726
    /**
2727
     * resetConstraints must be called if you manually reposition a dd element.
2728
     * @method resetConstraints
2729
     */
2730
    resetConstraints: function() {
2731
2732
2733
        // Maintain offsets if necessary
2734
        if (this.initPageX || this.initPageX === 0) {
2735
            // figure out how much this thing has moved
2736
            var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
2737
            var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
2738
2739
            this.setInitPosition(dx, dy);
2740
2741
        // This is the first time we have detected the element's position
2742
        } else {
2743
            this.setInitPosition();
2744
        }
2745
2746
        if (this.constrainX) {
2747
            this.setXConstraint( this.leftConstraint, 
2748
                                 this.rightConstraint, 
2749
                                 this.xTickSize        );
2750
        }
2751
2752
        if (this.constrainY) {
2753
            this.setYConstraint( this.topConstraint, 
2754
                                 this.bottomConstraint, 
2755
                                 this.yTickSize         );
2756
        }
2757
    },
2758
2759
    /**
2760
     * Normally the drag element is moved pixel by pixel, but we can specify 
2761
     * that it move a number of pixels at a time.  This method resolves the 
2762
     * location when we have it set up like this.
2763
     * @method getTick
2764
     * @param {int} val where we want to place the object
2765
     * @param {int[]} tickArray sorted array of valid points
2766
     * @return {int} the closest tick
2767
     * @private
2768
     */
2769
    getTick: function(val, tickArray) {
2770
2771
        if (!tickArray) {
2772
            // If tick interval is not defined, it is effectively 1 pixel, 
2773
            // so we return the value passed to us.
2774
            return val; 
2775
        } else if (tickArray[0] >= val) {
2776
            // The value is lower than the first tick, so we return the first
2777
            // tick.
2778
            return tickArray[0];
2779
        } else {
2780
            for (var i=0, len=tickArray.length; i<len; ++i) {
2781
                var next = i + 1;
2782
                if (tickArray[next] && tickArray[next] >= val) {
2783
                    var diff1 = val - tickArray[i];
2784
                    var diff2 = tickArray[next] - val;
2785
                    return (diff2 > diff1) ? tickArray[i] : tickArray[next];
2786
                }
2787
            }
2788
2789
            // The value is larger than the last tick, so we return the last
2790
            // tick.
2791
            return tickArray[tickArray.length - 1];
2792
        }
2793
    },
2794
2795
    /**
2796
     * toString method
2797
     * @method toString
2798
     * @return {string} string representation of the dd obj
2799
     */
2800
    toString: function() {
2801
        return ("DragDrop " + this.id);
2802
    }
2803
2804
};
2805
YAHOO.augment(YAHOO.util.DragDrop, YAHOO.util.EventProvider);
2806
2807
/**
2808
* @event mouseDownEvent
2809
* @description Provides access to the mousedown event. The mousedown does not always result in a drag operation.
2810
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2811
*/
2812
2813
/**
2814
* @event b4MouseDownEvent
2815
* @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag.
2816
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2817
*/
2818
2819
/**
2820
* @event mouseUpEvent
2821
* @description Fired from inside DragDropMgr when the drag operation is finished.
2822
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2823
*/
2824
2825
/**
2826
* @event b4StartDragEvent
2827
* @description Fires before the startDragEvent, returning false will cancel the startDrag Event.
2828
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2829
*/
2830
2831
/**
2832
* @event startDragEvent
2833
* @description Occurs after a mouse down and the drag threshold has been met. The drag threshold default is either 3 pixels of mouse movement or 1 full second of holding the mousedown. 
2834
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2835
*/
2836
2837
/**
2838
* @event b4EndDragEvent
2839
* @description Fires before the endDragEvent. Returning false will cancel.
2840
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2841
*/
2842
2843
/**
2844
* @event endDragEvent
2845
* @description Fires on the mouseup event after a drag has been initiated (startDrag fired).
2846
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2847
*/
2848
2849
/**
2850
* @event dragEvent
2851
* @description Occurs every mousemove event while dragging.
2852
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2853
*/
2854
/**
2855
* @event b4DragEvent
2856
* @description Fires before the dragEvent.
2857
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2858
*/
2859
/**
2860
* @event invalidDropEvent
2861
* @description Fires when the dragged objects is dropped in a location that contains no drop targets.
2862
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2863
*/
2864
/**
2865
* @event b4DragOutEvent
2866
* @description Fires before the dragOutEvent
2867
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2868
*/
2869
/**
2870
* @event dragOutEvent
2871
* @description Fires when a dragged object is no longer over an object that had the onDragEnter fire. 
2872
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2873
*/
2874
/**
2875
* @event dragEnterEvent
2876
* @description Occurs when the dragged object first interacts with another targettable drag and drop object.
2877
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2878
*/
2879
/**
2880
* @event b4DragOverEvent
2881
* @description Fires before the dragOverEvent.
2882
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2883
*/
2884
/**
2885
* @event dragOverEvent
2886
* @description Fires every mousemove event while over a drag and drop object.
2887
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2888
*/
2889
/**
2890
* @event b4DragDropEvent 
2891
* @description Fires before the dragDropEvent
2892
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2893
*/
2894
/**
2895
* @event dragDropEvent
2896
* @description Fires when the dragged objects is dropped on another.
2897
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2898
*/
2899
})();
2900
/**
2901
 * A DragDrop implementation where the linked element follows the 
2902
 * mouse cursor during a drag.
2903
 * @class DD
2904
 * @extends YAHOO.util.DragDrop
2905
 * @constructor
2906
 * @param {String} id the id of the linked element 
2907
 * @param {String} sGroup the group of related DragDrop items
2908
 * @param {object} config an object containing configurable attributes
2909
 *                Valid properties for DD: 
2910
 *                    scroll
2911
 */
2912
YAHOO.util.DD = function(id, sGroup, config) {
2913
    if (id) {
2914
        this.init(id, sGroup, config);
2915
    }
2916
};
2917
2918
YAHOO.extend(YAHOO.util.DD, YAHOO.util.DragDrop, {
2919
2920
    /**
2921
     * When set to true, the utility automatically tries to scroll the browser
2922
     * window when a drag and drop element is dragged near the viewport boundary.
2923
     * Defaults to true.
2924
     * @property scroll
2925
     * @type boolean
2926
     */
2927
    scroll: true, 
2928
2929
    /**
2930
     * Sets the pointer offset to the distance between the linked element's top 
2931
     * left corner and the location the element was clicked
2932
     * @method autoOffset
2933
     * @param {int} iPageX the X coordinate of the click
2934
     * @param {int} iPageY the Y coordinate of the click
2935
     */
2936
    autoOffset: function(iPageX, iPageY) {
2937
        var x = iPageX - this.startPageX;
2938
        var y = iPageY - this.startPageY;
2939
        this.setDelta(x, y);
2940
    },
2941
2942
    /** 
2943
     * Sets the pointer offset.  You can call this directly to force the 
2944
     * offset to be in a particular location (e.g., pass in 0,0 to set it 
2945
     * to the center of the object, as done in YAHOO.widget.Slider)
2946
     * @method setDelta
2947
     * @param {int} iDeltaX the distance from the left
2948
     * @param {int} iDeltaY the distance from the top
2949
     */
2950
    setDelta: function(iDeltaX, iDeltaY) {
2951
        this.deltaX = iDeltaX;
2952
        this.deltaY = iDeltaY;
2953
    },
2954
2955
    /**
2956
     * Sets the drag element to the location of the mousedown or click event, 
2957
     * maintaining the cursor location relative to the location on the element 
2958
     * that was clicked.  Override this if you want to place the element in a 
2959
     * location other than where the cursor is.
2960
     * @method setDragElPos
2961
     * @param {int} iPageX the X coordinate of the mousedown or drag event
2962
     * @param {int} iPageY the Y coordinate of the mousedown or drag event
2963
     */
2964
    setDragElPos: function(iPageX, iPageY) {
2965
        // the first time we do this, we are going to check to make sure
2966
        // the element has css positioning
2967
2968
        var el = this.getDragEl();
2969
        this.alignElWithMouse(el, iPageX, iPageY);
2970
    },
2971
2972
    /**
2973
     * Sets the element to the location of the mousedown or click event, 
2974
     * maintaining the cursor location relative to the location on the element 
2975
     * that was clicked.  Override this if you want to place the element in a 
2976
     * location other than where the cursor is.
2977
     * @method alignElWithMouse
2978
     * @param {HTMLElement} el the element to move
2979
     * @param {int} iPageX the X coordinate of the mousedown or drag event
2980
     * @param {int} iPageY the Y coordinate of the mousedown or drag event
2981
     */
2982
    alignElWithMouse: function(el, iPageX, iPageY) {
2983
        var oCoord = this.getTargetCoord(iPageX, iPageY);
2984
2985
        if (!this.deltaSetXY) {
2986
            var aCoord = [oCoord.x, oCoord.y];
2987
            YAHOO.util.Dom.setXY(el, aCoord);
2988
2989
            var newLeft = parseInt( YAHOO.util.Dom.getStyle(el, "left"), 10 );
2990
            var newTop  = parseInt( YAHOO.util.Dom.getStyle(el, "top" ), 10 );
2991
2992
            this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
2993
        } else {
2994
            YAHOO.util.Dom.setStyle(el, "left", (oCoord.x + this.deltaSetXY[0]) + "px");
2995
            YAHOO.util.Dom.setStyle(el, "top",  (oCoord.y + this.deltaSetXY[1]) + "px");
2996
        }
2997
        
2998
        this.cachePosition(oCoord.x, oCoord.y);
2999
        var self = this;
3000
        setTimeout(function() {
3001
            self.autoScroll.call(self, oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
3002
        }, 0);
3003
    },
3004
3005
    /**
3006
     * Saves the most recent position so that we can reset the constraints and
3007
     * tick marks on-demand.  We need to know this so that we can calculate the
3008
     * number of pixels the element is offset from its original position.
3009
     * @method cachePosition
3010
     * @param iPageX the current x position (optional, this just makes it so we
3011
     * don't have to look it up again)
3012
     * @param iPageY the current y position (optional, this just makes it so we
3013
     * don't have to look it up again)
3014
     */
3015
    cachePosition: function(iPageX, iPageY) {
3016
        if (iPageX) {
3017
            this.lastPageX = iPageX;
3018
            this.lastPageY = iPageY;
3019
        } else {
3020
            var aCoord = YAHOO.util.Dom.getXY(this.getEl());
3021
            this.lastPageX = aCoord[0];
3022
            this.lastPageY = aCoord[1];
3023
        }
3024
    },
3025
3026
    /**
3027
     * Auto-scroll the window if the dragged object has been moved beyond the 
3028
     * visible window boundary.
3029
     * @method autoScroll
3030
     * @param {int} x the drag element's x position
3031
     * @param {int} y the drag element's y position
3032
     * @param {int} h the height of the drag element
3033
     * @param {int} w the width of the drag element
3034
     * @private
3035
     */
3036
    autoScroll: function(x, y, h, w) {
3037
3038
        if (this.scroll) {
3039
            // The client height
3040
            var clientH = this.DDM.getClientHeight();
3041
3042
            // The client width
3043
            var clientW = this.DDM.getClientWidth();
3044
3045
            // The amt scrolled down
3046
            var st = this.DDM.getScrollTop();
3047
3048
            // The amt scrolled right
3049
            var sl = this.DDM.getScrollLeft();
3050
3051
            // Location of the bottom of the element
3052
            var bot = h + y;
3053
3054
            // Location of the right of the element
3055
            var right = w + x;
3056
3057
            // The distance from the cursor to the bottom of the visible area, 
3058
            // adjusted so that we don't scroll if the cursor is beyond the
3059
            // element drag constraints
3060
            var toBot = (clientH + st - y - this.deltaY);
3061
3062
            // The distance from the cursor to the right of the visible area
3063
            var toRight = (clientW + sl - x - this.deltaX);
3064
3065
3066
            // How close to the edge the cursor must be before we scroll
3067
            // var thresh = (document.all) ? 100 : 40;
3068
            var thresh = 40;
3069
3070
            // How many pixels to scroll per autoscroll op.  This helps to reduce 
3071
            // clunky scrolling. IE is more sensitive about this ... it needs this 
3072
            // value to be higher.
3073
            var scrAmt = (document.all) ? 80 : 30;
3074
3075
            // Scroll down if we are near the bottom of the visible page and the 
3076
            // obj extends below the crease
3077
            if ( bot > clientH && toBot < thresh ) { 
3078
                window.scrollTo(sl, st + scrAmt); 
3079
            }
3080
3081
            // Scroll up if the window is scrolled down and the top of the object
3082
            // goes above the top border
3083
            if ( y < st && st > 0 && y - st < thresh ) { 
3084
                window.scrollTo(sl, st - scrAmt); 
3085
            }
3086
3087
            // Scroll right if the obj is beyond the right border and the cursor is
3088
            // near the border.
3089
            if ( right > clientW && toRight < thresh ) { 
3090
                window.scrollTo(sl + scrAmt, st); 
3091
            }
3092
3093
            // Scroll left if the window has been scrolled to the right and the obj
3094
            // extends past the left border
3095
            if ( x < sl && sl > 0 && x - sl < thresh ) { 
3096
                window.scrollTo(sl - scrAmt, st);
3097
            }
3098
        }
3099
    },
3100
3101
    /*
3102
     * Sets up config options specific to this class. Overrides
3103
     * YAHOO.util.DragDrop, but all versions of this method through the 
3104
     * inheritance chain are called
3105
     */
3106
    applyConfig: function() {
3107
        YAHOO.util.DD.superclass.applyConfig.call(this);
3108
        this.scroll = (this.config.scroll !== false);
3109
    },
3110
3111
    /*
3112
     * Event that fires prior to the onMouseDown event.  Overrides 
3113
     * YAHOO.util.DragDrop.
3114
     */
3115
    b4MouseDown: function(e) {
3116
        this.setStartPosition();
3117
        // this.resetConstraints();
3118
        this.autoOffset(YAHOO.util.Event.getPageX(e), 
3119
                            YAHOO.util.Event.getPageY(e));
3120
    },
3121
3122
    /*
3123
     * Event that fires prior to the onDrag event.  Overrides 
3124
     * YAHOO.util.DragDrop.
3125
     */
3126
    b4Drag: function(e) {
3127
        this.setDragElPos(YAHOO.util.Event.getPageX(e), 
3128
                            YAHOO.util.Event.getPageY(e));
3129
    },
3130
3131
    toString: function() {
3132
        return ("DD " + this.id);
3133
    }
3134
3135
    //////////////////////////////////////////////////////////////////////////
3136
    // Debugging ygDragDrop events that can be overridden
3137
    //////////////////////////////////////////////////////////////////////////
3138
    /*
3139
    startDrag: function(x, y) {
3140
    },
3141
3142
    onDrag: function(e) {
3143
    },
3144
3145
    onDragEnter: function(e, id) {
3146
    },
3147
3148
    onDragOver: function(e, id) {
3149
    },
3150
3151
    onDragOut: function(e, id) {
3152
    },
3153
3154
    onDragDrop: function(e, id) {
3155
    },
3156
3157
    endDrag: function(e) {
3158
    }
3159
3160
    */
3161
3162
/**
3163
* @event mouseDownEvent
3164
* @description Provides access to the mousedown event. The mousedown does not always result in a drag operation.
3165
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3166
*/
3167
3168
/**
3169
* @event b4MouseDownEvent
3170
* @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag.
3171
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3172
*/
3173
3174
/**
3175
* @event mouseUpEvent
3176
* @description Fired from inside DragDropMgr when the drag operation is finished.
3177
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3178
*/
3179
3180
/**
3181
* @event b4StartDragEvent
3182
* @description Fires before the startDragEvent, returning false will cancel the startDrag Event.
3183
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3184
*/
3185
3186
/**
3187
* @event startDragEvent
3188
* @description Occurs after a mouse down and the drag threshold has been met. The drag threshold default is either 3 pixels of mouse movement or 1 full second of holding the mousedown. 
3189
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3190
*/
3191
3192
/**
3193
* @event b4EndDragEvent
3194
* @description Fires before the endDragEvent. Returning false will cancel.
3195
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3196
*/
3197
3198
/**
3199
* @event endDragEvent
3200
* @description Fires on the mouseup event after a drag has been initiated (startDrag fired).
3201
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3202
*/
3203
3204
/**
3205
* @event dragEvent
3206
* @description Occurs every mousemove event while dragging.
3207
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3208
*/
3209
/**
3210
* @event b4DragEvent
3211
* @description Fires before the dragEvent.
3212
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3213
*/
3214
/**
3215
* @event invalidDropEvent
3216
* @description Fires when the dragged objects is dropped in a location that contains no drop targets.
3217
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3218
*/
3219
/**
3220
* @event b4DragOutEvent
3221
* @description Fires before the dragOutEvent
3222
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3223
*/
3224
/**
3225
* @event dragOutEvent
3226
* @description Fires when a dragged object is no longer over an object that had the onDragEnter fire. 
3227
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3228
*/
3229
/**
3230
* @event dragEnterEvent
3231
* @description Occurs when the dragged object first interacts with another targettable drag and drop object.
3232
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3233
*/
3234
/**
3235
* @event b4DragOverEvent
3236
* @description Fires before the dragOverEvent.
3237
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3238
*/
3239
/**
3240
* @event dragOverEvent
3241
* @description Fires every mousemove event while over a drag and drop object.
3242
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3243
*/
3244
/**
3245
* @event b4DragDropEvent 
3246
* @description Fires before the dragDropEvent
3247
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3248
*/
3249
/**
3250
* @event dragDropEvent
3251
* @description Fires when the dragged objects is dropped on another.
3252
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3253
*/
3254
});
3255
/**
3256
 * A DragDrop implementation that inserts an empty, bordered div into
3257
 * the document that follows the cursor during drag operations.  At the time of
3258
 * the click, the frame div is resized to the dimensions of the linked html
3259
 * element, and moved to the exact location of the linked element.
3260
 *
3261
 * References to the "frame" element refer to the single proxy element that
3262
 * was created to be dragged in place of all DDProxy elements on the
3263
 * page.
3264
 *
3265
 * @class DDProxy
3266
 * @extends YAHOO.util.DD
3267
 * @constructor
3268
 * @param {String} id the id of the linked html element
3269
 * @param {String} sGroup the group of related DragDrop objects
3270
 * @param {object} config an object containing configurable attributes
3271
 *                Valid properties for DDProxy in addition to those in DragDrop: 
3272
 *                   resizeFrame, centerFrame, dragElId
3273
 */
3274
YAHOO.util.DDProxy = function(id, sGroup, config) {
3275
    if (id) {
3276
        this.init(id, sGroup, config);
3277
        this.initFrame(); 
3278
    }
3279
};
3280
3281
/**
3282
 * The default drag frame div id
3283
 * @property YAHOO.util.DDProxy.dragElId
3284
 * @type String
3285
 * @static
3286
 */
3287
YAHOO.util.DDProxy.dragElId = "ygddfdiv";
3288
3289
YAHOO.extend(YAHOO.util.DDProxy, YAHOO.util.DD, {
3290
3291
    /**
3292
     * By default we resize the drag frame to be the same size as the element
3293
     * we want to drag (this is to get the frame effect).  We can turn it off
3294
     * if we want a different behavior.
3295
     * @property resizeFrame
3296
     * @type boolean
3297
     */
3298
    resizeFrame: true,
3299
3300
    /**
3301
     * By default the frame is positioned exactly where the drag element is, so
3302
     * we use the cursor offset provided by YAHOO.util.DD.  Another option that works only if
3303
     * you do not have constraints on the obj is to have the drag frame centered
3304
     * around the cursor.  Set centerFrame to true for this effect.
3305
     * @property centerFrame
3306
     * @type boolean
3307
     */
3308
    centerFrame: false,
3309
3310
    /**
3311
     * Creates the proxy element if it does not yet exist
3312
     * @method createFrame
3313
     */
3314
    createFrame: function() {
3315
        var self=this, body=document.body;
3316
3317
        if (!body || !body.firstChild) {
3318
            setTimeout( function() { self.createFrame(); }, 50 );
3319
            return;
3320
        }
3321
3322
        var div=this.getDragEl(), Dom=YAHOO.util.Dom;
3323
3324
        if (!div) {
3325
            div    = document.createElement("div");
3326
            div.id = this.dragElId;
3327
            var s  = div.style;
3328
3329
            s.position   = "absolute";
3330
            s.visibility = "hidden";
3331
            s.cursor     = "move";
3332
            s.border     = "2px solid #aaa";
3333
            s.zIndex     = 999;
3334
            s.height     = "25px";
3335
            s.width      = "25px";
3336
3337
            var _data = document.createElement('div');
3338
            Dom.setStyle(_data, 'height', '100%');
3339
            Dom.setStyle(_data, 'width', '100%');
3340
            /**
3341
            * If the proxy element has no background-color, then it is considered to the "transparent" by Internet Explorer.
3342
            * Since it is "transparent" then the events pass through it to the iframe below.
3343
            * So creating a "fake" div inside the proxy element and giving it a background-color, then setting it to an
3344
            * opacity of 0, it appears to not be there, however IE still thinks that it is so the events never pass through.
3345
            */
3346
            Dom.setStyle(_data, 'background-color', '#ccc');
3347
            Dom.setStyle(_data, 'opacity', '0');
3348
            div.appendChild(_data);
3349
3350
            // appendChild can blow up IE if invoked prior to the window load event
3351
            // while rendering a table.  It is possible there are other scenarios 
3352
            // that would cause this to happen as well.
3353
            body.insertBefore(div, body.firstChild);
3354
        }
3355
    },
3356
3357
    /**
3358
     * Initialization for the drag frame element.  Must be called in the
3359
     * constructor of all subclasses
3360
     * @method initFrame
3361
     */
3362
    initFrame: function() {
3363
        this.createFrame();
3364
    },
3365
3366
    applyConfig: function() {
3367
        YAHOO.util.DDProxy.superclass.applyConfig.call(this);
3368
3369
        this.resizeFrame = (this.config.resizeFrame !== false);
3370
        this.centerFrame = (this.config.centerFrame);
3371
        this.setDragElId(this.config.dragElId || YAHOO.util.DDProxy.dragElId);
3372
    },
3373
3374
    /**
3375
     * Resizes the drag frame to the dimensions of the clicked object, positions 
3376
     * it over the object, and finally displays it
3377
     * @method showFrame
3378
     * @param {int} iPageX X click position
3379
     * @param {int} iPageY Y click position
3380
     * @private
3381
     */
3382
    showFrame: function(iPageX, iPageY) {
3383
        var el = this.getEl();
3384
        var dragEl = this.getDragEl();
3385
        var s = dragEl.style;
3386
3387
        this._resizeProxy();
3388
3389
        if (this.centerFrame) {
3390
            this.setDelta( Math.round(parseInt(s.width,  10)/2), 
3391
                           Math.round(parseInt(s.height, 10)/2) );
3392
        }
3393
3394
        this.setDragElPos(iPageX, iPageY);
3395
3396
        YAHOO.util.Dom.setStyle(dragEl, "visibility", "visible"); 
3397
    },
3398
3399
    /**
3400
     * The proxy is automatically resized to the dimensions of the linked
3401
     * element when a drag is initiated, unless resizeFrame is set to false
3402
     * @method _resizeProxy
3403
     * @private
3404
     */
3405
    _resizeProxy: function() {
3406
        if (this.resizeFrame) {
3407
            var DOM    = YAHOO.util.Dom;
3408
            var el     = this.getEl();
3409
            var dragEl = this.getDragEl();
3410
3411
            var bt = parseInt( DOM.getStyle(dragEl, "borderTopWidth"    ), 10);
3412
            var br = parseInt( DOM.getStyle(dragEl, "borderRightWidth"  ), 10);
3413
            var bb = parseInt( DOM.getStyle(dragEl, "borderBottomWidth" ), 10);
3414
            var bl = parseInt( DOM.getStyle(dragEl, "borderLeftWidth"   ), 10);
3415
3416
            if (isNaN(bt)) { bt = 0; }
3417
            if (isNaN(br)) { br = 0; }
3418
            if (isNaN(bb)) { bb = 0; }
3419
            if (isNaN(bl)) { bl = 0; }
3420
3421
3422
            var newWidth  = Math.max(0, el.offsetWidth  - br - bl);                                                                                           
3423
            var newHeight = Math.max(0, el.offsetHeight - bt - bb);
3424
3425
3426
            DOM.setStyle( dragEl, "width",  newWidth  + "px" );
3427
            DOM.setStyle( dragEl, "height", newHeight + "px" );
3428
        }
3429
    },
3430
3431
    // overrides YAHOO.util.DragDrop
3432
    b4MouseDown: function(e) {
3433
        this.setStartPosition();
3434
        var x = YAHOO.util.Event.getPageX(e);
3435
        var y = YAHOO.util.Event.getPageY(e);
3436
        this.autoOffset(x, y);
3437
3438
        // This causes the autoscroll code to kick off, which means autoscroll can
3439
        // happen prior to the check for a valid drag handle.
3440
        // this.setDragElPos(x, y);
3441
    },
3442
3443
    // overrides YAHOO.util.DragDrop
3444
    b4StartDrag: function(x, y) {
3445
        // show the drag frame
3446
        this.showFrame(x, y);
3447
    },
3448
3449
    // overrides YAHOO.util.DragDrop
3450
    b4EndDrag: function(e) {
3451
        YAHOO.util.Dom.setStyle(this.getDragEl(), "visibility", "hidden"); 
3452
    },
3453
3454
    // overrides YAHOO.util.DragDrop
3455
    // By default we try to move the element to the last location of the frame.  
3456
    // This is so that the default behavior mirrors that of YAHOO.util.DD.  
3457
    endDrag: function(e) {
3458
        var DOM = YAHOO.util.Dom;
3459
        var lel = this.getEl();
3460
        var del = this.getDragEl();
3461
3462
        // Show the drag frame briefly so we can get its position
3463
        // del.style.visibility = "";
3464
        DOM.setStyle(del, "visibility", ""); 
3465
3466
        // Hide the linked element before the move to get around a Safari 
3467
        // rendering bug.
3468
        //lel.style.visibility = "hidden";
3469
        DOM.setStyle(lel, "visibility", "hidden"); 
3470
        YAHOO.util.DDM.moveToEl(lel, del);
3471
        //del.style.visibility = "hidden";
3472
        DOM.setStyle(del, "visibility", "hidden"); 
3473
        //lel.style.visibility = "";
3474
        DOM.setStyle(lel, "visibility", ""); 
3475
    },
3476
3477
    toString: function() {
3478
        return ("DDProxy " + this.id);
3479
    }
3480
/**
3481
* @event mouseDownEvent
3482
* @description Provides access to the mousedown event. The mousedown does not always result in a drag operation.
3483
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3484
*/
3485
3486
/**
3487
* @event b4MouseDownEvent
3488
* @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag.
3489
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3490
*/
3491
3492
/**
3493
* @event mouseUpEvent
3494
* @description Fired from inside DragDropMgr when the drag operation is finished.
3495
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3496
*/
3497
3498
/**
3499
* @event b4StartDragEvent
3500
* @description Fires before the startDragEvent, returning false will cancel the startDrag Event.
3501
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3502
*/
3503
3504
/**
3505
* @event startDragEvent
3506
* @description Occurs after a mouse down and the drag threshold has been met. The drag threshold default is either 3 pixels of mouse movement or 1 full second of holding the mousedown. 
3507
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3508
*/
3509
3510
/**
3511
* @event b4EndDragEvent
3512
* @description Fires before the endDragEvent. Returning false will cancel.
3513
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3514
*/
3515
3516
/**
3517
* @event endDragEvent
3518
* @description Fires on the mouseup event after a drag has been initiated (startDrag fired).
3519
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3520
*/
3521
3522
/**
3523
* @event dragEvent
3524
* @description Occurs every mousemove event while dragging.
3525
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3526
*/
3527
/**
3528
* @event b4DragEvent
3529
* @description Fires before the dragEvent.
3530
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3531
*/
3532
/**
3533
* @event invalidDropEvent
3534
* @description Fires when the dragged objects is dropped in a location that contains no drop targets.
3535
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3536
*/
3537
/**
3538
* @event b4DragOutEvent
3539
* @description Fires before the dragOutEvent
3540
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3541
*/
3542
/**
3543
* @event dragOutEvent
3544
* @description Fires when a dragged object is no longer over an object that had the onDragEnter fire. 
3545
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3546
*/
3547
/**
3548
* @event dragEnterEvent
3549
* @description Occurs when the dragged object first interacts with another targettable drag and drop object.
3550
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3551
*/
3552
/**
3553
* @event b4DragOverEvent
3554
* @description Fires before the dragOverEvent.
3555
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3556
*/
3557
/**
3558
* @event dragOverEvent
3559
* @description Fires every mousemove event while over a drag and drop object.
3560
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3561
*/
3562
/**
3563
* @event b4DragDropEvent 
3564
* @description Fires before the dragDropEvent
3565
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3566
*/
3567
/**
3568
* @event dragDropEvent
3569
* @description Fires when the dragged objects is dropped on another.
3570
* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3571
*/
3572
3573
});
3574
/**
3575
 * A DragDrop implementation that does not move, but can be a drop 
3576
 * target.  You would get the same result by simply omitting implementation 
3577
 * for the event callbacks, but this way we reduce the processing cost of the 
3578
 * event listener and the callbacks.
3579
 * @class DDTarget
3580
 * @extends YAHOO.util.DragDrop 
3581
 * @constructor
3582
 * @param {String} id the id of the element that is a drop target
3583
 * @param {String} sGroup the group of related DragDrop objects
3584
 * @param {object} config an object containing configurable attributes
3585
 *                 Valid properties for DDTarget in addition to those in 
3586
 *                 DragDrop: 
3587
 *                    none
3588
 */
3589
YAHOO.util.DDTarget = function(id, sGroup, config) {
3590
    if (id) {
3591
        this.initTarget(id, sGroup, config);
3592
    }
3593
};
3594
3595
// YAHOO.util.DDTarget.prototype = new YAHOO.util.DragDrop();
3596
YAHOO.extend(YAHOO.util.DDTarget, YAHOO.util.DragDrop, {
3597
    toString: function() {
3598
        return ("DDTarget " + this.id);
3599
    }
3600
});
3601
YAHOO.register("dragdrop", YAHOO.util.DragDropMgr, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/element/element-beta-min.js (-8 lines)
Lines 1-8 Link Here
1
/*
2
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
3
Code licensed under the BSD License:
4
http://developer.yahoo.net/yui/license.txt
5
version: 2.5.1
6
*/
7
YAHOO.util.Attribute=function(B,A){if(A){this.owner=A;this.configure(B,true);}};YAHOO.util.Attribute.prototype={name:undefined,value:null,owner:null,readOnly:false,writeOnce:false,_initialConfig:null,_written:false,method:null,validator:null,getValue:function(){return this.value;},setValue:function(F,B){var E;var A=this.owner;var C=this.name;var D={type:C,prevValue:this.getValue(),newValue:F};if(this.readOnly||(this.writeOnce&&this._written)){return false;}if(this.validator&&!this.validator.call(A,F)){return false;}if(!B){E=A.fireBeforeChangeEvent(D);if(E===false){return false;}}if(this.method){this.method.call(A,F);}this.value=F;this._written=true;D.type=C;if(!B){this.owner.fireChangeEvent(D);}return true;},configure:function(B,C){B=B||{};this._written=false;this._initialConfig=this._initialConfig||{};for(var A in B){if(A&&YAHOO.lang.hasOwnProperty(B,A)){this[A]=B[A];if(C){this._initialConfig[A]=B[A];}}}},resetValue:function(){return this.setValue(this._initialConfig.value);},resetConfig:function(){this.configure(this._initialConfig);},refresh:function(A){this.setValue(this.value,A);}};(function(){var A=YAHOO.util.Lang;YAHOO.util.AttributeProvider=function(){};YAHOO.util.AttributeProvider.prototype={_configs:null,get:function(C){this._configs=this._configs||{};var B=this._configs[C];if(!B){return undefined;}return B.value;},set:function(D,E,B){this._configs=this._configs||{};var C=this._configs[D];if(!C){return false;}return C.setValue(E,B);},getAttributeKeys:function(){this._configs=this._configs;var D=[];var B;for(var C in this._configs){B=this._configs[C];if(A.hasOwnProperty(this._configs,C)&&!A.isUndefined(B)){D[D.length]=C;}}return D;},setAttributes:function(D,B){for(var C in D){if(A.hasOwnProperty(D,C)){this.set(C,D[C],B);}}},resetValue:function(C,B){this._configs=this._configs||{};if(this._configs[C]){this.set(C,this._configs[C]._initialConfig.value,B);return true;}return false;},refresh:function(E,C){this._configs=this._configs;E=((A.isString(E))?[E]:E)||this.getAttributeKeys();for(var D=0,B=E.length;D<B;++D){if(this._configs[E[D]]&&!A.isUndefined(this._configs[E[D]].value)&&!A.isNull(this._configs[E[D]].value)){this._configs[E[D]].refresh(C);}}},register:function(B,C){this.setAttributeConfig(B,C);},getAttributeConfig:function(C){this._configs=this._configs||{};var B=this._configs[C]||{};var D={};for(C in B){if(A.hasOwnProperty(B,C)){D[C]=B[C];}}return D;},setAttributeConfig:function(B,C,D){this._configs=this._configs||{};C=C||{};if(!this._configs[B]){C.name=B;this._configs[B]=this.createAttribute(C);}else{this._configs[B].configure(C,D);}},configureAttribute:function(B,C,D){this.setAttributeConfig(B,C,D);},resetAttributeConfig:function(B){this._configs=this._configs||{};this._configs[B].resetConfig();},subscribe:function(B,C){this._events=this._events||{};if(!(B in this._events)){this._events[B]=this.createEvent(B);}YAHOO.util.EventProvider.prototype.subscribe.apply(this,arguments);},on:function(){this.subscribe.apply(this,arguments);},addListener:function(){this.subscribe.apply(this,arguments);},fireBeforeChangeEvent:function(C){var B="before";B+=C.type.charAt(0).toUpperCase()+C.type.substr(1)+"Change";C.type=B;return this.fireEvent(C.type,C);},fireChangeEvent:function(B){B.type+="Change";return this.fireEvent(B.type,B);},createAttribute:function(B){return new YAHOO.util.Attribute(B,this);}};YAHOO.augment(YAHOO.util.AttributeProvider,YAHOO.util.EventProvider);})();(function(){var D=YAHOO.util.Dom,F=YAHOO.util.AttributeProvider;YAHOO.util.Element=function(G,H){if(arguments.length){this.init(G,H);}};YAHOO.util.Element.prototype={DOM_EVENTS:null,appendChild:function(G){G=G.get?G.get("element"):G;this.get("element").appendChild(G);},getElementsByTagName:function(G){return this.get("element").getElementsByTagName(G);},hasChildNodes:function(){return this.get("element").hasChildNodes();},insertBefore:function(G,H){G=G.get?G.get("element"):G;H=(H&&H.get)?H.get("element"):H;this.get("element").insertBefore(G,H);},removeChild:function(G){G=G.get?G.get("element"):G;this.get("element").removeChild(G);return true;},replaceChild:function(G,H){G=G.get?G.get("element"):G;H=H.get?H.get("element"):H;return this.get("element").replaceChild(G,H);},initAttributes:function(G){},addListener:function(K,J,L,I){var H=this.get("element");I=I||this;H=this.get("id")||H;var G=this;if(!this._events[K]){if(this.DOM_EVENTS[K]){YAHOO.util.Event.addListener(H,K,function(M){if(M.srcElement&&!M.target){M.target=M.srcElement;}G.fireEvent(K,M);},L,I);}this.createEvent(K,this);}YAHOO.util.EventProvider.prototype.subscribe.apply(this,arguments);},on:function(){this.addListener.apply(this,arguments);},subscribe:function(){this.addListener.apply(this,arguments);},removeListener:function(H,G){this.unsubscribe.apply(this,arguments);},addClass:function(G){D.addClass(this.get("element"),G);},getElementsByClassName:function(H,G){return D.getElementsByClassName(H,G,this.get("element"));},hasClass:function(G){return D.hasClass(this.get("element"),G);},removeClass:function(G){return D.removeClass(this.get("element"),G);},replaceClass:function(H,G){return D.replaceClass(this.get("element"),H,G);},setStyle:function(I,H){var G=this.get("element");if(!G){return this._queue[this._queue.length]=["setStyle",arguments];}return D.setStyle(G,I,H);},getStyle:function(G){return D.getStyle(this.get("element"),G);},fireQueue:function(){var H=this._queue;for(var I=0,G=H.length;I<G;++I){this[H[I][0]].apply(this,H[I][1]);}},appendTo:function(H,I){H=(H.get)?H.get("element"):D.get(H);this.fireEvent("beforeAppendTo",{type:"beforeAppendTo",target:H});I=(I&&I.get)?I.get("element"):D.get(I);var G=this.get("element");if(!G){return false;}if(!H){return false;}if(G.parent!=H){if(I){H.insertBefore(G,I);}else{H.appendChild(G);}}this.fireEvent("appendTo",{type:"appendTo",target:H});},get:function(G){var I=this._configs||{};var H=I.element;if(H&&!I[G]&&!YAHOO.lang.isUndefined(H.value[G])){return H.value[G];}return F.prototype.get.call(this,G);},setAttributes:function(L,H){var K=this.get("element");
8
for(var J in L){if(!this._configs[J]&&!YAHOO.lang.isUndefined(K[J])){this.setAttributeConfig(J);}}for(var I=0,G=this._configOrder.length;I<G;++I){if(L[this._configOrder[I]]!==undefined){this.set(this._configOrder[I],L[this._configOrder[I]],H);}}},set:function(H,J,G){var I=this.get("element");if(!I){this._queue[this._queue.length]=["set",arguments];if(this._configs[H]){this._configs[H].value=J;}return ;}if(!this._configs[H]&&!YAHOO.lang.isUndefined(I[H])){C.call(this,H);}return F.prototype.set.apply(this,arguments);},setAttributeConfig:function(G,I,J){var H=this.get("element");if(H&&!this._configs[G]&&!YAHOO.lang.isUndefined(H[G])){C.call(this,G,I);}else{F.prototype.setAttributeConfig.apply(this,arguments);}this._configOrder.push(G);},getAttributeKeys:function(){var H=this.get("element");var I=F.prototype.getAttributeKeys.call(this);for(var G in H){if(!this._configs[G]){I[G]=I[G]||H[G];}}return I;},createEvent:function(H,G){this._events[H]=true;F.prototype.createEvent.apply(this,arguments);},init:function(H,G){A.apply(this,arguments);}};var A=function(H,G){this._queue=this._queue||[];this._events=this._events||{};this._configs=this._configs||{};this._configOrder=[];G=G||{};G.element=G.element||H||null;this.DOM_EVENTS={"click":true,"dblclick":true,"keydown":true,"keypress":true,"keyup":true,"mousedown":true,"mousemove":true,"mouseout":true,"mouseover":true,"mouseup":true,"focus":true,"blur":true,"submit":true};var I=false;if(YAHOO.lang.isString(H)){C.call(this,"id",{value:G.element});}if(D.get(H)){I=true;E.call(this,G);B.call(this,G);}YAHOO.util.Event.onAvailable(G.element,function(){if(!I){E.call(this,G);}this.fireEvent("available",{type:"available",target:G.element});},this,true);YAHOO.util.Event.onContentReady(G.element,function(){if(!I){B.call(this,G);}this.fireEvent("contentReady",{type:"contentReady",target:G.element});},this,true);};var E=function(G){this.setAttributeConfig("element",{value:D.get(G.element),readOnly:true});};var B=function(G){this.initAttributes(G);this.setAttributes(G,true);this.fireQueue();};var C=function(G,I){var H=this.get("element");I=I||{};I.name=G;I.method=I.method||function(J){H[G]=J;};I.value=I.value||H[G];this._configs[G]=new YAHOO.util.Attribute(I,this);};YAHOO.augment(YAHOO.util.Element,F);})();YAHOO.register("element",YAHOO.util.Element,{version:"2.5.1",build:"984"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/element/element-debug.js (-1106 lines)
Lines 1-1106 Link Here
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.8.0r4
6
*/
7
/**
8
 * Provides Attribute configurations.
9
 * @namespace YAHOO.util
10
 * @class Attribute
11
 * @constructor
12
 * @param hash {Object} The intial Attribute.
13
 * @param {YAHOO.util.AttributeProvider} The owner of the Attribute instance.
14
 */
15
16
YAHOO.util.Attribute = function(hash, owner) {
17
    if (owner) { 
18
        this.owner = owner;
19
        this.configure(hash, true);
20
    }
21
};
22
23
YAHOO.util.Attribute.prototype = {
24
    /**
25
     * The name of the attribute.
26
     * @property name
27
     * @type String
28
     */
29
    name: undefined,
30
    
31
    /**
32
     * The value of the attribute.
33
     * @property value
34
     * @type String
35
     */
36
    value: null,
37
    
38
    /**
39
     * The owner of the attribute.
40
     * @property owner
41
     * @type YAHOO.util.AttributeProvider
42
     */
43
    owner: null,
44
    
45
    /**
46
     * Whether or not the attribute is read only.
47
     * @property readOnly
48
     * @type Boolean
49
     */
50
    readOnly: false,
51
    
52
    /**
53
     * Whether or not the attribute can only be written once.
54
     * @property writeOnce
55
     * @type Boolean
56
     */
57
    writeOnce: false,
58
59
    /**
60
     * The attribute's initial configuration.
61
     * @private
62
     * @property _initialConfig
63
     * @type Object
64
     */
65
    _initialConfig: null,
66
    
67
    /**
68
     * Whether or not the attribute's value has been set.
69
     * @private
70
     * @property _written
71
     * @type Boolean
72
     */
73
    _written: false,
74
    
75
    /**
76
     * A function to call when setting the attribute's value.
77
     * The method receives the new value as the first arg and the attribute name as the 2nd
78
     * @property method
79
     * @type Function
80
     */
81
    method: null,
82
    
83
    /**
84
     * The function to use when setting the attribute's value.
85
     * The setter receives the new value as the first arg and the attribute name as the 2nd
86
     * The return value of the setter replaces the value passed to set(). 
87
     * @property setter
88
     * @type Function
89
     */
90
    setter: null,
91
    
92
    /**
93
     * The function to use when getting the attribute's value.
94
     * The getter receives the new value as the first arg and the attribute name as the 2nd
95
     * The return value of the getter will be used as the return from get().
96
     * @property getter
97
     * @type Function
98
     */
99
    getter: null,
100
101
    /**
102
     * The validator to use when setting the attribute's value.
103
     * @property validator
104
     * @type Function
105
     * @return Boolean
106
     */
107
    validator: null,
108
    
109
    /**
110
     * Retrieves the current value of the attribute.
111
     * @method getValue
112
     * @return {any} The current value of the attribute.
113
     */
114
    getValue: function() {
115
        var val = this.value;
116
117
        if (this.getter) {
118
            val = this.getter.call(this.owner, this.name, val);
119
        }
120
121
        return val;
122
    },
123
    
124
    /**
125
     * Sets the value of the attribute and fires beforeChange and change events.
126
     * @method setValue
127
     * @param {Any} value The value to apply to the attribute.
128
     * @param {Boolean} silent If true the change events will not be fired.
129
     * @return {Boolean} Whether or not the value was set.
130
     */
131
    setValue: function(value, silent) {
132
        var beforeRetVal,
133
            owner = this.owner,
134
            name = this.name;
135
        
136
        var event = {
137
            type: name, 
138
            prevValue: this.getValue(),
139
            newValue: value
140
        };
141
        
142
        if (this.readOnly || ( this.writeOnce && this._written) ) {
143
            YAHOO.log( 'setValue ' + name + ', ' +  value +
144
                    ' failed: read only', 'error', 'Attribute');
145
            return false; // write not allowed
146
        }
147
        
148
        if (this.validator && !this.validator.call(owner, value) ) {
149
            YAHOO.log( 'setValue ' + name + ', ' + value +
150
                    ' validation failed', 'error', 'Attribute');
151
            return false; // invalid value
152
        }
153
154
        if (!silent) {
155
            beforeRetVal = owner.fireBeforeChangeEvent(event);
156
            if (beforeRetVal === false) {
157
                YAHOO.log('setValue ' + name + 
158
                        ' cancelled by beforeChange event', 'info', 'Attribute');
159
                return false;
160
            }
161
        }
162
163
        if (this.setter) {
164
            value = this.setter.call(owner, value, this.name);
165
            if (value === undefined) {
166
                YAHOO.log('setter for ' + this.name + ' returned undefined', 'warn', 'Attribute');
167
            }
168
        }
169
        
170
        if (this.method) {
171
            this.method.call(owner, value, this.name);
172
        }
173
        
174
        this.value = value; // TODO: set before calling setter/method?
175
        this._written = true;
176
        
177
        event.type = name;
178
        
179
        if (!silent) {
180
            this.owner.fireChangeEvent(event);
181
        }
182
        
183
        return true;
184
    },
185
    
186
    /**
187
     * Allows for configuring the Attribute's properties.
188
     * @method configure
189
     * @param {Object} map A key-value map of Attribute properties.
190
     * @param {Boolean} init Whether or not this should become the initial config.
191
     */
192
    configure: function(map, init) {
193
        map = map || {};
194
195
        if (init) {
196
            this._written = false; // reset writeOnce
197
        }
198
199
        this._initialConfig = this._initialConfig || {};
200
        
201
        for (var key in map) {
202
            if ( map.hasOwnProperty(key) ) {
203
                this[key] = map[key];
204
                if (init) {
205
                    this._initialConfig[key] = map[key];
206
                }
207
            }
208
        }
209
    },
210
    
211
    /**
212
     * Resets the value to the initial config value.
213
     * @method resetValue
214
     * @return {Boolean} Whether or not the value was set.
215
     */
216
    resetValue: function() {
217
        return this.setValue(this._initialConfig.value);
218
    },
219
    
220
    /**
221
     * Resets the attribute config to the initial config state.
222
     * @method resetConfig
223
     */
224
    resetConfig: function() {
225
        this.configure(this._initialConfig, true);
226
    },
227
    
228
    /**
229
     * Resets the value to the current value.
230
     * Useful when values may have gotten out of sync with actual properties.
231
     * @method refresh
232
     * @return {Boolean} Whether or not the value was set.
233
     */
234
    refresh: function(silent) {
235
        this.setValue(this.value, silent);
236
    }
237
};
238
239
(function() {
240
    var Lang = YAHOO.util.Lang;
241
242
    /*
243
    Copyright (c) 2006, Yahoo! Inc. All rights reserved.
244
    Code licensed under the BSD License:
245
    http://developer.yahoo.net/yui/license.txt
246
    */
247
    
248
    /**
249
     * Provides and manages YAHOO.util.Attribute instances
250
     * @namespace YAHOO.util
251
     * @class AttributeProvider
252
     * @uses YAHOO.util.EventProvider
253
     */
254
    YAHOO.util.AttributeProvider = function() {};
255
256
    YAHOO.util.AttributeProvider.prototype = {
257
        
258
        /**
259
         * A key-value map of Attribute configurations
260
         * @property _configs
261
         * @protected (may be used by subclasses and augmentors)
262
         * @private
263
         * @type {Object}
264
         */
265
        _configs: null,
266
        /**
267
         * Returns the current value of the attribute.
268
         * @method get
269
         * @param {String} key The attribute whose value will be returned.
270
         * @return {Any} The current value of the attribute.
271
         */
272
        get: function(key){
273
            this._configs = this._configs || {};
274
            var config = this._configs[key];
275
            
276
            if (!config || !this._configs.hasOwnProperty(key)) {
277
                YAHOO.log(key + ' not found', 'error', 'AttributeProvider');
278
                return null;
279
            }
280
            
281
            return config.getValue();
282
        },
283
        
284
        /**
285
         * Sets the value of a config.
286
         * @method set
287
         * @param {String} key The name of the attribute
288
         * @param {Any} value The value to apply to the attribute
289
         * @param {Boolean} silent Whether or not to suppress change events
290
         * @return {Boolean} Whether or not the value was set.
291
         */
292
        set: function(key, value, silent){
293
            this._configs = this._configs || {};
294
            var config = this._configs[key];
295
            
296
            if (!config) {
297
                YAHOO.log('set failed: ' + key + ' not found',
298
                        'error', 'AttributeProvider');
299
                return false;
300
            }
301
            
302
            return config.setValue(value, silent);
303
        },
304
    
305
        /**
306
         * Returns an array of attribute names.
307
         * @method getAttributeKeys
308
         * @return {Array} An array of attribute names.
309
         */
310
        getAttributeKeys: function(){
311
            this._configs = this._configs;
312
            var keys = [], key;
313
314
            for (key in this._configs) {
315
                if ( Lang.hasOwnProperty(this._configs, key) && 
316
                        !Lang.isUndefined(this._configs[key]) ) {
317
                    keys[keys.length] = key;
318
                }
319
            }
320
            
321
            return keys;
322
        },
323
        
324
        /**
325
         * Sets multiple attribute values.
326
         * @method setAttributes
327
         * @param {Object} map  A key-value map of attributes
328
         * @param {Boolean} silent Whether or not to suppress change events
329
         */
330
        setAttributes: function(map, silent){
331
            for (var key in map) {
332
                if ( Lang.hasOwnProperty(map, key) ) {
333
                    this.set(key, map[key], silent);
334
                }
335
            }
336
        },
337
    
338
        /**
339
         * Resets the specified attribute's value to its initial value.
340
         * @method resetValue
341
         * @param {String} key The name of the attribute
342
         * @param {Boolean} silent Whether or not to suppress change events
343
         * @return {Boolean} Whether or not the value was set
344
         */
345
        resetValue: function(key, silent){
346
            this._configs = this._configs || {};
347
            if (this._configs[key]) {
348
                this.set(key, this._configs[key]._initialConfig.value, silent);
349
                return true;
350
            }
351
            return false;
352
        },
353
    
354
        /**
355
         * Sets the attribute's value to its current value.
356
         * @method refresh
357
         * @param {String | Array} key The attribute(s) to refresh
358
         * @param {Boolean} silent Whether or not to suppress change events
359
         */
360
        refresh: function(key, silent) {
361
            this._configs = this._configs || {};
362
            var configs = this._configs;
363
            
364
            key = ( ( Lang.isString(key) ) ? [key] : key ) || 
365
                    this.getAttributeKeys();
366
            
367
            for (var i = 0, len = key.length; i < len; ++i) { 
368
                if (configs.hasOwnProperty(key[i])) {
369
                    this._configs[key[i]].refresh(silent);
370
                }
371
            }
372
        },
373
    
374
        /**
375
         * Adds an Attribute to the AttributeProvider instance. 
376
         * @method register
377
         * @param {String} key The attribute's name
378
         * @param {Object} map A key-value map containing the
379
         * attribute's properties.
380
         * @deprecated Use setAttributeConfig
381
         */
382
        register: function(key, map) {
383
            this.setAttributeConfig(key, map);
384
        },
385
        
386
        
387
        /**
388
         * Returns the attribute's properties.
389
         * @method getAttributeConfig
390
         * @param {String} key The attribute's name
391
         * @private
392
         * @return {object} A key-value map containing all of the
393
         * attribute's properties.
394
         */
395
        getAttributeConfig: function(key) {
396
            this._configs = this._configs || {};
397
            var config = this._configs[key] || {};
398
            var map = {}; // returning a copy to prevent overrides
399
            
400
            for (key in config) {
401
                if ( Lang.hasOwnProperty(config, key) ) {
402
                    map[key] = config[key];
403
                }
404
            }
405
    
406
            return map;
407
        },
408
        
409
        /**
410
         * Sets or updates an Attribute instance's properties. 
411
         * @method setAttributeConfig
412
         * @param {String} key The attribute's name.
413
         * @param {Object} map A key-value map of attribute properties
414
         * @param {Boolean} init Whether or not this should become the intial config.
415
         */
416
        setAttributeConfig: function(key, map, init) {
417
            this._configs = this._configs || {};
418
            map = map || {};
419
            if (!this._configs[key]) {
420
                map.name = key;
421
                this._configs[key] = this.createAttribute(map);
422
            } else {
423
                this._configs[key].configure(map, init);
424
            }
425
        },
426
        
427
        /**
428
         * Sets or updates an Attribute instance's properties. 
429
         * @method configureAttribute
430
         * @param {String} key The attribute's name.
431
         * @param {Object} map A key-value map of attribute properties
432
         * @param {Boolean} init Whether or not this should become the intial config.
433
         * @deprecated Use setAttributeConfig
434
         */
435
        configureAttribute: function(key, map, init) {
436
            this.setAttributeConfig(key, map, init);
437
        },
438
        
439
        /**
440
         * Resets an attribute to its intial configuration. 
441
         * @method resetAttributeConfig
442
         * @param {String} key The attribute's name.
443
         * @private
444
         */
445
        resetAttributeConfig: function(key){
446
            this._configs = this._configs || {};
447
            this._configs[key].resetConfig();
448
        },
449
        
450
        // wrapper for EventProvider.subscribe
451
        // to create events on the fly
452
        subscribe: function(type, callback) {
453
            this._events = this._events || {};
454
455
            if ( !(type in this._events) ) {
456
                this._events[type] = this.createEvent(type);
457
            }
458
459
            YAHOO.util.EventProvider.prototype.subscribe.apply(this, arguments);
460
        },
461
462
        on: function() {
463
            this.subscribe.apply(this, arguments);
464
        },
465
466
        addListener: function() {
467
            this.subscribe.apply(this, arguments);
468
        },
469
470
        /**
471
         * Fires the attribute's beforeChange event. 
472
         * @method fireBeforeChangeEvent
473
         * @param {String} key The attribute's name.
474
         * @param {Obj} e The event object to pass to handlers.
475
         */
476
        fireBeforeChangeEvent: function(e) {
477
            var type = 'before';
478
            type += e.type.charAt(0).toUpperCase() + e.type.substr(1) + 'Change';
479
            e.type = type;
480
            return this.fireEvent(e.type, e);
481
        },
482
        
483
        /**
484
         * Fires the attribute's change event. 
485
         * @method fireChangeEvent
486
         * @param {String} key The attribute's name.
487
         * @param {Obj} e The event object to pass to the handlers.
488
         */
489
        fireChangeEvent: function(e) {
490
            e.type += 'Change';
491
            return this.fireEvent(e.type, e);
492
        },
493
494
        createAttribute: function(map) {
495
            return new YAHOO.util.Attribute(map, this);
496
        }
497
    };
498
    
499
    YAHOO.augment(YAHOO.util.AttributeProvider, YAHOO.util.EventProvider);
500
})();
501
502
(function() {
503
// internal shorthand
504
var Dom = YAHOO.util.Dom,
505
    AttributeProvider = YAHOO.util.AttributeProvider,
506
	specialTypes = {
507
		mouseenter: true,
508
		mouseleave: true
509
	};
510
511
/**
512
 * Element provides an wrapper object to simplify adding
513
 * event listeners, using dom methods, and managing attributes. 
514
 * @module element
515
 * @namespace YAHOO.util
516
 * @requires yahoo, dom, event
517
 */
518
519
/**
520
 * Element provides an wrapper object to simplify adding
521
 * event listeners, using dom methods, and managing attributes. 
522
 * @class Element
523
 * @uses YAHOO.util.AttributeProvider
524
 * @constructor
525
 * @param el {HTMLElement | String} The html element that 
526
 * represents the Element.
527
 * @param {Object} map A key-value map of initial config names and values
528
 */
529
var Element = function(el, map) {
530
    this.init.apply(this, arguments);
531
};
532
533
Element.DOM_EVENTS = {
534
    'click': true,
535
    'dblclick': true,
536
    'keydown': true,
537
    'keypress': true,
538
    'keyup': true,
539
    'mousedown': true,
540
    'mousemove': true,
541
    'mouseout': true, 
542
    'mouseover': true, 
543
    'mouseup': true,
544
    'mouseenter': true, 
545
    'mouseleave': true,
546
    'focus': true,
547
    'blur': true,
548
    'submit': true,
549
    'change': true
550
};
551
552
Element.prototype = {
553
    /**
554
     * Dom events supported by the Element instance.
555
     * @property DOM_EVENTS
556
     * @type Object
557
     */
558
    DOM_EVENTS: null,
559
560
    DEFAULT_HTML_SETTER: function(value, key) {
561
        var el = this.get('element');
562
        
563
        if (el) {
564
            el[key] = value;
565
        }
566
567
		return value;
568
569
    },
570
571
    DEFAULT_HTML_GETTER: function(key) {
572
        var el = this.get('element'),
573
            val;
574
575
        if (el) {
576
            val = el[key];
577
        }
578
579
        return val;
580
    },
581
582
    /**
583
     * Wrapper for HTMLElement method.
584
     * @method appendChild
585
     * @param {YAHOO.util.Element || HTMLElement} child The element to append. 
586
     * @return {HTMLElement} The appended DOM element. 
587
     */
588
    appendChild: function(child) {
589
        child = child.get ? child.get('element') : child;
590
        return this.get('element').appendChild(child);
591
    },
592
    
593
    /**
594
     * Wrapper for HTMLElement method.
595
     * @method getElementsByTagName
596
     * @param {String} tag The tagName to collect
597
     * @return {HTMLCollection} A collection of DOM elements. 
598
     */
599
    getElementsByTagName: function(tag) {
600
        return this.get('element').getElementsByTagName(tag);
601
    },
602
    
603
    /**
604
     * Wrapper for HTMLElement method.
605
     * @method hasChildNodes
606
     * @return {Boolean} Whether or not the element has childNodes
607
     */
608
    hasChildNodes: function() {
609
        return this.get('element').hasChildNodes();
610
    },
611
    
612
    /**
613
     * Wrapper for HTMLElement method.
614
     * @method insertBefore
615
     * @param {HTMLElement} element The HTMLElement to insert
616
     * @param {HTMLElement} before The HTMLElement to insert
617
     * the element before.
618
     * @return {HTMLElement} The inserted DOM element. 
619
     */
620
    insertBefore: function(element, before) {
621
        element = element.get ? element.get('element') : element;
622
        before = (before && before.get) ? before.get('element') : before;
623
        
624
        return this.get('element').insertBefore(element, before);
625
    },
626
    
627
    /**
628
     * Wrapper for HTMLElement method.
629
     * @method removeChild
630
     * @param {HTMLElement} child The HTMLElement to remove
631
     * @return {HTMLElement} The removed DOM element. 
632
     */
633
    removeChild: function(child) {
634
        child = child.get ? child.get('element') : child;
635
        return this.get('element').removeChild(child);
636
    },
637
    
638
    /**
639
     * Wrapper for HTMLElement method.
640
     * @method replaceChild
641
     * @param {HTMLElement} newNode The HTMLElement to insert
642
     * @param {HTMLElement} oldNode The HTMLElement to replace
643
     * @return {HTMLElement} The replaced DOM element. 
644
     */
645
    replaceChild: function(newNode, oldNode) {
646
        newNode = newNode.get ? newNode.get('element') : newNode;
647
        oldNode = oldNode.get ? oldNode.get('element') : oldNode;
648
        return this.get('element').replaceChild(newNode, oldNode);
649
    },
650
651
    
652
    /**
653
     * Registers Element specific attributes.
654
     * @method initAttributes
655
     * @param {Object} map A key-value map of initial attribute configs
656
     */
657
    initAttributes: function(map) {
658
    },
659
660
    /**
661
     * Adds a listener for the given event.  These may be DOM or 
662
     * customEvent listeners.  Any event that is fired via fireEvent
663
     * can be listened for.  All handlers receive an event object. 
664
     * @method addListener
665
     * @param {String} type The name of the event to listen for
666
     * @param {Function} fn The handler to call when the event fires
667
     * @param {Any} obj A variable to pass to the handler
668
     * @param {Object} scope The object to use for the scope of the handler 
669
     */
670
    addListener: function(type, fn, obj, scope) {
671
672
        scope = scope || this;
673
674
        var Event = YAHOO.util.Event,
675
			el = this.get('element') || this.get('id'),
676
        	self = this;
677
678
679
		if (specialTypes[type] && !Event._createMouseDelegate) {
680
	        YAHOO.log("Using a " + type + " event requires the event-mouseenter module", "error", "Event");
681
	        return false;	
682
		}
683
684
685
        if (!this._events[type]) { // create on the fly
686
687
            if (el && this.DOM_EVENTS[type]) {
688
				Event.on(el, type, function(e, matchedEl) {
689
690
					// Supplement IE with target, currentTarget relatedTarget
691
692
	                if (e.srcElement && !e.target) { 
693
	                    e.target = e.srcElement;
694
	                }
695
696
					if ((e.toElement && !e.relatedTarget) || (e.fromElement && !e.relatedTarget)) {
697
						e.relatedTarget = Event.getRelatedTarget(e);
698
					}
699
					
700
					if (!e.currentTarget) {
701
						e.currentTarget = el;
702
					}
703
704
					//	Note: matchedEl el is passed back for delegated listeners
705
		            self.fireEvent(type, e, matchedEl);
706
707
		        }, obj, scope);
708
            }
709
            this.createEvent(type, {scope: this});
710
        }
711
        
712
        return YAHOO.util.EventProvider.prototype.subscribe.apply(this, arguments); // notify via customEvent
713
    },
714
715
716
    /**
717
     * Alias for addListener
718
     * @method on
719
     * @param {String} type The name of the event to listen for
720
     * @param {Function} fn The function call when the event fires
721
     * @param {Any} obj A variable to pass to the handler
722
     * @param {Object} scope The object to use for the scope of the handler 
723
     */
724
    on: function() {
725
        return this.addListener.apply(this, arguments);
726
    },
727
    
728
    /**
729
     * Alias for addListener
730
     * @method subscribe
731
     * @param {String} type The name of the event to listen for
732
     * @param {Function} fn The function call when the event fires
733
     * @param {Any} obj A variable to pass to the handler
734
     * @param {Object} scope The object to use for the scope of the handler 
735
     */
736
    subscribe: function() {
737
        return this.addListener.apply(this, arguments);
738
    },
739
    
740
    /**
741
     * Remove an event listener
742
     * @method removeListener
743
     * @param {String} type The name of the event to listen for
744
     * @param {Function} fn The function call when the event fires
745
     */
746
    removeListener: function(type, fn) {
747
        return this.unsubscribe.apply(this, arguments);
748
    },
749
    
750
    /**
751
     * Wrapper for Dom method.
752
     * @method addClass
753
     * @param {String} className The className to add
754
     */
755
    addClass: function(className) {
756
        Dom.addClass(this.get('element'), className);
757
    },
758
    
759
    /**
760
     * Wrapper for Dom method.
761
     * @method getElementsByClassName
762
     * @param {String} className The className to collect
763
     * @param {String} tag (optional) The tag to use in
764
     * conjunction with class name
765
     * @return {Array} Array of HTMLElements
766
     */
767
    getElementsByClassName: function(className, tag) {
768
        return Dom.getElementsByClassName(className, tag,
769
                this.get('element') );
770
    },
771
    
772
    /**
773
     * Wrapper for Dom method.
774
     * @method hasClass
775
     * @param {String} className The className to add
776
     * @return {Boolean} Whether or not the element has the class name
777
     */
778
    hasClass: function(className) {
779
        return Dom.hasClass(this.get('element'), className); 
780
    },
781
    
782
    /**
783
     * Wrapper for Dom method.
784
     * @method removeClass
785
     * @param {String} className The className to remove
786
     */
787
    removeClass: function(className) {
788
        return Dom.removeClass(this.get('element'), className);
789
    },
790
    
791
    /**
792
     * Wrapper for Dom method.
793
     * @method replaceClass
794
     * @param {String} oldClassName The className to replace
795
     * @param {String} newClassName The className to add
796
     */
797
    replaceClass: function(oldClassName, newClassName) {
798
        return Dom.replaceClass(this.get('element'), 
799
                oldClassName, newClassName);
800
    },
801
    
802
    /**
803
     * Wrapper for Dom method.
804
     * @method setStyle
805
     * @param {String} property The style property to set
806
     * @param {String} value The value to apply to the style property
807
     */
808
    setStyle: function(property, value) {
809
        return Dom.setStyle(this.get('element'),  property, value); // TODO: always queuing?
810
    },
811
    
812
    /**
813
     * Wrapper for Dom method.
814
     * @method getStyle
815
     * @param {String} property The style property to retrieve
816
     * @return {String} The current value of the property
817
     */
818
    getStyle: function(property) {
819
        return Dom.getStyle(this.get('element'),  property);
820
    },
821
    
822
    /**
823
     * Apply any queued set calls.
824
     * @method fireQueue
825
     */
826
    fireQueue: function() {
827
        var queue = this._queue;
828
        for (var i = 0, len = queue.length; i < len; ++i) {
829
            this[queue[i][0]].apply(this, queue[i][1]);
830
        }
831
    },
832
    
833
    /**
834
     * Appends the HTMLElement into either the supplied parentNode.
835
     * @method appendTo
836
     * @param {HTMLElement | Element} parentNode The node to append to
837
     * @param {HTMLElement | Element} before An optional node to insert before
838
     * @return {HTMLElement} The appended DOM element. 
839
     */
840
    appendTo: function(parent, before) {
841
        parent = (parent.get) ?  parent.get('element') : Dom.get(parent);
842
        
843
        this.fireEvent('beforeAppendTo', {
844
            type: 'beforeAppendTo',
845
            target: parent
846
        });
847
        
848
        
849
        before = (before && before.get) ? 
850
                before.get('element') : Dom.get(before);
851
        var element = this.get('element');
852
        
853
        if (!element) {
854
            YAHOO.log('appendTo failed: element not available',
855
                    'error', 'Element');
856
            return false;
857
        }
858
        
859
        if (!parent) {
860
            YAHOO.log('appendTo failed: parent not available',
861
                    'error', 'Element');
862
            return false;
863
        }
864
        
865
        if (element.parent != parent) {
866
            if (before) {
867
                parent.insertBefore(element, before);
868
            } else {
869
                parent.appendChild(element);
870
            }
871
        }
872
        
873
        YAHOO.log(element + 'appended to ' + parent);
874
        
875
        this.fireEvent('appendTo', {
876
            type: 'appendTo',
877
            target: parent
878
        });
879
880
        return element;
881
    },
882
    
883
    get: function(key) {
884
        var configs = this._configs || {},
885
            el = configs.element; // avoid loop due to 'element'
886
887
        if (el && !configs[key] && !YAHOO.lang.isUndefined(el.value[key]) ) {
888
            this._setHTMLAttrConfig(key);
889
        }
890
891
        return AttributeProvider.prototype.get.call(this, key);
892
    },
893
894
    setAttributes: function(map, silent) {
895
        // set based on configOrder
896
        var done = {},
897
            configOrder = this._configOrder;
898
899
        // set based on configOrder
900
        for (var i = 0, len = configOrder.length; i < len; ++i) {
901
            if (map[configOrder[i]] !== undefined) {
902
                done[configOrder[i]] = true;
903
                this.set(configOrder[i], map[configOrder[i]], silent);
904
            }
905
        }
906
907
        // unconfigured (e.g. Dom attributes)
908
        for (var att in map) {
909
            if (map.hasOwnProperty(att) && !done[att]) {
910
                this.set(att, map[att], silent);
911
            }
912
        }
913
    },
914
915
    set: function(key, value, silent) {
916
        var el = this.get('element');
917
        if (!el) {
918
            this._queue[this._queue.length] = ['set', arguments];
919
            if (this._configs[key]) {
920
                this._configs[key].value = value; // so "get" works while queueing
921
            
922
            }
923
            return;
924
        }
925
        
926
        // set it on the element if not configured and is an HTML attribute
927
        if ( !this._configs[key] && !YAHOO.lang.isUndefined(el[key]) ) {
928
            this._setHTMLAttrConfig(key);
929
        }
930
931
        return AttributeProvider.prototype.set.apply(this, arguments);
932
    },
933
    
934
    setAttributeConfig: function(key, map, init) {
935
        this._configOrder.push(key);
936
        AttributeProvider.prototype.setAttributeConfig.apply(this, arguments);
937
    },
938
939
    createEvent: function(type, config) {
940
        this._events[type] = true;
941
        return AttributeProvider.prototype.createEvent.apply(this, arguments);
942
    },
943
    
944
    init: function(el, attr) {
945
        this._initElement(el, attr); 
946
    },
947
948
    destroy: function() {
949
        var el = this.get('element');
950
        YAHOO.util.Event.purgeElement(el, true); // purge DOM listeners recursively
951
        this.unsubscribeAll(); // unsubscribe all custom events
952
953
        if (el && el.parentNode) {
954
            el.parentNode.removeChild(el); // pull from the DOM
955
        }
956
957
        // revert initial configs
958
        this._queue = [];
959
        this._events = {};
960
        this._configs = {};
961
        this._configOrder = []; 
962
    },
963
964
    _initElement: function(el, attr) {
965
        this._queue = this._queue || [];
966
        this._events = this._events || {};
967
        this._configs = this._configs || {};
968
        this._configOrder = []; 
969
        attr = attr || {};
970
        attr.element = attr.element || el || null;
971
972
        var isReady = false;  // to determine when to init HTMLElement and content
973
974
        var DOM_EVENTS = Element.DOM_EVENTS;
975
        this.DOM_EVENTS = this.DOM_EVENTS || {};
976
977
        for (var event in DOM_EVENTS) {
978
            if (DOM_EVENTS.hasOwnProperty(event)) {
979
                this.DOM_EVENTS[event] = DOM_EVENTS[event];
980
            }
981
        }
982
983
        if (typeof attr.element === 'string') { // register ID for get() access
984
            this._setHTMLAttrConfig('id', { value: attr.element });
985
        }
986
987
        if (Dom.get(attr.element)) {
988
            isReady = true;
989
            this._initHTMLElement(attr);
990
            this._initContent(attr);
991
        }
992
993
        YAHOO.util.Event.onAvailable(attr.element, function() {
994
            if (!isReady) { // otherwise already done
995
                this._initHTMLElement(attr);
996
            }
997
998
            this.fireEvent('available', { type: 'available', target: Dom.get(attr.element) });  
999
        }, this, true);
1000
        
1001
        YAHOO.util.Event.onContentReady(attr.element, function() {
1002
            if (!isReady) { // otherwise already done
1003
                this._initContent(attr);
1004
            }
1005
            this.fireEvent('contentReady', { type: 'contentReady', target: Dom.get(attr.element) });  
1006
        }, this, true);
1007
    },
1008
1009
    _initHTMLElement: function(attr) {
1010
        /**
1011
         * The HTMLElement the Element instance refers to.
1012
         * @attribute element
1013
         * @type HTMLElement
1014
         */
1015
        this.setAttributeConfig('element', {
1016
            value: Dom.get(attr.element),
1017
            readOnly: true
1018
         });
1019
    },
1020
1021
    _initContent: function(attr) {
1022
        this.initAttributes(attr);
1023
        this.setAttributes(attr, true);
1024
        this.fireQueue();
1025
1026
    },
1027
1028
    /**
1029
     * Sets the value of the property and fires beforeChange and change events.
1030
     * @private
1031
     * @method _setHTMLAttrConfig
1032
     * @param {YAHOO.util.Element} element The Element instance to
1033
     * register the config to.
1034
     * @param {String} key The name of the config to register
1035
     * @param {Object} map A key-value map of the config's params
1036
     */
1037
    _setHTMLAttrConfig: function(key, map) {
1038
        var el = this.get('element');
1039
        map = map || {};
1040
        map.name = key;
1041
1042
        map.setter = map.setter || this.DEFAULT_HTML_SETTER;
1043
        map.getter = map.getter || this.DEFAULT_HTML_GETTER;
1044
1045
        map.value = map.value || el[key];
1046
        this._configs[key] = new YAHOO.util.Attribute(map, this);
1047
    }
1048
};
1049
1050
/**
1051
 * Fires when the Element's HTMLElement can be retrieved by Id.
1052
 * <p>See: <a href="#addListener">Element.addListener</a></p>
1053
 * <p><strong>Event fields:</strong><br>
1054
 * <code>&lt;String&gt; type</code> available<br>
1055
 * <code>&lt;HTMLElement&gt;
1056
 * target</code> the HTMLElement bound to this Element instance<br>
1057
 * <p><strong>Usage:</strong><br>
1058
 * <code>var handler = function(e) {var target = e.target};<br>
1059
 * myTabs.addListener('available', handler);</code></p>
1060
 * @event available
1061
 */
1062
 
1063
/**
1064
 * Fires when the Element's HTMLElement subtree is rendered.
1065
 * <p>See: <a href="#addListener">Element.addListener</a></p>
1066
 * <p><strong>Event fields:</strong><br>
1067
 * <code>&lt;String&gt; type</code> contentReady<br>
1068
 * <code>&lt;HTMLElement&gt;
1069
 * target</code> the HTMLElement bound to this Element instance<br>
1070
 * <p><strong>Usage:</strong><br>
1071
 * <code>var handler = function(e) {var target = e.target};<br>
1072
 * myTabs.addListener('contentReady', handler);</code></p>
1073
 * @event contentReady
1074
 */
1075
1076
/**
1077
 * Fires before the Element is appended to another Element.
1078
 * <p>See: <a href="#addListener">Element.addListener</a></p>
1079
 * <p><strong>Event fields:</strong><br>
1080
 * <code>&lt;String&gt; type</code> beforeAppendTo<br>
1081
 * <code>&lt;HTMLElement/Element&gt;
1082
 * target</code> the HTMLElement/Element being appended to 
1083
 * <p><strong>Usage:</strong><br>
1084
 * <code>var handler = function(e) {var target = e.target};<br>
1085
 * myTabs.addListener('beforeAppendTo', handler);</code></p>
1086
 * @event beforeAppendTo
1087
 */
1088
1089
/**
1090
 * Fires after the Element is appended to another Element.
1091
 * <p>See: <a href="#addListener">Element.addListener</a></p>
1092
 * <p><strong>Event fields:</strong><br>
1093
 * <code>&lt;String&gt; type</code> appendTo<br>
1094
 * <code>&lt;HTMLElement/Element&gt;
1095
 * target</code> the HTMLElement/Element being appended to 
1096
 * <p><strong>Usage:</strong><br>
1097
 * <code>var handler = function(e) {var target = e.target};<br>
1098
 * myTabs.addListener('appendTo', handler);</code></p>
1099
 * @event appendTo
1100
 */
1101
1102
YAHOO.augment(Element, AttributeProvider);
1103
YAHOO.util.Element = Element;
1104
})();
1105
1106
YAHOO.register("element", YAHOO.util.Element, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/element/element-min.js (-8 lines)
Lines 1-8 Link Here
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.8.0r4
6
*/
7
YAHOO.util.Attribute=function(B,A){if(A){this.owner=A;this.configure(B,true);}};YAHOO.util.Attribute.prototype={name:undefined,value:null,owner:null,readOnly:false,writeOnce:false,_initialConfig:null,_written:false,method:null,setter:null,getter:null,validator:null,getValue:function(){var A=this.value;if(this.getter){A=this.getter.call(this.owner,this.name,A);}return A;},setValue:function(F,B){var E,A=this.owner,C=this.name;var D={type:C,prevValue:this.getValue(),newValue:F};if(this.readOnly||(this.writeOnce&&this._written)){return false;}if(this.validator&&!this.validator.call(A,F)){return false;}if(!B){E=A.fireBeforeChangeEvent(D);if(E===false){return false;}}if(this.setter){F=this.setter.call(A,F,this.name);if(F===undefined){}}if(this.method){this.method.call(A,F,this.name);}this.value=F;this._written=true;D.type=C;if(!B){this.owner.fireChangeEvent(D);}return true;},configure:function(B,C){B=B||{};if(C){this._written=false;}this._initialConfig=this._initialConfig||{};for(var A in B){if(B.hasOwnProperty(A)){this[A]=B[A];if(C){this._initialConfig[A]=B[A];}}}},resetValue:function(){return this.setValue(this._initialConfig.value);},resetConfig:function(){this.configure(this._initialConfig,true);},refresh:function(A){this.setValue(this.value,A);}};(function(){var A=YAHOO.util.Lang;YAHOO.util.AttributeProvider=function(){};YAHOO.util.AttributeProvider.prototype={_configs:null,get:function(C){this._configs=this._configs||{};var B=this._configs[C];if(!B||!this._configs.hasOwnProperty(C)){return null;}return B.getValue();},set:function(D,E,B){this._configs=this._configs||{};var C=this._configs[D];if(!C){return false;}return C.setValue(E,B);},getAttributeKeys:function(){this._configs=this._configs;var C=[],B;for(B in this._configs){if(A.hasOwnProperty(this._configs,B)&&!A.isUndefined(this._configs[B])){C[C.length]=B;}}return C;},setAttributes:function(D,B){for(var C in D){if(A.hasOwnProperty(D,C)){this.set(C,D[C],B);}}},resetValue:function(C,B){this._configs=this._configs||{};if(this._configs[C]){this.set(C,this._configs[C]._initialConfig.value,B);return true;}return false;},refresh:function(E,C){this._configs=this._configs||{};var F=this._configs;E=((A.isString(E))?[E]:E)||this.getAttributeKeys();for(var D=0,B=E.length;D<B;++D){if(F.hasOwnProperty(E[D])){this._configs[E[D]].refresh(C);}}},register:function(B,C){this.setAttributeConfig(B,C);},getAttributeConfig:function(C){this._configs=this._configs||{};var B=this._configs[C]||{};var D={};for(C in B){if(A.hasOwnProperty(B,C)){D[C]=B[C];}}return D;},setAttributeConfig:function(B,C,D){this._configs=this._configs||{};C=C||{};if(!this._configs[B]){C.name=B;this._configs[B]=this.createAttribute(C);}else{this._configs[B].configure(C,D);}},configureAttribute:function(B,C,D){this.setAttributeConfig(B,C,D);},resetAttributeConfig:function(B){this._configs=this._configs||{};this._configs[B].resetConfig();},subscribe:function(B,C){this._events=this._events||{};if(!(B in this._events)){this._events[B]=this.createEvent(B);}YAHOO.util.EventProvider.prototype.subscribe.apply(this,arguments);},on:function(){this.subscribe.apply(this,arguments);},addListener:function(){this.subscribe.apply(this,arguments);},fireBeforeChangeEvent:function(C){var B="before";B+=C.type.charAt(0).toUpperCase()+C.type.substr(1)+"Change";C.type=B;return this.fireEvent(C.type,C);},fireChangeEvent:function(B){B.type+="Change";return this.fireEvent(B.type,B);},createAttribute:function(B){return new YAHOO.util.Attribute(B,this);}};YAHOO.augment(YAHOO.util.AttributeProvider,YAHOO.util.EventProvider);})();(function(){var B=YAHOO.util.Dom,D=YAHOO.util.AttributeProvider,C={mouseenter:true,mouseleave:true};var A=function(E,F){this.init.apply(this,arguments);};A.DOM_EVENTS={"click":true,"dblclick":true,"keydown":true,"keypress":true,"keyup":true,"mousedown":true,"mousemove":true,"mouseout":true,"mouseover":true,"mouseup":true,"mouseenter":true,"mouseleave":true,"focus":true,"blur":true,"submit":true,"change":true};A.prototype={DOM_EVENTS:null,DEFAULT_HTML_SETTER:function(G,E){var F=this.get("element");if(F){F[E]=G;}return G;},DEFAULT_HTML_GETTER:function(E){var F=this.get("element"),G;if(F){G=F[E];}return G;},appendChild:function(E){E=E.get?E.get("element"):E;return this.get("element").appendChild(E);},getElementsByTagName:function(E){return this.get("element").getElementsByTagName(E);},hasChildNodes:function(){return this.get("element").hasChildNodes();},insertBefore:function(E,F){E=E.get?E.get("element"):E;F=(F&&F.get)?F.get("element"):F;return this.get("element").insertBefore(E,F);},removeChild:function(E){E=E.get?E.get("element"):E;return this.get("element").removeChild(E);},replaceChild:function(E,F){E=E.get?E.get("element"):E;F=F.get?F.get("element"):F;return this.get("element").replaceChild(E,F);},initAttributes:function(E){},addListener:function(J,I,K,H){H=H||this;var E=YAHOO.util.Event,G=this.get("element")||this.get("id"),F=this;if(C[J]&&!E._createMouseDelegate){return false;}if(!this._events[J]){if(G&&this.DOM_EVENTS[J]){E.on(G,J,function(M,L){if(M.srcElement&&!M.target){M.target=M.srcElement;}if((M.toElement&&!M.relatedTarget)||(M.fromElement&&!M.relatedTarget)){M.relatedTarget=E.getRelatedTarget(M);}if(!M.currentTarget){M.currentTarget=G;}F.fireEvent(J,M,L);},K,H);}this.createEvent(J,{scope:this});}return YAHOO.util.EventProvider.prototype.subscribe.apply(this,arguments);},on:function(){return this.addListener.apply(this,arguments);},subscribe:function(){return this.addListener.apply(this,arguments);},removeListener:function(F,E){return this.unsubscribe.apply(this,arguments);},addClass:function(E){B.addClass(this.get("element"),E);},getElementsByClassName:function(F,E){return B.getElementsByClassName(F,E,this.get("element"));},hasClass:function(E){return B.hasClass(this.get("element"),E);},removeClass:function(E){return B.removeClass(this.get("element"),E);},replaceClass:function(F,E){return B.replaceClass(this.get("element"),F,E);},setStyle:function(F,E){return B.setStyle(this.get("element"),F,E);
8
},getStyle:function(E){return B.getStyle(this.get("element"),E);},fireQueue:function(){var F=this._queue;for(var G=0,E=F.length;G<E;++G){this[F[G][0]].apply(this,F[G][1]);}},appendTo:function(F,G){F=(F.get)?F.get("element"):B.get(F);this.fireEvent("beforeAppendTo",{type:"beforeAppendTo",target:F});G=(G&&G.get)?G.get("element"):B.get(G);var E=this.get("element");if(!E){return false;}if(!F){return false;}if(E.parent!=F){if(G){F.insertBefore(E,G);}else{F.appendChild(E);}}this.fireEvent("appendTo",{type:"appendTo",target:F});return E;},get:function(E){var G=this._configs||{},F=G.element;if(F&&!G[E]&&!YAHOO.lang.isUndefined(F.value[E])){this._setHTMLAttrConfig(E);}return D.prototype.get.call(this,E);},setAttributes:function(K,H){var F={},I=this._configOrder;for(var J=0,E=I.length;J<E;++J){if(K[I[J]]!==undefined){F[I[J]]=true;this.set(I[J],K[I[J]],H);}}for(var G in K){if(K.hasOwnProperty(G)&&!F[G]){this.set(G,K[G],H);}}},set:function(F,H,E){var G=this.get("element");if(!G){this._queue[this._queue.length]=["set",arguments];if(this._configs[F]){this._configs[F].value=H;}return;}if(!this._configs[F]&&!YAHOO.lang.isUndefined(G[F])){this._setHTMLAttrConfig(F);}return D.prototype.set.apply(this,arguments);},setAttributeConfig:function(E,F,G){this._configOrder.push(E);D.prototype.setAttributeConfig.apply(this,arguments);},createEvent:function(F,E){this._events[F]=true;return D.prototype.createEvent.apply(this,arguments);},init:function(F,E){this._initElement(F,E);},destroy:function(){var E=this.get("element");YAHOO.util.Event.purgeElement(E,true);this.unsubscribeAll();if(E&&E.parentNode){E.parentNode.removeChild(E);}this._queue=[];this._events={};this._configs={};this._configOrder=[];},_initElement:function(G,F){this._queue=this._queue||[];this._events=this._events||{};this._configs=this._configs||{};this._configOrder=[];F=F||{};F.element=F.element||G||null;var I=false;var E=A.DOM_EVENTS;this.DOM_EVENTS=this.DOM_EVENTS||{};for(var H in E){if(E.hasOwnProperty(H)){this.DOM_EVENTS[H]=E[H];}}if(typeof F.element==="string"){this._setHTMLAttrConfig("id",{value:F.element});}if(B.get(F.element)){I=true;this._initHTMLElement(F);this._initContent(F);}YAHOO.util.Event.onAvailable(F.element,function(){if(!I){this._initHTMLElement(F);}this.fireEvent("available",{type:"available",target:B.get(F.element)});},this,true);YAHOO.util.Event.onContentReady(F.element,function(){if(!I){this._initContent(F);}this.fireEvent("contentReady",{type:"contentReady",target:B.get(F.element)});},this,true);},_initHTMLElement:function(E){this.setAttributeConfig("element",{value:B.get(E.element),readOnly:true});},_initContent:function(E){this.initAttributes(E);this.setAttributes(E,true);this.fireQueue();},_setHTMLAttrConfig:function(E,G){var F=this.get("element");G=G||{};G.name=E;G.setter=G.setter||this.DEFAULT_HTML_SETTER;G.getter=G.getter||this.DEFAULT_HTML_GETTER;G.value=G.value||F[E];this._configs[E]=new YAHOO.util.Attribute(G,this);}};YAHOO.augment(A,D);YAHOO.util.Element=A;})();YAHOO.register("element",YAHOO.util.Element,{version:"2.8.0r4",build:"2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/element/element.js (-1090 lines)
Lines 1-1090 Link Here
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.8.0r4
6
*/
7
/**
8
 * Provides Attribute configurations.
9
 * @namespace YAHOO.util
10
 * @class Attribute
11
 * @constructor
12
 * @param hash {Object} The intial Attribute.
13
 * @param {YAHOO.util.AttributeProvider} The owner of the Attribute instance.
14
 */
15
16
YAHOO.util.Attribute = function(hash, owner) {
17
    if (owner) { 
18
        this.owner = owner;
19
        this.configure(hash, true);
20
    }
21
};
22
23
YAHOO.util.Attribute.prototype = {
24
    /**
25
     * The name of the attribute.
26
     * @property name
27
     * @type String
28
     */
29
    name: undefined,
30
    
31
    /**
32
     * The value of the attribute.
33
     * @property value
34
     * @type String
35
     */
36
    value: null,
37
    
38
    /**
39
     * The owner of the attribute.
40
     * @property owner
41
     * @type YAHOO.util.AttributeProvider
42
     */
43
    owner: null,
44
    
45
    /**
46
     * Whether or not the attribute is read only.
47
     * @property readOnly
48
     * @type Boolean
49
     */
50
    readOnly: false,
51
    
52
    /**
53
     * Whether or not the attribute can only be written once.
54
     * @property writeOnce
55
     * @type Boolean
56
     */
57
    writeOnce: false,
58
59
    /**
60
     * The attribute's initial configuration.
61
     * @private
62
     * @property _initialConfig
63
     * @type Object
64
     */
65
    _initialConfig: null,
66
    
67
    /**
68
     * Whether or not the attribute's value has been set.
69
     * @private
70
     * @property _written
71
     * @type Boolean
72
     */
73
    _written: false,
74
    
75
    /**
76
     * A function to call when setting the attribute's value.
77
     * The method receives the new value as the first arg and the attribute name as the 2nd
78
     * @property method
79
     * @type Function
80
     */
81
    method: null,
82
    
83
    /**
84
     * The function to use when setting the attribute's value.
85
     * The setter receives the new value as the first arg and the attribute name as the 2nd
86
     * The return value of the setter replaces the value passed to set(). 
87
     * @property setter
88
     * @type Function
89
     */
90
    setter: null,
91
    
92
    /**
93
     * The function to use when getting the attribute's value.
94
     * The getter receives the new value as the first arg and the attribute name as the 2nd
95
     * The return value of the getter will be used as the return from get().
96
     * @property getter
97
     * @type Function
98
     */
99
    getter: null,
100
101
    /**
102
     * The validator to use when setting the attribute's value.
103
     * @property validator
104
     * @type Function
105
     * @return Boolean
106
     */
107
    validator: null,
108
    
109
    /**
110
     * Retrieves the current value of the attribute.
111
     * @method getValue
112
     * @return {any} The current value of the attribute.
113
     */
114
    getValue: function() {
115
        var val = this.value;
116
117
        if (this.getter) {
118
            val = this.getter.call(this.owner, this.name, val);
119
        }
120
121
        return val;
122
    },
123
    
124
    /**
125
     * Sets the value of the attribute and fires beforeChange and change events.
126
     * @method setValue
127
     * @param {Any} value The value to apply to the attribute.
128
     * @param {Boolean} silent If true the change events will not be fired.
129
     * @return {Boolean} Whether or not the value was set.
130
     */
131
    setValue: function(value, silent) {
132
        var beforeRetVal,
133
            owner = this.owner,
134
            name = this.name;
135
        
136
        var event = {
137
            type: name, 
138
            prevValue: this.getValue(),
139
            newValue: value
140
        };
141
        
142
        if (this.readOnly || ( this.writeOnce && this._written) ) {
143
            return false; // write not allowed
144
        }
145
        
146
        if (this.validator && !this.validator.call(owner, value) ) {
147
            return false; // invalid value
148
        }
149
150
        if (!silent) {
151
            beforeRetVal = owner.fireBeforeChangeEvent(event);
152
            if (beforeRetVal === false) {
153
                return false;
154
            }
155
        }
156
157
        if (this.setter) {
158
            value = this.setter.call(owner, value, this.name);
159
            if (value === undefined) {
160
            }
161
        }
162
        
163
        if (this.method) {
164
            this.method.call(owner, value, this.name);
165
        }
166
        
167
        this.value = value; // TODO: set before calling setter/method?
168
        this._written = true;
169
        
170
        event.type = name;
171
        
172
        if (!silent) {
173
            this.owner.fireChangeEvent(event);
174
        }
175
        
176
        return true;
177
    },
178
    
179
    /**
180
     * Allows for configuring the Attribute's properties.
181
     * @method configure
182
     * @param {Object} map A key-value map of Attribute properties.
183
     * @param {Boolean} init Whether or not this should become the initial config.
184
     */
185
    configure: function(map, init) {
186
        map = map || {};
187
188
        if (init) {
189
            this._written = false; // reset writeOnce
190
        }
191
192
        this._initialConfig = this._initialConfig || {};
193
        
194
        for (var key in map) {
195
            if ( map.hasOwnProperty(key) ) {
196
                this[key] = map[key];
197
                if (init) {
198
                    this._initialConfig[key] = map[key];
199
                }
200
            }
201
        }
202
    },
203
    
204
    /**
205
     * Resets the value to the initial config value.
206
     * @method resetValue
207
     * @return {Boolean} Whether or not the value was set.
208
     */
209
    resetValue: function() {
210
        return this.setValue(this._initialConfig.value);
211
    },
212
    
213
    /**
214
     * Resets the attribute config to the initial config state.
215
     * @method resetConfig
216
     */
217
    resetConfig: function() {
218
        this.configure(this._initialConfig, true);
219
    },
220
    
221
    /**
222
     * Resets the value to the current value.
223
     * Useful when values may have gotten out of sync with actual properties.
224
     * @method refresh
225
     * @return {Boolean} Whether or not the value was set.
226
     */
227
    refresh: function(silent) {
228
        this.setValue(this.value, silent);
229
    }
230
};
231
232
(function() {
233
    var Lang = YAHOO.util.Lang;
234
235
    /*
236
    Copyright (c) 2006, Yahoo! Inc. All rights reserved.
237
    Code licensed under the BSD License:
238
    http://developer.yahoo.net/yui/license.txt
239
    */
240
    
241
    /**
242
     * Provides and manages YAHOO.util.Attribute instances
243
     * @namespace YAHOO.util
244
     * @class AttributeProvider
245
     * @uses YAHOO.util.EventProvider
246
     */
247
    YAHOO.util.AttributeProvider = function() {};
248
249
    YAHOO.util.AttributeProvider.prototype = {
250
        
251
        /**
252
         * A key-value map of Attribute configurations
253
         * @property _configs
254
         * @protected (may be used by subclasses and augmentors)
255
         * @private
256
         * @type {Object}
257
         */
258
        _configs: null,
259
        /**
260
         * Returns the current value of the attribute.
261
         * @method get
262
         * @param {String} key The attribute whose value will be returned.
263
         * @return {Any} The current value of the attribute.
264
         */
265
        get: function(key){
266
            this._configs = this._configs || {};
267
            var config = this._configs[key];
268
            
269
            if (!config || !this._configs.hasOwnProperty(key)) {
270
                return null;
271
            }
272
            
273
            return config.getValue();
274
        },
275
        
276
        /**
277
         * Sets the value of a config.
278
         * @method set
279
         * @param {String} key The name of the attribute
280
         * @param {Any} value The value to apply to the attribute
281
         * @param {Boolean} silent Whether or not to suppress change events
282
         * @return {Boolean} Whether or not the value was set.
283
         */
284
        set: function(key, value, silent){
285
            this._configs = this._configs || {};
286
            var config = this._configs[key];
287
            
288
            if (!config) {
289
                return false;
290
            }
291
            
292
            return config.setValue(value, silent);
293
        },
294
    
295
        /**
296
         * Returns an array of attribute names.
297
         * @method getAttributeKeys
298
         * @return {Array} An array of attribute names.
299
         */
300
        getAttributeKeys: function(){
301
            this._configs = this._configs;
302
            var keys = [], key;
303
304
            for (key in this._configs) {
305
                if ( Lang.hasOwnProperty(this._configs, key) && 
306
                        !Lang.isUndefined(this._configs[key]) ) {
307
                    keys[keys.length] = key;
308
                }
309
            }
310
            
311
            return keys;
312
        },
313
        
314
        /**
315
         * Sets multiple attribute values.
316
         * @method setAttributes
317
         * @param {Object} map  A key-value map of attributes
318
         * @param {Boolean} silent Whether or not to suppress change events
319
         */
320
        setAttributes: function(map, silent){
321
            for (var key in map) {
322
                if ( Lang.hasOwnProperty(map, key) ) {
323
                    this.set(key, map[key], silent);
324
                }
325
            }
326
        },
327
    
328
        /**
329
         * Resets the specified attribute's value to its initial value.
330
         * @method resetValue
331
         * @param {String} key The name of the attribute
332
         * @param {Boolean} silent Whether or not to suppress change events
333
         * @return {Boolean} Whether or not the value was set
334
         */
335
        resetValue: function(key, silent){
336
            this._configs = this._configs || {};
337
            if (this._configs[key]) {
338
                this.set(key, this._configs[key]._initialConfig.value, silent);
339
                return true;
340
            }
341
            return false;
342
        },
343
    
344
        /**
345
         * Sets the attribute's value to its current value.
346
         * @method refresh
347
         * @param {String | Array} key The attribute(s) to refresh
348
         * @param {Boolean} silent Whether or not to suppress change events
349
         */
350
        refresh: function(key, silent) {
351
            this._configs = this._configs || {};
352
            var configs = this._configs;
353
            
354
            key = ( ( Lang.isString(key) ) ? [key] : key ) || 
355
                    this.getAttributeKeys();
356
            
357
            for (var i = 0, len = key.length; i < len; ++i) { 
358
                if (configs.hasOwnProperty(key[i])) {
359
                    this._configs[key[i]].refresh(silent);
360
                }
361
            }
362
        },
363
    
364
        /**
365
         * Adds an Attribute to the AttributeProvider instance. 
366
         * @method register
367
         * @param {String} key The attribute's name
368
         * @param {Object} map A key-value map containing the
369
         * attribute's properties.
370
         * @deprecated Use setAttributeConfig
371
         */
372
        register: function(key, map) {
373
            this.setAttributeConfig(key, map);
374
        },
375
        
376
        
377
        /**
378
         * Returns the attribute's properties.
379
         * @method getAttributeConfig
380
         * @param {String} key The attribute's name
381
         * @private
382
         * @return {object} A key-value map containing all of the
383
         * attribute's properties.
384
         */
385
        getAttributeConfig: function(key) {
386
            this._configs = this._configs || {};
387
            var config = this._configs[key] || {};
388
            var map = {}; // returning a copy to prevent overrides
389
            
390
            for (key in config) {
391
                if ( Lang.hasOwnProperty(config, key) ) {
392
                    map[key] = config[key];
393
                }
394
            }
395
    
396
            return map;
397
        },
398
        
399
        /**
400
         * Sets or updates an Attribute instance's properties. 
401
         * @method setAttributeConfig
402
         * @param {String} key The attribute's name.
403
         * @param {Object} map A key-value map of attribute properties
404
         * @param {Boolean} init Whether or not this should become the intial config.
405
         */
406
        setAttributeConfig: function(key, map, init) {
407
            this._configs = this._configs || {};
408
            map = map || {};
409
            if (!this._configs[key]) {
410
                map.name = key;
411
                this._configs[key] = this.createAttribute(map);
412
            } else {
413
                this._configs[key].configure(map, init);
414
            }
415
        },
416
        
417
        /**
418
         * Sets or updates an Attribute instance's properties. 
419
         * @method configureAttribute
420
         * @param {String} key The attribute's name.
421
         * @param {Object} map A key-value map of attribute properties
422
         * @param {Boolean} init Whether or not this should become the intial config.
423
         * @deprecated Use setAttributeConfig
424
         */
425
        configureAttribute: function(key, map, init) {
426
            this.setAttributeConfig(key, map, init);
427
        },
428
        
429
        /**
430
         * Resets an attribute to its intial configuration. 
431
         * @method resetAttributeConfig
432
         * @param {String} key The attribute's name.
433
         * @private
434
         */
435
        resetAttributeConfig: function(key){
436
            this._configs = this._configs || {};
437
            this._configs[key].resetConfig();
438
        },
439
        
440
        // wrapper for EventProvider.subscribe
441
        // to create events on the fly
442
        subscribe: function(type, callback) {
443
            this._events = this._events || {};
444
445
            if ( !(type in this._events) ) {
446
                this._events[type] = this.createEvent(type);
447
            }
448
449
            YAHOO.util.EventProvider.prototype.subscribe.apply(this, arguments);
450
        },
451
452
        on: function() {
453
            this.subscribe.apply(this, arguments);
454
        },
455
456
        addListener: function() {
457
            this.subscribe.apply(this, arguments);
458
        },
459
460
        /**
461
         * Fires the attribute's beforeChange event. 
462
         * @method fireBeforeChangeEvent
463
         * @param {String} key The attribute's name.
464
         * @param {Obj} e The event object to pass to handlers.
465
         */
466
        fireBeforeChangeEvent: function(e) {
467
            var type = 'before';
468
            type += e.type.charAt(0).toUpperCase() + e.type.substr(1) + 'Change';
469
            e.type = type;
470
            return this.fireEvent(e.type, e);
471
        },
472
        
473
        /**
474
         * Fires the attribute's change event. 
475
         * @method fireChangeEvent
476
         * @param {String} key The attribute's name.
477
         * @param {Obj} e The event object to pass to the handlers.
478
         */
479
        fireChangeEvent: function(e) {
480
            e.type += 'Change';
481
            return this.fireEvent(e.type, e);
482
        },
483
484
        createAttribute: function(map) {
485
            return new YAHOO.util.Attribute(map, this);
486
        }
487
    };
488
    
489
    YAHOO.augment(YAHOO.util.AttributeProvider, YAHOO.util.EventProvider);
490
})();
491
492
(function() {
493
// internal shorthand
494
var Dom = YAHOO.util.Dom,
495
    AttributeProvider = YAHOO.util.AttributeProvider,
496
	specialTypes = {
497
		mouseenter: true,
498
		mouseleave: true
499
	};
500
501
/**
502
 * Element provides an wrapper object to simplify adding
503
 * event listeners, using dom methods, and managing attributes. 
504
 * @module element
505
 * @namespace YAHOO.util
506
 * @requires yahoo, dom, event
507
 */
508
509
/**
510
 * Element provides an wrapper object to simplify adding
511
 * event listeners, using dom methods, and managing attributes. 
512
 * @class Element
513
 * @uses YAHOO.util.AttributeProvider
514
 * @constructor
515
 * @param el {HTMLElement | String} The html element that 
516
 * represents the Element.
517
 * @param {Object} map A key-value map of initial config names and values
518
 */
519
var Element = function(el, map) {
520
    this.init.apply(this, arguments);
521
};
522
523
Element.DOM_EVENTS = {
524
    'click': true,
525
    'dblclick': true,
526
    'keydown': true,
527
    'keypress': true,
528
    'keyup': true,
529
    'mousedown': true,
530
    'mousemove': true,
531
    'mouseout': true, 
532
    'mouseover': true, 
533
    'mouseup': true,
534
    'mouseenter': true, 
535
    'mouseleave': true,
536
    'focus': true,
537
    'blur': true,
538
    'submit': true,
539
    'change': true
540
};
541
542
Element.prototype = {
543
    /**
544
     * Dom events supported by the Element instance.
545
     * @property DOM_EVENTS
546
     * @type Object
547
     */
548
    DOM_EVENTS: null,
549
550
    DEFAULT_HTML_SETTER: function(value, key) {
551
        var el = this.get('element');
552
        
553
        if (el) {
554
            el[key] = value;
555
        }
556
557
		return value;
558
559
    },
560
561
    DEFAULT_HTML_GETTER: function(key) {
562
        var el = this.get('element'),
563
            val;
564
565
        if (el) {
566
            val = el[key];
567
        }
568
569
        return val;
570
    },
571
572
    /**
573
     * Wrapper for HTMLElement method.
574
     * @method appendChild
575
     * @param {YAHOO.util.Element || HTMLElement} child The element to append. 
576
     * @return {HTMLElement} The appended DOM element. 
577
     */
578
    appendChild: function(child) {
579
        child = child.get ? child.get('element') : child;
580
        return this.get('element').appendChild(child);
581
    },
582
    
583
    /**
584
     * Wrapper for HTMLElement method.
585
     * @method getElementsByTagName
586
     * @param {String} tag The tagName to collect
587
     * @return {HTMLCollection} A collection of DOM elements. 
588
     */
589
    getElementsByTagName: function(tag) {
590
        return this.get('element').getElementsByTagName(tag);
591
    },
592
    
593
    /**
594
     * Wrapper for HTMLElement method.
595
     * @method hasChildNodes
596
     * @return {Boolean} Whether or not the element has childNodes
597
     */
598
    hasChildNodes: function() {
599
        return this.get('element').hasChildNodes();
600
    },
601
    
602
    /**
603
     * Wrapper for HTMLElement method.
604
     * @method insertBefore
605
     * @param {HTMLElement} element The HTMLElement to insert
606
     * @param {HTMLElement} before The HTMLElement to insert
607
     * the element before.
608
     * @return {HTMLElement} The inserted DOM element. 
609
     */
610
    insertBefore: function(element, before) {
611
        element = element.get ? element.get('element') : element;
612
        before = (before && before.get) ? before.get('element') : before;
613
        
614
        return this.get('element').insertBefore(element, before);
615
    },
616
    
617
    /**
618
     * Wrapper for HTMLElement method.
619
     * @method removeChild
620
     * @param {HTMLElement} child The HTMLElement to remove
621
     * @return {HTMLElement} The removed DOM element. 
622
     */
623
    removeChild: function(child) {
624
        child = child.get ? child.get('element') : child;
625
        return this.get('element').removeChild(child);
626
    },
627
    
628
    /**
629
     * Wrapper for HTMLElement method.
630
     * @method replaceChild
631
     * @param {HTMLElement} newNode The HTMLElement to insert
632
     * @param {HTMLElement} oldNode The HTMLElement to replace
633
     * @return {HTMLElement} The replaced DOM element. 
634
     */
635
    replaceChild: function(newNode, oldNode) {
636
        newNode = newNode.get ? newNode.get('element') : newNode;
637
        oldNode = oldNode.get ? oldNode.get('element') : oldNode;
638
        return this.get('element').replaceChild(newNode, oldNode);
639
    },
640
641
    
642
    /**
643
     * Registers Element specific attributes.
644
     * @method initAttributes
645
     * @param {Object} map A key-value map of initial attribute configs
646
     */
647
    initAttributes: function(map) {
648
    },
649
650
    /**
651
     * Adds a listener for the given event.  These may be DOM or 
652
     * customEvent listeners.  Any event that is fired via fireEvent
653
     * can be listened for.  All handlers receive an event object. 
654
     * @method addListener
655
     * @param {String} type The name of the event to listen for
656
     * @param {Function} fn The handler to call when the event fires
657
     * @param {Any} obj A variable to pass to the handler
658
     * @param {Object} scope The object to use for the scope of the handler 
659
     */
660
    addListener: function(type, fn, obj, scope) {
661
662
        scope = scope || this;
663
664
        var Event = YAHOO.util.Event,
665
			el = this.get('element') || this.get('id'),
666
        	self = this;
667
668
669
		if (specialTypes[type] && !Event._createMouseDelegate) {
670
	        return false;	
671
		}
672
673
674
        if (!this._events[type]) { // create on the fly
675
676
            if (el && this.DOM_EVENTS[type]) {
677
				Event.on(el, type, function(e, matchedEl) {
678
679
					// Supplement IE with target, currentTarget relatedTarget
680
681
	                if (e.srcElement && !e.target) { 
682
	                    e.target = e.srcElement;
683
	                }
684
685
					if ((e.toElement && !e.relatedTarget) || (e.fromElement && !e.relatedTarget)) {
686
						e.relatedTarget = Event.getRelatedTarget(e);
687
					}
688
					
689
					if (!e.currentTarget) {
690
						e.currentTarget = el;
691
					}
692
693
					//	Note: matchedEl el is passed back for delegated listeners
694
		            self.fireEvent(type, e, matchedEl);
695
696
		        }, obj, scope);
697
            }
698
            this.createEvent(type, {scope: this});
699
        }
700
        
701
        return YAHOO.util.EventProvider.prototype.subscribe.apply(this, arguments); // notify via customEvent
702
    },
703
704
705
    /**
706
     * Alias for addListener
707
     * @method on
708
     * @param {String} type The name of the event to listen for
709
     * @param {Function} fn The function call when the event fires
710
     * @param {Any} obj A variable to pass to the handler
711
     * @param {Object} scope The object to use for the scope of the handler 
712
     */
713
    on: function() {
714
        return this.addListener.apply(this, arguments);
715
    },
716
    
717
    /**
718
     * Alias for addListener
719
     * @method subscribe
720
     * @param {String} type The name of the event to listen for
721
     * @param {Function} fn The function call when the event fires
722
     * @param {Any} obj A variable to pass to the handler
723
     * @param {Object} scope The object to use for the scope of the handler 
724
     */
725
    subscribe: function() {
726
        return this.addListener.apply(this, arguments);
727
    },
728
    
729
    /**
730
     * Remove an event listener
731
     * @method removeListener
732
     * @param {String} type The name of the event to listen for
733
     * @param {Function} fn The function call when the event fires
734
     */
735
    removeListener: function(type, fn) {
736
        return this.unsubscribe.apply(this, arguments);
737
    },
738
    
739
    /**
740
     * Wrapper for Dom method.
741
     * @method addClass
742
     * @param {String} className The className to add
743
     */
744
    addClass: function(className) {
745
        Dom.addClass(this.get('element'), className);
746
    },
747
    
748
    /**
749
     * Wrapper for Dom method.
750
     * @method getElementsByClassName
751
     * @param {String} className The className to collect
752
     * @param {String} tag (optional) The tag to use in
753
     * conjunction with class name
754
     * @return {Array} Array of HTMLElements
755
     */
756
    getElementsByClassName: function(className, tag) {
757
        return Dom.getElementsByClassName(className, tag,
758
                this.get('element') );
759
    },
760
    
761
    /**
762
     * Wrapper for Dom method.
763
     * @method hasClass
764
     * @param {String} className The className to add
765
     * @return {Boolean} Whether or not the element has the class name
766
     */
767
    hasClass: function(className) {
768
        return Dom.hasClass(this.get('element'), className); 
769
    },
770
    
771
    /**
772
     * Wrapper for Dom method.
773
     * @method removeClass
774
     * @param {String} className The className to remove
775
     */
776
    removeClass: function(className) {
777
        return Dom.removeClass(this.get('element'), className);
778
    },
779
    
780
    /**
781
     * Wrapper for Dom method.
782
     * @method replaceClass
783
     * @param {String} oldClassName The className to replace
784
     * @param {String} newClassName The className to add
785
     */
786
    replaceClass: function(oldClassName, newClassName) {
787
        return Dom.replaceClass(this.get('element'), 
788
                oldClassName, newClassName);
789
    },
790
    
791
    /**
792
     * Wrapper for Dom method.
793
     * @method setStyle
794
     * @param {String} property The style property to set
795
     * @param {String} value The value to apply to the style property
796
     */
797
    setStyle: function(property, value) {
798
        return Dom.setStyle(this.get('element'),  property, value); // TODO: always queuing?
799
    },
800
    
801
    /**
802
     * Wrapper for Dom method.
803
     * @method getStyle
804
     * @param {String} property The style property to retrieve
805
     * @return {String} The current value of the property
806
     */
807
    getStyle: function(property) {
808
        return Dom.getStyle(this.get('element'),  property);
809
    },
810
    
811
    /**
812
     * Apply any queued set calls.
813
     * @method fireQueue
814
     */
815
    fireQueue: function() {
816
        var queue = this._queue;
817
        for (var i = 0, len = queue.length; i < len; ++i) {
818
            this[queue[i][0]].apply(this, queue[i][1]);
819
        }
820
    },
821
    
822
    /**
823
     * Appends the HTMLElement into either the supplied parentNode.
824
     * @method appendTo
825
     * @param {HTMLElement | Element} parentNode The node to append to
826
     * @param {HTMLElement | Element} before An optional node to insert before
827
     * @return {HTMLElement} The appended DOM element. 
828
     */
829
    appendTo: function(parent, before) {
830
        parent = (parent.get) ?  parent.get('element') : Dom.get(parent);
831
        
832
        this.fireEvent('beforeAppendTo', {
833
            type: 'beforeAppendTo',
834
            target: parent
835
        });
836
        
837
        
838
        before = (before && before.get) ? 
839
                before.get('element') : Dom.get(before);
840
        var element = this.get('element');
841
        
842
        if (!element) {
843
            return false;
844
        }
845
        
846
        if (!parent) {
847
            return false;
848
        }
849
        
850
        if (element.parent != parent) {
851
            if (before) {
852
                parent.insertBefore(element, before);
853
            } else {
854
                parent.appendChild(element);
855
            }
856
        }
857
        
858
        
859
        this.fireEvent('appendTo', {
860
            type: 'appendTo',
861
            target: parent
862
        });
863
864
        return element;
865
    },
866
    
867
    get: function(key) {
868
        var configs = this._configs || {},
869
            el = configs.element; // avoid loop due to 'element'
870
871
        if (el && !configs[key] && !YAHOO.lang.isUndefined(el.value[key]) ) {
872
            this._setHTMLAttrConfig(key);
873
        }
874
875
        return AttributeProvider.prototype.get.call(this, key);
876
    },
877
878
    setAttributes: function(map, silent) {
879
        // set based on configOrder
880
        var done = {},
881
            configOrder = this._configOrder;
882
883
        // set based on configOrder
884
        for (var i = 0, len = configOrder.length; i < len; ++i) {
885
            if (map[configOrder[i]] !== undefined) {
886
                done[configOrder[i]] = true;
887
                this.set(configOrder[i], map[configOrder[i]], silent);
888
            }
889
        }
890
891
        // unconfigured (e.g. Dom attributes)
892
        for (var att in map) {
893
            if (map.hasOwnProperty(att) && !done[att]) {
894
                this.set(att, map[att], silent);
895
            }
896
        }
897
    },
898
899
    set: function(key, value, silent) {
900
        var el = this.get('element');
901
        if (!el) {
902
            this._queue[this._queue.length] = ['set', arguments];
903
            if (this._configs[key]) {
904
                this._configs[key].value = value; // so "get" works while queueing
905
            
906
            }
907
            return;
908
        }
909
        
910
        // set it on the element if not configured and is an HTML attribute
911
        if ( !this._configs[key] && !YAHOO.lang.isUndefined(el[key]) ) {
912
            this._setHTMLAttrConfig(key);
913
        }
914
915
        return AttributeProvider.prototype.set.apply(this, arguments);
916
    },
917
    
918
    setAttributeConfig: function(key, map, init) {
919
        this._configOrder.push(key);
920
        AttributeProvider.prototype.setAttributeConfig.apply(this, arguments);
921
    },
922
923
    createEvent: function(type, config) {
924
        this._events[type] = true;
925
        return AttributeProvider.prototype.createEvent.apply(this, arguments);
926
    },
927
    
928
    init: function(el, attr) {
929
        this._initElement(el, attr); 
930
    },
931
932
    destroy: function() {
933
        var el = this.get('element');
934
        YAHOO.util.Event.purgeElement(el, true); // purge DOM listeners recursively
935
        this.unsubscribeAll(); // unsubscribe all custom events
936
937
        if (el && el.parentNode) {
938
            el.parentNode.removeChild(el); // pull from the DOM
939
        }
940
941
        // revert initial configs
942
        this._queue = [];
943
        this._events = {};
944
        this._configs = {};
945
        this._configOrder = []; 
946
    },
947
948
    _initElement: function(el, attr) {
949
        this._queue = this._queue || [];
950
        this._events = this._events || {};
951
        this._configs = this._configs || {};
952
        this._configOrder = []; 
953
        attr = attr || {};
954
        attr.element = attr.element || el || null;
955
956
        var isReady = false;  // to determine when to init HTMLElement and content
957
958
        var DOM_EVENTS = Element.DOM_EVENTS;
959
        this.DOM_EVENTS = this.DOM_EVENTS || {};
960
961
        for (var event in DOM_EVENTS) {
962
            if (DOM_EVENTS.hasOwnProperty(event)) {
963
                this.DOM_EVENTS[event] = DOM_EVENTS[event];
964
            }
965
        }
966
967
        if (typeof attr.element === 'string') { // register ID for get() access
968
            this._setHTMLAttrConfig('id', { value: attr.element });
969
        }
970
971
        if (Dom.get(attr.element)) {
972
            isReady = true;
973
            this._initHTMLElement(attr);
974
            this._initContent(attr);
975
        }
976
977
        YAHOO.util.Event.onAvailable(attr.element, function() {
978
            if (!isReady) { // otherwise already done
979
                this._initHTMLElement(attr);
980
            }
981
982
            this.fireEvent('available', { type: 'available', target: Dom.get(attr.element) });  
983
        }, this, true);
984
        
985
        YAHOO.util.Event.onContentReady(attr.element, function() {
986
            if (!isReady) { // otherwise already done
987
                this._initContent(attr);
988
            }
989
            this.fireEvent('contentReady', { type: 'contentReady', target: Dom.get(attr.element) });  
990
        }, this, true);
991
    },
992
993
    _initHTMLElement: function(attr) {
994
        /**
995
         * The HTMLElement the Element instance refers to.
996
         * @attribute element
997
         * @type HTMLElement
998
         */
999
        this.setAttributeConfig('element', {
1000
            value: Dom.get(attr.element),
1001
            readOnly: true
1002
         });
1003
    },
1004
1005
    _initContent: function(attr) {
1006
        this.initAttributes(attr);
1007
        this.setAttributes(attr, true);
1008
        this.fireQueue();
1009
1010
    },
1011
1012
    /**
1013
     * Sets the value of the property and fires beforeChange and change events.
1014
     * @private
1015
     * @method _setHTMLAttrConfig
1016
     * @param {YAHOO.util.Element} element The Element instance to
1017
     * register the config to.
1018
     * @param {String} key The name of the config to register
1019
     * @param {Object} map A key-value map of the config's params
1020
     */
1021
    _setHTMLAttrConfig: function(key, map) {
1022
        var el = this.get('element');
1023
        map = map || {};
1024
        map.name = key;
1025
1026
        map.setter = map.setter || this.DEFAULT_HTML_SETTER;
1027
        map.getter = map.getter || this.DEFAULT_HTML_GETTER;
1028
1029
        map.value = map.value || el[key];
1030
        this._configs[key] = new YAHOO.util.Attribute(map, this);
1031
    }
1032
};
1033
1034
/**
1035
 * Fires when the Element's HTMLElement can be retrieved by Id.
1036
 * <p>See: <a href="#addListener">Element.addListener</a></p>
1037
 * <p><strong>Event fields:</strong><br>
1038
 * <code>&lt;String&gt; type</code> available<br>
1039
 * <code>&lt;HTMLElement&gt;
1040
 * target</code> the HTMLElement bound to this Element instance<br>
1041
 * <p><strong>Usage:</strong><br>
1042
 * <code>var handler = function(e) {var target = e.target};<br>
1043
 * myTabs.addListener('available', handler);</code></p>
1044
 * @event available
1045
 */
1046
 
1047
/**
1048
 * Fires when the Element's HTMLElement subtree is rendered.
1049
 * <p>See: <a href="#addListener">Element.addListener</a></p>
1050
 * <p><strong>Event fields:</strong><br>
1051
 * <code>&lt;String&gt; type</code> contentReady<br>
1052
 * <code>&lt;HTMLElement&gt;
1053
 * target</code> the HTMLElement bound to this Element instance<br>
1054
 * <p><strong>Usage:</strong><br>
1055
 * <code>var handler = function(e) {var target = e.target};<br>
1056
 * myTabs.addListener('contentReady', handler);</code></p>
1057
 * @event contentReady
1058
 */
1059
1060
/**
1061
 * Fires before the Element is appended to another Element.
1062
 * <p>See: <a href="#addListener">Element.addListener</a></p>
1063
 * <p><strong>Event fields:</strong><br>
1064
 * <code>&lt;String&gt; type</code> beforeAppendTo<br>
1065
 * <code>&lt;HTMLElement/Element&gt;
1066
 * target</code> the HTMLElement/Element being appended to 
1067
 * <p><strong>Usage:</strong><br>
1068
 * <code>var handler = function(e) {var target = e.target};<br>
1069
 * myTabs.addListener('beforeAppendTo', handler);</code></p>
1070
 * @event beforeAppendTo
1071
 */
1072
1073
/**
1074
 * Fires after the Element is appended to another Element.
1075
 * <p>See: <a href="#addListener">Element.addListener</a></p>
1076
 * <p><strong>Event fields:</strong><br>
1077
 * <code>&lt;String&gt; type</code> appendTo<br>
1078
 * <code>&lt;HTMLElement/Element&gt;
1079
 * target</code> the HTMLElement/Element being appended to 
1080
 * <p><strong>Usage:</strong><br>
1081
 * <code>var handler = function(e) {var target = e.target};<br>
1082
 * myTabs.addListener('appendTo', handler);</code></p>
1083
 * @event appendTo
1084
 */
1085
1086
YAHOO.augment(Element, AttributeProvider);
1087
YAHOO.util.Element = Element;
1088
})();
1089
1090
YAHOO.register("element", YAHOO.util.Element, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/json/json-debug.js (-538 lines)
Lines 1-538 Link Here
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.8.0r4
6
*/
7
/**
8
 * Provides methods to parse JSON strings and convert objects to JSON strings.
9
 *
10
 * @module json
11
 * @class JSON
12
 * @namespace YAHOO.lang
13
 * @static
14
 */
15
(function () {
16
17
var l = YAHOO.lang,
18
    isFunction = l.isFunction,
19
    isObject   = l.isObject,
20
    isArray    = l.isArray,
21
    _toStr     = Object.prototype.toString,
22
                 // 'this' is the global object.  window in browser env.  Keep
23
                 // the code env agnostic.  Caja requies window, unfortunately.
24
    Native     = (YAHOO.env.ua.caja ? window : this).JSON,
25
26
/* Variables used by parse */
27
28
    /**
29
     * Replace certain Unicode characters that JavaScript may handle incorrectly
30
     * during eval--either by deleting them or treating them as line
31
     * endings--with escape sequences.
32
     * IMPORTANT NOTE: This regex will be used to modify the input if a match is
33
     * found.
34
     *
35
     * @property _UNICODE_EXCEPTIONS
36
     * @type {RegExp}
37
     * @private
38
     */
39
    _UNICODE_EXCEPTIONS = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
40
41
    /**
42
     * First step in the safety evaluation.  Regex used to replace all escape
43
     * sequences (i.e. "\\", etc) with '@' characters (a non-JSON character).
44
     *
45
     * @property _ESCAPES
46
     * @type {RegExp}
47
     * @static
48
     * @private
49
     */
50
    _ESCAPES = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
51
52
    /**
53
     * Second step in the safety evaluation.  Regex used to replace all simple
54
     * values with ']' characters.
55
     *
56
     * @property _VALUES
57
     * @type {RegExp}
58
     * @static
59
     * @private
60
     */
61
    _VALUES  = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
62
63
    /**
64
     * Third step in the safety evaluation.  Regex used to remove all open
65
     * square brackets following a colon, comma, or at the beginning of the
66
     * string.
67
     *
68
     * @property _BRACKETS
69
     * @type {RegExp}
70
     * @static
71
     * @private
72
     */
73
    _BRACKETS = /(?:^|:|,)(?:\s*\[)+/g,
74
75
    /**
76
     * Final step in the safety evaluation.  Regex used to test the string left
77
     * after all previous replacements for invalid characters.
78
     *
79
     * @property _UNSAFE
80
     * @type {RegExp}
81
     * @static
82
     * @private
83
     */
84
    _UNSAFE  = /^[\],:{}\s]*$/,
85
86
87
/* Variables used by stringify */
88
89
    /**
90
     * Regex used to replace special characters in strings for JSON
91
     * stringification.
92
     *
93
     * @property _SPECIAL_CHARS
94
     * @type {RegExp}
95
     * @static
96
     * @private
97
     */
98
    _SPECIAL_CHARS = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
99
100
    /**
101
     * Character substitution map for common escapes and special characters.
102
     *
103
     * @property _CHARS
104
     * @type {Object}
105
     * @static
106
     * @private
107
     */
108
    _CHARS = {
109
        '\b': '\\b',
110
        '\t': '\\t',
111
        '\n': '\\n',
112
        '\f': '\\f',
113
        '\r': '\\r',
114
        '"' : '\\"',
115
        '\\': '\\\\'
116
    },
117
    
118
    UNDEFINED = 'undefined',
119
    OBJECT    = 'object',
120
    NULL      = 'null',
121
    STRING    = 'string',
122
    NUMBER    = 'number',
123
    BOOLEAN   = 'boolean',
124
    DATE      = 'date',
125
    _allowable = {
126
        'undefined'        : UNDEFINED,
127
        'string'           : STRING,
128
        '[object String]'  : STRING,
129
        'number'           : NUMBER,
130
        '[object Number]'  : NUMBER,
131
        'boolean'          : BOOLEAN,
132
        '[object Boolean]' : BOOLEAN,
133
        '[object Date]'    : DATE,
134
        '[object RegExp]'  : OBJECT
135
    },
136
    EMPTY     = '',
137
    OPEN_O    = '{',
138
    CLOSE_O   = '}',
139
    OPEN_A    = '[',
140
    CLOSE_A   = ']',
141
    COMMA     = ',',
142
    COMMA_CR  = ",\n",
143
    CR        = "\n",
144
    COLON     = ':',
145
    COLON_SP  = ': ',
146
    QUOTE     = '"';
147
148
// Only accept JSON objects that report a [[Class]] of JSON
149
Native = _toStr.call(Native) === '[object JSON]' && Native;
150
151
// Escapes a special character to a safe Unicode representation
152
function _char(c) {
153
    if (!_CHARS[c]) {
154
        _CHARS[c] =  '\\u'+('0000'+(+(c.charCodeAt(0))).toString(16)).slice(-4);
155
    }
156
    return _CHARS[c];
157
}
158
159
160
/* functions used by parse */
161
162
/**
163
 * Traverses nested objects, applying a filter or reviver function to
164
 * each value.  The value returned from the function will replace the
165
 * original value in the key:value pair.  If the value returned is
166
 * undefined, the key will be omitted from the returned object.
167
 *
168
 * @method _revive
169
 * @param data {MIXED} Any JavaScript data
170
 * @param reviver {Function} filter or mutation function
171
 * @return {MIXED} The results of the filtered/mutated data structure
172
 * @private
173
 */
174
function _revive(data, reviver) {
175
    var walk = function (o,key) {
176
        var k,v,value = o[key];
177
        if (value && typeof value === 'object') {
178
            for (k in value) {
179
                if (l.hasOwnProperty(value,k)) {
180
                    v = walk(value, k);
181
                    if (v === undefined) {
182
                        delete value[k];
183
                    } else {
184
                        value[k] = v;
185
                    }
186
                }
187
            }
188
        }
189
        return reviver.call(o,key,value);
190
    };
191
192
    return typeof reviver === 'function' ? walk({'':data},'') : data;
193
}
194
195
/**
196
 * Replace certain Unicode characters that may be handled incorrectly by
197
 * some browser implementations.
198
 *
199
 * @method _prepare
200
 * @param s {String} parse input
201
 * @return {String} sanitized JSON string ready to be validated/parsed
202
 * @private
203
 */
204
function _prepare(s) {
205
    return s.replace(_UNICODE_EXCEPTIONS, _char);
206
}
207
208
function _isSafe(str) {
209
    return l.isString(str) &&
210
            _UNSAFE.test(str.replace(_ESCAPES,'@').
211
                             replace(_VALUES,']').
212
                             replace(_BRACKETS,''));
213
}
214
215
function _parse(s,reviver) {
216
    // sanitize
217
    s = _prepare(s);
218
219
    // Ensure valid JSON
220
    if (_isSafe(s)) {
221
        // Eval the text into a JavaScript data structure, apply the
222
        // reviver function if provided, and return
223
        return _revive( eval('(' + s + ')'), reviver );
224
    }
225
226
    // The text is not valid JSON
227
    throw new SyntaxError('JSON.parse');
228
}
229
230
231
232
/* functions used by stringify */
233
234
// Utility function used to determine how to serialize a variable.
235
function _type(o) {
236
    var t = typeof o;
237
    return  _allowable[t] ||              // number, string, boolean, undefined
238
            _allowable[_toStr.call(o)] || // Number, String, Boolean, Date
239
            (t === OBJECT ?
240
                (o ? OBJECT : NULL) :     // object, array, null, misc natives
241
                UNDEFINED);               // function, unknown
242
}
243
244
// Enclose escaped strings in quotes
245
function _string(s) {
246
    return QUOTE + s.replace(_SPECIAL_CHARS, _char) + QUOTE;
247
}
248
249
// Adds the provided space to the beginning of every line in the input string
250
function _indent(s,space) {
251
    return s.replace(/^/gm, space);
252
}
253
254
// JavaScript implementation of stringify (see API declaration of stringify)
255
function _stringify(o,w,space) {
256
    if (o === undefined) {
257
        return undefined;
258
    }
259
260
    var replacer = isFunction(w) ? w : null,
261
        format   = _toStr.call(space).match(/String|Number/) || [],
262
        _date    = YAHOO.lang.JSON.dateToString,
263
        stack    = [],
264
        tmp,i,len;
265
266
    if (replacer || !isArray(w)) {
267
        w = undefined;
268
    }
269
270
    // Ensure whitelist keys are unique (bug 2110391)
271
    if (w) {
272
        tmp = {};
273
        for (i = 0, len = w.length; i < len; ++i) {
274
            tmp[w[i]] = true;
275
        }
276
        w = tmp;
277
    }
278
279
    // Per the spec, strings are truncated to 10 characters and numbers
280
    // are converted to that number of spaces (max 10)
281
    space = format[0] === 'Number' ?
282
                new Array(Math.min(Math.max(0,space),10)+1).join(" ") :
283
                (space || EMPTY).slice(0,10);
284
285
    function _serialize(h,key) {
286
        var value = h[key],
287
            t     = _type(value),
288
            a     = [],
289
            colon = space ? COLON_SP : COLON,
290
            arr, i, keys, k, v;
291
292
        // Per the ECMA 5 spec, toJSON is applied before the replacer is
293
        // called.  Also per the spec, Date.prototype.toJSON has been added, so
294
        // Date instances should be serialized prior to exposure to the
295
        // replacer.  I disagree with this decision, but the spec is the spec.
296
        if (isObject(value) && isFunction(value.toJSON)) {
297
            value = value.toJSON(key);
298
        } else if (t === DATE) {
299
            value = _date(value);
300
        }
301
302
        if (isFunction(replacer)) {
303
            value = replacer.call(h,key,value);
304
        }
305
306
        if (value !== h[key]) {
307
            t = _type(value);
308
        }
309
310
        switch (t) {
311
            case DATE    : // intentional fallthrough.  Pre-replacer Dates are
312
                           // serialized in the toJSON stage.  Dates here would
313
                           // have been produced by the replacer.
314
            case OBJECT  : break;
315
            case STRING  : return _string(value);
316
            case NUMBER  : return isFinite(value) ? value+EMPTY : NULL;
317
            case BOOLEAN : return value+EMPTY;
318
            case NULL    : return NULL;
319
            default      : return undefined;
320
        }
321
322
        // Check for cyclical references in nested objects
323
        for (i = stack.length - 1; i >= 0; --i) {
324
            if (stack[i] === value) {
325
                throw new Error("JSON.stringify. Cyclical reference");
326
            }
327
        }
328
329
        arr = isArray(value);
330
331
        // Add the object to the processing stack
332
        stack.push(value);
333
334
        if (arr) { // Array
335
            for (i = value.length - 1; i >= 0; --i) {
336
                a[i] = _serialize(value, i) || NULL;
337
            }
338
        } else {   // Object
339
            // If whitelist provided, take only those keys
340
            keys = w || value;
341
            i = 0;
342
343
            for (k in keys) {
344
                if (keys.hasOwnProperty(k)) {
345
                    v = _serialize(value, k);
346
                    if (v) {
347
                        a[i++] = _string(k) + colon + v;
348
                    }
349
                }
350
            }
351
        }
352
353
        // remove the array from the stack
354
        stack.pop();
355
356
        if (space && a.length) {
357
            return arr ?
358
                OPEN_A + CR + _indent(a.join(COMMA_CR), space) + CR + CLOSE_A :
359
                OPEN_O + CR + _indent(a.join(COMMA_CR), space) + CR + CLOSE_O;
360
        } else {
361
            return arr ?
362
                OPEN_A + a.join(COMMA) + CLOSE_A :
363
                OPEN_O + a.join(COMMA) + CLOSE_O;
364
        }
365
    }
366
367
    // process the input
368
    return _serialize({'':o},'');
369
}
370
371
372
/* Public API */
373
YAHOO.lang.JSON = {
374
    /**
375
     * Leverage native JSON parse if the browser has a native implementation.
376
     * In general, this is a good idea.  See the Known Issues section in the
377
     * JSON user guide for caveats.  The default value is true for browsers with
378
     * native JSON support.
379
     *
380
     * @property useNativeParse
381
     * @type Boolean
382
     * @default true
383
     * @static
384
     */
385
    useNativeParse : !!Native,
386
387
    /**
388
     * Leverage native JSON stringify if the browser has a native
389
     * implementation.  In general, this is a good idea.  See the Known Issues
390
     * section in the JSON user guide for caveats.  The default value is true
391
     * for browsers with native JSON support.
392
     *
393
     * @property useNativeStringify
394
     * @type Boolean
395
     * @default true
396
     * @static
397
     */
398
    useNativeStringify : !!Native,
399
400
    /**
401
     * Four step determination whether a string is safe to eval. In three steps,
402
     * escape sequences, safe values, and properly placed open square brackets
403
     * are replaced with placeholders or removed.  Then in the final step, the
404
     * result of all these replacements is checked for invalid characters.
405
     *
406
     * @method isSafe
407
     * @param str {String} JSON string to be tested
408
     * @return {boolean} is the string safe for eval?
409
     * @static
410
     */
411
    isSafe : function (s) {
412
        return _isSafe(_prepare(s));
413
    },
414
415
    /**
416
     * <p>Parse a JSON string, returning the native JavaScript
417
     * representation.</p>
418
     *
419
     * <p>When lang.JSON.useNativeParse is true, this will defer to the native
420
     * JSON.parse if the browser has a native implementation.  Otherwise, a
421
     * JavaScript implementation based on http://www.json.org/json2.js
422
     * is used.</p>
423
     *
424
     * @method parse
425
     * @param s {string} JSON string data
426
     * @param reviver {function} (optional) function(k,v) passed each key:value
427
     *          pair of object literals, allowing pruning or altering values
428
     * @return {MIXED} the native JavaScript representation of the JSON string
429
     * @throws SyntaxError
430
     * @static
431
     */
432
    parse : function (s,reviver) {
433
        return Native && YAHOO.lang.JSON.useNativeParse ?
434
            Native.parse(s,reviver) : _parse(s,reviver);
435
    },
436
437
    /**
438
     * <p>Converts an arbitrary value to a JSON string representation.</p>
439
     *
440
     * <p>Objects with cyclical references will trigger an exception.</p>
441
     *
442
     * <p>If a whitelist is provided, only matching object keys will be
443
     * included.  Alternately, a replacer function may be passed as the
444
     * second parameter.  This function is executed on every value in the
445
     * input, and its return value will be used in place of the original value.
446
     * This is useful to serialize specialized objects or class instances.</p>
447
     *
448
     * <p>If a positive integer or non-empty string is passed as the third
449
     * parameter, the output will be formatted with carriage returns and
450
     * indentation for readability.  If a String is passed (such as "\t") it
451
     * will be used once for each indentation level.  If a number is passed,
452
     * that number of spaces will be used.</p>
453
     *
454
     * <p>When lang.JSON.useNativeStringify is true, this will defer to the
455
     * native JSON.stringify if the browser has a native implementation.
456
     * Otherwise, a JavaScript implementation is used.</p>
457
     *
458
     * @method stringify
459
     * @param o {MIXED} any arbitrary object to convert to JSON string
460
     * @param w {Array|Function} (optional) whitelist of acceptable object keys
461
     *                  to include OR a function(value,key) to alter values
462
     *                  before serialization
463
     * @param space {Number|String} (optional) indentation character(s) or
464
     *                  depthy of spaces to format the output 
465
     * @return {string} JSON string representation of the input
466
     * @throws Error
467
     * @static
468
     */
469
    stringify : function (o,w,space) {
470
        return Native && YAHOO.lang.JSON.useNativeStringify ?
471
            Native.stringify(o,w,space) : _stringify(o,w,space);
472
    },
473
474
    /**
475
     * Serializes a Date instance as a UTC date string.  Used internally by
476
     * the JavaScript implementation of stringify.  If you need a different
477
     * Date serialization format, override this method.  If you change this,
478
     * you should also set useNativeStringify to false, since native JSON
479
     * implementations serialize Dates per the ECMAScript 5 spec.  You've been
480
     * warned.
481
     *
482
     * @method dateToString
483
     * @param d {Date} The Date to serialize
484
     * @return {String} stringified Date in UTC format YYYY-MM-DDTHH:mm:SSZ
485
     * @static
486
     */
487
    dateToString : function (d) {
488
        function _zeroPad(v) {
489
            return v < 10 ? '0' + v : v;
490
        }
491
492
        return d.getUTCFullYear()         + '-' +
493
            _zeroPad(d.getUTCMonth() + 1) + '-' +
494
            _zeroPad(d.getUTCDate())      + 'T' +
495
            _zeroPad(d.getUTCHours())     + COLON +
496
            _zeroPad(d.getUTCMinutes())   + COLON +
497
            _zeroPad(d.getUTCSeconds())   + 'Z';
498
    },
499
500
    /**
501
     * Reconstitute Date instances from the default JSON UTC serialization.
502
     * Reference this from a reviver function to rebuild Dates during the
503
     * parse operation.
504
     *
505
     * @method stringToDate
506
     * @param str {String} String serialization of a Date
507
     * @return {Date}
508
     */
509
    stringToDate : function (str) {
510
        var m = str.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{3}))?Z$/);
511
        if (m) {
512
            var d = new Date();
513
            d.setUTCFullYear(m[1], m[2]-1, m[3]);
514
            d.setUTCHours(m[4], m[5], m[6], (m[7] || 0));
515
            return d;
516
        }
517
        return str;
518
    }
519
};
520
521
/**
522
 * <p>Four step determination whether a string is safe to eval. In three steps,
523
 * escape sequences, safe values, and properly placed open square brackets
524
 * are replaced with placeholders or removed.  Then in the final step, the
525
 * result of all these replacements is checked for invalid characters.</p>
526
 *
527
 * <p>This is an alias for isSafe.</p>
528
 *
529
 * @method isValid
530
 * @param str {String} JSON string to be tested
531
 * @return {boolean} is the string safe for eval?
532
 * @static
533
 * @deprecated use isSafe
534
 */
535
YAHOO.lang.JSON.isValid = YAHOO.lang.JSON.isSafe;
536
537
})();
538
YAHOO.register("json", YAHOO.lang.JSON, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/json/json-min.js (-7 lines)
Lines 1-7 Link Here
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.8.0r4
6
*/
7
(function(){var l=YAHOO.lang,isFunction=l.isFunction,isObject=l.isObject,isArray=l.isArray,_toStr=Object.prototype.toString,Native=(YAHOO.env.ua.caja?window:this).JSON,_UNICODE_EXCEPTIONS=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,_ESCAPES=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,_VALUES=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,_BRACKETS=/(?:^|:|,)(?:\s*\[)+/g,_UNSAFE=/^[\],:{}\s]*$/,_SPECIAL_CHARS=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,_CHARS={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},UNDEFINED="undefined",OBJECT="object",NULL="null",STRING="string",NUMBER="number",BOOLEAN="boolean",DATE="date",_allowable={"undefined":UNDEFINED,"string":STRING,"[object String]":STRING,"number":NUMBER,"[object Number]":NUMBER,"boolean":BOOLEAN,"[object Boolean]":BOOLEAN,"[object Date]":DATE,"[object RegExp]":OBJECT},EMPTY="",OPEN_O="{",CLOSE_O="}",OPEN_A="[",CLOSE_A="]",COMMA=",",COMMA_CR=",\n",CR="\n",COLON=":",COLON_SP=": ",QUOTE='"';Native=_toStr.call(Native)==="[object JSON]"&&Native;function _char(c){if(!_CHARS[c]){_CHARS[c]="\\u"+("0000"+(+(c.charCodeAt(0))).toString(16)).slice(-4);}return _CHARS[c];}function _revive(data,reviver){var walk=function(o,key){var k,v,value=o[key];if(value&&typeof value==="object"){for(k in value){if(l.hasOwnProperty(value,k)){v=walk(value,k);if(v===undefined){delete value[k];}else{value[k]=v;}}}}return reviver.call(o,key,value);};return typeof reviver==="function"?walk({"":data},""):data;}function _prepare(s){return s.replace(_UNICODE_EXCEPTIONS,_char);}function _isSafe(str){return l.isString(str)&&_UNSAFE.test(str.replace(_ESCAPES,"@").replace(_VALUES,"]").replace(_BRACKETS,""));}function _parse(s,reviver){s=_prepare(s);if(_isSafe(s)){return _revive(eval("("+s+")"),reviver);}throw new SyntaxError("JSON.parse");}function _type(o){var t=typeof o;return _allowable[t]||_allowable[_toStr.call(o)]||(t===OBJECT?(o?OBJECT:NULL):UNDEFINED);}function _string(s){return QUOTE+s.replace(_SPECIAL_CHARS,_char)+QUOTE;}function _indent(s,space){return s.replace(/^/gm,space);}function _stringify(o,w,space){if(o===undefined){return undefined;}var replacer=isFunction(w)?w:null,format=_toStr.call(space).match(/String|Number/)||[],_date=YAHOO.lang.JSON.dateToString,stack=[],tmp,i,len;if(replacer||!isArray(w)){w=undefined;}if(w){tmp={};for(i=0,len=w.length;i<len;++i){tmp[w[i]]=true;}w=tmp;}space=format[0]==="Number"?new Array(Math.min(Math.max(0,space),10)+1).join(" "):(space||EMPTY).slice(0,10);function _serialize(h,key){var value=h[key],t=_type(value),a=[],colon=space?COLON_SP:COLON,arr,i,keys,k,v;if(isObject(value)&&isFunction(value.toJSON)){value=value.toJSON(key);}else{if(t===DATE){value=_date(value);}}if(isFunction(replacer)){value=replacer.call(h,key,value);}if(value!==h[key]){t=_type(value);}switch(t){case DATE:case OBJECT:break;case STRING:return _string(value);case NUMBER:return isFinite(value)?value+EMPTY:NULL;case BOOLEAN:return value+EMPTY;case NULL:return NULL;default:return undefined;}for(i=stack.length-1;i>=0;--i){if(stack[i]===value){throw new Error("JSON.stringify. Cyclical reference");}}arr=isArray(value);stack.push(value);if(arr){for(i=value.length-1;i>=0;--i){a[i]=_serialize(value,i)||NULL;}}else{keys=w||value;i=0;for(k in keys){if(keys.hasOwnProperty(k)){v=_serialize(value,k);if(v){a[i++]=_string(k)+colon+v;}}}}stack.pop();if(space&&a.length){return arr?OPEN_A+CR+_indent(a.join(COMMA_CR),space)+CR+CLOSE_A:OPEN_O+CR+_indent(a.join(COMMA_CR),space)+CR+CLOSE_O;}else{return arr?OPEN_A+a.join(COMMA)+CLOSE_A:OPEN_O+a.join(COMMA)+CLOSE_O;}}return _serialize({"":o},"");}YAHOO.lang.JSON={useNativeParse:!!Native,useNativeStringify:!!Native,isSafe:function(s){return _isSafe(_prepare(s));},parse:function(s,reviver){return Native&&YAHOO.lang.JSON.useNativeParse?Native.parse(s,reviver):_parse(s,reviver);},stringify:function(o,w,space){return Native&&YAHOO.lang.JSON.useNativeStringify?Native.stringify(o,w,space):_stringify(o,w,space);},dateToString:function(d){function _zeroPad(v){return v<10?"0"+v:v;}return d.getUTCFullYear()+"-"+_zeroPad(d.getUTCMonth()+1)+"-"+_zeroPad(d.getUTCDate())+"T"+_zeroPad(d.getUTCHours())+COLON+_zeroPad(d.getUTCMinutes())+COLON+_zeroPad(d.getUTCSeconds())+"Z";},stringToDate:function(str){var m=str.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{3}))?Z$/);if(m){var d=new Date();d.setUTCFullYear(m[1],m[2]-1,m[3]);d.setUTCHours(m[4],m[5],m[6],(m[7]||0));return d;}return str;}};YAHOO.lang.JSON.isValid=YAHOO.lang.JSON.isSafe;})();YAHOO.register("json",YAHOO.lang.JSON,{version:"2.8.0r4",build:"2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/json/json.js (-538 lines)
Lines 1-538 Link Here
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.8.0r4
6
*/
7
/**
8
 * Provides methods to parse JSON strings and convert objects to JSON strings.
9
 *
10
 * @module json
11
 * @class JSON
12
 * @namespace YAHOO.lang
13
 * @static
14
 */
15
(function () {
16
17
var l = YAHOO.lang,
18
    isFunction = l.isFunction,
19
    isObject   = l.isObject,
20
    isArray    = l.isArray,
21
    _toStr     = Object.prototype.toString,
22
                 // 'this' is the global object.  window in browser env.  Keep
23
                 // the code env agnostic.  Caja requies window, unfortunately.
24
    Native     = (YAHOO.env.ua.caja ? window : this).JSON,
25
26
/* Variables used by parse */
27
28
    /**
29
     * Replace certain Unicode characters that JavaScript may handle incorrectly
30
     * during eval--either by deleting them or treating them as line
31
     * endings--with escape sequences.
32
     * IMPORTANT NOTE: This regex will be used to modify the input if a match is
33
     * found.
34
     *
35
     * @property _UNICODE_EXCEPTIONS
36
     * @type {RegExp}
37
     * @private
38
     */
39
    _UNICODE_EXCEPTIONS = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
40
41
    /**
42
     * First step in the safety evaluation.  Regex used to replace all escape
43
     * sequences (i.e. "\\", etc) with '@' characters (a non-JSON character).
44
     *
45
     * @property _ESCAPES
46
     * @type {RegExp}
47
     * @static
48
     * @private
49
     */
50
    _ESCAPES = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
51
52
    /**
53
     * Second step in the safety evaluation.  Regex used to replace all simple
54
     * values with ']' characters.
55
     *
56
     * @property _VALUES
57
     * @type {RegExp}
58
     * @static
59
     * @private
60
     */
61
    _VALUES  = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
62
63
    /**
64
     * Third step in the safety evaluation.  Regex used to remove all open
65
     * square brackets following a colon, comma, or at the beginning of the
66
     * string.
67
     *
68
     * @property _BRACKETS
69
     * @type {RegExp}
70
     * @static
71
     * @private
72
     */
73
    _BRACKETS = /(?:^|:|,)(?:\s*\[)+/g,
74
75
    /**
76
     * Final step in the safety evaluation.  Regex used to test the string left
77
     * after all previous replacements for invalid characters.
78
     *
79
     * @property _UNSAFE
80
     * @type {RegExp}
81
     * @static
82
     * @private
83
     */
84
    _UNSAFE  = /^[\],:{}\s]*$/,
85
86
87
/* Variables used by stringify */
88
89
    /**
90
     * Regex used to replace special characters in strings for JSON
91
     * stringification.
92
     *
93
     * @property _SPECIAL_CHARS
94
     * @type {RegExp}
95
     * @static
96
     * @private
97
     */
98
    _SPECIAL_CHARS = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
99
100
    /**
101
     * Character substitution map for common escapes and special characters.
102
     *
103
     * @property _CHARS
104
     * @type {Object}
105
     * @static
106
     * @private
107
     */
108
    _CHARS = {
109
        '\b': '\\b',
110
        '\t': '\\t',
111
        '\n': '\\n',
112
        '\f': '\\f',
113
        '\r': '\\r',
114
        '"' : '\\"',
115
        '\\': '\\\\'
116
    },
117
    
118
    UNDEFINED = 'undefined',
119
    OBJECT    = 'object',
120
    NULL      = 'null',
121
    STRING    = 'string',
122
    NUMBER    = 'number',
123
    BOOLEAN   = 'boolean',
124
    DATE      = 'date',
125
    _allowable = {
126
        'undefined'        : UNDEFINED,
127
        'string'           : STRING,
128
        '[object String]'  : STRING,
129
        'number'           : NUMBER,
130
        '[object Number]'  : NUMBER,
131
        'boolean'          : BOOLEAN,
132
        '[object Boolean]' : BOOLEAN,
133
        '[object Date]'    : DATE,
134
        '[object RegExp]'  : OBJECT
135
    },
136
    EMPTY     = '',
137
    OPEN_O    = '{',
138
    CLOSE_O   = '}',
139
    OPEN_A    = '[',
140
    CLOSE_A   = ']',
141
    COMMA     = ',',
142
    COMMA_CR  = ",\n",
143
    CR        = "\n",
144
    COLON     = ':',
145
    COLON_SP  = ': ',
146
    QUOTE     = '"';
147
148
// Only accept JSON objects that report a [[Class]] of JSON
149
Native = _toStr.call(Native) === '[object JSON]' && Native;
150
151
// Escapes a special character to a safe Unicode representation
152
function _char(c) {
153
    if (!_CHARS[c]) {
154
        _CHARS[c] =  '\\u'+('0000'+(+(c.charCodeAt(0))).toString(16)).slice(-4);
155
    }
156
    return _CHARS[c];
157
}
158
159
160
/* functions used by parse */
161
162
/**
163
 * Traverses nested objects, applying a filter or reviver function to
164
 * each value.  The value returned from the function will replace the
165
 * original value in the key:value pair.  If the value returned is
166
 * undefined, the key will be omitted from the returned object.
167
 *
168
 * @method _revive
169
 * @param data {MIXED} Any JavaScript data
170
 * @param reviver {Function} filter or mutation function
171
 * @return {MIXED} The results of the filtered/mutated data structure
172
 * @private
173
 */
174
function _revive(data, reviver) {
175
    var walk = function (o,key) {
176
        var k,v,value = o[key];
177
        if (value && typeof value === 'object') {
178
            for (k in value) {
179
                if (l.hasOwnProperty(value,k)) {
180
                    v = walk(value, k);
181
                    if (v === undefined) {
182
                        delete value[k];
183
                    } else {
184
                        value[k] = v;
185
                    }
186
                }
187
            }
188
        }
189
        return reviver.call(o,key,value);
190
    };
191
192
    return typeof reviver === 'function' ? walk({'':data},'') : data;
193
}
194
195
/**
196
 * Replace certain Unicode characters that may be handled incorrectly by
197
 * some browser implementations.
198
 *
199
 * @method _prepare
200
 * @param s {String} parse input
201
 * @return {String} sanitized JSON string ready to be validated/parsed
202
 * @private
203
 */
204
function _prepare(s) {
205
    return s.replace(_UNICODE_EXCEPTIONS, _char);
206
}
207
208
function _isSafe(str) {
209
    return l.isString(str) &&
210
            _UNSAFE.test(str.replace(_ESCAPES,'@').
211
                             replace(_VALUES,']').
212
                             replace(_BRACKETS,''));
213
}
214
215
function _parse(s,reviver) {
216
    // sanitize
217
    s = _prepare(s);
218
219
    // Ensure valid JSON
220
    if (_isSafe(s)) {
221
        // Eval the text into a JavaScript data structure, apply the
222
        // reviver function if provided, and return
223
        return _revive( eval('(' + s + ')'), reviver );
224
    }
225
226
    // The text is not valid JSON
227
    throw new SyntaxError('JSON.parse');
228
}
229
230
231
232
/* functions used by stringify */
233
234
// Utility function used to determine how to serialize a variable.
235
function _type(o) {
236
    var t = typeof o;
237
    return  _allowable[t] ||              // number, string, boolean, undefined
238
            _allowable[_toStr.call(o)] || // Number, String, Boolean, Date
239
            (t === OBJECT ?
240
                (o ? OBJECT : NULL) :     // object, array, null, misc natives
241
                UNDEFINED);               // function, unknown
242
}
243
244
// Enclose escaped strings in quotes
245
function _string(s) {
246
    return QUOTE + s.replace(_SPECIAL_CHARS, _char) + QUOTE;
247
}
248
249
// Adds the provided space to the beginning of every line in the input string
250
function _indent(s,space) {
251
    return s.replace(/^/gm, space);
252
}
253
254
// JavaScript implementation of stringify (see API declaration of stringify)
255
function _stringify(o,w,space) {
256
    if (o === undefined) {
257
        return undefined;
258
    }
259
260
    var replacer = isFunction(w) ? w : null,
261
        format   = _toStr.call(space).match(/String|Number/) || [],
262
        _date    = YAHOO.lang.JSON.dateToString,
263
        stack    = [],
264
        tmp,i,len;
265
266
    if (replacer || !isArray(w)) {
267
        w = undefined;
268
    }
269
270
    // Ensure whitelist keys are unique (bug 2110391)
271
    if (w) {
272
        tmp = {};
273
        for (i = 0, len = w.length; i < len; ++i) {
274
            tmp[w[i]] = true;
275
        }
276
        w = tmp;
277
    }
278
279
    // Per the spec, strings are truncated to 10 characters and numbers
280
    // are converted to that number of spaces (max 10)
281
    space = format[0] === 'Number' ?
282
                new Array(Math.min(Math.max(0,space),10)+1).join(" ") :
283
                (space || EMPTY).slice(0,10);
284
285
    function _serialize(h,key) {
286
        var value = h[key],
287
            t     = _type(value),
288
            a     = [],
289
            colon = space ? COLON_SP : COLON,
290
            arr, i, keys, k, v;
291
292
        // Per the ECMA 5 spec, toJSON is applied before the replacer is
293
        // called.  Also per the spec, Date.prototype.toJSON has been added, so
294
        // Date instances should be serialized prior to exposure to the
295
        // replacer.  I disagree with this decision, but the spec is the spec.
296
        if (isObject(value) && isFunction(value.toJSON)) {
297
            value = value.toJSON(key);
298
        } else if (t === DATE) {
299
            value = _date(value);
300
        }
301
302
        if (isFunction(replacer)) {
303
            value = replacer.call(h,key,value);
304
        }
305
306
        if (value !== h[key]) {
307
            t = _type(value);
308
        }
309
310
        switch (t) {
311
            case DATE    : // intentional fallthrough.  Pre-replacer Dates are
312
                           // serialized in the toJSON stage.  Dates here would
313
                           // have been produced by the replacer.
314
            case OBJECT  : break;
315
            case STRING  : return _string(value);
316
            case NUMBER  : return isFinite(value) ? value+EMPTY : NULL;
317
            case BOOLEAN : return value+EMPTY;
318
            case NULL    : return NULL;
319
            default      : return undefined;
320
        }
321
322
        // Check for cyclical references in nested objects
323
        for (i = stack.length - 1; i >= 0; --i) {
324
            if (stack[i] === value) {
325
                throw new Error("JSON.stringify. Cyclical reference");
326
            }
327
        }
328
329
        arr = isArray(value);
330
331
        // Add the object to the processing stack
332
        stack.push(value);
333
334
        if (arr) { // Array
335
            for (i = value.length - 1; i >= 0; --i) {
336
                a[i] = _serialize(value, i) || NULL;
337
            }
338
        } else {   // Object
339
            // If whitelist provided, take only those keys
340
            keys = w || value;
341
            i = 0;
342
343
            for (k in keys) {
344
                if (keys.hasOwnProperty(k)) {
345
                    v = _serialize(value, k);
346
                    if (v) {
347
                        a[i++] = _string(k) + colon + v;
348
                    }
349
                }
350
            }
351
        }
352
353
        // remove the array from the stack
354
        stack.pop();
355
356
        if (space && a.length) {
357
            return arr ?
358
                OPEN_A + CR + _indent(a.join(COMMA_CR), space) + CR + CLOSE_A :
359
                OPEN_O + CR + _indent(a.join(COMMA_CR), space) + CR + CLOSE_O;
360
        } else {
361
            return arr ?
362
                OPEN_A + a.join(COMMA) + CLOSE_A :
363
                OPEN_O + a.join(COMMA) + CLOSE_O;
364
        }
365
    }
366
367
    // process the input
368
    return _serialize({'':o},'');
369
}
370
371
372
/* Public API */
373
YAHOO.lang.JSON = {
374
    /**
375
     * Leverage native JSON parse if the browser has a native implementation.
376
     * In general, this is a good idea.  See the Known Issues section in the
377
     * JSON user guide for caveats.  The default value is true for browsers with
378
     * native JSON support.
379
     *
380
     * @property useNativeParse
381
     * @type Boolean
382
     * @default true
383
     * @static
384
     */
385
    useNativeParse : !!Native,
386
387
    /**
388
     * Leverage native JSON stringify if the browser has a native
389
     * implementation.  In general, this is a good idea.  See the Known Issues
390
     * section in the JSON user guide for caveats.  The default value is true
391
     * for browsers with native JSON support.
392
     *
393
     * @property useNativeStringify
394
     * @type Boolean
395
     * @default true
396
     * @static
397
     */
398
    useNativeStringify : !!Native,
399
400
    /**
401
     * Four step determination whether a string is safe to eval. In three steps,
402
     * escape sequences, safe values, and properly placed open square brackets
403
     * are replaced with placeholders or removed.  Then in the final step, the
404
     * result of all these replacements is checked for invalid characters.
405
     *
406
     * @method isSafe
407
     * @param str {String} JSON string to be tested
408
     * @return {boolean} is the string safe for eval?
409
     * @static
410
     */
411
    isSafe : function (s) {
412
        return _isSafe(_prepare(s));
413
    },
414
415
    /**
416
     * <p>Parse a JSON string, returning the native JavaScript
417
     * representation.</p>
418
     *
419
     * <p>When lang.JSON.useNativeParse is true, this will defer to the native
420
     * JSON.parse if the browser has a native implementation.  Otherwise, a
421
     * JavaScript implementation based on http://www.json.org/json2.js
422
     * is used.</p>
423
     *
424
     * @method parse
425
     * @param s {string} JSON string data
426
     * @param reviver {function} (optional) function(k,v) passed each key:value
427
     *          pair of object literals, allowing pruning or altering values
428
     * @return {MIXED} the native JavaScript representation of the JSON string
429
     * @throws SyntaxError
430
     * @static
431
     */
432
    parse : function (s,reviver) {
433
        return Native && YAHOO.lang.JSON.useNativeParse ?
434
            Native.parse(s,reviver) : _parse(s,reviver);
435
    },
436
437
    /**
438
     * <p>Converts an arbitrary value to a JSON string representation.</p>
439
     *
440
     * <p>Objects with cyclical references will trigger an exception.</p>
441
     *
442
     * <p>If a whitelist is provided, only matching object keys will be
443
     * included.  Alternately, a replacer function may be passed as the
444
     * second parameter.  This function is executed on every value in the
445
     * input, and its return value will be used in place of the original value.
446
     * This is useful to serialize specialized objects or class instances.</p>
447
     *
448
     * <p>If a positive integer or non-empty string is passed as the third
449
     * parameter, the output will be formatted with carriage returns and
450
     * indentation for readability.  If a String is passed (such as "\t") it
451
     * will be used once for each indentation level.  If a number is passed,
452
     * that number of spaces will be used.</p>
453
     *
454
     * <p>When lang.JSON.useNativeStringify is true, this will defer to the
455
     * native JSON.stringify if the browser has a native implementation.
456
     * Otherwise, a JavaScript implementation is used.</p>
457
     *
458
     * @method stringify
459
     * @param o {MIXED} any arbitrary object to convert to JSON string
460
     * @param w {Array|Function} (optional) whitelist of acceptable object keys
461
     *                  to include OR a function(value,key) to alter values
462
     *                  before serialization
463
     * @param space {Number|String} (optional) indentation character(s) or
464
     *                  depthy of spaces to format the output 
465
     * @return {string} JSON string representation of the input
466
     * @throws Error
467
     * @static
468
     */
469
    stringify : function (o,w,space) {
470
        return Native && YAHOO.lang.JSON.useNativeStringify ?
471
            Native.stringify(o,w,space) : _stringify(o,w,space);
472
    },
473
474
    /**
475
     * Serializes a Date instance as a UTC date string.  Used internally by
476
     * the JavaScript implementation of stringify.  If you need a different
477
     * Date serialization format, override this method.  If you change this,
478
     * you should also set useNativeStringify to false, since native JSON
479
     * implementations serialize Dates per the ECMAScript 5 spec.  You've been
480
     * warned.
481
     *
482
     * @method dateToString
483
     * @param d {Date} The Date to serialize
484
     * @return {String} stringified Date in UTC format YYYY-MM-DDTHH:mm:SSZ
485
     * @static
486
     */
487
    dateToString : function (d) {
488
        function _zeroPad(v) {
489
            return v < 10 ? '0' + v : v;
490
        }
491
492
        return d.getUTCFullYear()         + '-' +
493
            _zeroPad(d.getUTCMonth() + 1) + '-' +
494
            _zeroPad(d.getUTCDate())      + 'T' +
495
            _zeroPad(d.getUTCHours())     + COLON +
496
            _zeroPad(d.getUTCMinutes())   + COLON +
497
            _zeroPad(d.getUTCSeconds())   + 'Z';
498
    },
499
500
    /**
501
     * Reconstitute Date instances from the default JSON UTC serialization.
502
     * Reference this from a reviver function to rebuild Dates during the
503
     * parse operation.
504
     *
505
     * @method stringToDate
506
     * @param str {String} String serialization of a Date
507
     * @return {Date}
508
     */
509
    stringToDate : function (str) {
510
        var m = str.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{3}))?Z$/);
511
        if (m) {
512
            var d = new Date();
513
            d.setUTCFullYear(m[1], m[2]-1, m[3]);
514
            d.setUTCHours(m[4], m[5], m[6], (m[7] || 0));
515
            return d;
516
        }
517
        return str;
518
    }
519
};
520
521
/**
522
 * <p>Four step determination whether a string is safe to eval. In three steps,
523
 * escape sequences, safe values, and properly placed open square brackets
524
 * are replaced with placeholders or removed.  Then in the final step, the
525
 * result of all these replacements is checked for invalid characters.</p>
526
 *
527
 * <p>This is an alias for isSafe.</p>
528
 *
529
 * @method isValid
530
 * @param str {String} JSON string to be tested
531
 * @return {boolean} is the string safe for eval?
532
 * @static
533
 * @deprecated use isSafe
534
 */
535
YAHOO.lang.JSON.isValid = YAHOO.lang.JSON.isSafe;
536
537
})();
538
YAHOO.register("json", YAHOO.lang.JSON, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/menu/assets/menu-core.css (-242 lines)
Lines 1-242 Link Here
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.8.0r4
6
*/
7
/* Menu & MenuBar styles */
8
9
.yuimenu {
10
11
    top: -999em;
12
    left: -999em;
13
14
}
15
16
.yuimenubar {
17
18
    position: static;
19
20
}
21
22
.yuimenu .yuimenu,
23
.yuimenubar .yuimenu {
24
25
    position: absolute;
26
27
}
28
29
.yuimenubar li, 
30
.yuimenu li {
31
32
    list-style-type: none;    
33
34
}
35
36
.yuimenubar ul, 
37
.yuimenu ul,
38
.yuimenubar li, 
39
.yuimenu li,
40
.yuimenu h6,
41
.yuimenubar h6 { 
42
43
    margin: 0;
44
    padding: 0;
45
46
}
47
48
.yuimenuitemlabel,
49
.yuimenubaritemlabel {
50
51
    text-align: left;
52
    white-space: nowrap;
53
54
}
55
56
57
/* 
58
    The following style rule trigger the "hasLayout" property in 
59
    IE (http://msdn2.microsoft.com/en-us/library/ms533776.aspx) for a
60
    MenuBar instance's <ul> element, allowing both to clear their floated 
61
    child <li> elements.
62
*/
63
64
.yuimenubar ul {
65
66
    *zoom: 1;
67
68
}
69
70
71
/* 
72
    Remove the "hasLayout" trigger for submenus of MenuBar instances as it 
73
    is unnecessary. 
74
*/
75
76
.yuimenubar .yuimenu ul {
77
78
    *zoom: normal;
79
80
}
81
82
/*
83
    The following style rule allows a MenuBar instance's <ul> element to clear
84
    its floated <li> elements in Firefox, Safari and and Opera.
85
*/
86
87
.yuimenubar>.bd>ul:after {
88
89
    content: ".";
90
    display: block;
91
    clear: both;
92
    visibility: hidden;
93
    height: 0;
94
    line-height: 0;
95
96
}
97
98
.yuimenubaritem {
99
100
    float: left;
101
102
}
103
104
.yuimenubaritemlabel,
105
.yuimenuitemlabel {
106
107
    display: block;
108
109
}
110
111
.yuimenuitemlabel .helptext {
112
113
    font-style: normal;
114
    display: block;
115
    
116
    /*
117
        The value for the left margin controls how much the help text is
118
        offset from the text of the menu item.  This value will need to 
119
        be customized depending on the longest text label of a menu item.
120
    */
121
    
122
    margin: -1em 0 0 10em;
123
    
124
}
125
126
/*
127
    PLEASE NOTE: The <div> element used for a menu's shadow is appended 
128
    to its root element via JavaScript once it has been rendered.  The 
129
    code that creates the shadow lives in the menu's public "onRender" 
130
    event handler that is a prototype method of YAHOO.widget.Menu.  
131
    Implementers wishing to remove a menu's shadow or add any other markup
132
    required for a given skin for menu should override the "onRender" method.
133
*/
134
135
.yui-menu-shadow {
136
137
    position: absolute;
138
    visibility: hidden;
139
    z-index: -1;
140
141
}
142
143
.yui-menu-shadow-visible {
144
145
    top: 2px;
146
    right: -3px;
147
    left: -3px;
148
    bottom: -3px;
149
    visibility: visible;
150
151
}
152
153
154
/*
155
156
There are two known issues with YAHOO.widget.Overlay (the superclass class of 
157
Menu) that manifest in Gecko-based browsers on Mac OS X:
158
159
    1) Elements with scrollbars will poke through Overlay instances floating 
160
       above them.
161
    
162
    2) An Overlay's scrollbars and the scrollbars of its child nodes remain  
163
       visible when the Overlay is hidden.
164
165
To fix these bugs in Menu (a subclass of YAHOO.widget.Overlay):
166
167
    1) The "overflow" property of a Menu instance's shadow element and child 
168
       nodes is toggled between "hidden" and "auto" (through the application  
169
       and removal of the "hide-scrollbars" and "show-scrollbars" CSS classes)
170
       as its "visibility" configuration property is toggled between 
171
       "false" and "true."
172
    
173
    2) The "display" property of <select> elements that are child nodes of the 
174
       Menu instance's root element is set to "none" when it is hidden.
175
176
PLEASE NOTE:  
177
  
178
    1) The "hide-scrollbars" and "show-scrollbars" CSS classes classes are 
179
       applied only for Gecko on Mac OS X and are added/removed to/from the 
180
       Overlay's root HTML element (DIV) via the "hideMacGeckoScrollbars" and 
181
       "showMacGeckoScrollbars" methods of YAHOO.widget.Overlay.
182
    
183
    2) There may be instances where the CSS for a web page or application 
184
       contains style rules whose specificity override the rules implemented by 
185
       the Menu CSS files to fix this bug.  In such cases, is necessary to 
186
       leverage the provided "hide-scrollbars" and "show-scrollbars" classes to 
187
       write custom style rules to guard against this bug.
188
189
** For more information on this issue, see:
190
191
   + https://bugzilla.mozilla.org/show_bug.cgi?id=187435
192
   + YUILibrary bug #1723530
193
194
*/
195
196
.hide-scrollbars * {
197
198
	overflow: hidden;
199
200
}
201
202
.hide-scrollbars select {
203
204
	display: none;
205
206
}
207
208
209
/*
210
211
The following style rule (".yuimenu.show-scrollbars") overrides the 
212
".show-scrollbars" rule defined in container-core.css which sets the 
213
"overflow" property of a YAHOO.widget.Overlay instance's root HTML element to 
214
"auto" when it is visible.  Without this override, a Menu would have scrollbars
215
when one of its submenus is visible.
216
217
*/
218
219
.yuimenu.show-scrollbars,
220
.yuimenubar.show-scrollbars {
221
222
	overflow: visible; 
223
224
}
225
226
.yuimenu.hide-scrollbars .yui-menu-shadow,
227
.yuimenubar.hide-scrollbars .yui-menu-shadow {
228
229
    overflow: hidden;
230
231
}
232
233
.yuimenu.show-scrollbars .yui-menu-shadow,
234
.yuimenubar.show-scrollbars .yui-menu-shadow {
235
236
    overflow: auto;
237
238
}
239
240
.yui-overlay.yui-force-redraw {
241
   margin-bottom: 1px;
242
}
(-)a/koha-tmpl/intranet-tmpl/lib/yui/menu/assets/menu.css (-503 lines)
Lines 1-503 Link Here
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.8.0r4
6
*/
7
/* Menu & MenuBar styles */
8
9
.yuimenu {
10
11
    top: -999em;
12
    left: -999em;
13
14
}
15
16
.yuimenubar {
17
18
    position: static;
19
20
}
21
22
.yuimenu .yuimenu,
23
.yuimenubar .yuimenu {
24
25
    position: absolute;
26
27
}
28
29
.yuimenubar li, 
30
.yuimenu li {
31
32
    list-style-type: none;    
33
34
}
35
36
.yuimenubar ul, 
37
.yuimenu ul,
38
.yuimenubar li, 
39
.yuimenu li,
40
.yuimenu h6,
41
.yuimenubar h6 { 
42
43
    margin: 0;
44
    padding: 0;
45
46
}
47
48
.yuimenuitemlabel,
49
.yuimenubaritemlabel {
50
51
    text-align: left;
52
    white-space: nowrap;
53
54
}
55
56
57
/* 
58
    The following style rule trigger the "hasLayout" property in 
59
    IE (http://msdn2.microsoft.com/en-us/library/ms533776.aspx) for a
60
    MenuBar instance's <ul> element, allowing both to clear their floated 
61
    child <li> elements.
62
*/
63
64
.yuimenubar ul {
65
66
    *zoom: 1;
67
68
}
69
70
71
/* 
72
    Remove the "hasLayout" trigger for submenus of MenuBar instances as it 
73
    is unnecessary. 
74
*/
75
76
.yuimenubar .yuimenu ul {
77
78
    *zoom: normal;
79
80
}
81
82
/*
83
    The following style rule allows a MenuBar instance's <ul> element to clear
84
    its floated <li> elements in Firefox, Safari and and Opera.
85
*/
86
87
.yuimenubar>.bd>ul:after {
88
89
    content: ".";
90
    display: block;
91
    clear: both;
92
    visibility: hidden;
93
    height: 0;
94
    line-height: 0;
95
96
}
97
98
.yuimenubaritem {
99
100
    float: left;
101
102
}
103
104
.yuimenubaritemlabel,
105
.yuimenuitemlabel {
106
107
    display: block;
108
109
}
110
111
.yuimenuitemlabel .helptext {
112
113
    font-style: normal;
114
    display: block;
115
    
116
    /*
117
        The value for the left margin controls how much the help text is
118
        offset from the text of the menu item.  This value will need to 
119
        be customized depending on the longest text label of a menu item.
120
    */
121
    
122
    margin: -1em 0 0 10em;
123
    
124
}
125
126
/*
127
    PLEASE NOTE: The <div> element used for a menu's shadow is appended 
128
    to its root element via JavaScript once it has been rendered.  The 
129
    code that creates the shadow lives in the menu's public "onRender" 
130
    event handler that is a prototype method of YAHOO.widget.Menu.  
131
    Implementers wishing to remove a menu's shadow or add any other markup
132
    required for a given skin for menu should override the "onRender" method.
133
*/
134
135
.yui-menu-shadow {
136
137
    position: absolute;
138
    visibility: hidden;
139
    z-index: -1;
140
141
}
142
143
.yui-menu-shadow-visible {
144
145
    top: 2px;
146
    right: -3px;
147
    left: -3px;
148
    bottom: -3px;
149
    visibility: visible;
150
151
}
152
153
154
/*
155
156
There are two known issues with YAHOO.widget.Overlay (the superclass class of 
157
Menu) that manifest in Gecko-based browsers on Mac OS X:
158
159
    1) Elements with scrollbars will poke through Overlay instances floating 
160
       above them.
161
    
162
    2) An Overlay's scrollbars and the scrollbars of its child nodes remain  
163
       visible when the Overlay is hidden.
164
165
To fix these bugs in Menu (a subclass of YAHOO.widget.Overlay):
166
167
    1) The "overflow" property of a Menu instance's shadow element and child 
168
       nodes is toggled between "hidden" and "auto" (through the application  
169
       and removal of the "hide-scrollbars" and "show-scrollbars" CSS classes)
170
       as its "visibility" configuration property is toggled between 
171
       "false" and "true."
172
    
173
    2) The "display" property of <select> elements that are child nodes of the 
174
       Menu instance's root element is set to "none" when it is hidden.
175
176
PLEASE NOTE:  
177
  
178
    1) The "hide-scrollbars" and "show-scrollbars" CSS classes classes are 
179
       applied only for Gecko on Mac OS X and are added/removed to/from the 
180
       Overlay's root HTML element (DIV) via the "hideMacGeckoScrollbars" and 
181
       "showMacGeckoScrollbars" methods of YAHOO.widget.Overlay.
182
    
183
    2) There may be instances where the CSS for a web page or application 
184
       contains style rules whose specificity override the rules implemented by 
185
       the Menu CSS files to fix this bug.  In such cases, is necessary to 
186
       leverage the provided "hide-scrollbars" and "show-scrollbars" classes to 
187
       write custom style rules to guard against this bug.
188
189
** For more information on this issue, see:
190
191
   + https://bugzilla.mozilla.org/show_bug.cgi?id=187435
192
   + YUILibrary bug #1723530
193
194
*/
195
196
.hide-scrollbars * {
197
198
	overflow: hidden;
199
200
}
201
202
.hide-scrollbars select {
203
204
	display: none;
205
206
}
207
208
209
/*
210
211
The following style rule (".yuimenu.show-scrollbars") overrides the 
212
".show-scrollbars" rule defined in container-core.css which sets the 
213
"overflow" property of a YAHOO.widget.Overlay instance's root HTML element to 
214
"auto" when it is visible.  Without this override, a Menu would have scrollbars
215
when one of its submenus is visible.
216
217
*/
218
219
.yuimenu.show-scrollbars,
220
.yuimenubar.show-scrollbars {
221
222
	overflow: visible; 
223
224
}
225
226
.yuimenu.hide-scrollbars .yui-menu-shadow,
227
.yuimenubar.hide-scrollbars .yui-menu-shadow {
228
229
    overflow: hidden;
230
231
}
232
233
.yuimenu.show-scrollbars .yui-menu-shadow,
234
.yuimenubar.show-scrollbars .yui-menu-shadow {
235
236
    overflow: auto;
237
238
}
239
240
241
/* MenuBar style rules */
242
243
.yuimenubar {
244
245
    background-color: #f6f7ee;
246
    
247
}
248
249
250
251
/* Menu style rules */
252
253
.yuimenu {
254
255
    background-color: #f6f7ee;
256
    border: solid 1px #c4c4be;
257
    padding: 1px;
258
    
259
}
260
261
.yui-menu-shadow {
262
263
    display: none;
264
265
}
266
267
.yuimenu ul {
268
269
    border: solid 1px #c4c4be;
270
    border-width: 1px 0 0 0;
271
    padding: 10px 0;
272
273
}
274
275
.yuimenu .yui-menu-body-scrolled {
276
277
    overflow: hidden;
278
279
}
280
281
282
/* Group titles */
283
284
.yuimenu h6,
285
.yuimenubar h6 { 
286
287
    font-size: 100%;
288
    font-weight: normal;
289
    border: solid 1px #c4c4be;
290
    color: #b9b9b9;    
291
292
}
293
294
.yuimenubar h6 {
295
296
    float: left;
297
    padding: 4px 12px;
298
    border-width: 0 1px 0 0;
299
300
}
301
302
.yuimenubar .yuimenu h6 {
303
304
    float: none;
305
306
}
307
308
.yuimenu h6 {
309
310
    border-width: 1px 0 0 0;
311
    padding: 5px 10px 0 10px;
312
313
}
314
315
.yuimenu ul.first-of-type, 
316
.yuimenu ul.hastitle,
317
.yuimenu h6.first-of-type {
318
319
    border-width: 0;
320
321
}
322
323
324
325
/* Top and bottom scroll controls */
326
327
.yuimenu .topscrollbar,
328
.yuimenu .bottomscrollbar {
329
330
    height: 16px;
331
    background-position: center center;
332
    background-repeat: no-repeat;
333
334
}
335
336
.yuimenu .topscrollbar {
337
338
    background-image: url(menu_up_arrow.png);
339
340
}
341
342
.yuimenu .topscrollbar_disabled {
343
344
    background-image: url(menu_up_arrow_disabled.png);
345
346
}
347
348
.yuimenu .bottomscrollbar {
349
350
    background-image: url(menu_down_arrow.png);
351
352
}
353
354
.yuimenu .bottomscrollbar_disabled {
355
356
    background-image: url(menu_down_arrow_disabled.png);
357
358
}
359
360
361
/* MenuItem and MenuBarItem styles */
362
363
.yuimenuitem {
364
365
    /*
366
        For IE: Used to collapse superfluous white space between <li> elements
367
        that is triggered by the "display" property of the <a> elements being
368
        set to "block."
369
    */
370
371
    *border-bottom: solid 1px #f6f7ee;
372
373
}
374
375
.yuimenuitemlabel,
376
.yuimenuitemlabel:visited,
377
.yuimenubaritemlabel,
378
.yuimenubaritemlabel:visited {
379
380
    font-size: 85%;
381
    color: #000;
382
    text-decoration: none;
383
384
}
385
386
.yuimenuitemlabel {
387
388
    padding: 2px 24px;
389
    
390
}
391
392
.yuimenubaritemlabel {
393
394
    border-width: 0 0 0 1px;
395
    border-style: solid;
396
    border-color: #c4c4be;
397
    padding: 4px 24px;
398
399
}
400
401
.yuimenubar li.first-of-type .yuimenubaritemlabel {
402
403
    border-width: 0;
404
405
}
406
407
.yuimenubaritem-hassubmenu {
408
409
    background: url(menubaritem_submenuindicator.png) right center no-repeat;
410
411
}
412
413
.yuimenuitem-hassubmenu {
414
415
    background: url(menuitem_submenuindicator.png) right center no-repeat;
416
417
}
418
419
.yuimenuitem-checked {
420
421
    background: url(menuitem_checkbox.png) left center no-repeat;
422
423
}
424
425
.yuimenuitemlabel .helptext {
426
427
    margin-top: -1.1em;
428
    *margin-top: -1.2em;  /* For IE*/
429
    
430
}
431
432
433
434
/* MenuItem states */
435
436
437
/* Selected MenuItem */
438
439
.yuimenubaritem-selected,
440
.yuimenuitem-selected {
441
442
    background-color: #8c8ad0;
443
444
}
445
446
.yuimenubaritemlabel-selected,
447
.yuimenubaritemlabel-selected:visited,
448
.yuimenuitemlabel-selected,
449
.yuimenuitemlabel-selected:visited {
450
451
    text-decoration: underline;
452
    color: #fff;
453
454
}
455
456
.yuimenubaritem-hassubmenu-selected {
457
458
    background-image: url(menubaritem_submenuindicator_selected.png);
459
460
}
461
462
.yuimenuitem-hassubmenu-selected {
463
464
    background-image: url(menuitem_submenuindicator_selected.png);
465
466
}
467
468
.yuimenuitem-checked-selected {
469
470
    background-image: url(menuitem_checkbox_selected.png);
471
472
}
473
474
475
/* Disabled MenuItem */
476
477
.yuimenubaritemlabel-disabled,
478
.yuimenubaritemlabel-disabled:visited,
479
.yuimenuitemlabel-disabled,
480
.yuimenuitemlabel-disabled:visited {
481
482
    cursor: default;
483
    color: #b9b9b9;
484
485
}
486
487
.yuimenubaritem-hassubmenu-disabled {
488
489
    background-image: url(menubaritem_submenuindicator_disabled.png);
490
491
}
492
493
.yuimenuitem-hassubmenu-disabled {
494
495
    background-image: url(menuitem_submenuindicator_disabled.png);
496
497
}
498
499
.yuimenuitem-checked-disabled {
500
501
    background-image: url(menuitem_checkbox_disabled.png);
502
503
}
(-)a/koha-tmpl/intranet-tmpl/lib/yui/menu/assets/skins/sam/menu-skin.css (-339 lines)
Lines 1-339 Link Here
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.8.0r4
6
*/
7
/* MenuBar style rules */
8
9
.yui-skin-sam .yuimenubar {
10
11
    font-size: 93%;  /* 12px */
12
    line-height: 2;  /* ~24px */
13
    *line-height: 1.9; /* For IE */
14
    border: solid 1px #808080;
15
    background: url(../../../../assets/skins/sam/sprite.png) repeat-x 0 0;
16
17
}
18
19
20
/* MenuBarItem style rules */
21
22
.yui-skin-sam .yuimenubarnav .yuimenubaritem {
23
24
    border-right: solid 1px #ccc;
25
26
}
27
28
.yui-skin-sam .yuimenubaritemlabel {
29
30
    padding: 0 10px;
31
    color: #000;
32
    text-decoration: none;
33
    cursor: default;
34
    border-style: solid;
35
    border-color: #808080;
36
    border-width: 1px 0;
37
    *position: relative; /*  Necessary to get negative margins in IE. */
38
    margin: -1px 0;
39
40
}
41
42
.yui-skin-sam .yuimenubaritemlabel:visited {
43
44
	color: #000;
45
46
}
47
48
.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel {
49
50
    padding-right: 20px;
51
52
    /*
53
        Prevents the label from shifting left in IE when the 
54
        ".yui-skin-sam .yuimenubarnav .yuimenubaritemlabel-selected" 
55
        rule us applied.
56
    */
57
58
    *display: inline-block;
59
60
}
61
62
.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel-hassubmenu {
63
64
    background: url(menubaritem_submenuindicator.png) right center no-repeat;
65
66
}
67
68
69
70
/* MenuBarItem states */
71
72
/* Selected MenuBarItem */
73
74
.yui-skin-sam .yuimenubaritem-selected {
75
76
    background: url(../../../../assets/skins/sam/sprite.png) repeat-x 0 -1700px;
77
78
}
79
80
.yui-skin-sam .yuimenubaritemlabel-selected {
81
82
    border-color: #7D98B8;
83
84
}
85
86
.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel-selected {
87
88
    border-left-width: 1px;
89
    margin-left: -1px;
90
    *left: -1px;    /* For IE */
91
92
}
93
94
95
/* Disabled  MenuBarItem */
96
97
.yui-skin-sam .yuimenubaritemlabel-disabled,
98
.yui-skin-sam .yuimenubaritemlabel-disabled:visited {
99
100
    cursor: default;
101
    color: #A6A6A6;
102
103
}
104
105
.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel-hassubmenu-disabled {
106
107
    background-image: url(menubaritem_submenuindicator_disabled.png);
108
109
}
110
111
112
113
/* Menu style rules */
114
115
.yui-skin-sam .yuimenu {
116
117
    font-size: 93%;  /* 12px */
118
    line-height: 1.5;  /* 18px */
119
    *line-height: 1.45; /* For IE */
120
121
}
122
123
.yui-skin-sam .yuimenubar .yuimenu,
124
.yui-skin-sam .yuimenu .yuimenu {
125
126
    font-size: 100%;
127
128
}
129
130
.yui-skin-sam .yuimenu .bd {
131
132
	/*
133
		The following application of zoom:1 prevents first tier submenus of a MenuBar from hiding 
134
		when the mouse is moving from an item in a MenuBar to a submenu in IE 7.
135
	*/
136
137
	*zoom: 1;
138
	_zoom: normal;	/* Remove this rule for IE 6. */
139
    border: solid 1px #808080;
140
    background-color: #fff;
141
    
142
}
143
144
.yui-skin-sam .yuimenu .yuimenu .bd {
145
146
	*zoom: normal;
147
148
}
149
150
.yui-skin-sam .yuimenu ul {
151
152
    padding: 3px 0;
153
    border-width: 1px 0 0 0;
154
    border-color: #ccc;
155
    border-style: solid;
156
157
}
158
159
.yui-skin-sam .yuimenu ul.first-of-type {
160
161
    border-width: 0;
162
163
}
164
165
166
/* Group titles */
167
168
.yui-skin-sam .yuimenu h6 { 
169
170
    font-weight: bold;
171
    border-style: solid;
172
    border-color: #ccc;
173
    border-width: 1px 0 0 0;
174
    color: #a4a4a4;    
175
    padding: 3px 10px 0 10px;
176
177
}
178
179
.yui-skin-sam .yuimenu ul.hastitle,
180
.yui-skin-sam .yuimenu h6.first-of-type {
181
182
    border-width: 0;
183
184
}
185
186
187
/* Top and bottom scroll controls */
188
189
.yui-skin-sam .yuimenu .yui-menu-body-scrolled {
190
191
    border-color: #ccc #808080;
192
    overflow: hidden;
193
194
}
195
196
.yui-skin-sam .yuimenu .topscrollbar,
197
.yui-skin-sam .yuimenu .bottomscrollbar {
198
199
    height: 16px;
200
    border: solid 1px #808080;
201
    background: #fff url(../../../../assets/skins/sam/sprite.png) no-repeat 0 0;
202
203
}
204
205
.yui-skin-sam .yuimenu .topscrollbar {
206
207
    border-bottom-width: 0;
208
    background-position: center -950px;
209
210
}
211
212
.yui-skin-sam .yuimenu .topscrollbar_disabled {
213
214
    background-position: center -975px;
215
216
}
217
218
.yui-skin-sam .yuimenu .bottomscrollbar {
219
220
    border-top-width: 0;
221
    background-position: center -850px;
222
223
}
224
225
.yui-skin-sam .yuimenu .bottomscrollbar_disabled {
226
227
    background-position: center -875px;
228
229
}
230
231
232
/* MenuItem style rules */
233
234
.yui-skin-sam .yuimenuitem {
235
236
    /*
237
        For IE 7 Quirks and IE 6 Strict Mode and Quirks Mode:
238
        Used to collapse superfluous white space between <li> elements
239
        that is triggered by the "display" property of the <a> elements being
240
        set to "block."
241
    */
242
243
    _border-bottom: solid 1px #fff;
244
245
}
246
247
.yui-skin-sam .yuimenuitemlabel {
248
249
    padding: 0 20px;
250
    color: #000;
251
    text-decoration: none;
252
    cursor: default;
253
254
}
255
256
.yui-skin-sam .yuimenuitemlabel:visited {
257
258
    color: #000;
259
	
260
}
261
262
.yui-skin-sam .yuimenuitemlabel .helptext {
263
264
    margin-top: -1.5em;
265
    *margin-top: -1.45em;  /* For IE*/
266
    
267
}
268
269
.yui-skin-sam .yuimenuitem-hassubmenu {
270
271
    background-image: url(menuitem_submenuindicator.png);
272
    background-position: right center;
273
    background-repeat: no-repeat;
274
275
}
276
277
.yui-skin-sam .yuimenuitem-checked {
278
279
    background-image: url(menuitem_checkbox.png);
280
    background-position: left center;
281
    background-repeat: no-repeat;
282
283
}
284
285
286
/* Menu states */
287
288
289
/* Visible Menu */
290
291
.yui-skin-sam .yui-menu-shadow-visible {
292
293
    background-color: #000;
294
295
    /*
296
        Opacity can be expensive, so defer the use of opacity until the 
297
        menu is visible.
298
    */
299
300
    opacity: .12;
301
    filter: alpha(opacity=12);  /* For IE */
302
303
}
304
305
306
307
/* MenuItem states */
308
309
310
/* Selected MenuItem */
311
312
.yui-skin-sam .yuimenuitem-selected {
313
314
    background-color: #B3D4FF;
315
316
}
317
318
319
/* Disabled MenuItem */
320
321
.yui-skin-sam .yuimenuitemlabel-disabled,
322
.yui-skin-sam .yuimenuitemlabel-disabled:visited {
323
324
    cursor: default;
325
    color: #A6A6A6;
326
327
}
328
329
.yui-skin-sam .yuimenuitem-hassubmenu-disabled {
330
331
    background-image: url(menuitem_submenuindicator_disabled.png);
332
333
}
334
335
.yui-skin-sam .yuimenuitem-checked-disabled {
336
337
    background-image: url(menuitem_checkbox_disabled.png);
338
339
}
(-)a/koha-tmpl/intranet-tmpl/lib/yui/menu/assets/skins/sam/menu.css (-7 lines)
Lines 1-7 Link Here
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.8.0r4
6
*/
7
.yuimenu{top:-999em;left:-999em;}.yuimenubar{position:static;}.yuimenu .yuimenu,.yuimenubar .yuimenu{position:absolute;}.yuimenubar li,.yuimenu li{list-style-type:none;}.yuimenubar ul,.yuimenu ul,.yuimenubar li,.yuimenu li,.yuimenu h6,.yuimenubar h6{margin:0;padding:0;}.yuimenuitemlabel,.yuimenubaritemlabel{text-align:left;white-space:nowrap;}.yuimenubar ul{*zoom:1;}.yuimenubar .yuimenu ul{*zoom:normal;}.yuimenubar>.bd>ul:after{content:".";display:block;clear:both;visibility:hidden;height:0;line-height:0;}.yuimenubaritem{float:left;}.yuimenubaritemlabel,.yuimenuitemlabel{display:block;}.yuimenuitemlabel .helptext{font-style:normal;display:block;margin:-1em 0 0 10em;}.yui-menu-shadow{position:absolute;visibility:hidden;z-index:-1;}.yui-menu-shadow-visible{top:2px;right:-3px;left:-3px;bottom:-3px;visibility:visible;}.hide-scrollbars *{overflow:hidden;}.hide-scrollbars select{display:none;}.yuimenu.show-scrollbars,.yuimenubar.show-scrollbars{overflow:visible;}.yuimenu.hide-scrollbars .yui-menu-shadow,.yuimenubar.hide-scrollbars .yui-menu-shadow{overflow:hidden;}.yuimenu.show-scrollbars .yui-menu-shadow,.yuimenubar.show-scrollbars .yui-menu-shadow{overflow:auto;}.yui-overlay.yui-force-redraw{margin-bottom:1px;}.yui-skin-sam .yuimenubar{font-size:93%;line-height:2;*line-height:1.9;border:solid 1px #808080;background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 0;}.yui-skin-sam .yuimenubarnav .yuimenubaritem{border-right:solid 1px #ccc;}.yui-skin-sam .yuimenubaritemlabel{padding:0 10px;color:#000;text-decoration:none;cursor:default;border-style:solid;border-color:#808080;border-width:1px 0;*position:relative;margin:-1px 0;}.yui-skin-sam .yuimenubaritemlabel:visited{color:#000;}.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel{padding-right:20px;*display:inline-block;}.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel-hassubmenu{background:url(menubaritem_submenuindicator.png) right center no-repeat;}.yui-skin-sam .yuimenubaritem-selected{background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 -1700px;}.yui-skin-sam .yuimenubaritemlabel-selected{border-color:#7D98B8;}.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel-selected{border-left-width:1px;margin-left:-1px;*left:-1px;}.yui-skin-sam .yuimenubaritemlabel-disabled,.yui-skin-sam .yuimenubaritemlabel-disabled:visited{cursor:default;color:#A6A6A6;}.yui-skin-sam .yuimenubarnav .yuimenubaritemlabel-hassubmenu-disabled{background-image:url(menubaritem_submenuindicator_disabled.png);}.yui-skin-sam .yuimenu{font-size:93%;line-height:1.5;*line-height:1.45;}.yui-skin-sam .yuimenubar .yuimenu,.yui-skin-sam .yuimenu .yuimenu{font-size:100%;}.yui-skin-sam .yuimenu .bd{*zoom:1;_zoom:normal;border:solid 1px #808080;background-color:#fff;}.yui-skin-sam .yuimenu .yuimenu .bd{*zoom:normal;}.yui-skin-sam .yuimenu ul{padding:3px 0;border-width:1px 0 0 0;border-color:#ccc;border-style:solid;}.yui-skin-sam .yuimenu ul.first-of-type{border-width:0;}.yui-skin-sam .yuimenu h6{font-weight:bold;border-style:solid;border-color:#ccc;border-width:1px 0 0 0;color:#a4a4a4;padding:3px 10px 0 10px;}.yui-skin-sam .yuimenu ul.hastitle,.yui-skin-sam .yuimenu h6.first-of-type{border-width:0;}.yui-skin-sam .yuimenu .yui-menu-body-scrolled{border-color:#ccc #808080;overflow:hidden;}.yui-skin-sam .yuimenu .topscrollbar,.yui-skin-sam .yuimenu .bottomscrollbar{height:16px;border:solid 1px #808080;background:#fff url(../../../../assets/skins/sam/sprite.png) no-repeat 0 0;}.yui-skin-sam .yuimenu .topscrollbar{border-bottom-width:0;background-position:center -950px;}.yui-skin-sam .yuimenu .topscrollbar_disabled{background-position:center -975px;}.yui-skin-sam .yuimenu .bottomscrollbar{border-top-width:0;background-position:center -850px;}.yui-skin-sam .yuimenu .bottomscrollbar_disabled{background-position:center -875px;}.yui-skin-sam .yuimenuitem{_border-bottom:solid 1px #fff;}.yui-skin-sam .yuimenuitemlabel{padding:0 20px;color:#000;text-decoration:none;cursor:default;}.yui-skin-sam .yuimenuitemlabel:visited{color:#000;}.yui-skin-sam .yuimenuitemlabel .helptext{margin-top:-1.5em;*margin-top:-1.45em;}.yui-skin-sam .yuimenuitem-hassubmenu{background-image:url(menuitem_submenuindicator.png);background-position:right center;background-repeat:no-repeat;}.yui-skin-sam .yuimenuitem-checked{background-image:url(menuitem_checkbox.png);background-position:left center;background-repeat:no-repeat;}.yui-skin-sam .yui-menu-shadow-visible{background-color:#000;opacity:.12;filter:alpha(opacity=12);}.yui-skin-sam .yuimenuitem-selected{background-color:#B3D4FF;}.yui-skin-sam .yuimenuitemlabel-disabled,.yui-skin-sam .yuimenuitemlabel-disabled:visited{cursor:default;color:#A6A6A6;}.yui-skin-sam .yuimenuitem-hassubmenu-disabled{background-image:url(menuitem_submenuindicator_disabled.png);}.yui-skin-sam .yuimenuitem-checked-disabled{background-image:url(menuitem_checkbox_disabled.png);}
(-)a/koha-tmpl/intranet-tmpl/lib/yui/menu/menu-debug.js (-9870 lines)
Lines 1-9870 Link Here
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.8.0r4
6
*/
7
8
9
/**
10
* @module menu
11
* @description <p>The Menu family of components features a collection of 
12
* controls that make it easy to add menus to your website or web application.  
13
* With the Menu Controls you can create website fly-out menus, customized 
14
* context menus, or application-style menu bars with just a small amount of 
15
* scripting.</p><p>The Menu family of controls features:</p>
16
* <ul>
17
*    <li>Keyboard and mouse navigation.</li>
18
*    <li>A rich event model that provides access to all of a menu's 
19
*    interesting moments.</li>
20
*    <li>Support for 
21
*    <a href="http://en.wikipedia.org/wiki/Progressive_Enhancement">Progressive
22
*    Enhancement</a>; Menus can be created from simple, 
23
*    semantic markup on the page or purely through JavaScript.</li>
24
* </ul>
25
* @title Menu
26
* @namespace YAHOO.widget
27
* @requires Event, Dom, Container
28
*/
29
(function () {
30
31
    var UA = YAHOO.env.ua,
32
		Dom = YAHOO.util.Dom,
33
	    Event = YAHOO.util.Event,
34
	    Lang = YAHOO.lang,
35
36
		_DIV = "DIV",
37
    	_HD = "hd",
38
    	_BD = "bd",
39
    	_FT = "ft",
40
    	_LI = "LI",
41
    	_DISABLED = "disabled",
42
		_MOUSEOVER = "mouseover",
43
		_MOUSEOUT = "mouseout",
44
		_MOUSEDOWN = "mousedown",
45
		_MOUSEUP = "mouseup",
46
		_CLICK = "click",
47
		_KEYDOWN = "keydown",
48
		_KEYUP = "keyup",
49
		_KEYPRESS = "keypress",
50
		_CLICK_TO_HIDE = "clicktohide",
51
		_POSITION = "position", 
52
		_DYNAMIC = "dynamic",
53
		_SHOW_DELAY = "showdelay",
54
		_SELECTED = "selected",
55
		_VISIBLE = "visible",
56
		_UL = "UL",
57
		_MENUMANAGER = "MenuManager";
58
59
60
    /**
61
    * Singleton that manages a collection of all menus and menu items.  Listens 
62
    * for DOM events at the document level and dispatches the events to the 
63
    * corresponding menu or menu item.
64
    *
65
    * @namespace YAHOO.widget
66
    * @class MenuManager
67
    * @static
68
    */
69
    YAHOO.widget.MenuManager = function () {
70
    
71
        // Private member variables
72
    
73
    
74
        // Flag indicating if the DOM event handlers have been attached
75
    
76
        var m_bInitializedEventHandlers = false,
77
    
78
    
79
        // Collection of menus
80
81
        m_oMenus = {},
82
83
84
        // Collection of visible menus
85
    
86
        m_oVisibleMenus = {},
87
    
88
    
89
        //  Collection of menu items 
90
91
        m_oItems = {},
92
93
94
        // Map of DOM event types to their equivalent CustomEvent types
95
        
96
        m_oEventTypes = {
97
            "click": "clickEvent",
98
            "mousedown": "mouseDownEvent",
99
            "mouseup": "mouseUpEvent",
100
            "mouseover": "mouseOverEvent",
101
            "mouseout": "mouseOutEvent",
102
            "keydown": "keyDownEvent",
103
            "keyup": "keyUpEvent",
104
            "keypress": "keyPressEvent",
105
            "focus": "focusEvent",
106
            "focusin": "focusEvent",
107
            "blur": "blurEvent",
108
            "focusout": "blurEvent"
109
        },
110
    
111
    
112
        m_oFocusedMenuItem = null;
113
    
114
    
115
    
116
        // Private methods
117
    
118
    
119
        /**
120
        * @method getMenuRootElement
121
        * @description Finds the root DIV node of a menu or the root LI node of 
122
        * a menu item.
123
        * @private
124
        * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
125
        * level-one-html.html#ID-58190037">HTMLElement</a>} p_oElement Object 
126
        * specifying an HTML element.
127
        */
128
        function getMenuRootElement(p_oElement) {
129
        
130
            var oParentNode,
131
            	returnVal;
132
    
133
            if (p_oElement && p_oElement.tagName) {
134
            
135
                switch (p_oElement.tagName.toUpperCase()) {
136
                        
137
                case _DIV:
138
    
139
                    oParentNode = p_oElement.parentNode;
140
    
141
                    // Check if the DIV is the inner "body" node of a menu
142
143
                    if ((
144
                            Dom.hasClass(p_oElement, _HD) ||
145
                            Dom.hasClass(p_oElement, _BD) ||
146
                            Dom.hasClass(p_oElement, _FT)
147
                        ) && 
148
                        oParentNode && 
149
                        oParentNode.tagName && 
150
                        oParentNode.tagName.toUpperCase() == _DIV) {
151
                    
152
                        returnVal = oParentNode;
153
                    
154
                    }
155
                    else {
156
                    
157
                        returnVal = p_oElement;
158
                    
159
                    }
160
                
161
                    break;
162
163
                case _LI:
164
    
165
                    returnVal = p_oElement;
166
                    
167
                    break;
168
169
                default:
170
    
171
                    oParentNode = p_oElement.parentNode;
172
    
173
                    if (oParentNode) {
174
                    
175
                        returnVal = getMenuRootElement(oParentNode);
176
                    
177
                    }
178
                
179
                    break;
180
                
181
                }
182
    
183
            }
184
            
185
            return returnVal;
186
            
187
        }
188
    
189
    
190
    
191
        // Private event handlers
192
    
193
    
194
        /**
195
        * @method onDOMEvent
196
        * @description Generic, global event handler for all of a menu's 
197
        * DOM-based events.  This listens for events against the document 
198
        * object.  If the target of a given event is a member of a menu or 
199
        * menu item's DOM, the instance's corresponding Custom Event is fired.
200
        * @private
201
        * @param {Event} p_oEvent Object representing the DOM event object  
202
        * passed back by the event utility (YAHOO.util.Event).
203
        */
204
        function onDOMEvent(p_oEvent) {
205
    
206
            // Get the target node of the DOM event
207
        
208
            var oTarget = Event.getTarget(p_oEvent),
209
                
210
            // See if the target of the event was a menu, or a menu item
211
    
212
            oElement = getMenuRootElement(oTarget),
213
			bFireEvent = true,
214
			sEventType = p_oEvent.type,
215
            sCustomEventType,
216
            sTagName,
217
            sId,
218
            oMenuItem,
219
            oMenu; 
220
    
221
    
222
            if (oElement) {
223
    
224
                sTagName = oElement.tagName.toUpperCase();
225
        
226
                if (sTagName == _LI) {
227
            
228
                    sId = oElement.id;
229
            
230
                    if (sId && m_oItems[sId]) {
231
            
232
                        oMenuItem = m_oItems[sId];
233
                        oMenu = oMenuItem.parent;
234
            
235
                    }
236
                
237
                }
238
                else if (sTagName == _DIV) {
239
                
240
                    if (oElement.id) {
241
                    
242
                        oMenu = m_oMenus[oElement.id];
243
                    
244
                    }
245
                
246
                }
247
    
248
            }
249
    
250
    
251
            if (oMenu) {
252
    
253
                sCustomEventType = m_oEventTypes[sEventType];
254
255
				/*
256
					There is an inconsistency between Firefox for Mac OS X and 
257
					Firefox Windows & Linux regarding the triggering of the 
258
					display of the browser's context menu and the subsequent 
259
					firing of the "click" event. In Firefox for Windows & Linux, 
260
					when the user triggers the display of the browser's context 
261
					menu the "click" event also fires for the document object, 
262
					even though the "click" event did not fire for the element 
263
					that was the original target of the "contextmenu" event. 
264
					This is unique to Firefox on Windows & Linux.  For all 
265
					other A-Grade browsers, including Firefox for Mac OS X, the 
266
					"click" event doesn't fire for the document object. 
267
268
					This bug in Firefox for Windows affects Menu, as Menu 
269
					instances listen for events at the document level and 
270
					dispatches Custom Events of the same name.  Therefore users
271
					of Menu will get an unwanted firing of the "click" 
272
					custom event.  The following line fixes this bug.
273
				*/
274
				
275
276
277
				if (sEventType == "click" && 
278
					(UA.gecko && oMenu.platform != "mac") && 
279
					p_oEvent.button > 0) {
280
281
					bFireEvent = false;
282
283
				}
284
    
285
                // Fire the Custom Event that corresponds the current DOM event    
286
        
287
                if (bFireEvent && oMenuItem && !oMenuItem.cfg.getProperty(_DISABLED)) {
288
                    oMenuItem[sCustomEventType].fire(p_oEvent);                   
289
                }
290
        
291
				if (bFireEvent) {
292
                	oMenu[sCustomEventType].fire(p_oEvent, oMenuItem);
293
				}
294
            
295
            }
296
            else if (sEventType == _MOUSEDOWN) {
297
    
298
                /*
299
                    If the target of the event wasn't a menu, hide all 
300
                    dynamically positioned menus
301
                */
302
                
303
                for (var i in m_oVisibleMenus) {
304
        
305
                    if (Lang.hasOwnProperty(m_oVisibleMenus, i)) {
306
        
307
                        oMenu = m_oVisibleMenus[i];
308
309
                        if (oMenu.cfg.getProperty(_CLICK_TO_HIDE) && 
310
                            !(oMenu instanceof YAHOO.widget.MenuBar) && 
311
                            oMenu.cfg.getProperty(_POSITION) == _DYNAMIC) {
312
313
                            oMenu.hide();
314
315
							//	In IE when the user mouses down on a focusable 
316
							//	element that element will be focused and become 
317
							//	the "activeElement".
318
							//	(http://msdn.microsoft.com/en-us/library/ms533065(VS.85).aspx)
319
							//	However, there is a bug in IE where if there is 
320
							//	a positioned element with a focused descendant 
321
							//	that is hidden in response to the mousedown 
322
							//	event, the target of the mousedown event will 
323
							//	appear to have focus, but will not be set as 
324
							//	the activeElement.  This will result in the 
325
							//	element not firing key events, even though it
326
							//	appears to have focus.  The following call to 
327
							//	"setActive" fixes this bug.
328
329
							if (UA.ie && oTarget.focus) {
330
								oTarget.setActive();
331
							}
332
        
333
                        }
334
                        else {
335
                            
336
							if (oMenu.cfg.getProperty(_SHOW_DELAY) > 0) {
337
							
338
								oMenu._cancelShowDelay();
339
							
340
							}
341
342
343
							if (oMenu.activeItem) {
344
						
345
								oMenu.activeItem.blur();
346
								oMenu.activeItem.cfg.setProperty(_SELECTED, false);
347
						
348
								oMenu.activeItem = null;            
349
						
350
							}
351
        
352
                        }
353
        
354
                    }
355
        
356
                } 
357
    
358
            }
359
            
360
        }
361
    
362
    
363
        /**
364
        * @method onMenuDestroy
365
        * @description "destroy" event handler for a menu.
366
        * @private
367
        * @param {String} p_sType String representing the name of the event 
368
        * that was fired.
369
        * @param {Array} p_aArgs Array of arguments sent when the event 
370
        * was fired.
371
        * @param {YAHOO.widget.Menu} p_oMenu The menu that fired the event.
372
        */
373
        function onMenuDestroy(p_sType, p_aArgs, p_oMenu) {
374
    
375
            if (m_oMenus[p_oMenu.id]) {
376
    
377
                this.removeMenu(p_oMenu);
378
    
379
            }
380
    
381
        }
382
    
383
    
384
        /**
385
        * @method onMenuFocus
386
        * @description "focus" event handler for a MenuItem instance.
387
        * @private
388
        * @param {String} p_sType String representing the name of the event 
389
        * that was fired.
390
        * @param {Array} p_aArgs Array of arguments sent when the event 
391
        * was fired.
392
        */
393
        function onMenuFocus(p_sType, p_aArgs) {
394
    
395
            var oItem = p_aArgs[1];
396
    
397
            if (oItem) {
398
    
399
                m_oFocusedMenuItem = oItem;
400
            
401
            }
402
    
403
        }
404
    
405
    
406
        /**
407
        * @method onMenuBlur
408
        * @description "blur" event handler for a MenuItem instance.
409
        * @private
410
        * @param {String} p_sType String representing the name of the event  
411
        * that was fired.
412
        * @param {Array} p_aArgs Array of arguments sent when the event 
413
        * was fired.
414
        */
415
        function onMenuBlur(p_sType, p_aArgs) {
416
    
417
            m_oFocusedMenuItem = null;
418
    
419
        }
420
421
    
422
        /**
423
        * @method onMenuVisibleConfigChange
424
        * @description Event handler for when the "visible" configuration  
425
        * property of a Menu instance changes.
426
        * @private
427
        * @param {String} p_sType String representing the name of the event  
428
        * that was fired.
429
        * @param {Array} p_aArgs Array of arguments sent when the event 
430
        * was fired.
431
        */
432
        function onMenuVisibleConfigChange(p_sType, p_aArgs) {
433
    
434
            var bVisible = p_aArgs[0],
435
                sId = this.id;
436
            
437
            if (bVisible) {
438
    
439
                m_oVisibleMenus[sId] = this;
440
                
441
                YAHOO.log(this + " added to the collection of visible menus.", 
442
                	"info", _MENUMANAGER);
443
            
444
            }
445
            else if (m_oVisibleMenus[sId]) {
446
            
447
                delete m_oVisibleMenus[sId];
448
                
449
                YAHOO.log(this + " removed from the collection of visible menus.", 
450
                	"info", _MENUMANAGER);
451
            
452
            }
453
        
454
        }
455
    
456
    
457
        /**
458
        * @method onItemDestroy
459
        * @description "destroy" event handler for a MenuItem instance.
460
        * @private
461
        * @param {String} p_sType String representing the name of the event  
462
        * that was fired.
463
        * @param {Array} p_aArgs Array of arguments sent when the event 
464
        * was fired.
465
        */
466
        function onItemDestroy(p_sType, p_aArgs) {
467
    
468
            removeItem(this);
469
    
470
        }
471
472
473
        /**
474
        * @method removeItem
475
        * @description Removes a MenuItem instance from the MenuManager's collection of MenuItems.
476
        * @private
477
        * @param {MenuItem} p_oMenuItem The MenuItem instance to be removed.
478
        */    
479
        function removeItem(p_oMenuItem) {
480
481
            var sId = p_oMenuItem.id;
482
    
483
            if (sId && m_oItems[sId]) {
484
    
485
                if (m_oFocusedMenuItem == p_oMenuItem) {
486
    
487
                    m_oFocusedMenuItem = null;
488
    
489
                }
490
    
491
                delete m_oItems[sId];
492
                
493
                p_oMenuItem.destroyEvent.unsubscribe(onItemDestroy);
494
    
495
                YAHOO.log(p_oMenuItem + " successfully unregistered.", "info", _MENUMANAGER);
496
    
497
            }
498
499
        }
500
    
501
    
502
        /**
503
        * @method onItemAdded
504
        * @description "itemadded" event handler for a Menu instance.
505
        * @private
506
        * @param {String} p_sType String representing the name of the event  
507
        * that was fired.
508
        * @param {Array} p_aArgs Array of arguments sent when the event 
509
        * was fired.
510
        */
511
        function onItemAdded(p_sType, p_aArgs) {
512
    
513
            var oItem = p_aArgs[0],
514
                sId;
515
    
516
            if (oItem instanceof YAHOO.widget.MenuItem) { 
517
    
518
                sId = oItem.id;
519
        
520
                if (!m_oItems[sId]) {
521
            
522
                    m_oItems[sId] = oItem;
523
        
524
                    oItem.destroyEvent.subscribe(onItemDestroy);
525
        
526
                    YAHOO.log(oItem + " successfully registered.", "info", _MENUMANAGER);
527
        
528
                }
529
    
530
            }
531
        
532
        }
533
    
534
    
535
        return {
536
    
537
            // Privileged methods
538
    
539
    
540
            /**
541
            * @method addMenu
542
            * @description Adds a menu to the collection of known menus.
543
            * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu  
544
            * instance to be added.
545
            */
546
            addMenu: function (p_oMenu) {
547
    
548
                var oDoc;
549
    
550
                if (p_oMenu instanceof YAHOO.widget.Menu && p_oMenu.id && 
551
                    !m_oMenus[p_oMenu.id]) {
552
        
553
                    m_oMenus[p_oMenu.id] = p_oMenu;
554
                
555
            
556
                    if (!m_bInitializedEventHandlers) {
557
            
558
                        oDoc = document;
559
                
560
                        Event.on(oDoc, _MOUSEOVER, onDOMEvent, this, true);
561
                        Event.on(oDoc, _MOUSEOUT, onDOMEvent, this, true);
562
                        Event.on(oDoc, _MOUSEDOWN, onDOMEvent, this, true);
563
                        Event.on(oDoc, _MOUSEUP, onDOMEvent, this, true);
564
                        Event.on(oDoc, _CLICK, onDOMEvent, this, true);
565
                        Event.on(oDoc, _KEYDOWN, onDOMEvent, this, true);
566
                        Event.on(oDoc, _KEYUP, onDOMEvent, this, true);
567
                        Event.on(oDoc, _KEYPRESS, onDOMEvent, this, true);
568
    
569
						Event.onFocus(oDoc, onDOMEvent, this, true);
570
						Event.onBlur(oDoc, onDOMEvent, this, true);						
571
    
572
                        m_bInitializedEventHandlers = true;
573
                        
574
                        YAHOO.log("DOM event handlers initialized.", "info", _MENUMANAGER);
575
            
576
                    }
577
            
578
                    p_oMenu.cfg.subscribeToConfigEvent(_VISIBLE, onMenuVisibleConfigChange);
579
                    p_oMenu.destroyEvent.subscribe(onMenuDestroy, p_oMenu, this);
580
                    p_oMenu.itemAddedEvent.subscribe(onItemAdded);
581
                    p_oMenu.focusEvent.subscribe(onMenuFocus);
582
                    p_oMenu.blurEvent.subscribe(onMenuBlur);
583
        
584
                    YAHOO.log(p_oMenu + " successfully registered.", "info", _MENUMANAGER);
585
        
586
                }
587
        
588
            },
589
    
590
        
591
            /**
592
            * @method removeMenu
593
            * @description Removes a menu from the collection of known menus.
594
            * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu  
595
            * instance to be removed.
596
            */
597
            removeMenu: function (p_oMenu) {
598
    
599
                var sId,
600
                    aItems,
601
                    i;
602
        
603
                if (p_oMenu) {
604
    
605
                    sId = p_oMenu.id;
606
        
607
                    if ((sId in m_oMenus) && (m_oMenus[sId] == p_oMenu)) {
608
609
                        // Unregister each menu item
610
611
                        aItems = p_oMenu.getItems();
612
613
                        if (aItems && aItems.length > 0) {
614
615
                            i = aItems.length - 1;
616
617
                            do {
618
619
                                removeItem(aItems[i]);
620
621
                            }
622
                            while (i--);
623
624
                        }
625
626
627
                        // Unregister the menu
628
629
                        delete m_oMenus[sId];
630
            
631
                        YAHOO.log(p_oMenu + " successfully unregistered.", "info", _MENUMANAGER);
632
        
633
634
                        /*
635
                             Unregister the menu from the collection of 
636
                             visible menus
637
                        */
638
639
                        if ((sId in m_oVisibleMenus) && (m_oVisibleMenus[sId] == p_oMenu)) {
640
            
641
                            delete m_oVisibleMenus[sId];
642
                            
643
                            YAHOO.log(p_oMenu + " unregistered from the" + 
644
                                        " collection of visible menus.", "info", _MENUMANAGER);
645
       
646
                        }
647
648
649
                        // Unsubscribe event listeners
650
651
                        if (p_oMenu.cfg) {
652
653
                            p_oMenu.cfg.unsubscribeFromConfigEvent(_VISIBLE, 
654
                                onMenuVisibleConfigChange);
655
                            
656
                        }
657
658
                        p_oMenu.destroyEvent.unsubscribe(onMenuDestroy, 
659
                            p_oMenu);
660
                
661
                        p_oMenu.itemAddedEvent.unsubscribe(onItemAdded);
662
                        p_oMenu.focusEvent.unsubscribe(onMenuFocus);
663
                        p_oMenu.blurEvent.unsubscribe(onMenuBlur);
664
665
                    }
666
                
667
                }
668
    
669
            },
670
        
671
        
672
            /**
673
            * @method hideVisible
674
            * @description Hides all visible, dynamically positioned menus 
675
            * (excluding instances of YAHOO.widget.MenuBar).
676
            */
677
            hideVisible: function () {
678
        
679
                var oMenu;
680
        
681
                for (var i in m_oVisibleMenus) {
682
        
683
                    if (Lang.hasOwnProperty(m_oVisibleMenus, i)) {
684
        
685
                        oMenu = m_oVisibleMenus[i];
686
        
687
                        if (!(oMenu instanceof YAHOO.widget.MenuBar) && 
688
                            oMenu.cfg.getProperty(_POSITION) == _DYNAMIC) {
689
        
690
                            oMenu.hide();
691
        
692
                        }
693
        
694
                    }
695
        
696
                }        
697
    
698
            },
699
700
701
            /**
702
            * @method getVisible
703
            * @description Returns a collection of all visible menus registered
704
            * with the menu manger.
705
            * @return {Object}
706
            */
707
            getVisible: function () {
708
            
709
                return m_oVisibleMenus;
710
            
711
            },
712
713
    
714
            /**
715
            * @method getMenus
716
            * @description Returns a collection of all menus registered with the 
717
            * menu manger.
718
            * @return {Object}
719
            */
720
            getMenus: function () {
721
    
722
                return m_oMenus;
723
            
724
            },
725
    
726
    
727
            /**
728
            * @method getMenu
729
            * @description Returns a menu with the specified id.
730
            * @param {String} p_sId String specifying the id of the 
731
            * <code>&#60;div&#62;</code> element representing the menu to
732
            * be retrieved.
733
            * @return {YAHOO.widget.Menu}
734
            */
735
            getMenu: function (p_sId) {
736
                
737
                var returnVal;
738
                
739
                if (p_sId in m_oMenus) {
740
                
741
					returnVal = m_oMenus[p_sId];
742
				
743
				}
744
            
745
            	return returnVal;
746
            
747
            },
748
    
749
    
750
            /**
751
            * @method getMenuItem
752
            * @description Returns a menu item with the specified id.
753
            * @param {String} p_sId String specifying the id of the 
754
            * <code>&#60;li&#62;</code> element representing the menu item to
755
            * be retrieved.
756
            * @return {YAHOO.widget.MenuItem}
757
            */
758
            getMenuItem: function (p_sId) {
759
    
760
    			var returnVal;
761
    
762
    			if (p_sId in m_oItems) {
763
    
764
					returnVal = m_oItems[p_sId];
765
				
766
				}
767
				
768
				return returnVal;
769
            
770
            },
771
772
773
            /**
774
            * @method getMenuItemGroup
775
            * @description Returns an array of menu item instances whose 
776
            * corresponding <code>&#60;li&#62;</code> elements are child 
777
            * nodes of the <code>&#60;ul&#62;</code> element with the 
778
            * specified id.
779
            * @param {String} p_sId String specifying the id of the 
780
            * <code>&#60;ul&#62;</code> element representing the group of 
781
            * menu items to be retrieved.
782
            * @return {Array}
783
            */
784
            getMenuItemGroup: function (p_sId) {
785
786
                var oUL = Dom.get(p_sId),
787
                    aItems,
788
                    oNode,
789
                    oItem,
790
                    sId,
791
                    returnVal;
792
    
793
794
                if (oUL && oUL.tagName && oUL.tagName.toUpperCase() == _UL) {
795
796
                    oNode = oUL.firstChild;
797
798
                    if (oNode) {
799
800
                        aItems = [];
801
                        
802
                        do {
803
804
                            sId = oNode.id;
805
806
                            if (sId) {
807
                            
808
                                oItem = this.getMenuItem(sId);
809
                                
810
                                if (oItem) {
811
                                
812
                                    aItems[aItems.length] = oItem;
813
                                
814
                                }
815
                            
816
                            }
817
                        
818
                        }
819
                        while ((oNode = oNode.nextSibling));
820
821
822
                        if (aItems.length > 0) {
823
824
                            returnVal = aItems;
825
                        
826
                        }
827
828
                    }
829
                
830
                }
831
832
				return returnVal;
833
            
834
            },
835
836
    
837
            /**
838
            * @method getFocusedMenuItem
839
            * @description Returns a reference to the menu item that currently 
840
            * has focus.
841
            * @return {YAHOO.widget.MenuItem}
842
            */
843
            getFocusedMenuItem: function () {
844
    
845
                return m_oFocusedMenuItem;
846
    
847
            },
848
    
849
    
850
            /**
851
            * @method getFocusedMenu
852
            * @description Returns a reference to the menu that currently 
853
            * has focus.
854
            * @return {YAHOO.widget.Menu}
855
            */
856
            getFocusedMenu: function () {
857
858
				var returnVal;
859
    
860
                if (m_oFocusedMenuItem) {
861
    
862
                    returnVal = m_oFocusedMenuItem.parent.getRoot();
863
                
864
                }
865
    
866
    			return returnVal;
867
    
868
            },
869
    
870
        
871
            /**
872
            * @method toString
873
            * @description Returns a string representing the menu manager.
874
            * @return {String}
875
            */
876
            toString: function () {
877
            
878
                return _MENUMANAGER;
879
            
880
            }
881
    
882
        };
883
    
884
    }();
885
886
})();
887
888
889
890
(function () {
891
892
	var Lang = YAHOO.lang,
893
894
	// String constants
895
	
896
		_MENU = "Menu",
897
		_DIV_UPPERCASE = "DIV",
898
		_DIV_LOWERCASE = "div",
899
		_ID = "id",
900
		_SELECT = "SELECT",
901
		_XY = "xy",
902
		_Y = "y",
903
		_UL_UPPERCASE = "UL",
904
		_UL_LOWERCASE = "ul",
905
		_FIRST_OF_TYPE = "first-of-type",
906
		_LI = "LI",
907
		_OPTGROUP = "OPTGROUP",
908
		_OPTION = "OPTION",
909
		_DISABLED = "disabled",
910
		_NONE = "none",
911
		_SELECTED = "selected",
912
		_GROUP_INDEX = "groupindex",
913
		_INDEX = "index",
914
		_SUBMENU = "submenu",
915
		_VISIBLE = "visible",
916
		_HIDE_DELAY = "hidedelay",
917
		_POSITION = "position",
918
		_DYNAMIC = "dynamic",
919
		_STATIC = "static",
920
		_DYNAMIC_STATIC = _DYNAMIC + "," + _STATIC,
921
		_URL = "url",
922
		_HASH = "#",
923
		_TARGET = "target",
924
		_MAX_HEIGHT = "maxheight",
925
        _TOP_SCROLLBAR = "topscrollbar",
926
        _BOTTOM_SCROLLBAR = "bottomscrollbar",
927
        _UNDERSCORE = "_",
928
		_TOP_SCROLLBAR_DISABLED = _TOP_SCROLLBAR + _UNDERSCORE + _DISABLED,
929
		_BOTTOM_SCROLLBAR_DISABLED = _BOTTOM_SCROLLBAR + _UNDERSCORE + _DISABLED,
930
		_MOUSEMOVE = "mousemove",
931
		_SHOW_DELAY = "showdelay",
932
		_SUBMENU_HIDE_DELAY = "submenuhidedelay",
933
		_IFRAME = "iframe",
934
		_CONSTRAIN_TO_VIEWPORT = "constraintoviewport",
935
		_PREVENT_CONTEXT_OVERLAP = "preventcontextoverlap",
936
		_SUBMENU_ALIGNMENT = "submenualignment",
937
		_AUTO_SUBMENU_DISPLAY = "autosubmenudisplay",
938
		_CLICK_TO_HIDE = "clicktohide",
939
		_CONTAINER = "container",
940
		_SCROLL_INCREMENT = "scrollincrement",
941
		_MIN_SCROLL_HEIGHT = "minscrollheight",
942
		_CLASSNAME = "classname",
943
		_SHADOW = "shadow",
944
		_KEEP_OPEN = "keepopen",
945
		_HD = "hd",
946
		_HAS_TITLE = "hastitle",
947
		_CONTEXT = "context",
948
		_EMPTY_STRING = "",
949
		_MOUSEDOWN = "mousedown",
950
		_KEYDOWN = "keydown",
951
		_HEIGHT = "height",
952
		_WIDTH = "width",
953
		_PX = "px",
954
		_EFFECT = "effect",
955
		_MONITOR_RESIZE = "monitorresize",
956
		_DISPLAY = "display",
957
		_BLOCK = "block",
958
		_VISIBILITY = "visibility",
959
		_ABSOLUTE = "absolute",
960
		_ZINDEX = "zindex",
961
		_YUI_MENU_BODY_SCROLLED = "yui-menu-body-scrolled",
962
		_NON_BREAKING_SPACE = "&#32;",
963
		_SPACE = " ",
964
		_MOUSEOVER = "mouseover",
965
		_MOUSEOUT = "mouseout",
966
        _ITEM_ADDED = "itemAdded",
967
        _ITEM_REMOVED = "itemRemoved",
968
        _HIDDEN = "hidden",
969
        _YUI_MENU_SHADOW = "yui-menu-shadow",
970
        _YUI_MENU_SHADOW_VISIBLE = _YUI_MENU_SHADOW + "-visible",
971
        _YUI_MENU_SHADOW_YUI_MENU_SHADOW_VISIBLE = _YUI_MENU_SHADOW + _SPACE + _YUI_MENU_SHADOW_VISIBLE;
972
973
974
/**
975
* The Menu class creates a container that holds a vertical list representing 
976
* a set of options or commands.  Menu is the base class for all 
977
* menu containers. 
978
* @param {String} p_oElement String specifying the id attribute of the 
979
* <code>&#60;div&#62;</code> element of the menu.
980
* @param {String} p_oElement String specifying the id attribute of the 
981
* <code>&#60;select&#62;</code> element to be used as the data source 
982
* for the menu.
983
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
984
* level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object 
985
* specifying the <code>&#60;div&#62;</code> element of the menu.
986
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
987
* level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement 
988
* Object specifying the <code>&#60;select&#62;</code> element to be used as 
989
* the data source for the menu.
990
* @param {Object} p_oConfig Optional. Object literal specifying the 
991
* configuration for the menu. See configuration class documentation for 
992
* more details.
993
* @namespace YAHOO.widget
994
* @class Menu
995
* @constructor
996
* @extends YAHOO.widget.Overlay
997
*/
998
YAHOO.widget.Menu = function (p_oElement, p_oConfig) {
999
1000
    if (p_oConfig) {
1001
1002
        this.parent = p_oConfig.parent;
1003
        this.lazyLoad = p_oConfig.lazyLoad || p_oConfig.lazyload;
1004
        this.itemData = p_oConfig.itemData || p_oConfig.itemdata;
1005
1006
    }
1007
1008
1009
    YAHOO.widget.Menu.superclass.constructor.call(this, p_oElement, p_oConfig);
1010
1011
};
1012
1013
1014
1015
/**
1016
* @method checkPosition
1017
* @description Checks to make sure that the value of the "position" property 
1018
* is one of the supported strings. Returns true if the position is supported.
1019
* @private
1020
* @param {Object} p_sPosition String specifying the position of the menu.
1021
* @return {Boolean}
1022
*/
1023
function checkPosition(p_sPosition) {
1024
1025
	var returnVal = false;
1026
1027
    if (Lang.isString(p_sPosition)) {
1028
1029
        returnVal = (_DYNAMIC_STATIC.indexOf((p_sPosition.toLowerCase())) != -1);
1030
1031
    }
1032
1033
	return returnVal;
1034
1035
}
1036
1037
1038
var Dom = YAHOO.util.Dom,
1039
    Event = YAHOO.util.Event,
1040
    Module = YAHOO.widget.Module,
1041
    Overlay = YAHOO.widget.Overlay,
1042
    Menu = YAHOO.widget.Menu,
1043
    MenuManager = YAHOO.widget.MenuManager,
1044
    CustomEvent = YAHOO.util.CustomEvent,
1045
    UA = YAHOO.env.ua,
1046
    
1047
    m_oShadowTemplate,
1048
1049
	bFocusListenerInitialized = false,
1050
1051
	oFocusedElement,
1052
1053
	EVENT_TYPES = [
1054
    
1055
		["mouseOverEvent", _MOUSEOVER],
1056
		["mouseOutEvent", _MOUSEOUT],
1057
		["mouseDownEvent", _MOUSEDOWN],
1058
		["mouseUpEvent", "mouseup"],
1059
		["clickEvent", "click"],
1060
		["keyPressEvent", "keypress"],
1061
		["keyDownEvent", _KEYDOWN],
1062
		["keyUpEvent", "keyup"],
1063
		["focusEvent", "focus"],
1064
		["blurEvent", "blur"],
1065
		["itemAddedEvent", _ITEM_ADDED],
1066
		["itemRemovedEvent", _ITEM_REMOVED]
1067
1068
	],
1069
1070
	VISIBLE_CONFIG =  { 
1071
		key: _VISIBLE, 
1072
		value: false, 
1073
		validator: Lang.isBoolean
1074
	}, 
1075
1076
	CONSTRAIN_TO_VIEWPORT_CONFIG =  {
1077
		key: _CONSTRAIN_TO_VIEWPORT, 
1078
		value: true, 
1079
		validator: Lang.isBoolean, 
1080
		supercedes: [_IFRAME,"x",_Y,_XY]
1081
	}, 
1082
1083
	PREVENT_CONTEXT_OVERLAP_CONFIG =  {
1084
		key: _PREVENT_CONTEXT_OVERLAP,
1085
		value: true,
1086
		validator: Lang.isBoolean,  
1087
		supercedes: [_CONSTRAIN_TO_VIEWPORT]
1088
	},
1089
1090
	POSITION_CONFIG =  { 
1091
		key: _POSITION, 
1092
		value: _DYNAMIC, 
1093
		validator: checkPosition, 
1094
		supercedes: [_VISIBLE, _IFRAME]
1095
	}, 
1096
1097
	SUBMENU_ALIGNMENT_CONFIG =  { 
1098
		key: _SUBMENU_ALIGNMENT, 
1099
		value: ["tl","tr"]
1100
	},
1101
1102
	AUTO_SUBMENU_DISPLAY_CONFIG =  { 
1103
		key: _AUTO_SUBMENU_DISPLAY, 
1104
		value: true, 
1105
		validator: Lang.isBoolean,
1106
		suppressEvent: true
1107
	}, 
1108
1109
	SHOW_DELAY_CONFIG =  { 
1110
		key: _SHOW_DELAY, 
1111
		value: 250, 
1112
		validator: Lang.isNumber, 
1113
		suppressEvent: true
1114
	}, 
1115
1116
	HIDE_DELAY_CONFIG =  { 
1117
		key: _HIDE_DELAY, 
1118
		value: 0, 
1119
		validator: Lang.isNumber, 
1120
		suppressEvent: true
1121
	}, 
1122
1123
	SUBMENU_HIDE_DELAY_CONFIG =  { 
1124
		key: _SUBMENU_HIDE_DELAY, 
1125
		value: 250, 
1126
		validator: Lang.isNumber,
1127
		suppressEvent: true
1128
	}, 
1129
1130
	CLICK_TO_HIDE_CONFIG =  { 
1131
		key: _CLICK_TO_HIDE, 
1132
		value: true, 
1133
		validator: Lang.isBoolean,
1134
		suppressEvent: true
1135
	},
1136
1137
	CONTAINER_CONFIG =  { 
1138
		key: _CONTAINER,
1139
		suppressEvent: true
1140
	}, 
1141
1142
	SCROLL_INCREMENT_CONFIG =  { 
1143
		key: _SCROLL_INCREMENT, 
1144
		value: 1, 
1145
		validator: Lang.isNumber,
1146
		supercedes: [_MAX_HEIGHT],
1147
		suppressEvent: true
1148
	},
1149
1150
	MIN_SCROLL_HEIGHT_CONFIG =  { 
1151
		key: _MIN_SCROLL_HEIGHT, 
1152
		value: 90, 
1153
		validator: Lang.isNumber,
1154
		supercedes: [_MAX_HEIGHT],
1155
		suppressEvent: true
1156
	},    
1157
1158
	MAX_HEIGHT_CONFIG =  { 
1159
		key: _MAX_HEIGHT, 
1160
		value: 0, 
1161
		validator: Lang.isNumber,
1162
		supercedes: [_IFRAME],
1163
		suppressEvent: true
1164
	}, 
1165
1166
	CLASS_NAME_CONFIG =  { 
1167
		key: _CLASSNAME, 
1168
		value: null, 
1169
		validator: Lang.isString,
1170
		suppressEvent: true
1171
	}, 
1172
1173
	DISABLED_CONFIG =  { 
1174
		key: _DISABLED, 
1175
		value: false, 
1176
		validator: Lang.isBoolean,
1177
		suppressEvent: true
1178
	},
1179
	
1180
	SHADOW_CONFIG =  { 
1181
		key: _SHADOW, 
1182
		value: true, 
1183
		validator: Lang.isBoolean,
1184
		suppressEvent: true,
1185
		supercedes: [_VISIBLE]
1186
	},
1187
	
1188
	KEEP_OPEN_CONFIG = {
1189
		key: _KEEP_OPEN, 
1190
		value: false, 
1191
		validator: Lang.isBoolean
1192
	};
1193
1194
1195
function onDocFocus(event) {
1196
1197
	oFocusedElement = Event.getTarget(event);
1198
1199
}
1200
1201
1202
1203
YAHOO.lang.extend(Menu, Overlay, {
1204
1205
1206
// Constants
1207
1208
1209
/**
1210
* @property CSS_CLASS_NAME
1211
* @description String representing the CSS class(es) to be applied to the 
1212
* menu's <code>&#60;div&#62;</code> element.
1213
* @default "yuimenu"
1214
* @final
1215
* @type String
1216
*/
1217
CSS_CLASS_NAME: "yuimenu",
1218
1219
1220
/**
1221
* @property ITEM_TYPE
1222
* @description Object representing the type of menu item to instantiate and 
1223
* add when parsing the child nodes (either <code>&#60;li&#62;</code> element, 
1224
* <code>&#60;optgroup&#62;</code> element or <code>&#60;option&#62;</code>) 
1225
* of the menu's source HTML element.
1226
* @default YAHOO.widget.MenuItem
1227
* @final
1228
* @type YAHOO.widget.MenuItem
1229
*/
1230
ITEM_TYPE: null,
1231
1232
1233
/**
1234
* @property GROUP_TITLE_TAG_NAME
1235
* @description String representing the tagname of the HTML element used to 
1236
* title the menu's item groups.
1237
* @default H6
1238
* @final
1239
* @type String
1240
*/
1241
GROUP_TITLE_TAG_NAME: "h6",
1242
1243
1244
/**
1245
* @property OFF_SCREEN_POSITION
1246
* @description Array representing the default x and y position that a menu 
1247
* should have when it is positioned outside the viewport by the 
1248
* "poistionOffScreen" method.
1249
* @default "-999em"
1250
* @final
1251
* @type String
1252
*/
1253
OFF_SCREEN_POSITION: "-999em",
1254
1255
1256
// Private properties
1257
1258
1259
/** 
1260
* @property _useHideDelay
1261
* @description Boolean indicating if the "mouseover" and "mouseout" event 
1262
* handlers used for hiding the menu via a call to "YAHOO.lang.later" have 
1263
* already been assigned.
1264
* @default false
1265
* @private
1266
* @type Boolean
1267
*/
1268
_useHideDelay: false,
1269
1270
1271
/**
1272
* @property _bHandledMouseOverEvent
1273
* @description Boolean indicating the current state of the menu's 
1274
* "mouseover" event.
1275
* @default false
1276
* @private
1277
* @type Boolean
1278
*/
1279
_bHandledMouseOverEvent: false,
1280
1281
1282
/**
1283
* @property _bHandledMouseOutEvent
1284
* @description Boolean indicating the current state of the menu's
1285
* "mouseout" event.
1286
* @default false
1287
* @private
1288
* @type Boolean
1289
*/
1290
_bHandledMouseOutEvent: false,
1291
1292
1293
/**
1294
* @property _aGroupTitleElements
1295
* @description Array of HTML element used to title groups of menu items.
1296
* @default []
1297
* @private
1298
* @type Array
1299
*/
1300
_aGroupTitleElements: null,
1301
1302
1303
/**
1304
* @property _aItemGroups
1305
* @description Multi-dimensional Array representing the menu items as they
1306
* are grouped in the menu.
1307
* @default []
1308
* @private
1309
* @type Array
1310
*/
1311
_aItemGroups: null,
1312
1313
1314
/**
1315
* @property _aListElements
1316
* @description Array of <code>&#60;ul&#62;</code> elements, each of which is 
1317
* the parent node for each item's <code>&#60;li&#62;</code> element.
1318
* @default []
1319
* @private
1320
* @type Array
1321
*/
1322
_aListElements: null,
1323
1324
1325
/**
1326
* @property _nCurrentMouseX
1327
* @description The current x coordinate of the mouse inside the area of 
1328
* the menu.
1329
* @default 0
1330
* @private
1331
* @type Number
1332
*/
1333
_nCurrentMouseX: 0,
1334
1335
1336
/**
1337
* @property _bStopMouseEventHandlers
1338
* @description Stops "mouseover," "mouseout," and "mousemove" event handlers 
1339
* from executing.
1340
* @default false
1341
* @private
1342
* @type Boolean
1343
*/
1344
_bStopMouseEventHandlers: false,
1345
1346
1347
/**
1348
* @property _sClassName
1349
* @description The current value of the "classname" configuration attribute.
1350
* @default null
1351
* @private
1352
* @type String
1353
*/
1354
_sClassName: null,
1355
1356
1357
1358
// Public properties
1359
1360
1361
/**
1362
* @property lazyLoad
1363
* @description Boolean indicating if the menu's "lazy load" feature is 
1364
* enabled.  If set to "true," initialization and rendering of the menu's 
1365
* items will be deferred until the first time it is made visible.  This 
1366
* property should be set via the constructor using the configuration 
1367
* object literal.
1368
* @default false
1369
* @type Boolean
1370
*/
1371
lazyLoad: false,
1372
1373
1374
/**
1375
* @property itemData
1376
* @description Array of items to be added to the menu.  The array can contain 
1377
* strings representing the text for each item to be created, object literals 
1378
* representing the menu item configuration properties, or MenuItem instances.  
1379
* This property should be set via the constructor using the configuration 
1380
* object literal.
1381
* @default null
1382
* @type Array
1383
*/
1384
itemData: null,
1385
1386
1387
/**
1388
* @property activeItem
1389
* @description Object reference to the item in the menu that has is selected.
1390
* @default null
1391
* @type YAHOO.widget.MenuItem
1392
*/
1393
activeItem: null,
1394
1395
1396
/**
1397
* @property parent
1398
* @description Object reference to the menu's parent menu or menu item.  
1399
* This property can be set via the constructor using the configuration 
1400
* object literal.
1401
* @default null
1402
* @type YAHOO.widget.MenuItem
1403
*/
1404
parent: null,
1405
1406
1407
/**
1408
* @property srcElement
1409
* @description Object reference to the HTML element (either 
1410
* <code>&#60;select&#62;</code> or <code>&#60;div&#62;</code>) used to 
1411
* create the menu.
1412
* @default null
1413
* @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1414
* level-one-html.html#ID-94282980">HTMLSelectElement</a>|<a 
1415
* href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.
1416
* html#ID-22445964">HTMLDivElement</a>
1417
*/
1418
srcElement: null,
1419
1420
1421
1422
// Events
1423
1424
1425
/**
1426
* @event mouseOverEvent
1427
* @description Fires when the mouse has entered the menu.  Passes back 
1428
* the DOM Event object as an argument.
1429
*/
1430
1431
1432
/**
1433
* @event mouseOutEvent
1434
* @description Fires when the mouse has left the menu.  Passes back the DOM 
1435
* Event object as an argument.
1436
* @type YAHOO.util.CustomEvent
1437
*/
1438
1439
1440
/**
1441
* @event mouseDownEvent
1442
* @description Fires when the user mouses down on the menu.  Passes back the 
1443
* DOM Event object as an argument.
1444
* @type YAHOO.util.CustomEvent
1445
*/
1446
1447
1448
/**
1449
* @event mouseUpEvent
1450
* @description Fires when the user releases a mouse button while the mouse is 
1451
* over the menu.  Passes back the DOM Event object as an argument.
1452
* @type YAHOO.util.CustomEvent
1453
*/
1454
1455
1456
/**
1457
* @event clickEvent
1458
* @description Fires when the user clicks the on the menu.  Passes back the 
1459
* DOM Event object as an argument.
1460
* @type YAHOO.util.CustomEvent
1461
*/
1462
1463
1464
/**
1465
* @event keyPressEvent
1466
* @description Fires when the user presses an alphanumeric key when one of the
1467
* menu's items has focus.  Passes back the DOM Event object as an argument.
1468
* @type YAHOO.util.CustomEvent
1469
*/
1470
1471
1472
/**
1473
* @event keyDownEvent
1474
* @description Fires when the user presses a key when one of the menu's items 
1475
* has focus.  Passes back the DOM Event object as an argument.
1476
* @type YAHOO.util.CustomEvent
1477
*/
1478
1479
1480
/**
1481
* @event keyUpEvent
1482
* @description Fires when the user releases a key when one of the menu's items 
1483
* has focus.  Passes back the DOM Event object as an argument.
1484
* @type YAHOO.util.CustomEvent
1485
*/
1486
1487
1488
/**
1489
* @event itemAddedEvent
1490
* @description Fires when an item is added to the menu.
1491
* @type YAHOO.util.CustomEvent
1492
*/
1493
1494
1495
/**
1496
* @event itemRemovedEvent
1497
* @description Fires when an item is removed to the menu.
1498
* @type YAHOO.util.CustomEvent
1499
*/
1500
1501
1502
/**
1503
* @method init
1504
* @description The Menu class's initialization method. This method is 
1505
* automatically called by the constructor, and sets up all DOM references 
1506
* for pre-existing markup, and creates required markup if it is not 
1507
* already present.
1508
* @param {String} p_oElement String specifying the id attribute of the 
1509
* <code>&#60;div&#62;</code> element of the menu.
1510
* @param {String} p_oElement String specifying the id attribute of the 
1511
* <code>&#60;select&#62;</code> element to be used as the data source 
1512
* for the menu.
1513
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1514
* level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object 
1515
* specifying the <code>&#60;div&#62;</code> element of the menu.
1516
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1517
* level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement 
1518
* Object specifying the <code>&#60;select&#62;</code> element to be used as 
1519
* the data source for the menu.
1520
* @param {Object} p_oConfig Optional. Object literal specifying the 
1521
* configuration for the menu. See configuration class documentation for 
1522
* more details.
1523
*/
1524
init: function (p_oElement, p_oConfig) {
1525
1526
    this._aItemGroups = [];
1527
    this._aListElements = [];
1528
    this._aGroupTitleElements = [];
1529
1530
    if (!this.ITEM_TYPE) {
1531
1532
        this.ITEM_TYPE = YAHOO.widget.MenuItem;
1533
1534
    }
1535
1536
1537
    var oElement;
1538
1539
    if (Lang.isString(p_oElement)) {
1540
1541
        oElement = Dom.get(p_oElement);
1542
1543
    }
1544
    else if (p_oElement.tagName) {
1545
1546
        oElement = p_oElement;
1547
1548
    }
1549
1550
1551
    if (oElement && oElement.tagName) {
1552
1553
        switch(oElement.tagName.toUpperCase()) {
1554
    
1555
            case _DIV_UPPERCASE:
1556
1557
                this.srcElement = oElement;
1558
1559
                if (!oElement.id) {
1560
1561
                    oElement.setAttribute(_ID, Dom.generateId());
1562
1563
                }
1564
1565
1566
                /* 
1567
                    Note: we don't pass the user config in here yet 
1568
                    because we only want it executed once, at the lowest 
1569
                    subclass level.
1570
                */ 
1571
            
1572
                Menu.superclass.init.call(this, oElement);
1573
1574
                this.beforeInitEvent.fire(Menu);
1575
1576
                YAHOO.log("Source element: " + this.srcElement.tagName, "info", this.toString());
1577
    
1578
            break;
1579
    
1580
            case _SELECT:
1581
    
1582
                this.srcElement = oElement;
1583
1584
    
1585
                /*
1586
                    The source element is not something that we can use 
1587
                    outright, so we need to create a new Overlay
1588
1589
                    Note: we don't pass the user config in here yet 
1590
                    because we only want it executed once, at the lowest 
1591
                    subclass level.
1592
                */ 
1593
1594
                Menu.superclass.init.call(this, Dom.generateId());
1595
1596
                this.beforeInitEvent.fire(Menu);
1597
1598
				YAHOO.log("Source element: " + this.srcElement.tagName, "info", this.toString());
1599
1600
            break;
1601
1602
        }
1603
1604
    }
1605
    else {
1606
1607
        /* 
1608
            Note: we don't pass the user config in here yet 
1609
            because we only want it executed once, at the lowest 
1610
            subclass level.
1611
        */ 
1612
    
1613
        Menu.superclass.init.call(this, p_oElement);
1614
1615
        this.beforeInitEvent.fire(Menu);
1616
1617
		YAHOO.log("No source element found.  Created element with id: " + this.id, "info", this.toString());
1618
1619
    }
1620
1621
1622
    if (this.element) {
1623
1624
        Dom.addClass(this.element, this.CSS_CLASS_NAME);
1625
1626
1627
        // Subscribe to Custom Events
1628
1629
        this.initEvent.subscribe(this._onInit);
1630
        this.beforeRenderEvent.subscribe(this._onBeforeRender);
1631
        this.renderEvent.subscribe(this._onRender);
1632
        this.beforeShowEvent.subscribe(this._onBeforeShow);
1633
		this.hideEvent.subscribe(this._onHide);
1634
        this.showEvent.subscribe(this._onShow);
1635
		this.beforeHideEvent.subscribe(this._onBeforeHide);
1636
        this.mouseOverEvent.subscribe(this._onMouseOver);
1637
        this.mouseOutEvent.subscribe(this._onMouseOut);
1638
        this.clickEvent.subscribe(this._onClick);
1639
        this.keyDownEvent.subscribe(this._onKeyDown);
1640
        this.keyPressEvent.subscribe(this._onKeyPress);
1641
        this.blurEvent.subscribe(this._onBlur);
1642
1643
1644
		if (!bFocusListenerInitialized) {
1645
			Event.onFocus(document, onDocFocus);
1646
			bFocusListenerInitialized = true;
1647
		}
1648
1649
1650
		//	Fixes an issue in Firefox 2 and Webkit where Dom's "getX" and "getY" 
1651
		//	methods return values that don't take scrollTop into consideration 
1652
1653
        if ((UA.gecko && UA.gecko < 1.9) || UA.webkit) {
1654
1655
            this.cfg.subscribeToConfigEvent(_Y, this._onYChange);
1656
1657
        }
1658
1659
1660
        if (p_oConfig) {
1661
    
1662
            this.cfg.applyConfig(p_oConfig, true);
1663
    
1664
        }
1665
1666
1667
        // Register the Menu instance with the MenuManager
1668
1669
        MenuManager.addMenu(this);
1670
1671
1672
        this.initEvent.fire(Menu);
1673
1674
    }
1675
1676
},
1677
1678
1679
1680
// Private methods
1681
1682
1683
/**
1684
* @method _initSubTree
1685
* @description Iterates the childNodes of the source element to find nodes 
1686
* used to instantiate menu and menu items.
1687
* @private
1688
*/
1689
_initSubTree: function () {
1690
1691
    var oSrcElement = this.srcElement,
1692
        sSrcElementTagName,
1693
        nGroup,
1694
        sGroupTitleTagName,
1695
        oNode,
1696
        aListElements,
1697
        nListElements,
1698
        i;
1699
1700
1701
    if (oSrcElement) {
1702
    
1703
        sSrcElementTagName = 
1704
            (oSrcElement.tagName && oSrcElement.tagName.toUpperCase());
1705
1706
1707
        if (sSrcElementTagName == _DIV_UPPERCASE) {
1708
    
1709
            //  Populate the collection of item groups and item group titles
1710
    
1711
            oNode = this.body.firstChild;
1712
    
1713
1714
            if (oNode) {
1715
    
1716
                nGroup = 0;
1717
                sGroupTitleTagName = this.GROUP_TITLE_TAG_NAME.toUpperCase();
1718
        
1719
                do {
1720
        
1721
1722
                    if (oNode && oNode.tagName) {
1723
        
1724
                        switch (oNode.tagName.toUpperCase()) {
1725
        
1726
                            case sGroupTitleTagName:
1727
                            
1728
                                this._aGroupTitleElements[nGroup] = oNode;
1729
        
1730
                            break;
1731
        
1732
                            case _UL_UPPERCASE:
1733
        
1734
                                this._aListElements[nGroup] = oNode;
1735
                                this._aItemGroups[nGroup] = [];
1736
                                nGroup++;
1737
        
1738
                            break;
1739
        
1740
                        }
1741
                    
1742
                    }
1743
        
1744
                }
1745
                while ((oNode = oNode.nextSibling));
1746
        
1747
        
1748
                /*
1749
                    Apply the "first-of-type" class to the first UL to mimic 
1750
                    the ":first-of-type" CSS3 psuedo class.
1751
                */
1752
        
1753
                if (this._aListElements[0]) {
1754
        
1755
                    Dom.addClass(this._aListElements[0], _FIRST_OF_TYPE);
1756
        
1757
                }
1758
            
1759
            }
1760
    
1761
        }
1762
    
1763
    
1764
        oNode = null;
1765
    
1766
        YAHOO.log("Searching DOM for items to initialize.", "info", this.toString());
1767
    
1768
1769
        if (sSrcElementTagName) {
1770
    
1771
            switch (sSrcElementTagName) {
1772
        
1773
                case _DIV_UPPERCASE:
1774
1775
                    aListElements = this._aListElements;
1776
                    nListElements = aListElements.length;
1777
        
1778
                    if (nListElements > 0) {
1779
        
1780
        				YAHOO.log("Found " + nListElements + " item groups to initialize.", 
1781
        							"info", this.toString());
1782
        
1783
                        i = nListElements - 1;
1784
        
1785
                        do {
1786
        
1787
                            oNode = aListElements[i].firstChild;
1788
            
1789
                            if (oNode) {
1790
1791
                                YAHOO.log("Scanning " + 
1792
                                    aListElements[i].childNodes.length + 
1793
                                    " child nodes for items to initialize.", "info", this.toString());
1794
            
1795
                                do {
1796
                
1797
                                    if (oNode && oNode.tagName && 
1798
                                        oNode.tagName.toUpperCase() == _LI) {
1799
                
1800
                                        YAHOO.log("Initializing " + 
1801
                                            oNode.tagName + " node.", "info", this.toString());
1802
        
1803
                                        this.addItem(new this.ITEM_TYPE(oNode, 
1804
                                                    { parent: this }), i);
1805
            
1806
                                    }
1807
                        
1808
                                }
1809
                                while ((oNode = oNode.nextSibling));
1810
                            
1811
                            }
1812
                    
1813
                        }
1814
                        while (i--);
1815
        
1816
                    }
1817
        
1818
                break;
1819
        
1820
                case _SELECT:
1821
        
1822
                    YAHOO.log("Scanning " +  
1823
                        oSrcElement.childNodes.length + 
1824
                        " child nodes for items to initialize.", "info", this.toString());
1825
        
1826
                    oNode = oSrcElement.firstChild;
1827
        
1828
                    do {
1829
        
1830
                        if (oNode && oNode.tagName) {
1831
                        
1832
                            switch (oNode.tagName.toUpperCase()) {
1833
            
1834
                                case _OPTGROUP:
1835
                                case _OPTION:
1836
            
1837
                                    YAHOO.log("Initializing " +  
1838
                                        oNode.tagName + " node.", "info", this.toString());
1839
            
1840
                                    this.addItem(
1841
                                            new this.ITEM_TYPE(
1842
                                                    oNode, 
1843
                                                    { parent: this }
1844
                                                )
1845
                                            );
1846
            
1847
                                break;
1848
            
1849
                            }
1850
    
1851
                        }
1852
        
1853
                    }
1854
                    while ((oNode = oNode.nextSibling));
1855
        
1856
                break;
1857
        
1858
            }
1859
    
1860
        }    
1861
    
1862
    }
1863
1864
},
1865
1866
1867
/**
1868
* @method _getFirstEnabledItem
1869
* @description Returns the first enabled item in the menu.
1870
* @return {YAHOO.widget.MenuItem}
1871
* @private
1872
*/
1873
_getFirstEnabledItem: function () {
1874
1875
    var aItems = this.getItems(),
1876
        nItems = aItems.length,
1877
        oItem,
1878
        returnVal;
1879
    
1880
1881
    for(var i=0; i<nItems; i++) {
1882
1883
        oItem = aItems[i];
1884
1885
        if (oItem && !oItem.cfg.getProperty(_DISABLED) && oItem.element.style.display != _NONE) {
1886
1887
            returnVal = oItem;
1888
            break;
1889
1890
        }
1891
    
1892
    }
1893
    
1894
    return returnVal;
1895
    
1896
},
1897
1898
1899
/**
1900
* @method _addItemToGroup
1901
* @description Adds a menu item to a group.
1902
* @private
1903
* @param {Number} p_nGroupIndex Number indicating the group to which the 
1904
* item belongs.
1905
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem 
1906
* instance to be added to the menu.
1907
* @param {String} p_oItem String specifying the text of the item to be added 
1908
* to the menu.
1909
* @param {Object} p_oItem Object literal containing a set of menu item 
1910
* configuration properties.
1911
* @param {Number} p_nItemIndex Optional. Number indicating the index at 
1912
* which the menu item should be added.
1913
* @return {YAHOO.widget.MenuItem}
1914
*/
1915
_addItemToGroup: function (p_nGroupIndex, p_oItem, p_nItemIndex) {
1916
1917
    var oItem,
1918
        nGroupIndex,
1919
        aGroup,
1920
        oGroupItem,
1921
        bAppend,
1922
        oNextItemSibling,
1923
        nItemIndex,
1924
        returnVal;
1925
1926
1927
    function getNextItemSibling(p_aArray, p_nStartIndex) {
1928
1929
        return (p_aArray[p_nStartIndex] || getNextItemSibling(p_aArray, (p_nStartIndex+1)));
1930
1931
    }
1932
1933
1934
    if (p_oItem instanceof this.ITEM_TYPE) {
1935
1936
        oItem = p_oItem;
1937
        oItem.parent = this;
1938
1939
    }
1940
    else if (Lang.isString(p_oItem)) {
1941
1942
        oItem = new this.ITEM_TYPE(p_oItem, { parent: this });
1943
    
1944
    }
1945
    else if (Lang.isObject(p_oItem)) {
1946
1947
        p_oItem.parent = this;
1948
1949
        oItem = new this.ITEM_TYPE(p_oItem.text, p_oItem);
1950
1951
    }
1952
1953
1954
    if (oItem) {
1955
1956
        if (oItem.cfg.getProperty(_SELECTED)) {
1957
1958
            this.activeItem = oItem;
1959
        
1960
        }
1961
1962
1963
        nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0;
1964
        aGroup = this._getItemGroup(nGroupIndex);
1965
1966
1967
1968
        if (!aGroup) {
1969
1970
            aGroup = this._createItemGroup(nGroupIndex);
1971
1972
        }
1973
1974
1975
        if (Lang.isNumber(p_nItemIndex)) {
1976
1977
            bAppend = (p_nItemIndex >= aGroup.length);            
1978
1979
1980
            if (aGroup[p_nItemIndex]) {
1981
    
1982
                aGroup.splice(p_nItemIndex, 0, oItem);
1983
    
1984
            }
1985
            else {
1986
    
1987
                aGroup[p_nItemIndex] = oItem;
1988
    
1989
            }
1990
1991
1992
            oGroupItem = aGroup[p_nItemIndex];
1993
1994
            if (oGroupItem) {
1995
1996
                if (bAppend && (!oGroupItem.element.parentNode || 
1997
                        oGroupItem.element.parentNode.nodeType == 11)) {
1998
        
1999
                    this._aListElements[nGroupIndex].appendChild(oGroupItem.element);
2000
    
2001
                }
2002
                else {
2003
    
2004
                    oNextItemSibling = getNextItemSibling(aGroup, (p_nItemIndex+1));
2005
    
2006
                    if (oNextItemSibling && (!oGroupItem.element.parentNode || 
2007
                            oGroupItem.element.parentNode.nodeType == 11)) {
2008
            
2009
                        this._aListElements[nGroupIndex].insertBefore(
2010
                                oGroupItem.element, oNextItemSibling.element);
2011
        
2012
                    }
2013
    
2014
                }
2015
    
2016
2017
                oGroupItem.parent = this;
2018
        
2019
                this._subscribeToItemEvents(oGroupItem);
2020
    
2021
                this._configureSubmenu(oGroupItem);
2022
                
2023
                this._updateItemProperties(nGroupIndex);
2024
        
2025
                YAHOO.log("Item inserted." + 
2026
                    " Text: " + oGroupItem.cfg.getProperty("text") + ", " + 
2027
                    " Index: " + oGroupItem.index + ", " + 
2028
                    " Group Index: " + oGroupItem.groupIndex, "info", this.toString());
2029
2030
                this.itemAddedEvent.fire(oGroupItem);
2031
                this.changeContentEvent.fire();
2032
2033
                returnVal = oGroupItem;
2034
    
2035
            }
2036
2037
        }
2038
        else {
2039
    
2040
            nItemIndex = aGroup.length;
2041
    
2042
            aGroup[nItemIndex] = oItem;
2043
2044
            oGroupItem = aGroup[nItemIndex];
2045
    
2046
2047
            if (oGroupItem) {
2048
    
2049
                if (!Dom.isAncestor(this._aListElements[nGroupIndex], oGroupItem.element)) {
2050
    
2051
                    this._aListElements[nGroupIndex].appendChild(oGroupItem.element);
2052
    
2053
                }
2054
    
2055
                oGroupItem.element.setAttribute(_GROUP_INDEX, nGroupIndex);
2056
                oGroupItem.element.setAttribute(_INDEX, nItemIndex);
2057
        
2058
                oGroupItem.parent = this;
2059
    
2060
                oGroupItem.index = nItemIndex;
2061
                oGroupItem.groupIndex = nGroupIndex;
2062
        
2063
                this._subscribeToItemEvents(oGroupItem);
2064
    
2065
                this._configureSubmenu(oGroupItem);
2066
    
2067
                if (nItemIndex === 0) {
2068
        
2069
                    Dom.addClass(oGroupItem.element, _FIRST_OF_TYPE);
2070
        
2071
                }
2072
2073
                YAHOO.log("Item added." + 
2074
                    " Text: " + oGroupItem.cfg.getProperty("text") + ", " + 
2075
                    " Index: " + oGroupItem.index + ", " + 
2076
                    " Group Index: " + oGroupItem.groupIndex, "info", this.toString());
2077
        
2078
2079
                this.itemAddedEvent.fire(oGroupItem);
2080
                this.changeContentEvent.fire();
2081
2082
                returnVal = oGroupItem;
2083
    
2084
            }
2085
    
2086
        }
2087
2088
    }
2089
    
2090
    return returnVal;
2091
    
2092
},
2093
2094
2095
/**
2096
* @method _removeItemFromGroupByIndex
2097
* @description Removes a menu item from a group by index.  Returns the menu 
2098
* item that was removed.
2099
* @private
2100
* @param {Number} p_nGroupIndex Number indicating the group to which the menu 
2101
* item belongs.
2102
* @param {Number} p_nItemIndex Number indicating the index of the menu item 
2103
* to be removed.
2104
* @return {YAHOO.widget.MenuItem}
2105
*/
2106
_removeItemFromGroupByIndex: function (p_nGroupIndex, p_nItemIndex) {
2107
2108
    var nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0,
2109
        aGroup = this._getItemGroup(nGroupIndex),
2110
        aArray,
2111
        oItem,
2112
        oUL;
2113
2114
    if (aGroup) {
2115
2116
        aArray = aGroup.splice(p_nItemIndex, 1);
2117
        oItem = aArray[0];
2118
    
2119
        if (oItem) {
2120
    
2121
            // Update the index and className properties of each member        
2122
            
2123
            this._updateItemProperties(nGroupIndex);
2124
    
2125
            if (aGroup.length === 0) {
2126
    
2127
                // Remove the UL
2128
    
2129
                oUL = this._aListElements[nGroupIndex];
2130
    
2131
                if (this.body && oUL) {
2132
    
2133
                    this.body.removeChild(oUL);
2134
    
2135
                }
2136
    
2137
                // Remove the group from the array of items
2138
    
2139
                this._aItemGroups.splice(nGroupIndex, 1);
2140
    
2141
    
2142
                // Remove the UL from the array of ULs
2143
    
2144
                this._aListElements.splice(nGroupIndex, 1);
2145
    
2146
    
2147
                /*
2148
                     Assign the "first-of-type" class to the new first UL 
2149
                     in the collection
2150
                */
2151
    
2152
                oUL = this._aListElements[0];
2153
    
2154
                if (oUL) {
2155
    
2156
                    Dom.addClass(oUL, _FIRST_OF_TYPE);
2157
    
2158
                }            
2159
    
2160
            }
2161
    
2162
2163
            this.itemRemovedEvent.fire(oItem);
2164
            this.changeContentEvent.fire();
2165
    
2166
        }
2167
2168
    }
2169
2170
	// Return a reference to the item that was removed
2171
2172
	return oItem;
2173
    
2174
},
2175
2176
2177
/**
2178
* @method _removeItemFromGroupByValue
2179
* @description Removes a menu item from a group by reference.  Returns the 
2180
* menu item that was removed.
2181
* @private
2182
* @param {Number} p_nGroupIndex Number indicating the group to which the
2183
* menu item belongs.
2184
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem 
2185
* instance to be removed.
2186
* @return {YAHOO.widget.MenuItem}
2187
*/    
2188
_removeItemFromGroupByValue: function (p_nGroupIndex, p_oItem) {
2189
2190
    var aGroup = this._getItemGroup(p_nGroupIndex),
2191
        nItems,
2192
        nItemIndex,
2193
        returnVal,
2194
        i;
2195
2196
    if (aGroup) {
2197
2198
        nItems = aGroup.length;
2199
        nItemIndex = -1;
2200
    
2201
        if (nItems > 0) {
2202
    
2203
            i = nItems-1;
2204
        
2205
            do {
2206
        
2207
                if (aGroup[i] == p_oItem) {
2208
        
2209
                    nItemIndex = i;
2210
                    break;    
2211
        
2212
                }
2213
        
2214
            }
2215
            while (i--);
2216
        
2217
            if (nItemIndex > -1) {
2218
        
2219
                returnVal = this._removeItemFromGroupByIndex(p_nGroupIndex, nItemIndex);
2220
        
2221
            }
2222
    
2223
        }
2224
    
2225
    }
2226
    
2227
    return returnVal;
2228
2229
},
2230
2231
2232
/**
2233
* @method _updateItemProperties
2234
* @description Updates the "index," "groupindex," and "className" properties 
2235
* of the menu items in the specified group. 
2236
* @private
2237
* @param {Number} p_nGroupIndex Number indicating the group of items to update.
2238
*/
2239
_updateItemProperties: function (p_nGroupIndex) {
2240
2241
    var aGroup = this._getItemGroup(p_nGroupIndex),
2242
        nItems = aGroup.length,
2243
        oItem,
2244
        oLI,
2245
        i;
2246
2247
2248
    if (nItems > 0) {
2249
2250
        i = nItems - 1;
2251
2252
        // Update the index and className properties of each member
2253
    
2254
        do {
2255
2256
            oItem = aGroup[i];
2257
2258
            if (oItem) {
2259
    
2260
                oLI = oItem.element;
2261
2262
                oItem.index = i;
2263
                oItem.groupIndex = p_nGroupIndex;
2264
2265
                oLI.setAttribute(_GROUP_INDEX, p_nGroupIndex);
2266
                oLI.setAttribute(_INDEX, i);
2267
2268
                Dom.removeClass(oLI, _FIRST_OF_TYPE);
2269
2270
            }
2271
    
2272
        }
2273
        while (i--);
2274
2275
2276
        if (oLI) {
2277
2278
            Dom.addClass(oLI, _FIRST_OF_TYPE);
2279
2280
        }
2281
2282
    }
2283
2284
},
2285
2286
2287
/**
2288
* @method _createItemGroup
2289
* @description Creates a new menu item group (array) and its associated 
2290
* <code>&#60;ul&#62;</code> element. Returns an aray of menu item groups.
2291
* @private
2292
* @param {Number} p_nIndex Number indicating the group to create.
2293
* @return {Array}
2294
*/
2295
_createItemGroup: function (p_nIndex) {
2296
2297
    var oUL,
2298
    	returnVal;
2299
2300
    if (!this._aItemGroups[p_nIndex]) {
2301
2302
        this._aItemGroups[p_nIndex] = [];
2303
2304
        oUL = document.createElement(_UL_LOWERCASE);
2305
2306
        this._aListElements[p_nIndex] = oUL;
2307
2308
        returnVal = this._aItemGroups[p_nIndex];
2309
2310
    }
2311
    
2312
    return returnVal;
2313
2314
},
2315
2316
2317
/**
2318
* @method _getItemGroup
2319
* @description Returns the menu item group at the specified index.
2320
* @private
2321
* @param {Number} p_nIndex Number indicating the index of the menu item group 
2322
* to be retrieved.
2323
* @return {Array}
2324
*/
2325
_getItemGroup: function (p_nIndex) {
2326
2327
    var nIndex = Lang.isNumber(p_nIndex) ? p_nIndex : 0,
2328
    	aGroups = this._aItemGroups,
2329
    	returnVal;
2330
2331
	if (nIndex in aGroups) {
2332
2333
	    returnVal = aGroups[nIndex];
2334
2335
	}
2336
	
2337
	return returnVal;
2338
2339
},
2340
2341
2342
/**
2343
* @method _configureSubmenu
2344
* @description Subscribes the menu item's submenu to its parent menu's events.
2345
* @private
2346
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem 
2347
* instance with the submenu to be configured.
2348
*/
2349
_configureSubmenu: function (p_oItem) {
2350
2351
    var oSubmenu = p_oItem.cfg.getProperty(_SUBMENU);
2352
2353
    if (oSubmenu) {
2354
            
2355
        /*
2356
            Listen for configuration changes to the parent menu 
2357
            so they they can be applied to the submenu.
2358
        */
2359
2360
        this.cfg.configChangedEvent.subscribe(this._onParentMenuConfigChange, oSubmenu, true);
2361
2362
        this.renderEvent.subscribe(this._onParentMenuRender, oSubmenu, true);
2363
2364
    }
2365
2366
},
2367
2368
2369
2370
2371
/**
2372
* @method _subscribeToItemEvents
2373
* @description Subscribes a menu to a menu item's event.
2374
* @private
2375
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem 
2376
* instance whose events should be subscribed to.
2377
*/
2378
_subscribeToItemEvents: function (p_oItem) {
2379
2380
    p_oItem.destroyEvent.subscribe(this._onMenuItemDestroy, p_oItem, this);
2381
    p_oItem.cfg.configChangedEvent.subscribe(this._onMenuItemConfigChange, p_oItem, this);
2382
2383
},
2384
2385
2386
/**
2387
* @method _onVisibleChange
2388
* @description Change event handler for the menu's "visible" configuration
2389
* property.
2390
* @private
2391
* @param {String} p_sType String representing the name of the event that 
2392
* was fired.
2393
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
2394
*/
2395
_onVisibleChange: function (p_sType, p_aArgs) {
2396
2397
    var bVisible = p_aArgs[0];
2398
    
2399
    if (bVisible) {
2400
2401
        Dom.addClass(this.element, _VISIBLE);
2402
2403
    }
2404
    else {
2405
2406
        Dom.removeClass(this.element, _VISIBLE);
2407
2408
    }
2409
2410
},
2411
2412
2413
/**
2414
* @method _cancelHideDelay
2415
* @description Cancels the call to "hideMenu."
2416
* @private
2417
*/
2418
_cancelHideDelay: function () {
2419
2420
    var oTimer = this.getRoot()._hideDelayTimer;
2421
2422
    if (oTimer) {
2423
2424
		oTimer.cancel();
2425
2426
    }
2427
2428
},
2429
2430
2431
/**
2432
* @method _execHideDelay
2433
* @description Hides the menu after the number of milliseconds specified by 
2434
* the "hidedelay" configuration property.
2435
* @private
2436
*/
2437
_execHideDelay: function () {
2438
2439
    this._cancelHideDelay();
2440
2441
    var oRoot = this.getRoot();
2442
        
2443
	oRoot._hideDelayTimer = Lang.later(oRoot.cfg.getProperty(_HIDE_DELAY), this, function () {
2444
    
2445
        if (oRoot.activeItem) {
2446
2447
			if (oRoot.hasFocus()) {
2448
2449
				oRoot.activeItem.focus();
2450
			
2451
			}
2452
			
2453
            oRoot.clearActiveItem();
2454
2455
        }
2456
2457
        if (oRoot == this && !(this instanceof YAHOO.widget.MenuBar) && 
2458
            this.cfg.getProperty(_POSITION) == _DYNAMIC) {
2459
2460
            this.hide();
2461
        
2462
        }
2463
    
2464
    });
2465
2466
},
2467
2468
2469
/**
2470
* @method _cancelShowDelay
2471
* @description Cancels the call to the "showMenu."
2472
* @private
2473
*/
2474
_cancelShowDelay: function () {
2475
2476
    var oTimer = this.getRoot()._showDelayTimer;
2477
2478
    if (oTimer) {
2479
2480
        oTimer.cancel();
2481
2482
    }
2483
2484
},
2485
2486
2487
/**
2488
* @method _execSubmenuHideDelay
2489
* @description Hides a submenu after the number of milliseconds specified by 
2490
* the "submenuhidedelay" configuration property have ellapsed.
2491
* @private
2492
* @param {YAHOO.widget.Menu} p_oSubmenu Object specifying the submenu that  
2493
* should be hidden.
2494
* @param {Number} p_nMouseX The x coordinate of the mouse when it left 
2495
* the specified submenu's parent menu item.
2496
* @param {Number} p_nHideDelay The number of milliseconds that should ellapse
2497
* before the submenu is hidden.
2498
*/
2499
_execSubmenuHideDelay: function (p_oSubmenu, p_nMouseX, p_nHideDelay) {
2500
2501
	p_oSubmenu._submenuHideDelayTimer = Lang.later(50, this, function () {
2502
2503
        if (this._nCurrentMouseX > (p_nMouseX + 10)) {
2504
2505
            p_oSubmenu._submenuHideDelayTimer = Lang.later(p_nHideDelay, p_oSubmenu, function () {
2506
        
2507
                this.hide();
2508
2509
            });
2510
2511
        }
2512
        else {
2513
2514
            p_oSubmenu.hide();
2515
        
2516
        }
2517
	
2518
	});
2519
2520
},
2521
2522
2523
2524
// Protected methods
2525
2526
2527
/**
2528
* @method _disableScrollHeader
2529
* @description Disables the header used for scrolling the body of the menu.
2530
* @protected
2531
*/
2532
_disableScrollHeader: function () {
2533
2534
    if (!this._bHeaderDisabled) {
2535
2536
        Dom.addClass(this.header, _TOP_SCROLLBAR_DISABLED);
2537
        this._bHeaderDisabled = true;
2538
2539
    }
2540
2541
},
2542
2543
2544
/**
2545
* @method _disableScrollFooter
2546
* @description Disables the footer used for scrolling the body of the menu.
2547
* @protected
2548
*/
2549
_disableScrollFooter: function () {
2550
2551
    if (!this._bFooterDisabled) {
2552
2553
        Dom.addClass(this.footer, _BOTTOM_SCROLLBAR_DISABLED);
2554
        this._bFooterDisabled = true;
2555
2556
    }
2557
2558
},
2559
2560
2561
/**
2562
* @method _enableScrollHeader
2563
* @description Enables the header used for scrolling the body of the menu.
2564
* @protected
2565
*/
2566
_enableScrollHeader: function () {
2567
2568
    if (this._bHeaderDisabled) {
2569
2570
        Dom.removeClass(this.header, _TOP_SCROLLBAR_DISABLED);
2571
        this._bHeaderDisabled = false;
2572
2573
    }
2574
2575
},
2576
2577
2578
/**
2579
* @method _enableScrollFooter
2580
* @description Enables the footer used for scrolling the body of the menu.
2581
* @protected
2582
*/
2583
_enableScrollFooter: function () {
2584
2585
    if (this._bFooterDisabled) {
2586
2587
        Dom.removeClass(this.footer, _BOTTOM_SCROLLBAR_DISABLED);
2588
        this._bFooterDisabled = false;
2589
2590
    }
2591
2592
},
2593
2594
2595
/**
2596
* @method _onMouseOver
2597
* @description "mouseover" event handler for the menu.
2598
* @protected
2599
* @param {String} p_sType String representing the name of the event that 
2600
* was fired.
2601
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
2602
*/
2603
_onMouseOver: function (p_sType, p_aArgs) {
2604
2605
    var oEvent = p_aArgs[0],
2606
        oItem = p_aArgs[1],
2607
        oTarget = Event.getTarget(oEvent),
2608
        oRoot = this.getRoot(),
2609
        oSubmenuHideDelayTimer = this._submenuHideDelayTimer,
2610
        oParentMenu,
2611
        nShowDelay,
2612
        bShowDelay,
2613
        oActiveItem,
2614
        oItemCfg,
2615
        oSubmenu;
2616
2617
2618
    var showSubmenu = function () {
2619
2620
        if (this.parent.cfg.getProperty(_SELECTED)) {
2621
2622
            this.show();
2623
2624
        }
2625
2626
    };
2627
2628
2629
    if (!this._bStopMouseEventHandlers) {
2630
    
2631
		if (!this._bHandledMouseOverEvent && (oTarget == this.element || 
2632
				Dom.isAncestor(this.element, oTarget))) {
2633
	
2634
			// Menu mouseover logic
2635
2636
	        if (this._useHideDelay) {
2637
	        	this._cancelHideDelay();
2638
	        }
2639
	
2640
			this._nCurrentMouseX = 0;
2641
	
2642
			Event.on(this.element, _MOUSEMOVE, this._onMouseMove, this, true);
2643
2644
2645
			/*
2646
				If the mouse is moving from the submenu back to its corresponding menu item, 
2647
				don't hide the submenu or clear the active MenuItem.
2648
			*/
2649
2650
			if (!(oItem && Dom.isAncestor(oItem.element, Event.getRelatedTarget(oEvent)))) {
2651
2652
				this.clearActiveItem();
2653
2654
			}
2655
	
2656
2657
			if (this.parent && oSubmenuHideDelayTimer) {
2658
	
2659
				oSubmenuHideDelayTimer.cancel();
2660
	
2661
				this.parent.cfg.setProperty(_SELECTED, true);
2662
	
2663
				oParentMenu = this.parent.parent;
2664
	
2665
				oParentMenu._bHandledMouseOutEvent = true;
2666
				oParentMenu._bHandledMouseOverEvent = false;
2667
	
2668
			}
2669
	
2670
	
2671
			this._bHandledMouseOverEvent = true;
2672
			this._bHandledMouseOutEvent = false;
2673
		
2674
		}
2675
	
2676
	
2677
		if (oItem && !oItem.handledMouseOverEvent && !oItem.cfg.getProperty(_DISABLED) && 
2678
			(oTarget == oItem.element || Dom.isAncestor(oItem.element, oTarget))) {
2679
	
2680
			// Menu Item mouseover logic
2681
	
2682
			nShowDelay = this.cfg.getProperty(_SHOW_DELAY);
2683
			bShowDelay = (nShowDelay > 0);
2684
	
2685
	
2686
			if (bShowDelay) {
2687
			
2688
				this._cancelShowDelay();
2689
			
2690
			}
2691
	
2692
	
2693
			oActiveItem = this.activeItem;
2694
		
2695
			if (oActiveItem) {
2696
		
2697
				oActiveItem.cfg.setProperty(_SELECTED, false);
2698
		
2699
			}
2700
	
2701
	
2702
			oItemCfg = oItem.cfg;
2703
		
2704
			// Select and focus the current menu item
2705
		
2706
			oItemCfg.setProperty(_SELECTED, true);
2707
	
2708
	
2709
			if (this.hasFocus() || oRoot._hasFocus) {
2710
			
2711
				oItem.focus();
2712
				
2713
				oRoot._hasFocus = false;
2714
			
2715
			}
2716
	
2717
	
2718
			if (this.cfg.getProperty(_AUTO_SUBMENU_DISPLAY)) {
2719
	
2720
				// Show the submenu this menu item
2721
	
2722
				oSubmenu = oItemCfg.getProperty(_SUBMENU);
2723
			
2724
				if (oSubmenu) {
2725
			
2726
					if (bShowDelay) {
2727
	
2728
						oRoot._showDelayTimer = 
2729
							Lang.later(oRoot.cfg.getProperty(_SHOW_DELAY), oSubmenu, showSubmenu);
2730
			
2731
					}
2732
					else {
2733
	
2734
						oSubmenu.show();
2735
	
2736
					}
2737
	
2738
				}
2739
	
2740
			}                        
2741
	
2742
			oItem.handledMouseOverEvent = true;
2743
			oItem.handledMouseOutEvent = false;
2744
	
2745
		}
2746
    
2747
    }
2748
2749
},
2750
2751
2752
/**
2753
* @method _onMouseOut
2754
* @description "mouseout" event handler for the menu.
2755
* @protected
2756
* @param {String} p_sType String representing the name of the event that 
2757
* was fired.
2758
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
2759
*/
2760
_onMouseOut: function (p_sType, p_aArgs) {
2761
2762
    var oEvent = p_aArgs[0],
2763
        oItem = p_aArgs[1],
2764
        oRelatedTarget = Event.getRelatedTarget(oEvent),
2765
        bMovingToSubmenu = false,
2766
        oItemCfg,
2767
        oSubmenu,
2768
        nSubmenuHideDelay,
2769
        nShowDelay;
2770
2771
2772
    if (!this._bStopMouseEventHandlers) {
2773
    
2774
		if (oItem && !oItem.cfg.getProperty(_DISABLED)) {
2775
	
2776
			oItemCfg = oItem.cfg;
2777
			oSubmenu = oItemCfg.getProperty(_SUBMENU);
2778
	
2779
	
2780
			if (oSubmenu && (oRelatedTarget == oSubmenu.element ||
2781
					Dom.isAncestor(oSubmenu.element, oRelatedTarget))) {
2782
	
2783
				bMovingToSubmenu = true;
2784
	
2785
			}
2786
	
2787
	
2788
			if (!oItem.handledMouseOutEvent && ((oRelatedTarget != oItem.element &&  
2789
				!Dom.isAncestor(oItem.element, oRelatedTarget)) || bMovingToSubmenu)) {
2790
	
2791
				// Menu Item mouseout logic
2792
	
2793
				if (!bMovingToSubmenu) {
2794
	
2795
					oItem.cfg.setProperty(_SELECTED, false);
2796
	
2797
	
2798
					if (oSubmenu) {
2799
	
2800
						nSubmenuHideDelay = this.cfg.getProperty(_SUBMENU_HIDE_DELAY);
2801
	
2802
						nShowDelay = this.cfg.getProperty(_SHOW_DELAY);
2803
	
2804
						if (!(this instanceof YAHOO.widget.MenuBar) && nSubmenuHideDelay > 0 && 
2805
							nShowDelay >= nSubmenuHideDelay) {
2806
	
2807
							this._execSubmenuHideDelay(oSubmenu, Event.getPageX(oEvent),
2808
									nSubmenuHideDelay);
2809
	
2810
						}
2811
						else {
2812
	
2813
							oSubmenu.hide();
2814
	
2815
						}
2816
	
2817
					}
2818
	
2819
				}
2820
	
2821
	
2822
				oItem.handledMouseOutEvent = true;
2823
				oItem.handledMouseOverEvent = false;
2824
		
2825
			}
2826
	
2827
		}
2828
2829
2830
		if (!this._bHandledMouseOutEvent && ((oRelatedTarget != this.element &&  
2831
			!Dom.isAncestor(this.element, oRelatedTarget)) || bMovingToSubmenu)) {
2832
	
2833
			// Menu mouseout logic
2834
2835
	        if (this._useHideDelay) {
2836
	        	this._execHideDelay();
2837
	        }
2838
2839
			Event.removeListener(this.element, _MOUSEMOVE, this._onMouseMove);
2840
	
2841
			this._nCurrentMouseX = Event.getPageX(oEvent);
2842
	
2843
			this._bHandledMouseOutEvent = true;
2844
			this._bHandledMouseOverEvent = false;
2845
	
2846
		}
2847
    
2848
    }
2849
2850
},
2851
2852
2853
/**
2854
* @method _onMouseMove
2855
* @description "click" event handler for the menu.
2856
* @protected
2857
* @param {Event} p_oEvent Object representing the DOM event object passed 
2858
* back by the event utility (YAHOO.util.Event).
2859
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
2860
* fired the event.
2861
*/
2862
_onMouseMove: function (p_oEvent, p_oMenu) {
2863
2864
    if (!this._bStopMouseEventHandlers) {
2865
    
2866
	    this._nCurrentMouseX = Event.getPageX(p_oEvent);
2867
    
2868
    }
2869
2870
},
2871
2872
2873
/**
2874
* @method _onClick
2875
* @description "click" event handler for the menu.
2876
* @protected
2877
* @param {String} p_sType String representing the name of the event that 
2878
* was fired.
2879
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
2880
*/
2881
_onClick: function (p_sType, p_aArgs) {
2882
2883
	var oEvent = p_aArgs[0],
2884
		oItem = p_aArgs[1],
2885
		bInMenuAnchor = false,
2886
		oSubmenu,
2887
		oMenu,
2888
		oRoot,
2889
		sId,
2890
		sURL,
2891
		nHashPos,
2892
		nLen;
2893
2894
2895
	var hide = function () {
2896
		
2897
		oRoot = this.getRoot();
2898
2899
		if (oRoot instanceof YAHOO.widget.MenuBar || 
2900
			oRoot.cfg.getProperty(_POSITION) == _STATIC) {
2901
2902
			oRoot.clearActiveItem();
2903
2904
		}
2905
		else {
2906
2907
			oRoot.hide();
2908
		
2909
		}
2910
	
2911
	};
2912
2913
2914
	if (oItem) {
2915
	
2916
		if (oItem.cfg.getProperty(_DISABLED)) {
2917
		
2918
			Event.preventDefault(oEvent);
2919
2920
			hide.call(this);
2921
2922
		}
2923
		else {
2924
2925
			oSubmenu = oItem.cfg.getProperty(_SUBMENU);
2926
	
2927
			
2928
			/*
2929
				 Check if the URL of the anchor is pointing to an element that is 
2930
				 a child of the menu.
2931
			*/
2932
			
2933
			sURL = oItem.cfg.getProperty(_URL);
2934
2935
		
2936
			if (sURL) {
2937
	
2938
				nHashPos = sURL.indexOf(_HASH);
2939
	
2940
				nLen = sURL.length;
2941
	
2942
	
2943
				if (nHashPos != -1) {
2944
	
2945
					sURL = sURL.substr(nHashPos, nLen);
2946
		
2947
					nLen = sURL.length;
2948
	
2949
	
2950
					if (nLen > 1) {
2951
	
2952
						sId = sURL.substr(1, nLen);
2953
	
2954
						oMenu = YAHOO.widget.MenuManager.getMenu(sId);
2955
						
2956
						if (oMenu) {
2957
2958
							bInMenuAnchor = 
2959
								(this.getRoot() === oMenu.getRoot());
2960
2961
						}
2962
						
2963
					}
2964
					else if (nLen === 1) {
2965
	
2966
						bInMenuAnchor = true;
2967
					
2968
					}
2969
	
2970
				}
2971
			
2972
			}
2973
2974
	
2975
			if (bInMenuAnchor && !oItem.cfg.getProperty(_TARGET)) {
2976
	
2977
				Event.preventDefault(oEvent);
2978
				
2979
2980
				if (UA.webkit) {
2981
				
2982
					oItem.focus();
2983
				
2984
				}
2985
				else {
2986
2987
					oItem.focusEvent.fire();
2988
				
2989
				}
2990
			
2991
			}
2992
	
2993
	
2994
			if (!oSubmenu && !this.cfg.getProperty(_KEEP_OPEN)) {
2995
	
2996
				hide.call(this);
2997
	
2998
			}
2999
			
3000
		}
3001
	
3002
	}
3003
3004
},
3005
3006
3007
/**
3008
* @method _onKeyDown
3009
* @description "keydown" event handler for the menu.
3010
* @protected
3011
* @param {String} p_sType String representing the name of the event that 
3012
* was fired.
3013
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
3014
*/
3015
_onKeyDown: function (p_sType, p_aArgs) {
3016
3017
    var oEvent = p_aArgs[0],
3018
        oItem = p_aArgs[1],
3019
        oSubmenu,
3020
        oItemCfg,
3021
        oParentItem,
3022
        oRoot,
3023
        oNextItem,
3024
        oBody,
3025
        nBodyScrollTop,
3026
        nBodyOffsetHeight,
3027
        aItems,
3028
        nItems,
3029
        nNextItemOffsetTop,
3030
        nScrollTarget,
3031
        oParentMenu,
3032
		oFocusedEl;
3033
3034
3035
	if (this._useHideDelay) {
3036
		this._cancelHideDelay();
3037
	}
3038
3039
3040
    /*
3041
        This function is called to prevent a bug in Firefox.  In Firefox,
3042
        moving a DOM element into a stationary mouse pointer will cause the 
3043
        browser to fire mouse events.  This can result in the menu mouse
3044
        event handlers being called uncessarily, especially when menus are 
3045
        moved into a stationary mouse pointer as a result of a 
3046
        key event handler.
3047
    */
3048
    function stopMouseEventHandlers() {
3049
3050
        this._bStopMouseEventHandlers = true;
3051
        
3052
        Lang.later(10, this, function () {
3053
3054
            this._bStopMouseEventHandlers = false;
3055
        
3056
        });
3057
3058
    }
3059
3060
3061
    if (oItem && !oItem.cfg.getProperty(_DISABLED)) {
3062
3063
        oItemCfg = oItem.cfg;
3064
        oParentItem = this.parent;
3065
3066
        switch(oEvent.keyCode) {
3067
    
3068
            case 38:    // Up arrow
3069
            case 40:    // Down arrow
3070
    
3071
                oNextItem = (oEvent.keyCode == 38) ? 
3072
                    oItem.getPreviousEnabledSibling() : 
3073
                    oItem.getNextEnabledSibling();
3074
        
3075
                if (oNextItem) {
3076
3077
                    this.clearActiveItem();
3078
3079
                    oNextItem.cfg.setProperty(_SELECTED, true);
3080
                    oNextItem.focus();
3081
3082
3083
                    if (this.cfg.getProperty(_MAX_HEIGHT) > 0) {
3084
3085
                        oBody = this.body;
3086
                        nBodyScrollTop = oBody.scrollTop;
3087
                        nBodyOffsetHeight = oBody.offsetHeight;
3088
                        aItems = this.getItems();
3089
                        nItems = aItems.length - 1;
3090
                        nNextItemOffsetTop = oNextItem.element.offsetTop;
3091
3092
3093
                        if (oEvent.keyCode == 40 ) {    // Down
3094
                       
3095
                            if (nNextItemOffsetTop >= (nBodyOffsetHeight + nBodyScrollTop)) {
3096
3097
                                oBody.scrollTop = nNextItemOffsetTop - nBodyOffsetHeight;
3098
3099
                            }
3100
                            else if (nNextItemOffsetTop <= nBodyScrollTop) {
3101
                            
3102
                                oBody.scrollTop = 0;
3103
                            
3104
                            }
3105
3106
3107
                            if (oNextItem == aItems[nItems]) {
3108
3109
                                oBody.scrollTop = oNextItem.element.offsetTop;
3110
3111
                            }
3112
3113
                        }
3114
                        else {  // Up
3115
3116
                            if (nNextItemOffsetTop <= nBodyScrollTop) {
3117
3118
                                oBody.scrollTop = nNextItemOffsetTop - oNextItem.element.offsetHeight;
3119
                            
3120
                            }
3121
                            else if (nNextItemOffsetTop >= (nBodyScrollTop + nBodyOffsetHeight)) {
3122
                            
3123
                                oBody.scrollTop = nNextItemOffsetTop;
3124
                            
3125
                            }
3126
3127
3128
                            if (oNextItem == aItems[0]) {
3129
                            
3130
                                oBody.scrollTop = 0;
3131
                            
3132
                            }
3133
3134
                        }
3135
3136
3137
                        nBodyScrollTop = oBody.scrollTop;
3138
                        nScrollTarget = oBody.scrollHeight - oBody.offsetHeight;
3139
3140
                        if (nBodyScrollTop === 0) {
3141
3142
                            this._disableScrollHeader();
3143
                            this._enableScrollFooter();
3144
3145
                        }
3146
                        else if (nBodyScrollTop == nScrollTarget) {
3147
3148
                             this._enableScrollHeader();
3149
                             this._disableScrollFooter();
3150
3151
                        }
3152
                        else {
3153
3154
                            this._enableScrollHeader();
3155
                            this._enableScrollFooter();
3156
3157
                        }
3158
3159
                    }
3160
3161
                }
3162
3163
    
3164
                Event.preventDefault(oEvent);
3165
3166
                stopMouseEventHandlers();
3167
    
3168
            break;
3169
            
3170
    
3171
            case 39:    // Right arrow
3172
    
3173
                oSubmenu = oItemCfg.getProperty(_SUBMENU);
3174
    
3175
                if (oSubmenu) {
3176
    
3177
                    if (!oItemCfg.getProperty(_SELECTED)) {
3178
        
3179
                        oItemCfg.setProperty(_SELECTED, true);
3180
        
3181
                    }
3182
    
3183
                    oSubmenu.show();
3184
                    oSubmenu.setInitialFocus();
3185
                    oSubmenu.setInitialSelection();
3186
    
3187
                }
3188
                else {
3189
    
3190
                    oRoot = this.getRoot();
3191
                    
3192
                    if (oRoot instanceof YAHOO.widget.MenuBar) {
3193
    
3194
                        oNextItem = oRoot.activeItem.getNextEnabledSibling();
3195
    
3196
                        if (oNextItem) {
3197
                        
3198
                            oRoot.clearActiveItem();
3199
    
3200
                            oNextItem.cfg.setProperty(_SELECTED, true);
3201
    
3202
                            oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
3203
    
3204
                            if (oSubmenu) {
3205
    
3206
                                oSubmenu.show();
3207
                                oSubmenu.setInitialFocus();
3208
                            
3209
                            }
3210
                            else {
3211
    
3212
                            	oNextItem.focus();
3213
                            
3214
                            }
3215
                        
3216
                        }
3217
                    
3218
                    }
3219
                
3220
                }
3221
    
3222
    
3223
                Event.preventDefault(oEvent);
3224
3225
                stopMouseEventHandlers();
3226
3227
            break;
3228
    
3229
    
3230
            case 37:    // Left arrow
3231
    
3232
                if (oParentItem) {
3233
    
3234
                    oParentMenu = oParentItem.parent;
3235
    
3236
                    if (oParentMenu instanceof YAHOO.widget.MenuBar) {
3237
    
3238
                        oNextItem = 
3239
                            oParentMenu.activeItem.getPreviousEnabledSibling();
3240
    
3241
                        if (oNextItem) {
3242
                        
3243
                            oParentMenu.clearActiveItem();
3244
    
3245
                            oNextItem.cfg.setProperty(_SELECTED, true);
3246
    
3247
                            oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
3248
    
3249
                            if (oSubmenu) {
3250
                            
3251
                                oSubmenu.show();
3252
								oSubmenu.setInitialFocus();                                
3253
                            
3254
                            }
3255
                            else {
3256
    
3257
                            	oNextItem.focus();
3258
                            
3259
                            }
3260
                        
3261
                        } 
3262
                    
3263
                    }
3264
                    else {
3265
    
3266
                        this.hide();
3267
    
3268
                        oParentItem.focus();
3269
                    
3270
                    }
3271
    
3272
                }
3273
    
3274
                Event.preventDefault(oEvent);
3275
3276
                stopMouseEventHandlers();
3277
3278
            break;        
3279
    
3280
        }
3281
3282
3283
    }
3284
3285
3286
    if (oEvent.keyCode == 27) { // Esc key
3287
3288
        if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3289
        
3290
            this.hide();
3291
3292
            if (this.parent) {
3293
3294
                this.parent.focus();
3295
            
3296
            }
3297
			else {
3298
				// Focus the element that previously had focus
3299
3300
				oFocusedEl = this._focusedElement;
3301
3302
				if (oFocusedEl && oFocusedEl.focus) {
3303
3304
					try {
3305
						oFocusedEl.focus();
3306
					}
3307
					catch(ex) {
3308
					}
3309
3310
				}
3311
				
3312
			}
3313
3314
        }
3315
        else if (this.activeItem) {
3316
3317
            oSubmenu = this.activeItem.cfg.getProperty(_SUBMENU);
3318
3319
            if (oSubmenu && oSubmenu.cfg.getProperty(_VISIBLE)) {
3320
            
3321
                oSubmenu.hide();
3322
                this.activeItem.focus();
3323
            
3324
            }
3325
            else {
3326
3327
                this.activeItem.blur();
3328
                this.activeItem.cfg.setProperty(_SELECTED, false);
3329
        
3330
            }
3331
        
3332
        }
3333
3334
3335
        Event.preventDefault(oEvent);
3336
    
3337
    }
3338
    
3339
},
3340
3341
3342
/**
3343
* @method _onKeyPress
3344
* @description "keypress" event handler for a Menu instance.
3345
* @protected
3346
* @param {String} p_sType The name of the event that was fired.
3347
* @param {Array} p_aArgs Collection of arguments sent when the event 
3348
* was fired.
3349
*/
3350
_onKeyPress: function (p_sType, p_aArgs) {
3351
    
3352
    var oEvent = p_aArgs[0];
3353
3354
3355
    if (oEvent.keyCode == 40 || oEvent.keyCode == 38) {
3356
3357
        Event.preventDefault(oEvent);
3358
3359
    }
3360
3361
},
3362
3363
3364
/**
3365
* @method _onBlur
3366
* @description "blur" event handler for a Menu instance.
3367
* @protected
3368
* @param {String} p_sType The name of the event that was fired.
3369
* @param {Array} p_aArgs Collection of arguments sent when the event 
3370
* was fired.
3371
*/
3372
_onBlur: function (p_sType, p_aArgs) {
3373
        
3374
	if (this._hasFocus) {
3375
		this._hasFocus = false;
3376
	}
3377
3378
},
3379
3380
/**
3381
* @method _onYChange
3382
* @description "y" event handler for a Menu instance.
3383
* @protected
3384
* @param {String} p_sType The name of the event that was fired.
3385
* @param {Array} p_aArgs Collection of arguments sent when the event 
3386
* was fired.
3387
*/
3388
_onYChange: function (p_sType, p_aArgs) {
3389
3390
    var oParent = this.parent,
3391
        nScrollTop,
3392
        oIFrame,
3393
        nY;
3394
3395
3396
    if (oParent) {
3397
3398
        nScrollTop = oParent.parent.body.scrollTop;
3399
3400
3401
        if (nScrollTop > 0) {
3402
    
3403
            nY = (this.cfg.getProperty(_Y) - nScrollTop);
3404
            
3405
            Dom.setY(this.element, nY);
3406
3407
            oIFrame = this.iframe;            
3408
    
3409
3410
            if (oIFrame) {
3411
    
3412
                Dom.setY(oIFrame, nY);
3413
    
3414
            }
3415
            
3416
            this.cfg.setProperty(_Y, nY, true);
3417
        
3418
        }
3419
    
3420
    }
3421
3422
},
3423
3424
3425
/**
3426
* @method _onScrollTargetMouseOver
3427
* @description "mouseover" event handler for the menu's "header" and "footer" 
3428
* elements.  Used to scroll the body of the menu up and down when the 
3429
* menu's "maxheight" configuration property is set to a value greater than 0.
3430
* @protected
3431
* @param {Event} p_oEvent Object representing the DOM event object passed 
3432
* back by the event utility (YAHOO.util.Event).
3433
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
3434
* fired the event.
3435
*/
3436
_onScrollTargetMouseOver: function (p_oEvent, p_oMenu) {
3437
3438
	var oBodyScrollTimer = this._bodyScrollTimer;
3439
3440
3441
	if (oBodyScrollTimer) {
3442
3443
		oBodyScrollTimer.cancel();
3444
3445
	}
3446
3447
3448
	this._cancelHideDelay();
3449
3450
3451
    var oTarget = Event.getTarget(p_oEvent),
3452
        oBody = this.body,
3453
        nScrollIncrement = this.cfg.getProperty(_SCROLL_INCREMENT),
3454
        nScrollTarget,
3455
        fnScrollFunction;
3456
3457
3458
    function scrollBodyDown() {
3459
3460
        var nScrollTop = oBody.scrollTop;
3461
3462
3463
        if (nScrollTop < nScrollTarget) {
3464
3465
            oBody.scrollTop = (nScrollTop + nScrollIncrement);
3466
3467
            this._enableScrollHeader();
3468
3469
        }
3470
        else {
3471
3472
            oBody.scrollTop = nScrollTarget;
3473
3474
            this._bodyScrollTimer.cancel();
3475
3476
            this._disableScrollFooter();
3477
3478
        }
3479
3480
    }
3481
3482
3483
    function scrollBodyUp() {
3484
3485
        var nScrollTop = oBody.scrollTop;
3486
3487
3488
        if (nScrollTop > 0) {
3489
3490
            oBody.scrollTop = (nScrollTop - nScrollIncrement);
3491
3492
            this._enableScrollFooter();
3493
3494
        }
3495
        else {
3496
3497
            oBody.scrollTop = 0;
3498
3499
			this._bodyScrollTimer.cancel();
3500
3501
            this._disableScrollHeader();
3502
3503
        }
3504
3505
    }
3506
3507
    
3508
    if (Dom.hasClass(oTarget, _HD)) {
3509
3510
        fnScrollFunction = scrollBodyUp;
3511
    
3512
    }
3513
    else {
3514
3515
        nScrollTarget = oBody.scrollHeight - oBody.offsetHeight;
3516
3517
        fnScrollFunction = scrollBodyDown;
3518
    
3519
    }
3520
    
3521
3522
    this._bodyScrollTimer = Lang.later(10, this, fnScrollFunction, null, true);
3523
3524
},
3525
3526
3527
/**
3528
* @method _onScrollTargetMouseOut
3529
* @description "mouseout" event handler for the menu's "header" and "footer" 
3530
* elements.  Used to stop scrolling the body of the menu up and down when the 
3531
* menu's "maxheight" configuration property is set to a value greater than 0.
3532
* @protected
3533
* @param {Event} p_oEvent Object representing the DOM event object passed 
3534
* back by the event utility (YAHOO.util.Event).
3535
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
3536
* fired the event.
3537
*/
3538
_onScrollTargetMouseOut: function (p_oEvent, p_oMenu) {
3539
3540
	var oBodyScrollTimer = this._bodyScrollTimer;
3541
3542
	if (oBodyScrollTimer) {
3543
3544
		oBodyScrollTimer.cancel();
3545
3546
	}
3547
	
3548
    this._cancelHideDelay();
3549
3550
},
3551
3552
3553
3554
// Private methods
3555
3556
3557
/**
3558
* @method _onInit
3559
* @description "init" event handler for the menu.
3560
* @private
3561
* @param {String} p_sType String representing the name of the event that 
3562
* was fired.
3563
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
3564
*/
3565
_onInit: function (p_sType, p_aArgs) {
3566
3567
    this.cfg.subscribeToConfigEvent(_VISIBLE, this._onVisibleChange);
3568
3569
    var bRootMenu = !this.parent,
3570
        bLazyLoad = this.lazyLoad;
3571
3572
3573
    /*
3574
        Automatically initialize a menu's subtree if:
3575
3576
        1) This is the root menu and lazyload is off
3577
        
3578
        2) This is the root menu, lazyload is on, but the menu is 
3579
           already visible
3580
3581
        3) This menu is a submenu and lazyload is off
3582
    */
3583
3584
3585
3586
    if (((bRootMenu && !bLazyLoad) || 
3587
        (bRootMenu && (this.cfg.getProperty(_VISIBLE) || 
3588
        this.cfg.getProperty(_POSITION) == _STATIC)) || 
3589
        (!bRootMenu && !bLazyLoad)) && this.getItemGroups().length === 0) {
3590
3591
        if (this.srcElement) {
3592
3593
            this._initSubTree();
3594
        
3595
        }
3596
3597
3598
        if (this.itemData) {
3599
3600
            this.addItems(this.itemData);
3601
3602
        }
3603
    
3604
    }
3605
    else if (bLazyLoad) {
3606
3607
        this.cfg.fireQueue();
3608
    
3609
    }
3610
3611
},
3612
3613
3614
/**
3615
* @method _onBeforeRender
3616
* @description "beforerender" event handler for the menu.  Appends all of the 
3617
* <code>&#60;ul&#62;</code>, <code>&#60;li&#62;</code> and their accompanying 
3618
* title elements to the body element of the menu.
3619
* @private
3620
* @param {String} p_sType String representing the name of the event that 
3621
* was fired.
3622
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
3623
*/
3624
_onBeforeRender: function (p_sType, p_aArgs) {
3625
3626
    var oEl = this.element,
3627
        nListElements = this._aListElements.length,
3628
        bFirstList = true,
3629
        i = 0,
3630
        oUL,
3631
        oGroupTitle;
3632
3633
    if (nListElements > 0) {
3634
3635
        do {
3636
3637
            oUL = this._aListElements[i];
3638
3639
            if (oUL) {
3640
3641
                if (bFirstList) {
3642
        
3643
                    Dom.addClass(oUL, _FIRST_OF_TYPE);
3644
                    bFirstList = false;
3645
        
3646
                }
3647
3648
3649
                if (!Dom.isAncestor(oEl, oUL)) {
3650
3651
                    this.appendToBody(oUL);
3652
3653
                }
3654
3655
3656
                oGroupTitle = this._aGroupTitleElements[i];
3657
3658
                if (oGroupTitle) {
3659
3660
                    if (!Dom.isAncestor(oEl, oGroupTitle)) {
3661
3662
                        oUL.parentNode.insertBefore(oGroupTitle, oUL);
3663
3664
                    }
3665
3666
3667
                    Dom.addClass(oUL, _HAS_TITLE);
3668
3669
                }
3670
3671
            }
3672
3673
            i++;
3674
3675
        }
3676
        while (i < nListElements);
3677
3678
    }
3679
3680
},
3681
3682
3683
/**
3684
* @method _onRender
3685
* @description "render" event handler for the menu.
3686
* @private
3687
* @param {String} p_sType String representing the name of the event that 
3688
* was fired.
3689
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
3690
*/
3691
_onRender: function (p_sType, p_aArgs) {
3692
3693
    if (this.cfg.getProperty(_POSITION) == _DYNAMIC) { 
3694
3695
        if (!this.cfg.getProperty(_VISIBLE)) {
3696
3697
            this.positionOffScreen();
3698
3699
        }
3700
    
3701
    }
3702
3703
},
3704
3705
3706
3707
3708
3709
/**
3710
* @method _onBeforeShow
3711
* @description "beforeshow" event handler for the menu.
3712
* @private
3713
* @param {String} p_sType String representing the name of the event that 
3714
* was fired.
3715
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
3716
*/
3717
_onBeforeShow: function (p_sType, p_aArgs) {
3718
3719
    var nOptions,
3720
        n,
3721
        oSrcElement,
3722
        oContainer = this.cfg.getProperty(_CONTAINER);
3723
3724
3725
    if (this.lazyLoad && this.getItemGroups().length === 0) {
3726
3727
        if (this.srcElement) {
3728
        
3729
            this._initSubTree();
3730
3731
        }
3732
3733
3734
        if (this.itemData) {
3735
3736
            if (this.parent && this.parent.parent && 
3737
                this.parent.parent.srcElement && 
3738
                this.parent.parent.srcElement.tagName.toUpperCase() == 
3739
                _SELECT) {
3740
3741
                nOptions = this.itemData.length;
3742
    
3743
                for(n=0; n<nOptions; n++) {
3744
3745
                    if (this.itemData[n].tagName) {
3746
3747
                        this.addItem((new this.ITEM_TYPE(this.itemData[n])));
3748
    
3749
                    }
3750
    
3751
                }
3752
            
3753
            }
3754
            else {
3755
3756
                this.addItems(this.itemData);
3757
            
3758
            }
3759
        
3760
        }
3761
3762
3763
        oSrcElement = this.srcElement;
3764
3765
        if (oSrcElement) {
3766
3767
            if (oSrcElement.tagName.toUpperCase() == _SELECT) {
3768
3769
                if (Dom.inDocument(oSrcElement)) {
3770
3771
                    this.render(oSrcElement.parentNode);
3772
                
3773
                }
3774
                else {
3775
                
3776
                    this.render(oContainer);
3777
                
3778
                }
3779
3780
            }
3781
            else {
3782
3783
                this.render();
3784
3785
            }
3786
3787
        }
3788
        else {
3789
3790
            if (this.parent) {
3791
3792
                this.render(this.parent.element);     
3793
3794
            }
3795
            else {
3796
3797
                this.render(oContainer);
3798
3799
            }                
3800
3801
        }
3802
3803
    }
3804
3805
3806
3807
    var oParent = this.parent,
3808
		aAlignment;
3809
3810
3811
    if (!oParent && this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3812
3813
        this.cfg.refireEvent(_XY);
3814
   
3815
    }
3816
3817
3818
	if (oParent) {
3819
3820
		aAlignment = oParent.parent.cfg.getProperty(_SUBMENU_ALIGNMENT);
3821
		
3822
		this.cfg.setProperty(_CONTEXT, [oParent.element, aAlignment[0], aAlignment[1]]);
3823
		this.align();
3824
	
3825
	}
3826
3827
},
3828
3829
3830
getConstrainedY: function (y) {
3831
3832
	var oMenu = this,
3833
	
3834
		aContext = oMenu.cfg.getProperty(_CONTEXT),
3835
		nInitialMaxHeight = oMenu.cfg.getProperty(_MAX_HEIGHT),
3836
3837
		nMaxHeight,
3838
3839
		oOverlapPositions = {
3840
3841
			"trbr": true,
3842
			"tlbl": true,
3843
			"bltl": true,
3844
			"brtr": true
3845
3846
		},
3847
3848
		bPotentialContextOverlap = (aContext && oOverlapPositions[aContext[1] + aContext[2]]),
3849
	
3850
		oMenuEl = oMenu.element,
3851
		nMenuOffsetHeight = oMenuEl.offsetHeight,
3852
	
3853
		nViewportOffset = Overlay.VIEWPORT_OFFSET,
3854
		viewPortHeight = Dom.getViewportHeight(),
3855
		scrollY = Dom.getDocumentScrollTop(),
3856
3857
		bCanConstrain = 
3858
			(oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT) + nViewportOffset < viewPortHeight),
3859
3860
		nAvailableHeight,
3861
3862
		oContextEl,
3863
		nContextElY,
3864
		nContextElHeight,
3865
3866
		bFlipped = false,
3867
3868
		nTopRegionHeight,
3869
		nBottomRegionHeight,
3870
3871
		topConstraint = scrollY + nViewportOffset,
3872
		bottomConstraint = scrollY + viewPortHeight - nMenuOffsetHeight - nViewportOffset,
3873
3874
		yNew = y;
3875
		
3876
3877
	var flipVertical = function () {
3878
3879
		var nNewY;
3880
	
3881
		// The Menu is below the context element, flip it above
3882
		if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) { 
3883
			nNewY = (nContextElY - nMenuOffsetHeight);
3884
		}
3885
		else {	// The Menu is above the context element, flip it below
3886
			nNewY = (nContextElY + nContextElHeight);
3887
		}
3888
3889
		oMenu.cfg.setProperty(_Y, (nNewY + scrollY), true);
3890
		
3891
		return nNewY;
3892
	
3893
	};
3894
3895
3896
	/*
3897
		 Uses the context element's position to calculate the availble height 
3898
		 above and below it to display its corresponding Menu.
3899
	*/
3900
3901
	var getDisplayRegionHeight = function () {
3902
3903
		// The Menu is below the context element
3904
		if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
3905
			return (nBottomRegionHeight - nViewportOffset);				
3906
		}
3907
		else {	// The Menu is above the context element
3908
			return (nTopRegionHeight - nViewportOffset);				
3909
		}
3910
3911
	};
3912
3913
3914
	/*
3915
		Sets the Menu's "y" configuration property to the correct value based on its
3916
		current orientation.
3917
	*/ 
3918
3919
	var alignY = function () {
3920
3921
		var nNewY;
3922
3923
		if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) { 
3924
			nNewY = (nContextElY + nContextElHeight);
3925
		}
3926
		else {	
3927
			nNewY = (nContextElY - oMenuEl.offsetHeight);
3928
		}
3929
3930
		oMenu.cfg.setProperty(_Y, (nNewY + scrollY), true);
3931
	
3932
	};
3933
3934
3935
	//	Resets the maxheight of the Menu to the value set by the user
3936
3937
	var resetMaxHeight = function () {
3938
3939
		oMenu._setScrollHeight(this.cfg.getProperty(_MAX_HEIGHT));
3940
3941
		oMenu.hideEvent.unsubscribe(resetMaxHeight);
3942
	
3943
	};
3944
3945
3946
	/*
3947
		Trys to place the Menu in the best possible position (either above or 
3948
		below its corresponding context element).
3949
	*/
3950
3951
	var setVerticalPosition = function () {
3952
3953
		var nDisplayRegionHeight = getDisplayRegionHeight(),
3954
			bMenuHasItems = (oMenu.getItems().length > 0),
3955
			nMenuMinScrollHeight,
3956
			fnReturnVal;
3957
3958
3959
		if (nMenuOffsetHeight > nDisplayRegionHeight) {
3960
3961
			nMenuMinScrollHeight = 
3962
				bMenuHasItems ? oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT) : nMenuOffsetHeight;
3963
3964
3965
			if ((nDisplayRegionHeight > nMenuMinScrollHeight) && bMenuHasItems) {
3966
				nMaxHeight = nDisplayRegionHeight;
3967
			}
3968
			else {
3969
				nMaxHeight = nInitialMaxHeight;
3970
			}
3971
3972
3973
			oMenu._setScrollHeight(nMaxHeight);
3974
			oMenu.hideEvent.subscribe(resetMaxHeight);
3975
			
3976
3977
			// Re-align the Menu since its height has just changed
3978
			// as a result of the setting of the maxheight property.
3979
3980
			alignY();
3981
			
3982
3983
			if (nDisplayRegionHeight < nMenuMinScrollHeight) {
3984
3985
				if (bFlipped) {
3986
	
3987
					/*
3988
						 All possible positions and values for the "maxheight" 
3989
						 configuration property have been tried, but none were 
3990
						 successful, so fall back to the original size and position.
3991
					*/
3992
3993
					flipVertical();
3994
					
3995
				}
3996
				else {
3997
	
3998
					flipVertical();
3999
4000
					bFlipped = true;
4001
	
4002
					fnReturnVal = setVerticalPosition();
4003
	
4004
				}
4005
				
4006
			}
4007
		
4008
		}
4009
		else if (nMaxHeight && (nMaxHeight !== nInitialMaxHeight)) {
4010
		
4011
			oMenu._setScrollHeight(nInitialMaxHeight);
4012
			oMenu.hideEvent.subscribe(resetMaxHeight);
4013
4014
			// Re-align the Menu since its height has just changed
4015
			// as a result of the setting of the maxheight property.
4016
4017
			alignY();
4018
		
4019
		}
4020
4021
		return fnReturnVal;
4022
4023
	};
4024
4025
4026
	// Determine if the current value for the Menu's "y" configuration property will
4027
	// result in the Menu being positioned outside the boundaries of the viewport
4028
4029
	if (y < topConstraint || y  > bottomConstraint) {
4030
4031
		// The current value for the Menu's "y" configuration property WILL
4032
		// result in the Menu being positioned outside the boundaries of the viewport
4033
4034
		if (bCanConstrain) {
4035
4036
			if (oMenu.cfg.getProperty(_PREVENT_CONTEXT_OVERLAP) && bPotentialContextOverlap) {
4037
		
4038
				//	SOLUTION #1:
4039
				//	If the "preventcontextoverlap" configuration property is set to "true", 
4040
				//	try to flip and/or scroll the Menu to both keep it inside the boundaries of the 
4041
				//	viewport AND from overlaping its context element (MenuItem or MenuBarItem).
4042
4043
				oContextEl = aContext[0];
4044
				nContextElHeight = oContextEl.offsetHeight;
4045
				nContextElY = (Dom.getY(oContextEl) - scrollY);
4046
	
4047
				nTopRegionHeight = nContextElY;
4048
				nBottomRegionHeight = (viewPortHeight - (nContextElY + nContextElHeight));
4049
	
4050
				setVerticalPosition();
4051
				
4052
				yNew = oMenu.cfg.getProperty(_Y);
4053
		
4054
			}
4055
			else if (!(oMenu instanceof YAHOO.widget.MenuBar) && 
4056
				nMenuOffsetHeight >= viewPortHeight) {
4057
4058
				//	SOLUTION #2:
4059
				//	If the Menu exceeds the height of the viewport, introduce scroll bars
4060
				//	to keep the Menu inside the boundaries of the viewport
4061
4062
				nAvailableHeight = (viewPortHeight - (nViewportOffset * 2));
4063
		
4064
				if (nAvailableHeight > oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT)) {
4065
		
4066
					oMenu._setScrollHeight(nAvailableHeight);
4067
					oMenu.hideEvent.subscribe(resetMaxHeight);
4068
		
4069
					alignY();
4070
					
4071
					yNew = oMenu.cfg.getProperty(_Y);
4072
				
4073
				}
4074
		
4075
			}	
4076
			else {
4077
4078
				//	SOLUTION #3:
4079
			
4080
				if (y < topConstraint) {
4081
					yNew  = topConstraint;
4082
				} else if (y  > bottomConstraint) {
4083
					yNew  = bottomConstraint;
4084
				}				
4085
			
4086
			}
4087
4088
		}
4089
		else {
4090
			//	The "y" configuration property cannot be set to a value that will keep
4091
			//	entire Menu inside the boundary of the viewport.  Therefore, set  
4092
			//	the "y" configuration property to scrollY to keep as much of the 
4093
			//	Menu inside the viewport as possible.
4094
			yNew = nViewportOffset + scrollY;
4095
		}	
4096
4097
	}
4098
4099
	return yNew;
4100
4101
},
4102
4103
4104
/**
4105
* @method _onHide
4106
* @description "hide" event handler for the menu.
4107
* @private
4108
* @param {String} p_sType String representing the name of the event that 
4109
* was fired.
4110
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4111
*/
4112
_onHide: function (p_sType, p_aArgs) {
4113
4114
	if (this.cfg.getProperty(_POSITION) === _DYNAMIC) {
4115
	
4116
		this.positionOffScreen();
4117
	
4118
	}
4119
4120
},
4121
4122
4123
/**
4124
* @method _onShow
4125
* @description "show" event handler for the menu.
4126
* @private
4127
* @param {String} p_sType String representing the name of the event that 
4128
* was fired.
4129
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4130
*/
4131
_onShow: function (p_sType, p_aArgs) {
4132
4133
    var oParent = this.parent,
4134
        oParentMenu,
4135
		oElement,
4136
		nOffsetWidth,
4137
		sWidth;        
4138
4139
4140
    function disableAutoSubmenuDisplay(p_oEvent) {
4141
4142
        var oTarget;
4143
4144
        if (p_oEvent.type == _MOUSEDOWN || (p_oEvent.type == _KEYDOWN && p_oEvent.keyCode == 27)) {
4145
4146
            /*  
4147
                Set the "autosubmenudisplay" to "false" if the user
4148
                clicks outside the menu bar.
4149
            */
4150
4151
            oTarget = Event.getTarget(p_oEvent);
4152
4153
            if (oTarget != oParentMenu.element || !Dom.isAncestor(oParentMenu.element, oTarget)) {
4154
4155
                oParentMenu.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, false);
4156
4157
                Event.removeListener(document, _MOUSEDOWN, disableAutoSubmenuDisplay);
4158
                Event.removeListener(document, _KEYDOWN, disableAutoSubmenuDisplay);
4159
4160
            }
4161
        
4162
        }
4163
4164
    }
4165
4166
4167
	function onSubmenuHide(p_sType, p_aArgs, p_sWidth) {
4168
	
4169
		this.cfg.setProperty(_WIDTH, _EMPTY_STRING);
4170
		this.hideEvent.unsubscribe(onSubmenuHide, p_sWidth);
4171
	
4172
	}
4173
4174
4175
    if (oParent) {
4176
4177
        oParentMenu = oParent.parent;
4178
4179
4180
        if (!oParentMenu.cfg.getProperty(_AUTO_SUBMENU_DISPLAY) && 
4181
            (oParentMenu instanceof YAHOO.widget.MenuBar || 
4182
            oParentMenu.cfg.getProperty(_POSITION) == _STATIC)) {
4183
4184
            oParentMenu.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, true);
4185
4186
            Event.on(document, _MOUSEDOWN, disableAutoSubmenuDisplay);                             
4187
            Event.on(document, _KEYDOWN, disableAutoSubmenuDisplay);
4188
4189
        }
4190
4191
4192
		//	The following fixes an issue with the selected state of a MenuItem 
4193
		//	not rendering correctly when a submenu is aligned to the left of
4194
		//	its parent Menu instance.
4195
4196
		if ((this.cfg.getProperty("x") < oParentMenu.cfg.getProperty("x")) && 
4197
			(UA.gecko && UA.gecko < 1.9) && !this.cfg.getProperty(_WIDTH)) {
4198
4199
			oElement = this.element;
4200
			nOffsetWidth = oElement.offsetWidth;
4201
			
4202
			/*
4203
				Measuring the difference of the offsetWidth before and after
4204
				setting the "width" style attribute allows us to compute the 
4205
				about of padding and borders applied to the element, which in 
4206
				turn allows us to set the "width" property correctly.
4207
			*/
4208
			
4209
			oElement.style.width = nOffsetWidth + _PX;
4210
			
4211
			sWidth = (nOffsetWidth - (oElement.offsetWidth - nOffsetWidth)) + _PX;
4212
			
4213
			this.cfg.setProperty(_WIDTH, sWidth);
4214
		
4215
			this.hideEvent.subscribe(onSubmenuHide, sWidth);
4216
		
4217
		}
4218
4219
    }
4220
4221
4222
	/*
4223
		Dynamically positioned, root Menus focus themselves when visible, and 
4224
		will then, when hidden, restore focus to the UI control that had focus 
4225
		before the Menu was made visible.
4226
	*/ 
4227
4228
	if (this === this.getRoot() && this.cfg.getProperty(_POSITION) === _DYNAMIC) {
4229
4230
		this._focusedElement = oFocusedElement;
4231
		
4232
		this.focus();
4233
	
4234
	}
4235
4236
4237
},
4238
4239
4240
/**
4241
* @method _onBeforeHide
4242
* @description "beforehide" event handler for the menu.
4243
* @private
4244
* @param {String} p_sType String representing the name of the event that 
4245
* was fired.
4246
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4247
*/
4248
_onBeforeHide: function (p_sType, p_aArgs) {
4249
4250
    var oActiveItem = this.activeItem,
4251
        oRoot = this.getRoot(),
4252
        oConfig,
4253
        oSubmenu;
4254
4255
4256
    if (oActiveItem) {
4257
4258
        oConfig = oActiveItem.cfg;
4259
4260
        oConfig.setProperty(_SELECTED, false);
4261
4262
        oSubmenu = oConfig.getProperty(_SUBMENU);
4263
4264
        if (oSubmenu) {
4265
4266
            oSubmenu.hide();
4267
4268
        }
4269
4270
    }
4271
4272
4273
	/*
4274
		Focus can get lost in IE when the mouse is moving from a submenu back to its parent Menu.  
4275
		For this reason, it is necessary to maintain the focused state in a private property 
4276
		so that the _onMouseOver event handler is able to determined whether or not to set focus
4277
		to MenuItems as the user is moving the mouse.
4278
	*/ 
4279
4280
	if (UA.ie && this.cfg.getProperty(_POSITION) === _DYNAMIC && this.parent) {
4281
4282
		oRoot._hasFocus = this.hasFocus();
4283
	
4284
	}
4285
4286
4287
    if (oRoot == this) {
4288
4289
        oRoot.blur();
4290
    
4291
    }
4292
4293
},
4294
4295
4296
/**
4297
* @method _onParentMenuConfigChange
4298
* @description "configchange" event handler for a submenu.
4299
* @private
4300
* @param {String} p_sType String representing the name of the event that 
4301
* was fired.
4302
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4303
* @param {YAHOO.widget.Menu} p_oSubmenu Object representing the submenu that 
4304
* subscribed to the event.
4305
*/
4306
_onParentMenuConfigChange: function (p_sType, p_aArgs, p_oSubmenu) {
4307
    
4308
    var sPropertyName = p_aArgs[0][0],
4309
        oPropertyValue = p_aArgs[0][1];
4310
4311
    switch(sPropertyName) {
4312
4313
        case _IFRAME:
4314
        case _CONSTRAIN_TO_VIEWPORT:
4315
        case _HIDE_DELAY:
4316
        case _SHOW_DELAY:
4317
        case _SUBMENU_HIDE_DELAY:
4318
        case _CLICK_TO_HIDE:
4319
        case _EFFECT:
4320
        case _CLASSNAME:
4321
        case _SCROLL_INCREMENT:
4322
        case _MAX_HEIGHT:
4323
        case _MIN_SCROLL_HEIGHT:
4324
        case _MONITOR_RESIZE:
4325
        case _SHADOW:
4326
        case _PREVENT_CONTEXT_OVERLAP:
4327
		case _KEEP_OPEN:
4328
4329
            p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue);
4330
                
4331
        break;
4332
        
4333
        case _SUBMENU_ALIGNMENT:
4334
4335
			if (!(this.parent.parent instanceof YAHOO.widget.MenuBar)) {
4336
		
4337
				p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue);
4338
		
4339
			}
4340
        
4341
        break;
4342
        
4343
    }
4344
    
4345
},
4346
4347
4348
/**
4349
* @method _onParentMenuRender
4350
* @description "render" event handler for a submenu.  Renders a  
4351
* submenu in response to the firing of its parent's "render" event.
4352
* @private
4353
* @param {String} p_sType String representing the name of the event that 
4354
* was fired.
4355
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4356
* @param {YAHOO.widget.Menu} p_oSubmenu Object representing the submenu that 
4357
* subscribed to the event.
4358
*/
4359
_onParentMenuRender: function (p_sType, p_aArgs, p_oSubmenu) {
4360
4361
    var oParentMenu = p_oSubmenu.parent.parent,
4362
    	oParentCfg = oParentMenu.cfg,
4363
4364
        oConfig = {
4365
4366
            constraintoviewport: oParentCfg.getProperty(_CONSTRAIN_TO_VIEWPORT),
4367
4368
            xy: [0,0],
4369
4370
            clicktohide: oParentCfg.getProperty(_CLICK_TO_HIDE),
4371
                
4372
            effect: oParentCfg.getProperty(_EFFECT),
4373
4374
            showdelay: oParentCfg.getProperty(_SHOW_DELAY),
4375
            
4376
            hidedelay: oParentCfg.getProperty(_HIDE_DELAY),
4377
4378
            submenuhidedelay: oParentCfg.getProperty(_SUBMENU_HIDE_DELAY),
4379
4380
            classname: oParentCfg.getProperty(_CLASSNAME),
4381
            
4382
            scrollincrement: oParentCfg.getProperty(_SCROLL_INCREMENT),
4383
            
4384
			maxheight: oParentCfg.getProperty(_MAX_HEIGHT),
4385
4386
            minscrollheight: oParentCfg.getProperty(_MIN_SCROLL_HEIGHT),
4387
            
4388
            iframe: oParentCfg.getProperty(_IFRAME),
4389
            
4390
            shadow: oParentCfg.getProperty(_SHADOW),
4391
4392
			preventcontextoverlap: oParentCfg.getProperty(_PREVENT_CONTEXT_OVERLAP),
4393
            
4394
            monitorresize: oParentCfg.getProperty(_MONITOR_RESIZE),
4395
4396
			keepopen: oParentCfg.getProperty(_KEEP_OPEN)
4397
4398
        },
4399
        
4400
        oLI;
4401
4402
4403
	
4404
	if (!(oParentMenu instanceof YAHOO.widget.MenuBar)) {
4405
4406
		oConfig[_SUBMENU_ALIGNMENT] = oParentCfg.getProperty(_SUBMENU_ALIGNMENT);
4407
4408
	}
4409
4410
4411
    p_oSubmenu.cfg.applyConfig(oConfig);
4412
4413
4414
    if (!this.lazyLoad) {
4415
4416
        oLI = this.parent.element;
4417
4418
        if (this.element.parentNode == oLI) {
4419
    
4420
            this.render();
4421
    
4422
        }
4423
        else {
4424
4425
            this.render(oLI);
4426
    
4427
        }
4428
4429
    }
4430
    
4431
},
4432
4433
4434
/**
4435
* @method _onMenuItemDestroy
4436
* @description "destroy" event handler for the menu's items.
4437
* @private
4438
* @param {String} p_sType String representing the name of the event 
4439
* that was fired.
4440
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4441
* @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item 
4442
* that fired the event.
4443
*/
4444
_onMenuItemDestroy: function (p_sType, p_aArgs, p_oItem) {
4445
4446
    this._removeItemFromGroupByValue(p_oItem.groupIndex, p_oItem);
4447
4448
},
4449
4450
4451
/**
4452
* @method _onMenuItemConfigChange
4453
* @description "configchange" event handler for the menu's items.
4454
* @private
4455
* @param {String} p_sType String representing the name of the event that 
4456
* was fired.
4457
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4458
* @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item 
4459
* that fired the event.
4460
*/
4461
_onMenuItemConfigChange: function (p_sType, p_aArgs, p_oItem) {
4462
4463
    var sPropertyName = p_aArgs[0][0],
4464
        oPropertyValue = p_aArgs[0][1],
4465
        oSubmenu;
4466
4467
4468
    switch(sPropertyName) {
4469
4470
        case _SELECTED:
4471
4472
            if (oPropertyValue === true) {
4473
4474
                this.activeItem = p_oItem;
4475
            
4476
            }
4477
4478
        break;
4479
4480
        case _SUBMENU:
4481
4482
            oSubmenu = p_aArgs[0][1];
4483
4484
            if (oSubmenu) {
4485
4486
                this._configureSubmenu(p_oItem);
4487
4488
            }
4489
4490
        break;
4491
4492
    }
4493
4494
},
4495
4496
4497
4498
// Public event handlers for configuration properties
4499
4500
4501
/**
4502
* @method configVisible
4503
* @description Event handler for when the "visible" configuration property 
4504
* the menu changes.
4505
* @param {String} p_sType String representing the name of the event that 
4506
* was fired.
4507
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4508
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
4509
* fired the event.
4510
*/
4511
configVisible: function (p_sType, p_aArgs, p_oMenu) {
4512
4513
    var bVisible,
4514
        sDisplay;
4515
4516
    if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
4517
4518
        Menu.superclass.configVisible.call(this, p_sType, p_aArgs, p_oMenu);
4519
4520
    }
4521
    else {
4522
4523
        bVisible = p_aArgs[0];
4524
        sDisplay = Dom.getStyle(this.element, _DISPLAY);
4525
4526
        Dom.setStyle(this.element, _VISIBILITY, _VISIBLE);
4527
4528
        if (bVisible) {
4529
4530
            if (sDisplay != _BLOCK) {
4531
                this.beforeShowEvent.fire();
4532
                Dom.setStyle(this.element, _DISPLAY, _BLOCK);
4533
                this.showEvent.fire();
4534
            }
4535
        
4536
        }
4537
        else {
4538
4539
			if (sDisplay == _BLOCK) {
4540
				this.beforeHideEvent.fire();
4541
				Dom.setStyle(this.element, _DISPLAY, _NONE);
4542
				this.hideEvent.fire();
4543
			}
4544
        
4545
        }
4546
4547
    }
4548
4549
},
4550
4551
4552
/**
4553
* @method configPosition
4554
* @description Event handler for when the "position" configuration property 
4555
* of the menu changes.
4556
* @param {String} p_sType String representing the name of the event that 
4557
* was fired.
4558
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4559
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
4560
* fired the event.
4561
*/
4562
configPosition: function (p_sType, p_aArgs, p_oMenu) {
4563
4564
    var oElement = this.element,
4565
        sCSSPosition = p_aArgs[0] == _STATIC ? _STATIC : _ABSOLUTE,
4566
        oCfg = this.cfg,
4567
        nZIndex;
4568
4569
4570
    Dom.setStyle(oElement, _POSITION, sCSSPosition);
4571
4572
4573
    if (sCSSPosition == _STATIC) {
4574
4575
        // Statically positioned menus are visible by default
4576
        
4577
        Dom.setStyle(oElement, _DISPLAY, _BLOCK);
4578
4579
        oCfg.setProperty(_VISIBLE, true);
4580
4581
    }
4582
    else {
4583
4584
        /*
4585
            Even though the "visible" property is queued to 
4586
            "false" by default, we need to set the "visibility" property to 
4587
            "hidden" since Overlay's "configVisible" implementation checks the 
4588
            element's "visibility" style property before deciding whether 
4589
            or not to show an Overlay instance.
4590
        */
4591
4592
        Dom.setStyle(oElement, _VISIBILITY, _HIDDEN);
4593
    
4594
    }
4595
4596
  	 
4597
     if (sCSSPosition == _ABSOLUTE) { 	 
4598
  	 
4599
         nZIndex = oCfg.getProperty(_ZINDEX);
4600
  	 
4601
         if (!nZIndex || nZIndex === 0) { 	 
4602
  	 
4603
             oCfg.setProperty(_ZINDEX, 1); 	 
4604
  	 
4605
         } 	 
4606
  	 
4607
     }
4608
4609
},
4610
4611
4612
/**
4613
* @method configIframe
4614
* @description Event handler for when the "iframe" configuration property of 
4615
* the menu changes.
4616
* @param {String} p_sType String representing the name of the event that 
4617
* was fired.
4618
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4619
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
4620
* fired the event.
4621
*/
4622
configIframe: function (p_sType, p_aArgs, p_oMenu) {    
4623
4624
    if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
4625
4626
        Menu.superclass.configIframe.call(this, p_sType, p_aArgs, p_oMenu);
4627
4628
    }
4629
4630
},
4631
4632
4633
/**
4634
* @method configHideDelay
4635
* @description Event handler for when the "hidedelay" configuration property 
4636
* of the menu changes.
4637
* @param {String} p_sType String representing the name of the event that 
4638
* was fired.
4639
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4640
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
4641
* fired the event.
4642
*/
4643
configHideDelay: function (p_sType, p_aArgs, p_oMenu) {
4644
4645
    var nHideDelay = p_aArgs[0];
4646
4647
	this._useHideDelay = (nHideDelay > 0);
4648
4649
},
4650
4651
4652
/**
4653
* @method configContainer
4654
* @description Event handler for when the "container" configuration property 
4655
* of the menu changes.
4656
* @param {String} p_sType String representing the name of the event that 
4657
* was fired.
4658
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4659
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
4660
* fired the event.
4661
*/
4662
configContainer: function (p_sType, p_aArgs, p_oMenu) {
4663
4664
	var oElement = p_aArgs[0];
4665
4666
	if (Lang.isString(oElement)) {
4667
4668
        this.cfg.setProperty(_CONTAINER, Dom.get(oElement), true);
4669
4670
	}
4671
4672
},
4673
4674
4675
/**
4676
* @method _clearSetWidthFlag
4677
* @description Change event listener for the "width" configuration property.  This listener is 
4678
* added when a Menu's "width" configuration property is set by the "_setScrollHeight" method, and 
4679
* is used to set the "_widthSetForScroll" property to "false" if the "width" configuration property 
4680
* is changed after it was set by the "_setScrollHeight" method.  If the "_widthSetForScroll" 
4681
* property is set to "false", and the "_setScrollHeight" method is in the process of tearing down 
4682
* scrolling functionality, it will maintain the Menu's new width rather than reseting it.
4683
* @private
4684
*/
4685
_clearSetWidthFlag: function () {
4686
4687
	this._widthSetForScroll = false;
4688
	
4689
	this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4690
4691
},
4692
4693
4694
/**
4695
* @method _setScrollHeight
4696
* @description 
4697
* @param {String} p_nScrollHeight Number representing the scrolling height of the Menu.
4698
* @private
4699
*/
4700
_setScrollHeight: function (p_nScrollHeight) {
4701
4702
    var nScrollHeight = p_nScrollHeight,
4703
		bRefireIFrameAndShadow = false,
4704
		bSetWidth = false,
4705
        oElement,
4706
        oBody,
4707
        oHeader,
4708
        oFooter,
4709
        fnMouseOver,
4710
        fnMouseOut,
4711
        nMinScrollHeight,
4712
        nHeight,
4713
        nOffsetWidth,
4714
        sWidth;
4715
4716
4717
	if (this.getItems().length > 0) {
4718
	
4719
        oElement = this.element;
4720
        oBody = this.body;
4721
        oHeader = this.header;
4722
        oFooter = this.footer;
4723
        fnMouseOver = this._onScrollTargetMouseOver;
4724
        fnMouseOut = this._onScrollTargetMouseOut;
4725
        nMinScrollHeight = this.cfg.getProperty(_MIN_SCROLL_HEIGHT);
4726
4727
4728
		if (nScrollHeight > 0 && nScrollHeight < nMinScrollHeight) {
4729
		
4730
			nScrollHeight = nMinScrollHeight;
4731
		
4732
		}
4733
4734
4735
		Dom.setStyle(oBody, _HEIGHT, _EMPTY_STRING);
4736
		Dom.removeClass(oBody, _YUI_MENU_BODY_SCROLLED);
4737
		oBody.scrollTop = 0;
4738
4739
4740
		//	Need to set a width for the Menu to fix the following problems in 
4741
		//	Firefox 2 and IE:
4742
4743
		//	#1) Scrolled Menus will render at 1px wide in Firefox 2
4744
4745
		//	#2) There is a bug in gecko-based browsers where an element whose 
4746
		//	"position" property is set to "absolute" and "overflow" property is 
4747
		//	set to "hidden" will not render at the correct width when its 
4748
		//	offsetParent's "position" property is also set to "absolute."  It is 
4749
		//	possible to work around this bug by specifying a value for the width 
4750
		//	property in addition to overflow.
4751
4752
		//	#3) In IE it is necessary to give the Menu a width before the 
4753
		//	scrollbars are rendered to prevent the Menu from rendering with a 
4754
		//	width that is 100% of the browser viewport.
4755
	
4756
		bSetWidth = ((UA.gecko && UA.gecko < 1.9) || UA.ie);
4757
4758
		if (nScrollHeight > 0 && bSetWidth && !this.cfg.getProperty(_WIDTH)) {
4759
4760
			nOffsetWidth = oElement.offsetWidth;
4761
	
4762
			/*
4763
				Measuring the difference of the offsetWidth before and after
4764
				setting the "width" style attribute allows us to compute the 
4765
				about of padding and borders applied to the element, which in 
4766
				turn allows us to set the "width" property correctly.
4767
			*/
4768
			
4769
			oElement.style.width = nOffsetWidth + _PX;
4770
	
4771
			sWidth = (nOffsetWidth - (oElement.offsetWidth - nOffsetWidth)) + _PX;
4772
4773
4774
			this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4775
4776
			YAHOO.log("Setting the \"width\" configuration property to " + sWidth + " for srolling.", 
4777
				"info", this.toString());
4778
4779
			this.cfg.setProperty(_WIDTH, sWidth);
4780
4781
4782
			/*
4783
				Set a flag (_widthSetForScroll) to maintain some history regarding how the 
4784
				"width" configuration property was set.  If the "width" configuration property 
4785
				is set by something other than the "_setScrollHeight" method, it will be 
4786
				necessary to maintain that new value and not clear the width if scrolling 
4787
				is turned off.
4788
			*/
4789
4790
			this._widthSetForScroll = true;
4791
4792
			this.cfg.subscribeToConfigEvent(_WIDTH, this._clearSetWidthFlag);
4793
	
4794
		}
4795
	
4796
	
4797
		if (nScrollHeight > 0 && (!oHeader && !oFooter)) {
4798
	
4799
			YAHOO.log("Creating header and footer for scrolling.", "info", this.toString());
4800
	
4801
			this.setHeader(_NON_BREAKING_SPACE);
4802
			this.setFooter(_NON_BREAKING_SPACE);
4803
	
4804
			oHeader = this.header;
4805
			oFooter = this.footer;
4806
	
4807
			Dom.addClass(oHeader, _TOP_SCROLLBAR);
4808
			Dom.addClass(oFooter, _BOTTOM_SCROLLBAR);
4809
			
4810
			oElement.insertBefore(oHeader, oBody);
4811
			oElement.appendChild(oFooter);
4812
		
4813
		}
4814
	
4815
	
4816
		nHeight = nScrollHeight;
4817
	
4818
	
4819
		if (oHeader && oFooter) {
4820
			nHeight = (nHeight - (oHeader.offsetHeight + oFooter.offsetHeight));
4821
		}
4822
	
4823
	
4824
		if ((nHeight > 0) && (oBody.offsetHeight > nScrollHeight)) {
4825
4826
			YAHOO.log("Setting up styles and event handlers for scrolling.", 
4827
				"info", this.toString());
4828
	
4829
			Dom.addClass(oBody, _YUI_MENU_BODY_SCROLLED);
4830
			Dom.setStyle(oBody, _HEIGHT, (nHeight + _PX));
4831
4832
			if (!this._hasScrollEventHandlers) {
4833
	
4834
				Event.on(oHeader, _MOUSEOVER, fnMouseOver, this, true);
4835
				Event.on(oHeader, _MOUSEOUT, fnMouseOut, this, true);
4836
				Event.on(oFooter, _MOUSEOVER, fnMouseOver, this, true);
4837
				Event.on(oFooter, _MOUSEOUT, fnMouseOut, this, true);
4838
	
4839
				this._hasScrollEventHandlers = true;
4840
	
4841
			}
4842
	
4843
			this._disableScrollHeader();
4844
			this._enableScrollFooter();
4845
			
4846
			bRefireIFrameAndShadow = true;			
4847
	
4848
		}
4849
		else if (oHeader && oFooter) {
4850
4851
			YAHOO.log("Removing styles and event handlers for scrolling.", "info", this.toString());
4852
	
4853
4854
			/*
4855
				Only clear the "width" configuration property if it was set the
4856
				"_setScrollHeight" method and wasn't changed by some other means after it was set.
4857
			*/	
4858
	
4859
			if (this._widthSetForScroll) {
4860
	
4861
				YAHOO.log("Clearing width used for scrolling.", "info", this.toString());
4862
4863
				this._widthSetForScroll = false;
4864
4865
				this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4866
	
4867
				this.cfg.setProperty(_WIDTH, _EMPTY_STRING);
4868
			
4869
			}
4870
	
4871
	
4872
			this._enableScrollHeader();
4873
			this._enableScrollFooter();
4874
	
4875
			if (this._hasScrollEventHandlers) {
4876
	
4877
				Event.removeListener(oHeader, _MOUSEOVER, fnMouseOver);
4878
				Event.removeListener(oHeader, _MOUSEOUT, fnMouseOut);
4879
				Event.removeListener(oFooter, _MOUSEOVER, fnMouseOver);
4880
				Event.removeListener(oFooter, _MOUSEOUT, fnMouseOut);
4881
4882
				this._hasScrollEventHandlers = false;
4883
	
4884
			}
4885
4886
			oElement.removeChild(oHeader);
4887
			oElement.removeChild(oFooter);
4888
	
4889
			this.header = null;
4890
			this.footer = null;
4891
			
4892
			bRefireIFrameAndShadow = true;
4893
		
4894
		}
4895
4896
4897
		if (bRefireIFrameAndShadow) {
4898
	
4899
			this.cfg.refireEvent(_IFRAME);
4900
			this.cfg.refireEvent(_SHADOW);
4901
		
4902
		}
4903
	
4904
	}
4905
4906
},
4907
4908
4909
/**
4910
* @method _setMaxHeight
4911
* @description "renderEvent" handler used to defer the setting of the 
4912
* "maxheight" configuration property until the menu is rendered in lazy 
4913
* load scenarios.
4914
* @param {String} p_sType The name of the event that was fired.
4915
* @param {Array} p_aArgs Collection of arguments sent when the event 
4916
* was fired.
4917
* @param {Number} p_nMaxHeight Number representing the value to set for the 
4918
* "maxheight" configuration property.
4919
* @private
4920
*/
4921
_setMaxHeight: function (p_sType, p_aArgs, p_nMaxHeight) {
4922
4923
    this._setScrollHeight(p_nMaxHeight);
4924
    this.renderEvent.unsubscribe(this._setMaxHeight);
4925
4926
},
4927
4928
4929
/**
4930
* @method configMaxHeight
4931
* @description Event handler for when the "maxheight" configuration property of 
4932
* a Menu changes.
4933
* @param {String} p_sType The name of the event that was fired.
4934
* @param {Array} p_aArgs Collection of arguments sent when the event 
4935
* was fired.
4936
* @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired
4937
* the event.
4938
*/
4939
configMaxHeight: function (p_sType, p_aArgs, p_oMenu) {
4940
4941
	var nMaxHeight = p_aArgs[0];
4942
4943
	if (this.lazyLoad && !this.body && nMaxHeight > 0) {
4944
	
4945
		this.renderEvent.subscribe(this._setMaxHeight, nMaxHeight, this);
4946
4947
	}
4948
	else {
4949
4950
		this._setScrollHeight(nMaxHeight);
4951
	
4952
	}
4953
4954
},
4955
4956
4957
/**
4958
* @method configClassName
4959
* @description Event handler for when the "classname" configuration property of 
4960
* a menu changes.
4961
* @param {String} p_sType The name of the event that was fired.
4962
* @param {Array} p_aArgs Collection of arguments sent when the event was fired.
4963
* @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
4964
*/
4965
configClassName: function (p_sType, p_aArgs, p_oMenu) {
4966
4967
    var sClassName = p_aArgs[0];
4968
4969
    if (this._sClassName) {
4970
4971
        Dom.removeClass(this.element, this._sClassName);
4972
4973
    }
4974
4975
    Dom.addClass(this.element, sClassName);
4976
    this._sClassName = sClassName;
4977
4978
},
4979
4980
4981
/**
4982
* @method _onItemAdded
4983
* @description "itemadded" event handler for a Menu instance.
4984
* @private
4985
* @param {String} p_sType The name of the event that was fired.
4986
* @param {Array} p_aArgs Collection of arguments sent when the event 
4987
* was fired.
4988
*/
4989
_onItemAdded: function (p_sType, p_aArgs) {
4990
4991
    var oItem = p_aArgs[0];
4992
    
4993
    if (oItem) {
4994
4995
        oItem.cfg.setProperty(_DISABLED, true);
4996
    
4997
    }
4998
4999
},
5000
5001
5002
/**
5003
* @method configDisabled
5004
* @description Event handler for when the "disabled" configuration property of 
5005
* a menu changes.
5006
* @param {String} p_sType The name of the event that was fired.
5007
* @param {Array} p_aArgs Collection of arguments sent when the event was fired.
5008
* @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
5009
*/
5010
configDisabled: function (p_sType, p_aArgs, p_oMenu) {
5011
5012
    var bDisabled = p_aArgs[0],
5013
        aItems = this.getItems(),
5014
        nItems,
5015
        i;
5016
5017
    if (Lang.isArray(aItems)) {
5018
5019
        nItems = aItems.length;
5020
    
5021
        if (nItems > 0) {
5022
        
5023
            i = nItems - 1;
5024
    
5025
            do {
5026
    
5027
                aItems[i].cfg.setProperty(_DISABLED, bDisabled);
5028
            
5029
            }
5030
            while (i--);
5031
        
5032
        }
5033
5034
5035
        if (bDisabled) {
5036
5037
            this.clearActiveItem(true);
5038
5039
            Dom.addClass(this.element, _DISABLED);
5040
5041
            this.itemAddedEvent.subscribe(this._onItemAdded);
5042
5043
        }
5044
        else {
5045
5046
            Dom.removeClass(this.element, _DISABLED);
5047
5048
            this.itemAddedEvent.unsubscribe(this._onItemAdded);
5049
5050
        }
5051
        
5052
    }
5053
5054
},
5055
5056
5057
/**
5058
* @method configShadow
5059
* @description Event handler for when the "shadow" configuration property of 
5060
* a menu changes.
5061
* @param {String} p_sType The name of the event that was fired.
5062
* @param {Array} p_aArgs Collection of arguments sent when the event was fired.
5063
* @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
5064
*/
5065
configShadow: function (p_sType, p_aArgs, p_oMenu) {
5066
5067
    var sizeShadow = function () {
5068
5069
        var oElement = this.element,
5070
            oShadow = this._shadow;
5071
    
5072
        if (oShadow && oElement) {
5073
5074
			// Clear the previous width
5075
5076
			if (oShadow.style.width && oShadow.style.height) {
5077
			
5078
				oShadow.style.width = _EMPTY_STRING;
5079
				oShadow.style.height = _EMPTY_STRING;
5080
			
5081
			}
5082
5083
            oShadow.style.width = (oElement.offsetWidth + 6) + _PX;
5084
            oShadow.style.height = (oElement.offsetHeight + 1) + _PX;
5085
            
5086
        }
5087
    
5088
    };
5089
5090
5091
    var replaceShadow = function () {
5092
5093
        this.element.appendChild(this._shadow);
5094
5095
    };
5096
5097
5098
    var addShadowVisibleClass = function () {
5099
    
5100
        Dom.addClass(this._shadow, _YUI_MENU_SHADOW_VISIBLE);
5101
    
5102
    };
5103
    
5104
5105
    var removeShadowVisibleClass = function () {
5106
5107
        Dom.removeClass(this._shadow, _YUI_MENU_SHADOW_VISIBLE);
5108
    
5109
    };
5110
5111
5112
    var createShadow = function () {
5113
5114
        var oShadow = this._shadow,
5115
            oElement;
5116
5117
        if (!oShadow) {
5118
5119
            oElement = this.element;
5120
5121
5122
            if (!m_oShadowTemplate) {
5123
5124
                m_oShadowTemplate = document.createElement(_DIV_LOWERCASE);
5125
                m_oShadowTemplate.className = _YUI_MENU_SHADOW_YUI_MENU_SHADOW_VISIBLE;
5126
            
5127
            }
5128
5129
            oShadow = m_oShadowTemplate.cloneNode(false);
5130
5131
            oElement.appendChild(oShadow);
5132
            
5133
            this._shadow = oShadow;
5134
5135
            this.beforeShowEvent.subscribe(addShadowVisibleClass);
5136
            this.beforeHideEvent.subscribe(removeShadowVisibleClass);
5137
5138
5139
            if (UA.ie) {
5140
        
5141
                /*
5142
                     Need to call sizeShadow & syncIframe via setTimeout for 
5143
                     IE 7 Quirks Mode and IE 6 Standards Mode and Quirks Mode 
5144
                     or the shadow and iframe shim will not be sized and 
5145
                     positioned properly.
5146
                */
5147
        
5148
				Lang.later(0, this, function () {
5149
5150
                    sizeShadow.call(this); 
5151
                    this.syncIframe();
5152
				
5153
				});
5154
5155
5156
                this.cfg.subscribeToConfigEvent(_WIDTH, sizeShadow);
5157
                this.cfg.subscribeToConfigEvent(_HEIGHT, sizeShadow);
5158
                this.cfg.subscribeToConfigEvent(_MAX_HEIGHT, sizeShadow);
5159
                this.changeContentEvent.subscribe(sizeShadow);
5160
5161
                Module.textResizeEvent.subscribe(sizeShadow, this, true);
5162
                
5163
                this.destroyEvent.subscribe(function () {
5164
                
5165
                    Module.textResizeEvent.unsubscribe(sizeShadow, this);
5166
                
5167
                });
5168
        
5169
            }
5170
5171
            this.cfg.subscribeToConfigEvent(_MAX_HEIGHT, replaceShadow);
5172
5173
        }
5174
5175
    };
5176
5177
5178
    var onBeforeShow = function () {
5179
5180
    	if (this._shadow) {
5181
5182
			// If called because the "shadow" event was refired - just append again and resize
5183
			
5184
			replaceShadow.call(this);
5185
			
5186
			if (UA.ie) {
5187
				sizeShadow.call(this);
5188
			}
5189
    	
5190
    	}
5191
    	else {
5192
    
5193
        	createShadow.call(this);
5194
        
5195
        }
5196
5197
        this.beforeShowEvent.unsubscribe(onBeforeShow);
5198
    
5199
    };
5200
5201
5202
	var bShadow = p_aArgs[0];
5203
5204
5205
    if (bShadow && this.cfg.getProperty(_POSITION) == _DYNAMIC) {
5206
5207
        if (this.cfg.getProperty(_VISIBLE)) {
5208
5209
			if (this._shadow) {
5210
5211
				// If the "shadow" event was refired - just append again and resize
5212
				
5213
				replaceShadow.call(this);
5214
				
5215
				if (UA.ie) {
5216
					sizeShadow.call(this);
5217
				}
5218
				
5219
			} 
5220
			else {
5221
            	createShadow.call(this);
5222
            }
5223
        
5224
        }
5225
        else {
5226
5227
            this.beforeShowEvent.subscribe(onBeforeShow);
5228
        
5229
        }
5230
    
5231
    }
5232
    
5233
},
5234
5235
5236
5237
// Public methods
5238
5239
5240
/**
5241
* @method initEvents
5242
* @description Initializes the custom events for the menu.
5243
*/
5244
initEvents: function () {
5245
5246
	Menu.superclass.initEvents.call(this);
5247
5248
    // Create custom events
5249
5250
	var i = EVENT_TYPES.length - 1,
5251
		aEventData,
5252
		oCustomEvent;
5253
5254
5255
	do {
5256
5257
		aEventData = EVENT_TYPES[i];
5258
5259
		oCustomEvent = this.createEvent(aEventData[1]);
5260
		oCustomEvent.signature = CustomEvent.LIST;
5261
		
5262
		this[aEventData[0]] = oCustomEvent;
5263
5264
	}
5265
	while (i--);
5266
5267
},
5268
5269
5270
/**
5271
* @method positionOffScreen
5272
* @description Positions the menu outside of the boundaries of the browser's 
5273
* viewport.  Called automatically when a menu is hidden to ensure that 
5274
* it doesn't force the browser to render uncessary scrollbars.
5275
*/
5276
positionOffScreen: function () {
5277
5278
    var oIFrame = this.iframe,
5279
    	oElement = this.element,
5280
        sPos = this.OFF_SCREEN_POSITION;
5281
    
5282
    oElement.style.top = _EMPTY_STRING;
5283
    oElement.style.left = _EMPTY_STRING;
5284
    
5285
    if (oIFrame) {
5286
5287
		oIFrame.style.top = sPos;
5288
		oIFrame.style.left = sPos;
5289
    
5290
    }
5291
5292
},
5293
5294
5295
/**
5296
* @method getRoot
5297
* @description Finds the menu's root menu.
5298
*/
5299
getRoot: function () {
5300
5301
    var oItem = this.parent,
5302
        oParentMenu,
5303
        returnVal;
5304
5305
    if (oItem) {
5306
5307
        oParentMenu = oItem.parent;
5308
5309
        returnVal = oParentMenu ? oParentMenu.getRoot() : this;
5310
5311
    }
5312
    else {
5313
    
5314
        returnVal = this;
5315
    
5316
    }
5317
    
5318
    return returnVal;
5319
5320
},
5321
5322
5323
/**
5324
* @method toString
5325
* @description Returns a string representing the menu.
5326
* @return {String}
5327
*/
5328
toString: function () {
5329
5330
    var sReturnVal = _MENU,
5331
        sId = this.id;
5332
5333
    if (sId) {
5334
5335
        sReturnVal += (_SPACE + sId);
5336
    
5337
    }
5338
5339
    return sReturnVal;
5340
5341
},
5342
5343
5344
/**
5345
* @method setItemGroupTitle
5346
* @description Sets the title of a group of menu items.
5347
* @param {String} p_sGroupTitle String specifying the title of the group.
5348
* @param {Number} p_nGroupIndex Optional. Number specifying the group to which
5349
* the title belongs.
5350
*/
5351
setItemGroupTitle: function (p_sGroupTitle, p_nGroupIndex) {
5352
5353
    var nGroupIndex,
5354
        oTitle,
5355
        i,
5356
        nFirstIndex;
5357
        
5358
    if (Lang.isString(p_sGroupTitle) && p_sGroupTitle.length > 0) {
5359
5360
        nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0;
5361
        oTitle = this._aGroupTitleElements[nGroupIndex];
5362
5363
5364
        if (oTitle) {
5365
5366
            oTitle.innerHTML = p_sGroupTitle;
5367
            
5368
        }
5369
        else {
5370
5371
            oTitle = document.createElement(this.GROUP_TITLE_TAG_NAME);
5372
                    
5373
            oTitle.innerHTML = p_sGroupTitle;
5374
5375
            this._aGroupTitleElements[nGroupIndex] = oTitle;
5376
5377
        }
5378
5379
5380
        i = this._aGroupTitleElements.length - 1;
5381
5382
        do {
5383
5384
            if (this._aGroupTitleElements[i]) {
5385
5386
                Dom.removeClass(this._aGroupTitleElements[i], _FIRST_OF_TYPE);
5387
5388
                nFirstIndex = i;
5389
5390
            }
5391
5392
        }
5393
        while (i--);
5394
5395
5396
        if (nFirstIndex !== null) {
5397
5398
            Dom.addClass(this._aGroupTitleElements[nFirstIndex], 
5399
                _FIRST_OF_TYPE);
5400
5401
        }
5402
5403
        this.changeContentEvent.fire();
5404
5405
    }
5406
5407
},
5408
5409
5410
5411
/**
5412
* @method addItem
5413
* @description Appends an item to the menu.
5414
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem 
5415
* instance to be added to the menu.
5416
* @param {String} p_oItem String specifying the text of the item to be added 
5417
* to the menu.
5418
* @param {Object} p_oItem Object literal containing a set of menu item 
5419
* configuration properties.
5420
* @param {Number} p_nGroupIndex Optional. Number indicating the group to
5421
* which the item belongs.
5422
* @return {YAHOO.widget.MenuItem}
5423
*/
5424
addItem: function (p_oItem, p_nGroupIndex) {
5425
5426
	return this._addItemToGroup(p_nGroupIndex, p_oItem);
5427
5428
},
5429
5430
5431
/**
5432
* @method addItems
5433
* @description Adds an array of items to the menu.
5434
* @param {Array} p_aItems Array of items to be added to the menu.  The array 
5435
* can contain strings specifying the text for each item to be created, object
5436
* literals specifying each of the menu item configuration properties, 
5437
* or MenuItem instances.
5438
* @param {Number} p_nGroupIndex Optional. Number specifying the group to 
5439
* which the items belongs.
5440
* @return {Array}
5441
*/
5442
addItems: function (p_aItems, p_nGroupIndex) {
5443
5444
    var nItems,
5445
        aItems,
5446
        oItem,
5447
        i,
5448
        returnVal;
5449
5450
5451
    if (Lang.isArray(p_aItems)) {
5452
5453
        nItems = p_aItems.length;
5454
        aItems = [];
5455
5456
        for(i=0; i<nItems; i++) {
5457
5458
            oItem = p_aItems[i];
5459
5460
            if (oItem) {
5461
5462
                if (Lang.isArray(oItem)) {
5463
    
5464
                    aItems[aItems.length] = this.addItems(oItem, i);
5465
    
5466
                }
5467
                else {
5468
    
5469
                    aItems[aItems.length] = this._addItemToGroup(p_nGroupIndex, oItem);
5470
                
5471
                }
5472
5473
            }
5474
    
5475
        }
5476
5477
5478
        if (aItems.length) {
5479
        
5480
            returnVal = aItems;
5481
        
5482
        }
5483
5484
    }
5485
5486
	return returnVal;
5487
5488
},
5489
5490
5491
/**
5492
* @method insertItem
5493
* @description Inserts an item into the menu at the specified index.
5494
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem 
5495
* instance to be added to the menu.
5496
* @param {String} p_oItem String specifying the text of the item to be added 
5497
* to the menu.
5498
* @param {Object} p_oItem Object literal containing a set of menu item 
5499
* configuration properties.
5500
* @param {Number} p_nItemIndex Number indicating the ordinal position at which
5501
* the item should be added.
5502
* @param {Number} p_nGroupIndex Optional. Number indicating the group to which 
5503
* the item belongs.
5504
* @return {YAHOO.widget.MenuItem}
5505
*/
5506
insertItem: function (p_oItem, p_nItemIndex, p_nGroupIndex) {
5507
    
5508
	return this._addItemToGroup(p_nGroupIndex, p_oItem, p_nItemIndex);
5509
5510
},
5511
5512
5513
/**
5514
* @method removeItem
5515
* @description Removes the specified item from the menu.
5516
* @param {YAHOO.widget.MenuItem} p_oObject Object reference for the MenuItem 
5517
* instance to be removed from the menu.
5518
* @param {Number} p_oObject Number specifying the index of the item 
5519
* to be removed.
5520
* @param {Number} p_nGroupIndex Optional. Number specifying the group to 
5521
* which the item belongs.
5522
* @return {YAHOO.widget.MenuItem}
5523
*/
5524
removeItem: function (p_oObject, p_nGroupIndex) {
5525
5526
    var oItem,
5527
    	returnVal;
5528
    
5529
    if (!Lang.isUndefined(p_oObject)) {
5530
5531
        if (p_oObject instanceof YAHOO.widget.MenuItem) {
5532
5533
            oItem = this._removeItemFromGroupByValue(p_nGroupIndex, p_oObject);           
5534
5535
        }
5536
        else if (Lang.isNumber(p_oObject)) {
5537
5538
            oItem = this._removeItemFromGroupByIndex(p_nGroupIndex, p_oObject);
5539
5540
        }
5541
5542
        if (oItem) {
5543
5544
            oItem.destroy();
5545
5546
            YAHOO.log("Item removed." + 
5547
                " Text: " + oItem.cfg.getProperty("text") + ", " + 
5548
                " Index: " + oItem.index + ", " + 
5549
                " Group Index: " + oItem.groupIndex, "info", this.toString());
5550
5551
            returnVal = oItem;
5552
5553
        }
5554
5555
    }
5556
5557
	return returnVal;
5558
5559
},
5560
5561
5562
/**
5563
* @method getItems
5564
* @description Returns an array of all of the items in the menu.
5565
* @return {Array}
5566
*/
5567
getItems: function () {
5568
5569
    var aGroups = this._aItemGroups,
5570
        nGroups,
5571
        returnVal,
5572
        aItems = [];
5573
5574
5575
    if (Lang.isArray(aGroups)) {
5576
5577
        nGroups = aGroups.length;
5578
5579
        returnVal = ((nGroups == 1) ? aGroups[0] : (Array.prototype.concat.apply(aItems, aGroups)));
5580
5581
    }
5582
5583
	return returnVal;
5584
5585
},
5586
5587
5588
/**
5589
* @method getItemGroups
5590
* @description Multi-dimensional Array representing the menu items as they 
5591
* are grouped in the menu.
5592
* @return {Array}
5593
*/        
5594
getItemGroups: function () {
5595
5596
    return this._aItemGroups;
5597
5598
},
5599
5600
5601
/**
5602
* @method getItem
5603
* @description Returns the item at the specified index.
5604
* @param {Number} p_nItemIndex Number indicating the ordinal position of the 
5605
* item to be retrieved.
5606
* @param {Number} p_nGroupIndex Optional. Number indicating the group to which 
5607
* the item belongs.
5608
* @return {YAHOO.widget.MenuItem}
5609
*/
5610
getItem: function (p_nItemIndex, p_nGroupIndex) {
5611
    
5612
    var aGroup,
5613
    	returnVal;
5614
    
5615
    if (Lang.isNumber(p_nItemIndex)) {
5616
5617
        aGroup = this._getItemGroup(p_nGroupIndex);
5618
5619
        if (aGroup) {
5620
5621
            returnVal = aGroup[p_nItemIndex];
5622
        
5623
        }
5624
5625
    }
5626
    
5627
    return returnVal;
5628
    
5629
},
5630
5631
5632
/**
5633
* @method getSubmenus
5634
* @description Returns an array of all of the submenus that are immediate 
5635
* children of the menu.
5636
* @return {Array}
5637
*/
5638
getSubmenus: function () {
5639
5640
    var aItems = this.getItems(),
5641
        nItems = aItems.length,
5642
        aSubmenus,
5643
        oSubmenu,
5644
        oItem,
5645
        i;
5646
5647
5648
    if (nItems > 0) {
5649
        
5650
        aSubmenus = [];
5651
5652
        for(i=0; i<nItems; i++) {
5653
5654
            oItem = aItems[i];
5655
            
5656
            if (oItem) {
5657
5658
                oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5659
                
5660
                if (oSubmenu) {
5661
5662
                    aSubmenus[aSubmenus.length] = oSubmenu;
5663
5664
                }
5665
            
5666
            }
5667
        
5668
        }
5669
    
5670
    }
5671
5672
    return aSubmenus;
5673
5674
},
5675
5676
5677
/**
5678
* @method clearContent
5679
* @description Removes all of the content from the menu, including the menu 
5680
* items, group titles, header and footer.
5681
*/
5682
clearContent: function () {
5683
5684
    var aItems = this.getItems(),
5685
        nItems = aItems.length,
5686
        oElement = this.element,
5687
        oBody = this.body,
5688
        oHeader = this.header,
5689
        oFooter = this.footer,
5690
        oItem,
5691
        oSubmenu,
5692
        i;
5693
5694
5695
    if (nItems > 0) {
5696
5697
        i = nItems - 1;
5698
5699
        do {
5700
5701
            oItem = aItems[i];
5702
5703
            if (oItem) {
5704
5705
                oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5706
5707
                if (oSubmenu) {
5708
5709
                    this.cfg.configChangedEvent.unsubscribe(
5710
                        this._onParentMenuConfigChange, oSubmenu);
5711
5712
                    this.renderEvent.unsubscribe(this._onParentMenuRender, 
5713
                        oSubmenu);
5714
5715
                }
5716
                
5717
                this.removeItem(oItem, oItem.groupIndex);
5718
5719
            }
5720
        
5721
        }
5722
        while (i--);
5723
5724
    }
5725
5726
5727
    if (oHeader) {
5728
5729
        Event.purgeElement(oHeader);
5730
        oElement.removeChild(oHeader);
5731
5732
    }
5733
    
5734
5735
    if (oFooter) {
5736
5737
        Event.purgeElement(oFooter);
5738
        oElement.removeChild(oFooter);
5739
    }
5740
5741
5742
    if (oBody) {
5743
5744
        Event.purgeElement(oBody);
5745
5746
        oBody.innerHTML = _EMPTY_STRING;
5747
5748
    }
5749
5750
    this.activeItem = null;
5751
5752
    this._aItemGroups = [];
5753
    this._aListElements = [];
5754
    this._aGroupTitleElements = [];
5755
5756
    this.cfg.setProperty(_WIDTH, null);
5757
5758
},
5759
5760
5761
/**
5762
* @method destroy
5763
* @description Removes the menu's <code>&#60;div&#62;</code> element 
5764
* (and accompanying child nodes) from the document.
5765
*/
5766
destroy: function () {
5767
5768
    // Remove all items
5769
5770
    this.clearContent();
5771
5772
    this._aItemGroups = null;
5773
    this._aListElements = null;
5774
    this._aGroupTitleElements = null;
5775
5776
5777
    // Continue with the superclass implementation of this method
5778
5779
    Menu.superclass.destroy.call(this);
5780
    
5781
    YAHOO.log("Destroyed.", "info", this.toString());
5782
5783
},
5784
5785
5786
/**
5787
* @method setInitialFocus
5788
* @description Sets focus to the menu's first enabled item.
5789
*/
5790
setInitialFocus: function () {
5791
5792
    var oItem = this._getFirstEnabledItem();
5793
    
5794
    if (oItem) {
5795
5796
        oItem.focus();
5797
5798
    }
5799
    
5800
},
5801
5802
5803
/**
5804
* @method setInitialSelection
5805
* @description Sets the "selected" configuration property of the menu's first 
5806
* enabled item to "true."
5807
*/
5808
setInitialSelection: function () {
5809
5810
    var oItem = this._getFirstEnabledItem();
5811
    
5812
    if (oItem) {
5813
    
5814
        oItem.cfg.setProperty(_SELECTED, true);
5815
    }        
5816
5817
},
5818
5819
5820
/**
5821
* @method clearActiveItem
5822
* @description Sets the "selected" configuration property of the menu's active
5823
* item to "false" and hides the item's submenu.
5824
* @param {Boolean} p_bBlur Boolean indicating if the menu's active item 
5825
* should be blurred.  
5826
*/
5827
clearActiveItem: function (p_bBlur) {
5828
5829
    if (this.cfg.getProperty(_SHOW_DELAY) > 0) {
5830
    
5831
        this._cancelShowDelay();
5832
    
5833
    }
5834
5835
5836
    var oActiveItem = this.activeItem,
5837
        oConfig,
5838
        oSubmenu;
5839
5840
    if (oActiveItem) {
5841
5842
        oConfig = oActiveItem.cfg;
5843
5844
        if (p_bBlur) {
5845
5846
            oActiveItem.blur();
5847
            
5848
            this.getRoot()._hasFocus = true;
5849
        
5850
        }
5851
5852
        oConfig.setProperty(_SELECTED, false);
5853
5854
        oSubmenu = oConfig.getProperty(_SUBMENU);
5855
5856
5857
        if (oSubmenu) {
5858
5859
            oSubmenu.hide();
5860
5861
        }
5862
5863
        this.activeItem = null;  
5864
5865
    }
5866
5867
},
5868
5869
5870
/**
5871
* @method focus
5872
* @description Causes the menu to receive focus and fires the "focus" event.
5873
*/
5874
focus: function () {
5875
5876
    if (!this.hasFocus()) {
5877
5878
        this.setInitialFocus();
5879
    
5880
    }
5881
5882
},
5883
5884
5885
/**
5886
* @method blur
5887
* @description Causes the menu to lose focus and fires the "blur" event.
5888
*/    
5889
blur: function () {
5890
5891
    var oItem;
5892
5893
    if (this.hasFocus()) {
5894
    
5895
        oItem = MenuManager.getFocusedMenuItem();
5896
        
5897
        if (oItem) {
5898
5899
            oItem.blur();
5900
5901
        }
5902
5903
    }
5904
5905
},
5906
5907
5908
/**
5909
* @method hasFocus
5910
* @description Returns a boolean indicating whether or not the menu has focus.
5911
* @return {Boolean}
5912
*/
5913
hasFocus: function () {
5914
5915
    return (MenuManager.getFocusedMenu() == this.getRoot());
5916
5917
},
5918
5919
5920
_doItemSubmenuSubscribe: function (p_sType, p_aArgs, p_oObject) {
5921
5922
    var oItem = p_aArgs[0],
5923
        oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5924
5925
    if (oSubmenu) {
5926
        oSubmenu.subscribe.apply(oSubmenu, p_oObject);
5927
    }
5928
5929
},
5930
5931
5932
_doSubmenuSubscribe: function (p_sType, p_aArgs, p_oObject) { 
5933
5934
    var oSubmenu = this.cfg.getProperty(_SUBMENU);
5935
    
5936
    if (oSubmenu) {
5937
        oSubmenu.subscribe.apply(oSubmenu, p_oObject);
5938
    }
5939
5940
},
5941
5942
5943
/**
5944
* Adds the specified CustomEvent subscriber to the menu and each of 
5945
* its submenus.
5946
* @method subscribe
5947
* @param p_type     {string}   the type, or name of the event
5948
* @param p_fn       {function} the function to exectute when the event fires
5949
* @param p_obj      {Object}   An object to be passed along when the event 
5950
*                              fires
5951
* @param p_override {boolean}  If true, the obj passed in becomes the 
5952
*                              execution scope of the listener
5953
*/
5954
subscribe: function () {
5955
5956
	//	Subscribe to the event for this Menu instance
5957
    Menu.superclass.subscribe.apply(this, arguments);
5958
5959
	//	Subscribe to the "itemAdded" event so that all future submenus
5960
	//	also subscribe to this event
5961
    Menu.superclass.subscribe.call(this, _ITEM_ADDED, this._doItemSubmenuSubscribe, arguments);
5962
5963
5964
    var aItems = this.getItems(),
5965
        nItems,
5966
        oItem,
5967
        oSubmenu,
5968
        i;
5969
        
5970
5971
    if (aItems) {
5972
5973
        nItems = aItems.length;
5974
        
5975
        if (nItems > 0) {
5976
        
5977
            i = nItems - 1;
5978
            
5979
            do {
5980
5981
                oItem = aItems[i];
5982
                oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5983
                
5984
                if (oSubmenu) {
5985
                    oSubmenu.subscribe.apply(oSubmenu, arguments);
5986
                }
5987
                else {
5988
                    oItem.cfg.subscribeToConfigEvent(_SUBMENU, this._doSubmenuSubscribe, arguments);
5989
                }
5990
5991
            }
5992
            while (i--);
5993
        
5994
        }
5995
5996
    }
5997
5998
},
5999
6000
6001
unsubscribe: function () {
6002
6003
	//	Remove the event for this Menu instance
6004
    Menu.superclass.unsubscribe.apply(this, arguments);
6005
6006
	//	Remove the "itemAdded" event so that all future submenus don't have 
6007
	//	the event handler
6008
    Menu.superclass.unsubscribe.call(this, _ITEM_ADDED, this._doItemSubmenuSubscribe, arguments);
6009
6010
6011
    var aItems = this.getItems(),
6012
        nItems,
6013
        oItem,
6014
        oSubmenu,
6015
        i;
6016
        
6017
6018
    if (aItems) {
6019
6020
        nItems = aItems.length;
6021
        
6022
        if (nItems > 0) {
6023
        
6024
            i = nItems - 1;
6025
            
6026
            do {
6027
6028
                oItem = aItems[i];
6029
                oSubmenu = oItem.cfg.getProperty(_SUBMENU);
6030
                
6031
                if (oSubmenu) {
6032
                    oSubmenu.unsubscribe.apply(oSubmenu, arguments);
6033
                }
6034
                else {
6035
                    oItem.cfg.unsubscribeFromConfigEvent(_SUBMENU, this._doSubmenuSubscribe, arguments);
6036
                }
6037
6038
            }
6039
            while (i--);
6040
        
6041
        }
6042
6043
    }
6044
6045
},
6046
6047
6048
/**
6049
* @description Initializes the class's configurable properties which can be
6050
* changed using the menu's Config object ("cfg").
6051
* @method initDefaultConfig
6052
*/
6053
initDefaultConfig: function () {
6054
6055
    Menu.superclass.initDefaultConfig.call(this);
6056
6057
    var oConfig = this.cfg;
6058
6059
6060
    // Module documentation overrides
6061
6062
    /**
6063
    * @config effect
6064
    * @description Object or array of objects representing the ContainerEffect 
6065
    * classes that are active for animating the container.  When set this 
6066
    * property is automatically applied to all submenus.
6067
    * @type Object
6068
    * @default null
6069
    */
6070
6071
    // Overlay documentation overrides
6072
6073
6074
    /**
6075
    * @config x
6076
    * @description Number representing the absolute x-coordinate position of 
6077
    * the Menu.  This property is only applied when the "position" 
6078
    * configuration property is set to dynamic.
6079
    * @type Number
6080
    * @default null
6081
    */
6082
    
6083
6084
    /**
6085
    * @config y
6086
    * @description Number representing the absolute y-coordinate position of 
6087
    * the Menu.  This property is only applied when the "position" 
6088
    * configuration property is set to dynamic.
6089
    * @type Number
6090
    * @default null
6091
    */
6092
6093
6094
    /**
6095
    * @description Array of the absolute x and y positions of the Menu.  This 
6096
    * property is only applied when the "position" configuration property is 
6097
    * set to dynamic.
6098
    * @config xy
6099
    * @type Number[]
6100
    * @default null
6101
    */
6102
    
6103
6104
    /**
6105
    * @config context
6106
    * @description Array of context arguments for context-sensitive positioning.  
6107
    * The format is: [id or element, element corner, context corner]. 
6108
    * For example, setting this property to ["img1", "tl", "bl"] would 
6109
    * align the Menu's top left corner to the context element's 
6110
    * bottom left corner.  This property is only applied when the "position" 
6111
    * configuration property is set to dynamic.
6112
    * @type Array
6113
    * @default null
6114
    */
6115
    
6116
    
6117
    /**
6118
    * @config fixedcenter
6119
    * @description Boolean indicating if the Menu should be anchored to the 
6120
    * center of the viewport.  This property is only applied when the 
6121
    * "position" configuration property is set to dynamic.
6122
    * @type Boolean
6123
    * @default false
6124
    */
6125
    
6126
    
6127
    /**
6128
    * @config iframe
6129
    * @description Boolean indicating whether or not the Menu should 
6130
    * have an IFRAME shim; used to prevent SELECT elements from 
6131
    * poking through an Overlay instance in IE6.  When set to "true", 
6132
    * the iframe shim is created when the Menu instance is intially
6133
    * made visible.  This property is only applied when the "position" 
6134
    * configuration property is set to dynamic and is automatically applied 
6135
    * to all submenus.
6136
    * @type Boolean
6137
    * @default true for IE6 and below, false for all other browsers.
6138
    */
6139
6140
6141
	// Add configuration attributes
6142
6143
    /*
6144
        Change the default value for the "visible" configuration 
6145
        property to "false" by re-adding the property.
6146
    */
6147
6148
    /**
6149
    * @config visible
6150
    * @description Boolean indicating whether or not the menu is visible.  If 
6151
    * the menu's "position" configuration property is set to "dynamic" (the 
6152
    * default), this property toggles the menu's <code>&#60;div&#62;</code> 
6153
    * element's "visibility" style property between "visible" (true) or 
6154
    * "hidden" (false).  If the menu's "position" configuration property is 
6155
    * set to "static" this property toggles the menu's 
6156
    * <code>&#60;div&#62;</code> element's "display" style property 
6157
    * between "block" (true) or "none" (false).
6158
    * @default false
6159
    * @type Boolean
6160
    */
6161
    oConfig.addProperty(
6162
        VISIBLE_CONFIG.key, 
6163
        {
6164
            handler: this.configVisible, 
6165
            value: VISIBLE_CONFIG.value, 
6166
            validator: VISIBLE_CONFIG.validator
6167
        }
6168
     );
6169
6170
6171
    /*
6172
        Change the default value for the "constraintoviewport" configuration 
6173
        property (inherited by YAHOO.widget.Overlay) to "true" by re-adding the property.
6174
    */
6175
6176
    /**
6177
    * @config constraintoviewport
6178
    * @description Boolean indicating if the menu will try to remain inside 
6179
    * the boundaries of the size of viewport.  This property is only applied 
6180
    * when the "position" configuration property is set to dynamic and is 
6181
    * automatically applied to all submenus.
6182
    * @default true
6183
    * @type Boolean
6184
    */
6185
    oConfig.addProperty(
6186
        CONSTRAIN_TO_VIEWPORT_CONFIG.key, 
6187
        {
6188
            handler: this.configConstrainToViewport, 
6189
            value: CONSTRAIN_TO_VIEWPORT_CONFIG.value, 
6190
            validator: CONSTRAIN_TO_VIEWPORT_CONFIG.validator, 
6191
            supercedes: CONSTRAIN_TO_VIEWPORT_CONFIG.supercedes 
6192
        } 
6193
    );
6194
6195
6196
    /*
6197
        Change the default value for the "preventcontextoverlap" configuration 
6198
        property (inherited by YAHOO.widget.Overlay) to "true" by re-adding the property.
6199
    */
6200
6201
	/**
6202
	* @config preventcontextoverlap
6203
	* @description Boolean indicating whether or not a submenu should overlap its parent MenuItem 
6204
	* when the "constraintoviewport" configuration property is set to "true".
6205
	* @type Boolean
6206
	* @default true
6207
	*/
6208
	oConfig.addProperty(PREVENT_CONTEXT_OVERLAP_CONFIG.key, {
6209
6210
		value: PREVENT_CONTEXT_OVERLAP_CONFIG.value, 
6211
		validator: PREVENT_CONTEXT_OVERLAP_CONFIG.validator, 
6212
		supercedes: PREVENT_CONTEXT_OVERLAP_CONFIG.supercedes
6213
6214
	});
6215
6216
6217
    /**
6218
    * @config position
6219
    * @description String indicating how a menu should be positioned on the 
6220
    * screen.  Possible values are "static" and "dynamic."  Static menus are 
6221
    * visible by default and reside in the normal flow of the document 
6222
    * (CSS position: static).  Dynamic menus are hidden by default, reside 
6223
    * out of the normal flow of the document (CSS position: absolute), and 
6224
    * can overlay other elements on the screen.
6225
    * @default dynamic
6226
    * @type String
6227
    */
6228
    oConfig.addProperty(
6229
        POSITION_CONFIG.key, 
6230
        {
6231
            handler: this.configPosition,
6232
            value: POSITION_CONFIG.value, 
6233
            validator: POSITION_CONFIG.validator,
6234
            supercedes: POSITION_CONFIG.supercedes
6235
        }
6236
    );
6237
6238
6239
    /**
6240
    * @config submenualignment
6241
    * @description Array defining how submenus should be aligned to their 
6242
    * parent menu item. The format is: [itemCorner, submenuCorner]. By default
6243
    * a submenu's top left corner is aligned to its parent menu item's top 
6244
    * right corner.
6245
    * @default ["tl","tr"]
6246
    * @type Array
6247
    */
6248
    oConfig.addProperty(
6249
        SUBMENU_ALIGNMENT_CONFIG.key, 
6250
        { 
6251
            value: SUBMENU_ALIGNMENT_CONFIG.value,
6252
            suppressEvent: SUBMENU_ALIGNMENT_CONFIG.suppressEvent
6253
        }
6254
    );
6255
6256
6257
    /**
6258
    * @config autosubmenudisplay
6259
    * @description Boolean indicating if submenus are automatically made 
6260
    * visible when the user mouses over the menu's items.
6261
    * @default true
6262
    * @type Boolean
6263
    */
6264
	oConfig.addProperty(
6265
	   AUTO_SUBMENU_DISPLAY_CONFIG.key, 
6266
	   { 
6267
	       value: AUTO_SUBMENU_DISPLAY_CONFIG.value, 
6268
	       validator: AUTO_SUBMENU_DISPLAY_CONFIG.validator,
6269
	       suppressEvent: AUTO_SUBMENU_DISPLAY_CONFIG.suppressEvent
6270
       } 
6271
    );
6272
6273
6274
    /**
6275
    * @config showdelay
6276
    * @description Number indicating the time (in milliseconds) that should 
6277
    * expire before a submenu is made visible when the user mouses over 
6278
    * the menu's items.  This property is only applied when the "position" 
6279
    * configuration property is set to dynamic and is automatically applied 
6280
    * to all submenus.
6281
    * @default 250
6282
    * @type Number
6283
    */
6284
	oConfig.addProperty(
6285
	   SHOW_DELAY_CONFIG.key, 
6286
	   { 
6287
	       value: SHOW_DELAY_CONFIG.value, 
6288
	       validator: SHOW_DELAY_CONFIG.validator,
6289
	       suppressEvent: SHOW_DELAY_CONFIG.suppressEvent
6290
       } 
6291
    );
6292
6293
6294
    /**
6295
    * @config hidedelay
6296
    * @description Number indicating the time (in milliseconds) that should 
6297
    * expire before the menu is hidden.  This property is only applied when 
6298
    * the "position" configuration property is set to dynamic and is 
6299
    * automatically applied to all submenus.
6300
    * @default 0
6301
    * @type Number
6302
    */
6303
	oConfig.addProperty(
6304
	   HIDE_DELAY_CONFIG.key, 
6305
	   { 
6306
	       handler: this.configHideDelay,
6307
	       value: HIDE_DELAY_CONFIG.value, 
6308
	       validator: HIDE_DELAY_CONFIG.validator, 
6309
	       suppressEvent: HIDE_DELAY_CONFIG.suppressEvent
6310
       } 
6311
    );
6312
6313
6314
    /**
6315
    * @config submenuhidedelay
6316
    * @description Number indicating the time (in milliseconds) that should 
6317
    * expire before a submenu is hidden when the user mouses out of a menu item 
6318
    * heading in the direction of a submenu.  The value must be greater than or 
6319
    * equal to the value specified for the "showdelay" configuration property.
6320
    * This property is only applied when the "position" configuration property 
6321
    * is set to dynamic and is automatically applied to all submenus.
6322
    * @default 250
6323
    * @type Number
6324
    */
6325
	oConfig.addProperty(
6326
	   SUBMENU_HIDE_DELAY_CONFIG.key, 
6327
	   { 
6328
	       value: SUBMENU_HIDE_DELAY_CONFIG.value, 
6329
	       validator: SUBMENU_HIDE_DELAY_CONFIG.validator,
6330
	       suppressEvent: SUBMENU_HIDE_DELAY_CONFIG.suppressEvent
6331
       } 
6332
    );
6333
6334
6335
    /**
6336
    * @config clicktohide
6337
    * @description Boolean indicating if the menu will automatically be 
6338
    * hidden if the user clicks outside of it.  This property is only 
6339
    * applied when the "position" configuration property is set to dynamic 
6340
    * and is automatically applied to all submenus.
6341
    * @default true
6342
    * @type Boolean
6343
    */
6344
    oConfig.addProperty(
6345
        CLICK_TO_HIDE_CONFIG.key,
6346
        {
6347
            value: CLICK_TO_HIDE_CONFIG.value,
6348
            validator: CLICK_TO_HIDE_CONFIG.validator,
6349
            suppressEvent: CLICK_TO_HIDE_CONFIG.suppressEvent
6350
        }
6351
    );
6352
6353
6354
	/**
6355
	* @config container
6356
	* @description HTML element reference or string specifying the id 
6357
	* attribute of the HTML element that the menu's markup should be 
6358
	* rendered into.
6359
	* @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
6360
	* level-one-html.html#ID-58190037">HTMLElement</a>|String
6361
	* @default document.body
6362
	*/
6363
	oConfig.addProperty(
6364
	   CONTAINER_CONFIG.key, 
6365
	   { 
6366
	       handler: this.configContainer,
6367
	       value: document.body,
6368
           suppressEvent: CONTAINER_CONFIG.suppressEvent
6369
       } 
6370
   );
6371
6372
6373
    /**
6374
    * @config scrollincrement
6375
    * @description Number used to control the scroll speed of a menu.  Used to 
6376
    * increment the "scrollTop" property of the menu's body by when a menu's 
6377
    * content is scrolling.  When set this property is automatically applied 
6378
    * to all submenus.
6379
    * @default 1
6380
    * @type Number
6381
    */
6382
    oConfig.addProperty(
6383
        SCROLL_INCREMENT_CONFIG.key, 
6384
        { 
6385
            value: SCROLL_INCREMENT_CONFIG.value, 
6386
            validator: SCROLL_INCREMENT_CONFIG.validator,
6387
            supercedes: SCROLL_INCREMENT_CONFIG.supercedes,
6388
            suppressEvent: SCROLL_INCREMENT_CONFIG.suppressEvent
6389
        }
6390
    );
6391
6392
6393
    /**
6394
    * @config minscrollheight
6395
    * @description Number defining the minimum threshold for the "maxheight" 
6396
    * configuration property.  When set this property is automatically applied 
6397
    * to all submenus.
6398
    * @default 90
6399
    * @type Number
6400
    */
6401
    oConfig.addProperty(
6402
        MIN_SCROLL_HEIGHT_CONFIG.key, 
6403
        { 
6404
            value: MIN_SCROLL_HEIGHT_CONFIG.value, 
6405
            validator: MIN_SCROLL_HEIGHT_CONFIG.validator,
6406
            supercedes: MIN_SCROLL_HEIGHT_CONFIG.supercedes,
6407
            suppressEvent: MIN_SCROLL_HEIGHT_CONFIG.suppressEvent
6408
        }
6409
    );
6410
6411
6412
    /**
6413
    * @config maxheight
6414
    * @description Number defining the maximum height (in pixels) for a menu's 
6415
    * body element (<code>&#60;div class="bd"&#62;</code>).  Once a menu's body 
6416
    * exceeds this height, the contents of the body are scrolled to maintain 
6417
    * this value.  This value cannot be set lower than the value of the 
6418
    * "minscrollheight" configuration property.
6419
    * @default 0
6420
    * @type Number
6421
    */
6422
    oConfig.addProperty(
6423
       MAX_HEIGHT_CONFIG.key, 
6424
       {
6425
            handler: this.configMaxHeight,
6426
            value: MAX_HEIGHT_CONFIG.value,
6427
            validator: MAX_HEIGHT_CONFIG.validator,
6428
            suppressEvent: MAX_HEIGHT_CONFIG.suppressEvent,
6429
            supercedes: MAX_HEIGHT_CONFIG.supercedes            
6430
       } 
6431
    );
6432
6433
6434
    /**
6435
    * @config classname
6436
    * @description String representing the CSS class to be applied to the 
6437
    * menu's root <code>&#60;div&#62;</code> element.  The specified class(es)  
6438
    * are appended in addition to the default class as specified by the menu's
6439
    * CSS_CLASS_NAME constant. When set this property is automatically 
6440
    * applied to all submenus.
6441
    * @default null
6442
    * @type String
6443
    */
6444
    oConfig.addProperty(
6445
        CLASS_NAME_CONFIG.key, 
6446
        { 
6447
            handler: this.configClassName,
6448
            value: CLASS_NAME_CONFIG.value, 
6449
            validator: CLASS_NAME_CONFIG.validator,
6450
            supercedes: CLASS_NAME_CONFIG.supercedes      
6451
        }
6452
    );
6453
6454
6455
    /**
6456
    * @config disabled
6457
    * @description Boolean indicating if the menu should be disabled.  
6458
    * Disabling a menu disables each of its items.  (Disabled menu items are 
6459
    * dimmed and will not respond to user input or fire events.)  Disabled
6460
    * menus have a corresponding "disabled" CSS class applied to their root
6461
    * <code>&#60;div&#62;</code> element.
6462
    * @default false
6463
    * @type Boolean
6464
    */
6465
    oConfig.addProperty(
6466
        DISABLED_CONFIG.key, 
6467
        { 
6468
            handler: this.configDisabled,
6469
            value: DISABLED_CONFIG.value, 
6470
            validator: DISABLED_CONFIG.validator,
6471
            suppressEvent: DISABLED_CONFIG.suppressEvent
6472
        }
6473
    );
6474
6475
6476
    /**
6477
    * @config shadow
6478
    * @description Boolean indicating if the menu should have a shadow.
6479
    * @default true
6480
    * @type Boolean
6481
    */
6482
    oConfig.addProperty(
6483
        SHADOW_CONFIG.key, 
6484
        { 
6485
            handler: this.configShadow,
6486
            value: SHADOW_CONFIG.value, 
6487
            validator: SHADOW_CONFIG.validator
6488
        }
6489
    );
6490
6491
6492
    /**
6493
    * @config keepopen
6494
    * @description Boolean indicating if the menu should remain open when clicked.
6495
    * @default false
6496
    * @type Boolean
6497
    */
6498
    oConfig.addProperty(
6499
        KEEP_OPEN_CONFIG.key, 
6500
        { 
6501
            value: KEEP_OPEN_CONFIG.value, 
6502
            validator: KEEP_OPEN_CONFIG.validator
6503
        }
6504
    );
6505
6506
}
6507
6508
}); // END YAHOO.lang.extend
6509
6510
})();
6511
6512
6513
6514
(function () {
6515
6516
/**
6517
* Creates an item for a menu.
6518
* 
6519
* @param {String} p_oObject String specifying the text of the menu item.
6520
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6521
* one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying 
6522
* the <code>&#60;li&#62;</code> element of the menu item.
6523
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6524
* one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object 
6525
* specifying the <code>&#60;optgroup&#62;</code> element of the menu item.
6526
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6527
* one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object 
6528
* specifying the <code>&#60;option&#62;</code> element of the menu item.
6529
* @param {Object} p_oConfig Optional. Object literal specifying the 
6530
* configuration for the menu item. See configuration class documentation 
6531
* for more details.
6532
* @class MenuItem
6533
* @constructor
6534
*/
6535
YAHOO.widget.MenuItem = function (p_oObject, p_oConfig) {
6536
6537
    if (p_oObject) {
6538
6539
        if (p_oConfig) {
6540
    
6541
            this.parent = p_oConfig.parent;
6542
            this.value = p_oConfig.value;
6543
            this.id = p_oConfig.id;
6544
6545
        }
6546
6547
        this.init(p_oObject, p_oConfig);
6548
6549
    }
6550
6551
};
6552
6553
6554
var Dom = YAHOO.util.Dom,
6555
    Module = YAHOO.widget.Module,
6556
    Menu = YAHOO.widget.Menu,
6557
    MenuItem = YAHOO.widget.MenuItem,
6558
    CustomEvent = YAHOO.util.CustomEvent,
6559
    UA = YAHOO.env.ua,
6560
    Lang = YAHOO.lang,
6561
6562
	// Private string constants
6563
6564
	_TEXT = "text",
6565
	_HASH = "#",
6566
	_HYPHEN = "-",
6567
	_HELP_TEXT = "helptext",
6568
	_URL = "url",
6569
	_TARGET = "target",
6570
	_EMPHASIS = "emphasis",
6571
	_STRONG_EMPHASIS = "strongemphasis",
6572
	_CHECKED = "checked",
6573
	_SUBMENU = "submenu",
6574
	_DISABLED = "disabled",
6575
	_SELECTED = "selected",
6576
	_HAS_SUBMENU = "hassubmenu",
6577
	_CHECKED_DISABLED = "checked-disabled",
6578
	_HAS_SUBMENU_DISABLED = "hassubmenu-disabled",
6579
	_HAS_SUBMENU_SELECTED = "hassubmenu-selected",
6580
	_CHECKED_SELECTED = "checked-selected",
6581
	_ONCLICK = "onclick",
6582
	_CLASSNAME = "classname",
6583
	_EMPTY_STRING = "",
6584
	_OPTION = "OPTION",
6585
	_OPTGROUP = "OPTGROUP",
6586
	_LI_UPPERCASE = "LI",
6587
	_HREF = "href",
6588
	_SELECT = "SELECT",
6589
	_DIV = "DIV",
6590
	_START_HELP_TEXT = "<em class=\"helptext\">",
6591
	_START_EM = "<em>",
6592
	_END_EM = "</em>",
6593
	_START_STRONG = "<strong>",
6594
	_END_STRONG = "</strong>",
6595
	_PREVENT_CONTEXT_OVERLAP = "preventcontextoverlap",
6596
	_OBJ = "obj",
6597
	_SCOPE = "scope",
6598
	_NONE = "none",
6599
	_VISIBLE = "visible",
6600
	_SPACE = " ",
6601
	_MENUITEM = "MenuItem",
6602
	_CLICK = "click",
6603
	_SHOW = "show",
6604
	_HIDE = "hide",
6605
	_LI_LOWERCASE = "li",
6606
	_ANCHOR_TEMPLATE = "<a href=\"#\"></a>",
6607
6608
    EVENT_TYPES = [
6609
    
6610
        ["mouseOverEvent", "mouseover"],
6611
        ["mouseOutEvent", "mouseout"],
6612
        ["mouseDownEvent", "mousedown"],
6613
        ["mouseUpEvent", "mouseup"],
6614
        ["clickEvent", _CLICK],
6615
        ["keyPressEvent", "keypress"],
6616
        ["keyDownEvent", "keydown"],
6617
        ["keyUpEvent", "keyup"],
6618
        ["focusEvent", "focus"],
6619
        ["blurEvent", "blur"],
6620
        ["destroyEvent", "destroy"]
6621
    
6622
    ],
6623
6624
	TEXT_CONFIG = { 
6625
		key: _TEXT, 
6626
		value: _EMPTY_STRING, 
6627
		validator: Lang.isString, 
6628
		suppressEvent: true 
6629
	}, 
6630
6631
	HELP_TEXT_CONFIG = { 
6632
		key: _HELP_TEXT,
6633
		supercedes: [_TEXT], 
6634
		suppressEvent: true 
6635
	},
6636
6637
	URL_CONFIG = { 
6638
		key: _URL, 
6639
		value: _HASH, 
6640
		suppressEvent: true 
6641
	}, 
6642
6643
	TARGET_CONFIG = { 
6644
		key: _TARGET, 
6645
		suppressEvent: true 
6646
	}, 
6647
6648
	EMPHASIS_CONFIG = { 
6649
		key: _EMPHASIS, 
6650
		value: false, 
6651
		validator: Lang.isBoolean, 
6652
		suppressEvent: true, 
6653
		supercedes: [_TEXT]
6654
	}, 
6655
6656
	STRONG_EMPHASIS_CONFIG = { 
6657
		key: _STRONG_EMPHASIS, 
6658
		value: false, 
6659
		validator: Lang.isBoolean, 
6660
		suppressEvent: true,
6661
		supercedes: [_TEXT]
6662
	},
6663
6664
	CHECKED_CONFIG = { 
6665
		key: _CHECKED, 
6666
		value: false, 
6667
		validator: Lang.isBoolean, 
6668
		suppressEvent: true, 
6669
		supercedes: [_DISABLED, _SELECTED]
6670
	}, 
6671
6672
	SUBMENU_CONFIG = { 
6673
		key: _SUBMENU,
6674
		suppressEvent: true,
6675
		supercedes: [_DISABLED, _SELECTED]
6676
	},
6677
6678
	DISABLED_CONFIG = { 
6679
		key: _DISABLED, 
6680
		value: false, 
6681
		validator: Lang.isBoolean, 
6682
		suppressEvent: true,
6683
		supercedes: [_TEXT, _SELECTED]
6684
	},
6685
6686
	SELECTED_CONFIG = { 
6687
		key: _SELECTED, 
6688
		value: false, 
6689
		validator: Lang.isBoolean, 
6690
		suppressEvent: true
6691
	},
6692
6693
	ONCLICK_CONFIG = { 
6694
		key: _ONCLICK,
6695
		suppressEvent: true
6696
	},
6697
6698
	CLASS_NAME_CONFIG = { 
6699
		key: _CLASSNAME, 
6700
		value: null, 
6701
		validator: Lang.isString,
6702
		suppressEvent: true
6703
	},
6704
    
6705
	KEY_LISTENER_CONFIG = {
6706
		key: "keylistener", 
6707
		value: null, 
6708
		suppressEvent: true
6709
	},
6710
6711
	m_oMenuItemTemplate = null,
6712
6713
    CLASS_NAMES = {};
6714
6715
6716
/**
6717
* @method getClassNameForState
6718
* @description Returns a class name for the specified prefix and state.  If the class name does not 
6719
* yet exist, it is created and stored in the CLASS_NAMES object to increase performance.
6720
* @private
6721
* @param {String} prefix String representing the prefix for the class name
6722
* @param {String} state String representing a state - "disabled," "checked," etc.
6723
*/  
6724
var getClassNameForState = function (prefix, state) {
6725
6726
	var oClassNames = CLASS_NAMES[prefix];
6727
	
6728
	if (!oClassNames) {
6729
		CLASS_NAMES[prefix] = {};
6730
		oClassNames = CLASS_NAMES[prefix];
6731
	}
6732
6733
6734
	var sClassName = oClassNames[state];
6735
6736
	if (!sClassName) {
6737
		sClassName = prefix + _HYPHEN + state;
6738
		oClassNames[state] = sClassName;
6739
	}
6740
6741
	return sClassName;
6742
	
6743
};
6744
6745
6746
/**
6747
* @method addClassNameForState
6748
* @description Applies a class name to a MenuItem instance's &#60;LI&#62; and &#60;A&#62; elements
6749
* that represents a MenuItem's state - "disabled," "checked," etc.
6750
* @private
6751
* @param {String} state String representing a state - "disabled," "checked," etc.
6752
*/  
6753
var addClassNameForState = function (state) {
6754
6755
	Dom.addClass(this.element, getClassNameForState(this.CSS_CLASS_NAME, state));
6756
	Dom.addClass(this._oAnchor, getClassNameForState(this.CSS_LABEL_CLASS_NAME, state));
6757
6758
};
6759
6760
/**
6761
* @method removeClassNameForState
6762
* @description Removes a class name from a MenuItem instance's &#60;LI&#62; and &#60;A&#62; elements
6763
* that represents a MenuItem's state - "disabled," "checked," etc.
6764
* @private
6765
* @param {String} state String representing a state - "disabled," "checked," etc.
6766
*/  
6767
var removeClassNameForState = function (state) {
6768
6769
	Dom.removeClass(this.element, getClassNameForState(this.CSS_CLASS_NAME, state));
6770
	Dom.removeClass(this._oAnchor, getClassNameForState(this.CSS_LABEL_CLASS_NAME, state));
6771
6772
};
6773
6774
6775
MenuItem.prototype = {
6776
6777
    /**
6778
    * @property CSS_CLASS_NAME
6779
    * @description String representing the CSS class(es) to be applied to the 
6780
    * <code>&#60;li&#62;</code> element of the menu item.
6781
    * @default "yuimenuitem"
6782
    * @final
6783
    * @type String
6784
    */
6785
    CSS_CLASS_NAME: "yuimenuitem",
6786
6787
6788
    /**
6789
    * @property CSS_LABEL_CLASS_NAME
6790
    * @description String representing the CSS class(es) to be applied to the 
6791
    * menu item's <code>&#60;a&#62;</code> element.
6792
    * @default "yuimenuitemlabel"
6793
    * @final
6794
    * @type String
6795
    */
6796
    CSS_LABEL_CLASS_NAME: "yuimenuitemlabel",
6797
6798
6799
    /**
6800
    * @property SUBMENU_TYPE
6801
    * @description Object representing the type of menu to instantiate and 
6802
    * add when parsing the child nodes of the menu item's source HTML element.
6803
    * @final
6804
    * @type YAHOO.widget.Menu
6805
    */
6806
    SUBMENU_TYPE: null,
6807
6808
6809
6810
    // Private member variables
6811
    
6812
6813
    /**
6814
    * @property _oAnchor
6815
    * @description Object reference to the menu item's 
6816
    * <code>&#60;a&#62;</code> element.
6817
    * @default null 
6818
    * @private
6819
    * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6820
    * one-html.html#ID-48250443">HTMLAnchorElement</a>
6821
    */
6822
    _oAnchor: null,
6823
    
6824
    
6825
    /**
6826
    * @property _oHelpTextEM
6827
    * @description Object reference to the menu item's help text 
6828
    * <code>&#60;em&#62;</code> element.
6829
    * @default null
6830
    * @private
6831
    * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6832
    * one-html.html#ID-58190037">HTMLElement</a>
6833
    */
6834
    _oHelpTextEM: null,
6835
    
6836
    
6837
    /**
6838
    * @property _oSubmenu
6839
    * @description Object reference to the menu item's submenu.
6840
    * @default null
6841
    * @private
6842
    * @type YAHOO.widget.Menu
6843
    */
6844
    _oSubmenu: null,
6845
6846
6847
    /** 
6848
    * @property _oOnclickAttributeValue
6849
    * @description Object reference to the menu item's current value for the 
6850
    * "onclick" configuration attribute.
6851
    * @default null
6852
    * @private
6853
    * @type Object
6854
    */
6855
    _oOnclickAttributeValue: null,
6856
6857
6858
    /**
6859
    * @property _sClassName
6860
    * @description The current value of the "classname" configuration attribute.
6861
    * @default null
6862
    * @private
6863
    * @type String
6864
    */
6865
    _sClassName: null,
6866
6867
6868
6869
    // Public properties
6870
6871
6872
	/**
6873
    * @property constructor
6874
	* @description Object reference to the menu item's constructor function.
6875
    * @default YAHOO.widget.MenuItem
6876
	* @type YAHOO.widget.MenuItem
6877
	*/
6878
	constructor: MenuItem,
6879
6880
6881
    /**
6882
    * @property index
6883
    * @description Number indicating the ordinal position of the menu item in 
6884
    * its group.
6885
    * @default null
6886
    * @type Number
6887
    */
6888
    index: null,
6889
6890
6891
    /**
6892
    * @property groupIndex
6893
    * @description Number indicating the index of the group to which the menu 
6894
    * item belongs.
6895
    * @default null
6896
    * @type Number
6897
    */
6898
    groupIndex: null,
6899
6900
6901
    /**
6902
    * @property parent
6903
    * @description Object reference to the menu item's parent menu.
6904
    * @default null
6905
    * @type YAHOO.widget.Menu
6906
    */
6907
    parent: null,
6908
6909
6910
    /**
6911
    * @property element
6912
    * @description Object reference to the menu item's 
6913
    * <code>&#60;li&#62;</code> element.
6914
    * @default <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level
6915
    * -one-html.html#ID-74680021">HTMLLIElement</a>
6916
    * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6917
    * one-html.html#ID-74680021">HTMLLIElement</a>
6918
    */
6919
    element: null,
6920
6921
6922
    /**
6923
    * @property srcElement
6924
    * @description Object reference to the HTML element (either 
6925
    * <code>&#60;li&#62;</code>, <code>&#60;optgroup&#62;</code> or 
6926
    * <code>&#60;option&#62;</code>) used create the menu item.
6927
    * @default <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
6928
    * level-one-html.html#ID-74680021">HTMLLIElement</a>|<a href="http://www.
6929
    * w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-38450247"
6930
    * >HTMLOptGroupElement</a>|<a href="http://www.w3.org/TR/2000/WD-DOM-
6931
    * Level-1-20000929/level-one-html.html#ID-70901257">HTMLOptionElement</a>
6932
    * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6933
    * one-html.html#ID-74680021">HTMLLIElement</a>|<a href="http://www.w3.
6934
    * org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-38450247">
6935
    * HTMLOptGroupElement</a>|<a href="http://www.w3.org/TR/2000/WD-DOM-
6936
    * Level-1-20000929/level-one-html.html#ID-70901257">HTMLOptionElement</a>
6937
    */
6938
    srcElement: null,
6939
6940
6941
    /**
6942
    * @property value
6943
    * @description Object reference to the menu item's value.
6944
    * @default null
6945
    * @type Object
6946
    */
6947
    value: null,
6948
6949
6950
	/**
6951
    * @property browser
6952
    * @deprecated Use YAHOO.env.ua
6953
	* @description String representing the browser.
6954
	* @type String
6955
	*/
6956
	browser: Module.prototype.browser,
6957
6958
6959
    /**
6960
    * @property id
6961
    * @description Id of the menu item's root <code>&#60;li&#62;</code> 
6962
    * element.  This property should be set via the constructor using the 
6963
    * configuration object literal.  If an id is not specified, then one will 
6964
    * be created using the "generateId" method of the Dom utility.
6965
    * @default null
6966
    * @type String
6967
    */
6968
    id: null,
6969
6970
6971
6972
    // Events
6973
6974
6975
    /**
6976
    * @event destroyEvent
6977
    * @description Fires when the menu item's <code>&#60;li&#62;</code> 
6978
    * element is removed from its parent <code>&#60;ul&#62;</code> element.
6979
    * @type YAHOO.util.CustomEvent
6980
    */
6981
6982
6983
    /**
6984
    * @event mouseOverEvent
6985
    * @description Fires when the mouse has entered the menu item.  Passes 
6986
    * back the DOM Event object as an argument.
6987
    * @type YAHOO.util.CustomEvent
6988
    */
6989
6990
6991
    /**
6992
    * @event mouseOutEvent
6993
    * @description Fires when the mouse has left the menu item.  Passes back 
6994
    * the DOM Event object as an argument.
6995
    * @type YAHOO.util.CustomEvent
6996
    */
6997
6998
6999
    /**
7000
    * @event mouseDownEvent
7001
    * @description Fires when the user mouses down on the menu item.  Passes 
7002
    * back the DOM Event object as an argument.
7003
    * @type YAHOO.util.CustomEvent
7004
    */
7005
7006
7007
    /**
7008
    * @event mouseUpEvent
7009
    * @description Fires when the user releases a mouse button while the mouse 
7010
    * is over the menu item.  Passes back the DOM Event object as an argument.
7011
    * @type YAHOO.util.CustomEvent
7012
    */
7013
7014
7015
    /**
7016
    * @event clickEvent
7017
    * @description Fires when the user clicks the on the menu item.  Passes 
7018
    * back the DOM Event object as an argument.
7019
    * @type YAHOO.util.CustomEvent
7020
    */
7021
7022
7023
    /**
7024
    * @event keyPressEvent
7025
    * @description Fires when the user presses an alphanumeric key when the 
7026
    * menu item has focus.  Passes back the DOM Event object as an argument.
7027
    * @type YAHOO.util.CustomEvent
7028
    */
7029
7030
7031
    /**
7032
    * @event keyDownEvent
7033
    * @description Fires when the user presses a key when the menu item has 
7034
    * focus.  Passes back the DOM Event object as an argument.
7035
    * @type YAHOO.util.CustomEvent
7036
    */
7037
7038
7039
    /**
7040
    * @event keyUpEvent
7041
    * @description Fires when the user releases a key when the menu item has 
7042
    * focus.  Passes back the DOM Event object as an argument.
7043
    * @type YAHOO.util.CustomEvent
7044
    */
7045
7046
7047
    /**
7048
    * @event focusEvent
7049
    * @description Fires when the menu item receives focus.
7050
    * @type YAHOO.util.CustomEvent
7051
    */
7052
7053
7054
    /**
7055
    * @event blurEvent
7056
    * @description Fires when the menu item loses the input focus.
7057
    * @type YAHOO.util.CustomEvent
7058
    */
7059
7060
7061
    /**
7062
    * @method init
7063
    * @description The MenuItem class's initialization method. This method is 
7064
    * automatically called by the constructor, and sets up all DOM references 
7065
    * for pre-existing markup, and creates required markup if it is not 
7066
    * already present.
7067
    * @param {String} p_oObject String specifying the text of the menu item.
7068
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
7069
    * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying 
7070
    * the <code>&#60;li&#62;</code> element of the menu item.
7071
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
7072
    * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object 
7073
    * specifying the <code>&#60;optgroup&#62;</code> element of the menu item.
7074
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
7075
    * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object 
7076
    * specifying the <code>&#60;option&#62;</code> element of the menu item.
7077
    * @param {Object} p_oConfig Optional. Object literal specifying the 
7078
    * configuration for the menu item. See configuration class documentation 
7079
    * for more details.
7080
    */
7081
    init: function (p_oObject, p_oConfig) {
7082
7083
7084
        if (!this.SUBMENU_TYPE) {
7085
    
7086
            this.SUBMENU_TYPE = Menu;
7087
    
7088
        }
7089
7090
7091
        // Create the config object
7092
7093
        this.cfg = new YAHOO.util.Config(this);
7094
7095
        this.initDefaultConfig();
7096
7097
        var oConfig = this.cfg,
7098
            sURL = _HASH,
7099
            oCustomEvent,
7100
			aEventData,
7101
            oAnchor,
7102
            sTarget,
7103
            sText,
7104
            sId,
7105
            i;
7106
7107
7108
        if (Lang.isString(p_oObject)) {
7109
7110
            this._createRootNodeStructure();
7111
7112
            oConfig.queueProperty(_TEXT, p_oObject);
7113
7114
        }
7115
        else if (p_oObject && p_oObject.tagName) {
7116
7117
            switch(p_oObject.tagName.toUpperCase()) {
7118
7119
                case _OPTION:
7120
7121
                    this._createRootNodeStructure();
7122
7123
                    oConfig.queueProperty(_TEXT, p_oObject.text);
7124
                    oConfig.queueProperty(_DISABLED, p_oObject.disabled);
7125
7126
                    this.value = p_oObject.value;
7127
7128
                    this.srcElement = p_oObject;
7129
7130
                break;
7131
7132
                case _OPTGROUP:
7133
7134
                    this._createRootNodeStructure();
7135
7136
                    oConfig.queueProperty(_TEXT, p_oObject.label);
7137
                    oConfig.queueProperty(_DISABLED, p_oObject.disabled);
7138
7139
                    this.srcElement = p_oObject;
7140
7141
                    this._initSubTree();
7142
7143
                break;
7144
7145
                case _LI_UPPERCASE:
7146
7147
                    // Get the anchor node (if it exists)
7148
                    
7149
                    oAnchor = Dom.getFirstChild(p_oObject);
7150
7151
7152
                    // Capture the "text" and/or the "URL"
7153
7154
                    if (oAnchor) {
7155
7156
                        sURL = oAnchor.getAttribute(_HREF, 2);
7157
                        sTarget = oAnchor.getAttribute(_TARGET);
7158
7159
                        sText = oAnchor.innerHTML;
7160
7161
                    }
7162
7163
                    this.srcElement = p_oObject;
7164
                    this.element = p_oObject;
7165
                    this._oAnchor = oAnchor;
7166
7167
                    /*
7168
                        Set these properties silently to sync up the 
7169
                        configuration object without making changes to the 
7170
                        element's DOM
7171
                    */ 
7172
7173
                    oConfig.setProperty(_TEXT, sText, true);
7174
                    oConfig.setProperty(_URL, sURL, true);
7175
                    oConfig.setProperty(_TARGET, sTarget, true);
7176
7177
                    this._initSubTree();
7178
7179
                break;
7180
7181
            }            
7182
7183
        }
7184
7185
7186
        if (this.element) {
7187
7188
            sId = (this.srcElement || this.element).id;
7189
7190
            if (!sId) {
7191
7192
                sId = this.id || Dom.generateId();
7193
7194
                this.element.id = sId;
7195
7196
            }
7197
7198
            this.id = sId;
7199
7200
7201
            Dom.addClass(this.element, this.CSS_CLASS_NAME);
7202
            Dom.addClass(this._oAnchor, this.CSS_LABEL_CLASS_NAME);
7203
7204
7205
			i = EVENT_TYPES.length - 1;
7206
7207
			do {
7208
7209
				aEventData = EVENT_TYPES[i];
7210
7211
				oCustomEvent = this.createEvent(aEventData[1]);
7212
				oCustomEvent.signature = CustomEvent.LIST;
7213
				
7214
				this[aEventData[0]] = oCustomEvent;
7215
7216
			}
7217
			while (i--);
7218
7219
7220
            if (p_oConfig) {
7221
    
7222
                oConfig.applyConfig(p_oConfig);
7223
    
7224
            }        
7225
7226
            oConfig.fireQueue();
7227
7228
        }
7229
7230
    },
7231
7232
7233
7234
    // Private methods
7235
7236
    /**
7237
    * @method _createRootNodeStructure
7238
    * @description Creates the core DOM structure for the menu item.
7239
    * @private
7240
    */
7241
    _createRootNodeStructure: function () {
7242
7243
        var oElement,
7244
            oAnchor;
7245
7246
        if (!m_oMenuItemTemplate) {
7247
7248
            m_oMenuItemTemplate = document.createElement(_LI_LOWERCASE);
7249
            m_oMenuItemTemplate.innerHTML = _ANCHOR_TEMPLATE;
7250
7251
        }
7252
7253
        oElement = m_oMenuItemTemplate.cloneNode(true);
7254
        oElement.className = this.CSS_CLASS_NAME;
7255
7256
        oAnchor = oElement.firstChild;
7257
        oAnchor.className = this.CSS_LABEL_CLASS_NAME;
7258
7259
        this.element = oElement;
7260
        this._oAnchor = oAnchor;
7261
7262
    },
7263
7264
7265
    /**
7266
    * @method _initSubTree
7267
    * @description Iterates the source element's childNodes collection and uses 
7268
    * the child nodes to instantiate other menus.
7269
    * @private
7270
    */
7271
    _initSubTree: function () {
7272
7273
        var oSrcEl = this.srcElement,
7274
            oConfig = this.cfg,
7275
            oNode,
7276
            aOptions,
7277
            nOptions,
7278
            oMenu,
7279
            n;
7280
7281
7282
        if (oSrcEl.childNodes.length > 0) {
7283
7284
            if (this.parent.lazyLoad && this.parent.srcElement && 
7285
                this.parent.srcElement.tagName.toUpperCase() == _SELECT) {
7286
7287
                oConfig.setProperty(
7288
                        _SUBMENU, 
7289
                        { id: Dom.generateId(), itemdata: oSrcEl.childNodes }
7290
                    );
7291
7292
            }
7293
            else {
7294
7295
                oNode = oSrcEl.firstChild;
7296
                aOptions = [];
7297
    
7298
                do {
7299
    
7300
                    if (oNode && oNode.tagName) {
7301
    
7302
                        switch(oNode.tagName.toUpperCase()) {
7303
                
7304
                            case _DIV:
7305
                
7306
                                oConfig.setProperty(_SUBMENU, oNode);
7307
                
7308
                            break;
7309
         
7310
                            case _OPTION:
7311
        
7312
                                aOptions[aOptions.length] = oNode;
7313
        
7314
                            break;
7315
               
7316
                        }
7317
                    
7318
                    }
7319
                
7320
                }        
7321
                while((oNode = oNode.nextSibling));
7322
    
7323
    
7324
                nOptions = aOptions.length;
7325
    
7326
                if (nOptions > 0) {
7327
    
7328
                    oMenu = new this.SUBMENU_TYPE(Dom.generateId());
7329
                    
7330
                    oConfig.setProperty(_SUBMENU, oMenu);
7331
    
7332
                    for(n=0; n<nOptions; n++) {
7333
        
7334
                        oMenu.addItem((new oMenu.ITEM_TYPE(aOptions[n])));
7335
        
7336
                    }
7337
        
7338
                }
7339
            
7340
            }
7341
7342
        }
7343
7344
    },
7345
7346
7347
7348
    // Event handlers for configuration properties
7349
7350
7351
    /**
7352
    * @method configText
7353
    * @description Event handler for when the "text" configuration property of 
7354
    * the menu item changes.
7355
    * @param {String} p_sType String representing the name of the event that 
7356
    * was fired.
7357
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7358
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7359
    * that fired the event.
7360
    */
7361
    configText: function (p_sType, p_aArgs, p_oItem) {
7362
7363
        var sText = p_aArgs[0],
7364
            oConfig = this.cfg,
7365
            oAnchor = this._oAnchor,
7366
            sHelpText = oConfig.getProperty(_HELP_TEXT),
7367
            sHelpTextHTML = _EMPTY_STRING,
7368
            sEmphasisStartTag = _EMPTY_STRING,
7369
            sEmphasisEndTag = _EMPTY_STRING;
7370
7371
7372
        if (sText) {
7373
7374
7375
            if (sHelpText) {
7376
                    
7377
                sHelpTextHTML = _START_HELP_TEXT + sHelpText + _END_EM;
7378
            
7379
            }
7380
7381
7382
            if (oConfig.getProperty(_EMPHASIS)) {
7383
7384
                sEmphasisStartTag = _START_EM;
7385
                sEmphasisEndTag = _END_EM;
7386
7387
            }
7388
7389
7390
            if (oConfig.getProperty(_STRONG_EMPHASIS)) {
7391
7392
                sEmphasisStartTag = _START_STRONG;
7393
                sEmphasisEndTag = _END_STRONG;
7394
            
7395
            }
7396
7397
7398
            oAnchor.innerHTML = (sEmphasisStartTag + sText + sEmphasisEndTag + sHelpTextHTML);
7399
7400
        }
7401
7402
    },
7403
7404
7405
    /**
7406
    * @method configHelpText
7407
    * @description Event handler for when the "helptext" configuration property 
7408
    * of the menu item changes.
7409
    * @param {String} p_sType String representing the name of the event that 
7410
    * was fired.
7411
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7412
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7413
    * that fired the event.
7414
    */    
7415
    configHelpText: function (p_sType, p_aArgs, p_oItem) {
7416
7417
        this.cfg.refireEvent(_TEXT);
7418
7419
    },
7420
7421
7422
    /**
7423
    * @method configURL
7424
    * @description Event handler for when the "url" configuration property of 
7425
    * the menu item changes.
7426
    * @param {String} p_sType String representing the name of the event that 
7427
    * was fired.
7428
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7429
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7430
    * that fired the event.
7431
    */    
7432
    configURL: function (p_sType, p_aArgs, p_oItem) {
7433
7434
        var sURL = p_aArgs[0];
7435
7436
        if (!sURL) {
7437
7438
            sURL = _HASH;
7439
7440
        }
7441
7442
        var oAnchor = this._oAnchor;
7443
7444
        if (UA.opera) {
7445
7446
            oAnchor.removeAttribute(_HREF);
7447
        
7448
        }
7449
7450
        oAnchor.setAttribute(_HREF, sURL);
7451
7452
    },
7453
7454
7455
    /**
7456
    * @method configTarget
7457
    * @description Event handler for when the "target" configuration property 
7458
    * of the menu item changes.  
7459
    * @param {String} p_sType String representing the name of the event that 
7460
    * was fired.
7461
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7462
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7463
    * that fired the event.
7464
    */    
7465
    configTarget: function (p_sType, p_aArgs, p_oItem) {
7466
7467
        var sTarget = p_aArgs[0],
7468
            oAnchor = this._oAnchor;
7469
7470
        if (sTarget && sTarget.length > 0) {
7471
7472
            oAnchor.setAttribute(_TARGET, sTarget);
7473
7474
        }
7475
        else {
7476
7477
            oAnchor.removeAttribute(_TARGET);
7478
        
7479
        }
7480
7481
    },
7482
7483
7484
    /**
7485
    * @method configEmphasis
7486
    * @description Event handler for when the "emphasis" configuration property
7487
    * of the menu item changes.
7488
    * @param {String} p_sType String representing the name of the event that 
7489
    * was fired.
7490
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7491
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7492
    * that fired the event.
7493
    */    
7494
    configEmphasis: function (p_sType, p_aArgs, p_oItem) {
7495
7496
        var bEmphasis = p_aArgs[0],
7497
            oConfig = this.cfg;
7498
7499
7500
        if (bEmphasis && oConfig.getProperty(_STRONG_EMPHASIS)) {
7501
7502
            oConfig.setProperty(_STRONG_EMPHASIS, false);
7503
7504
        }
7505
7506
7507
        oConfig.refireEvent(_TEXT);
7508
7509
    },
7510
7511
7512
    /**
7513
    * @method configStrongEmphasis
7514
    * @description Event handler for when the "strongemphasis" configuration 
7515
    * property of the menu item changes.
7516
    * @param {String} p_sType String representing the name of the event that 
7517
    * was fired.
7518
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7519
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7520
    * that fired the event.
7521
    */    
7522
    configStrongEmphasis: function (p_sType, p_aArgs, p_oItem) {
7523
7524
        var bStrongEmphasis = p_aArgs[0],
7525
            oConfig = this.cfg;
7526
7527
7528
        if (bStrongEmphasis && oConfig.getProperty(_EMPHASIS)) {
7529
7530
            oConfig.setProperty(_EMPHASIS, false);
7531
7532
        }
7533
7534
        oConfig.refireEvent(_TEXT);
7535
7536
    },
7537
7538
7539
    /**
7540
    * @method configChecked
7541
    * @description Event handler for when the "checked" configuration property 
7542
    * of the menu item changes. 
7543
    * @param {String} p_sType String representing the name of the event that 
7544
    * was fired.
7545
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7546
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7547
    * that fired the event.
7548
    */    
7549
    configChecked: function (p_sType, p_aArgs, p_oItem) {
7550
7551
        var bChecked = p_aArgs[0],
7552
            oConfig = this.cfg;
7553
7554
7555
        if (bChecked) {
7556
7557
            addClassNameForState.call(this, _CHECKED);
7558
7559
        }
7560
        else {
7561
7562
            removeClassNameForState.call(this, _CHECKED);
7563
        }
7564
7565
7566
        oConfig.refireEvent(_TEXT);
7567
7568
7569
        if (oConfig.getProperty(_DISABLED)) {
7570
7571
            oConfig.refireEvent(_DISABLED);
7572
7573
        }
7574
7575
7576
        if (oConfig.getProperty(_SELECTED)) {
7577
7578
            oConfig.refireEvent(_SELECTED);
7579
7580
        }
7581
7582
    },
7583
7584
7585
7586
    /**
7587
    * @method configDisabled
7588
    * @description Event handler for when the "disabled" configuration property 
7589
    * of the menu item changes. 
7590
    * @param {String} p_sType String representing the name of the event that 
7591
    * was fired.
7592
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7593
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7594
    * that fired the event.
7595
    */    
7596
    configDisabled: function (p_sType, p_aArgs, p_oItem) {
7597
7598
        var bDisabled = p_aArgs[0],
7599
            oConfig = this.cfg,
7600
            oSubmenu = oConfig.getProperty(_SUBMENU),
7601
            bChecked = oConfig.getProperty(_CHECKED);
7602
7603
7604
        if (bDisabled) {
7605
7606
            if (oConfig.getProperty(_SELECTED)) {
7607
7608
                oConfig.setProperty(_SELECTED, false);
7609
7610
            }
7611
7612
7613
			addClassNameForState.call(this, _DISABLED);
7614
7615
7616
            if (oSubmenu) {
7617
7618
				addClassNameForState.call(this, _HAS_SUBMENU_DISABLED);
7619
            
7620
            }
7621
            
7622
7623
            if (bChecked) {
7624
7625
				addClassNameForState.call(this, _CHECKED_DISABLED);
7626
7627
            }
7628
7629
        }
7630
        else {
7631
7632
			removeClassNameForState.call(this, _DISABLED);
7633
7634
7635
            if (oSubmenu) {
7636
7637
				removeClassNameForState.call(this, _HAS_SUBMENU_DISABLED);
7638
            
7639
            }
7640
            
7641
7642
            if (bChecked) {
7643
7644
				removeClassNameForState.call(this, _CHECKED_DISABLED);
7645
7646
            }
7647
7648
        }
7649
7650
    },
7651
7652
7653
    /**
7654
    * @method configSelected
7655
    * @description Event handler for when the "selected" configuration property 
7656
    * of the menu item changes. 
7657
    * @param {String} p_sType String representing the name of the event that 
7658
    * was fired.
7659
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7660
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7661
    * that fired the event.
7662
    */    
7663
    configSelected: function (p_sType, p_aArgs, p_oItem) {
7664
7665
        var oConfig = this.cfg,
7666
        	oAnchor = this._oAnchor,
7667
        	
7668
            bSelected = p_aArgs[0],
7669
            bChecked = oConfig.getProperty(_CHECKED),
7670
            oSubmenu = oConfig.getProperty(_SUBMENU);
7671
7672
7673
        if (UA.opera) {
7674
7675
            oAnchor.blur();
7676
        
7677
        }
7678
7679
7680
        if (bSelected && !oConfig.getProperty(_DISABLED)) {
7681
7682
			addClassNameForState.call(this, _SELECTED);
7683
7684
7685
            if (oSubmenu) {
7686
7687
				addClassNameForState.call(this, _HAS_SUBMENU_SELECTED);
7688
            
7689
            }
7690
7691
7692
            if (bChecked) {
7693
7694
				addClassNameForState.call(this, _CHECKED_SELECTED);
7695
7696
            }
7697
7698
        }
7699
        else {
7700
7701
			removeClassNameForState.call(this, _SELECTED);
7702
7703
7704
            if (oSubmenu) {
7705
7706
				removeClassNameForState.call(this, _HAS_SUBMENU_SELECTED);
7707
            
7708
            }
7709
7710
7711
            if (bChecked) {
7712
7713
				removeClassNameForState.call(this, _CHECKED_SELECTED);
7714
7715
            }
7716
7717
        }
7718
7719
7720
        if (this.hasFocus() && UA.opera) {
7721
        
7722
            oAnchor.focus();
7723
        
7724
        }
7725
7726
    },
7727
7728
7729
    /**
7730
    * @method _onSubmenuBeforeHide
7731
    * @description "beforehide" Custom Event handler for a submenu.
7732
    * @private
7733
    * @param {String} p_sType String representing the name of the event that 
7734
    * was fired.
7735
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7736
    */
7737
    _onSubmenuBeforeHide: function (p_sType, p_aArgs) {
7738
7739
        var oItem = this.parent,
7740
            oMenu;
7741
7742
        function onHide() {
7743
7744
            oItem._oAnchor.blur();
7745
            oMenu.beforeHideEvent.unsubscribe(onHide);
7746
        
7747
        }
7748
7749
7750
        if (oItem.hasFocus()) {
7751
7752
            oMenu = oItem.parent;
7753
7754
            oMenu.beforeHideEvent.subscribe(onHide);
7755
        
7756
        }
7757
    
7758
    },
7759
7760
7761
    /**
7762
    * @method configSubmenu
7763
    * @description Event handler for when the "submenu" configuration property 
7764
    * of the menu item changes. 
7765
    * @param {String} p_sType String representing the name of the event that 
7766
    * was fired.
7767
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7768
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7769
    * that fired the event.
7770
    */
7771
    configSubmenu: function (p_sType, p_aArgs, p_oItem) {
7772
7773
        var oSubmenu = p_aArgs[0],
7774
            oConfig = this.cfg,
7775
            bLazyLoad = this.parent && this.parent.lazyLoad,
7776
            oMenu,
7777
            sSubmenuId,
7778
            oSubmenuConfig;
7779
7780
7781
        if (oSubmenu) {
7782
7783
            if (oSubmenu instanceof Menu) {
7784
7785
                oMenu = oSubmenu;
7786
                oMenu.parent = this;
7787
                oMenu.lazyLoad = bLazyLoad;
7788
7789
            }
7790
            else if (Lang.isObject(oSubmenu) && oSubmenu.id && !oSubmenu.nodeType) {
7791
7792
                sSubmenuId = oSubmenu.id;
7793
                oSubmenuConfig = oSubmenu;
7794
7795
                oSubmenuConfig.lazyload = bLazyLoad;
7796
                oSubmenuConfig.parent = this;
7797
7798
                oMenu = new this.SUBMENU_TYPE(sSubmenuId, oSubmenuConfig);
7799
7800
7801
                // Set the value of the property to the Menu instance
7802
7803
                oConfig.setProperty(_SUBMENU, oMenu, true);
7804
7805
            }
7806
            else {
7807
7808
                oMenu = new this.SUBMENU_TYPE(oSubmenu, { lazyload: bLazyLoad, parent: this });
7809
7810
7811
                // Set the value of the property to the Menu instance
7812
                
7813
                oConfig.setProperty(_SUBMENU, oMenu, true);
7814
7815
            }
7816
7817
7818
            if (oMenu) {
7819
7820
				oMenu.cfg.setProperty(_PREVENT_CONTEXT_OVERLAP, true);
7821
7822
                addClassNameForState.call(this, _HAS_SUBMENU);
7823
7824
7825
				if (oConfig.getProperty(_URL) === _HASH) {
7826
				
7827
					oConfig.setProperty(_URL, (_HASH + oMenu.id));
7828
				
7829
				}
7830
7831
7832
                this._oSubmenu = oMenu;
7833
7834
7835
                if (UA.opera) {
7836
                
7837
                    oMenu.beforeHideEvent.subscribe(this._onSubmenuBeforeHide);               
7838
                
7839
                }
7840
            
7841
            }
7842
7843
        }
7844
        else {
7845
7846
			removeClassNameForState.call(this, _HAS_SUBMENU);
7847
7848
            if (this._oSubmenu) {
7849
7850
                this._oSubmenu.destroy();
7851
7852
            }
7853
7854
        }
7855
7856
7857
        if (oConfig.getProperty(_DISABLED)) {
7858
7859
            oConfig.refireEvent(_DISABLED);
7860
7861
        }
7862
7863
7864
        if (oConfig.getProperty(_SELECTED)) {
7865
7866
            oConfig.refireEvent(_SELECTED);
7867
7868
        }
7869
7870
    },
7871
7872
7873
    /**
7874
    * @method configOnClick
7875
    * @description Event handler for when the "onclick" configuration property 
7876
    * of the menu item changes. 
7877
    * @param {String} p_sType String representing the name of the event that 
7878
    * was fired.
7879
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7880
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7881
    * that fired the event.
7882
    */
7883
    configOnClick: function (p_sType, p_aArgs, p_oItem) {
7884
7885
        var oObject = p_aArgs[0];
7886
7887
        /*
7888
            Remove any existing listeners if a "click" event handler has 
7889
            already been specified.
7890
        */
7891
7892
        if (this._oOnclickAttributeValue && (this._oOnclickAttributeValue != oObject)) {
7893
7894
            this.clickEvent.unsubscribe(this._oOnclickAttributeValue.fn, 
7895
                                this._oOnclickAttributeValue.obj);
7896
7897
            this._oOnclickAttributeValue = null;
7898
7899
        }
7900
7901
7902
        if (!this._oOnclickAttributeValue && Lang.isObject(oObject) && 
7903
            Lang.isFunction(oObject.fn)) {
7904
            
7905
            this.clickEvent.subscribe(oObject.fn, 
7906
                ((_OBJ in oObject) ? oObject.obj : this), 
7907
                ((_SCOPE in oObject) ? oObject.scope : null) );
7908
7909
            this._oOnclickAttributeValue = oObject;
7910
7911
        }
7912
    
7913
    },
7914
7915
7916
    /**
7917
    * @method configClassName
7918
    * @description Event handler for when the "classname" configuration 
7919
    * property of a menu item changes.
7920
    * @param {String} p_sType String representing the name of the event that 
7921
    * was fired.
7922
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7923
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7924
    * that fired the event.
7925
    */
7926
    configClassName: function (p_sType, p_aArgs, p_oItem) {
7927
    
7928
        var sClassName = p_aArgs[0];
7929
    
7930
        if (this._sClassName) {
7931
    
7932
            Dom.removeClass(this.element, this._sClassName);
7933
    
7934
        }
7935
    
7936
        Dom.addClass(this.element, sClassName);
7937
        this._sClassName = sClassName;
7938
    
7939
    },
7940
7941
7942
    /**
7943
    * @method _dispatchClickEvent
7944
    * @description Dispatches a DOM "click" event to the anchor element of a 
7945
	* MenuItem instance.
7946
	* @private	
7947
    */
7948
	_dispatchClickEvent: function () {
7949
7950
		var oMenuItem = this,
7951
			oAnchor,
7952
			oEvent;
7953
7954
		if (!oMenuItem.cfg.getProperty(_DISABLED)) {
7955
7956
			oAnchor = Dom.getFirstChild(oMenuItem.element);
7957
7958
			//	Dispatch a "click" event to the MenuItem's anchor so that its
7959
			//	"click" event handlers will get called in response to the user 
7960
			//	pressing the keyboard shortcut defined by the "keylistener"
7961
			//	configuration property.
7962
7963
			if (UA.ie) {
7964
				oAnchor.fireEvent(_ONCLICK);
7965
			}
7966
			else {
7967
7968
				if ((UA.gecko && UA.gecko >= 1.9) || UA.opera || UA.webkit) {
7969
7970
					oEvent = document.createEvent("HTMLEvents");
7971
					oEvent.initEvent(_CLICK, true, true);
7972
7973
				}
7974
				else {
7975
7976
					oEvent = document.createEvent("MouseEvents");
7977
					oEvent.initMouseEvent(_CLICK, true, true, window, 0, 0, 0, 
7978
						0, 0, false, false, false, false, 0, null);
7979
7980
				}
7981
7982
				oAnchor.dispatchEvent(oEvent);
7983
7984
			}
7985
7986
		}
7987
7988
	},
7989
7990
7991
    /**
7992
    * @method _createKeyListener
7993
    * @description "show" event handler for a Menu instance - responsible for 
7994
	* setting up the KeyListener instance for a MenuItem.
7995
	* @private	
7996
    * @param {String} type String representing the name of the event that 
7997
    * was fired.
7998
    * @param {Array} args Array of arguments sent when the event was fired.
7999
    * @param {Array} keyData Array of arguments sent when the event was fired.
8000
    */
8001
	_createKeyListener: function (type, args, keyData) {
8002
8003
		var oMenuItem = this,
8004
			oMenu = oMenuItem.parent;
8005
8006
		var oKeyListener = new YAHOO.util.KeyListener(
8007
										oMenu.element.ownerDocument, 
8008
										keyData, 
8009
										{
8010
											fn: oMenuItem._dispatchClickEvent, 
8011
											scope: oMenuItem, 
8012
											correctScope: true });
8013
8014
8015
		if (oMenu.cfg.getProperty(_VISIBLE)) {
8016
			oKeyListener.enable();
8017
		}
8018
8019
8020
		oMenu.subscribe(_SHOW, oKeyListener.enable, null, oKeyListener);
8021
		oMenu.subscribe(_HIDE, oKeyListener.disable, null, oKeyListener);
8022
		
8023
		oMenuItem._keyListener = oKeyListener;
8024
		
8025
		oMenu.unsubscribe(_SHOW, oMenuItem._createKeyListener, keyData);
8026
		
8027
	},
8028
8029
8030
    /**
8031
    * @method configKeyListener
8032
    * @description Event handler for when the "keylistener" configuration 
8033
    * property of a menu item changes.
8034
    * @param {String} p_sType String representing the name of the event that 
8035
    * was fired.
8036
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
8037
    */
8038
    configKeyListener: function (p_sType, p_aArgs) {
8039
8040
		var oKeyData = p_aArgs[0],
8041
			oMenuItem = this,
8042
			oMenu = oMenuItem.parent;
8043
8044
		if (oMenuItem._keyData) {
8045
8046
			//	Unsubscribe from the "show" event in case the keylistener 
8047
			//	config was changed before the Menu was ever made visible.
8048
8049
			oMenu.unsubscribe(_SHOW, 
8050
					oMenuItem._createKeyListener, oMenuItem._keyData);
8051
8052
			oMenuItem._keyData = null;					
8053
					
8054
		}
8055
8056
8057
		//	Tear down for the previous value of the "keylistener" property
8058
8059
		if (oMenuItem._keyListener) {
8060
8061
			oMenu.unsubscribe(_SHOW, oMenuItem._keyListener.enable);
8062
			oMenu.unsubscribe(_HIDE, oMenuItem._keyListener.disable);
8063
8064
			oMenuItem._keyListener.disable();
8065
			oMenuItem._keyListener = null;
8066
8067
		}
8068
8069
8070
    	if (oKeyData) {
8071
	
8072
			oMenuItem._keyData = oKeyData;
8073
8074
			//	Defer the creation of the KeyListener instance until the 
8075
			//	parent Menu is visible.  This is necessary since the 
8076
			//	KeyListener instance needs to be bound to the document the 
8077
			//	Menu has been rendered into.  Deferring creation of the 
8078
			//	KeyListener instance also improves performance.
8079
8080
			oMenu.subscribe(_SHOW, oMenuItem._createKeyListener, 
8081
				oKeyData, oMenuItem);
8082
		}
8083
    
8084
    },
8085
8086
8087
    // Public methods
8088
8089
8090
	/**
8091
    * @method initDefaultConfig
8092
	* @description Initializes an item's configurable properties.
8093
	*/
8094
	initDefaultConfig : function () {
8095
8096
        var oConfig = this.cfg;
8097
8098
8099
        // Define the configuration attributes
8100
8101
        /**
8102
        * @config text
8103
        * @description String specifying the text label for the menu item.  
8104
        * When building a menu from existing HTML the value of this property
8105
        * will be interpreted from the menu's markup.
8106
        * @default ""
8107
        * @type String
8108
        */
8109
        oConfig.addProperty(
8110
            TEXT_CONFIG.key, 
8111
            { 
8112
                handler: this.configText, 
8113
                value: TEXT_CONFIG.value, 
8114
                validator: TEXT_CONFIG.validator, 
8115
                suppressEvent: TEXT_CONFIG.suppressEvent 
8116
            }
8117
        );
8118
        
8119
8120
        /**
8121
        * @config helptext
8122
        * @description String specifying additional instructional text to 
8123
        * accompany the text for the menu item.
8124
        * @deprecated Use "text" configuration property to add help text markup.  
8125
        * For example: <code>oMenuItem.cfg.setProperty("text", "Copy &#60;em 
8126
        * class=\"helptext\"&#62;Ctrl + C&#60;/em&#62;");</code>
8127
        * @default null
8128
        * @type String|<a href="http://www.w3.org/TR/
8129
        * 2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-58190037">
8130
        * HTMLElement</a>
8131
        */
8132
        oConfig.addProperty(
8133
            HELP_TEXT_CONFIG.key,
8134
            {
8135
                handler: this.configHelpText, 
8136
                supercedes: HELP_TEXT_CONFIG.supercedes,
8137
                suppressEvent: HELP_TEXT_CONFIG.suppressEvent 
8138
            }
8139
        );
8140
8141
8142
        /**
8143
        * @config url
8144
        * @description String specifying the URL for the menu item's anchor's 
8145
        * "href" attribute.  When building a menu from existing HTML the value 
8146
        * of this property will be interpreted from the menu's markup.
8147
        * @default "#"
8148
        * @type String
8149
        */        
8150
        oConfig.addProperty(
8151
            URL_CONFIG.key, 
8152
            {
8153
                handler: this.configURL, 
8154
                value: URL_CONFIG.value, 
8155
                suppressEvent: URL_CONFIG.suppressEvent
8156
            }
8157
        );
8158
8159
8160
        /**
8161
        * @config target
8162
        * @description String specifying the value for the "target" attribute 
8163
        * of the menu item's anchor element. <strong>Specifying a target will 
8164
        * require the user to click directly on the menu item's anchor node in
8165
        * order to cause the browser to navigate to the specified URL.</strong> 
8166
        * When building a menu from existing HTML the value of this property 
8167
        * will be interpreted from the menu's markup.
8168
        * @default null
8169
        * @type String
8170
        */        
8171
        oConfig.addProperty(
8172
            TARGET_CONFIG.key, 
8173
            {
8174
                handler: this.configTarget, 
8175
                suppressEvent: TARGET_CONFIG.suppressEvent
8176
            }
8177
        );
8178
8179
8180
        /**
8181
        * @config emphasis
8182
        * @description Boolean indicating if the text of the menu item will be 
8183
        * rendered with emphasis.
8184
        * @deprecated Use the "text" configuration property to add emphasis.  
8185
        * For example: <code>oMenuItem.cfg.setProperty("text", "&#60;em&#62;Some 
8186
        * Text&#60;/em&#62;");</code>
8187
        * @default false
8188
        * @type Boolean
8189
        */
8190
        oConfig.addProperty(
8191
            EMPHASIS_CONFIG.key, 
8192
            { 
8193
                handler: this.configEmphasis, 
8194
                value: EMPHASIS_CONFIG.value, 
8195
                validator: EMPHASIS_CONFIG.validator, 
8196
                suppressEvent: EMPHASIS_CONFIG.suppressEvent,
8197
                supercedes: EMPHASIS_CONFIG.supercedes
8198
            }
8199
        );
8200
8201
8202
        /**
8203
        * @config strongemphasis
8204
        * @description Boolean indicating if the text of the menu item will be 
8205
        * rendered with strong emphasis.
8206
        * @deprecated Use the "text" configuration property to add strong emphasis.  
8207
        * For example: <code>oMenuItem.cfg.setProperty("text", "&#60;strong&#62; 
8208
        * Some Text&#60;/strong&#62;");</code>
8209
        * @default false
8210
        * @type Boolean
8211
        */
8212
        oConfig.addProperty(
8213
            STRONG_EMPHASIS_CONFIG.key,
8214
            {
8215
                handler: this.configStrongEmphasis,
8216
                value: STRONG_EMPHASIS_CONFIG.value,
8217
                validator: STRONG_EMPHASIS_CONFIG.validator,
8218
                suppressEvent: STRONG_EMPHASIS_CONFIG.suppressEvent,
8219
                supercedes: STRONG_EMPHASIS_CONFIG.supercedes
8220
            }
8221
        );
8222
8223
8224
        /**
8225
        * @config checked
8226
        * @description Boolean indicating if the menu item should be rendered 
8227
        * with a checkmark.
8228
        * @default false
8229
        * @type Boolean
8230
        */
8231
        oConfig.addProperty(
8232
            CHECKED_CONFIG.key, 
8233
            {
8234
                handler: this.configChecked, 
8235
                value: CHECKED_CONFIG.value, 
8236
                validator: CHECKED_CONFIG.validator, 
8237
                suppressEvent: CHECKED_CONFIG.suppressEvent,
8238
                supercedes: CHECKED_CONFIG.supercedes
8239
            } 
8240
        );
8241
8242
8243
        /**
8244
        * @config disabled
8245
        * @description Boolean indicating if the menu item should be disabled.  
8246
        * (Disabled menu items are  dimmed and will not respond to user input 
8247
        * or fire events.)
8248
        * @default false
8249
        * @type Boolean
8250
        */
8251
        oConfig.addProperty(
8252
            DISABLED_CONFIG.key,
8253
            {
8254
                handler: this.configDisabled,
8255
                value: DISABLED_CONFIG.value,
8256
                validator: DISABLED_CONFIG.validator,
8257
                suppressEvent: DISABLED_CONFIG.suppressEvent
8258
            }
8259
        );
8260
8261
8262
        /**
8263
        * @config selected
8264
        * @description Boolean indicating if the menu item should 
8265
        * be highlighted.
8266
        * @default false
8267
        * @type Boolean
8268
        */
8269
        oConfig.addProperty(
8270
            SELECTED_CONFIG.key,
8271
            {
8272
                handler: this.configSelected,
8273
                value: SELECTED_CONFIG.value,
8274
                validator: SELECTED_CONFIG.validator,
8275
                suppressEvent: SELECTED_CONFIG.suppressEvent
8276
            }
8277
        );
8278
8279
8280
        /**
8281
        * @config submenu
8282
        * @description Object specifying the submenu to be appended to the 
8283
        * menu item.  The value can be one of the following: <ul><li>Object 
8284
        * specifying a Menu instance.</li><li>Object literal specifying the
8285
        * menu to be created.  Format: <code>{ id: [menu id], itemdata: 
8286
        * [<a href="YAHOO.widget.Menu.html#itemData">array of values for 
8287
        * items</a>] }</code>.</li><li>String specifying the id attribute 
8288
        * of the <code>&#60;div&#62;</code> element of the menu.</li><li>
8289
        * Object specifying the <code>&#60;div&#62;</code> element of the 
8290
        * menu.</li></ul>
8291
        * @default null
8292
        * @type Menu|String|Object|<a href="http://www.w3.org/TR/2000/
8293
        * WD-DOM-Level-1-20000929/level-one-html.html#ID-58190037">
8294
        * HTMLElement</a>
8295
        */
8296
        oConfig.addProperty(
8297
            SUBMENU_CONFIG.key, 
8298
            {
8299
                handler: this.configSubmenu, 
8300
                supercedes: SUBMENU_CONFIG.supercedes,
8301
                suppressEvent: SUBMENU_CONFIG.suppressEvent
8302
            }
8303
        );
8304
8305
8306
        /**
8307
        * @config onclick
8308
        * @description Object literal representing the code to be executed when 
8309
        * the item is clicked.  Format:<br> <code> {<br> 
8310
        * <strong>fn:</strong> Function,   &#47;&#47; The handler to call when 
8311
        * the event fires.<br> <strong>obj:</strong> Object, &#47;&#47; An 
8312
        * object to  pass back to the handler.<br> <strong>scope:</strong> 
8313
        * Object &#47;&#47; The object to use for the scope of the handler.
8314
        * <br> } </code>
8315
        * @type Object
8316
        * @default null
8317
        */
8318
        oConfig.addProperty(
8319
            ONCLICK_CONFIG.key, 
8320
            {
8321
                handler: this.configOnClick, 
8322
                suppressEvent: ONCLICK_CONFIG.suppressEvent 
8323
            }
8324
        );
8325
8326
8327
        /**
8328
        * @config classname
8329
        * @description CSS class to be applied to the menu item's root 
8330
        * <code>&#60;li&#62;</code> element.  The specified class(es) are 
8331
        * appended in addition to the default class as specified by the menu 
8332
        * item's CSS_CLASS_NAME constant.
8333
        * @default null
8334
        * @type String
8335
        */
8336
        oConfig.addProperty(
8337
            CLASS_NAME_CONFIG.key, 
8338
            { 
8339
                handler: this.configClassName,
8340
                value: CLASS_NAME_CONFIG.value, 
8341
                validator: CLASS_NAME_CONFIG.validator,
8342
                suppressEvent: CLASS_NAME_CONFIG.suppressEvent 
8343
            }
8344
        );
8345
8346
8347
        /**
8348
        * @config keylistener
8349
        * @description Object literal representing the key(s) that can be used 
8350
 		* to trigger the MenuItem's "click" event.  Possible attributes are 
8351
		* shift (boolean), alt (boolean), ctrl (boolean) and keys (either an int 
8352
		* or an array of ints representing keycodes).
8353
        * @default null
8354
        * @type Object
8355
        */
8356
        oConfig.addProperty(
8357
            KEY_LISTENER_CONFIG.key, 
8358
            { 
8359
                handler: this.configKeyListener,
8360
                value: KEY_LISTENER_CONFIG.value, 
8361
                suppressEvent: KEY_LISTENER_CONFIG.suppressEvent 
8362
            }
8363
        );
8364
8365
	},
8366
8367
    /**
8368
    * @method getNextSibling
8369
    * @description Finds the menu item's next sibling.
8370
    * @return YAHOO.widget.MenuItem
8371
    */
8372
	getNextSibling: function () {
8373
	
8374
		var isUL = function (el) {
8375
				return (el.nodeName.toLowerCase() === "ul");
8376
			},
8377
	
8378
			menuitemEl = this.element,
8379
			next = Dom.getNextSibling(menuitemEl),
8380
			parent,
8381
			sibling,
8382
			list;
8383
		
8384
		if (!next) {
8385
			
8386
			parent = menuitemEl.parentNode;
8387
			sibling = Dom.getNextSiblingBy(parent, isUL);
8388
			
8389
			if (sibling) {
8390
				list = sibling;
8391
			}
8392
			else {
8393
				list = Dom.getFirstChildBy(parent.parentNode, isUL);
8394
			}
8395
			
8396
			next = Dom.getFirstChild(list);
8397
			
8398
		}
8399
8400
		return YAHOO.widget.MenuManager.getMenuItem(next.id);
8401
8402
	},
8403
8404
    /**
8405
    * @method getNextEnabledSibling
8406
    * @description Finds the menu item's next enabled sibling.
8407
    * @return YAHOO.widget.MenuItem
8408
    */
8409
	getNextEnabledSibling: function () {
8410
		
8411
		var next = this.getNextSibling();
8412
		
8413
        return (next.cfg.getProperty(_DISABLED) || next.element.style.display == _NONE) ? next.getNextEnabledSibling() : next;
8414
		
8415
	},
8416
8417
8418
    /**
8419
    * @method getPreviousSibling
8420
    * @description Finds the menu item's previous sibling.
8421
    * @return {YAHOO.widget.MenuItem}
8422
    */	
8423
	getPreviousSibling: function () {
8424
8425
		var isUL = function (el) {
8426
				return (el.nodeName.toLowerCase() === "ul");
8427
			},
8428
8429
			menuitemEl = this.element,
8430
			next = Dom.getPreviousSibling(menuitemEl),
8431
			parent,
8432
			sibling,
8433
			list;
8434
		
8435
		if (!next) {
8436
			
8437
			parent = menuitemEl.parentNode;
8438
			sibling = Dom.getPreviousSiblingBy(parent, isUL);
8439
			
8440
			if (sibling) {
8441
				list = sibling;
8442
			}
8443
			else {
8444
				list = Dom.getLastChildBy(parent.parentNode, isUL);
8445
			}
8446
			
8447
			next = Dom.getLastChild(list);
8448
			
8449
		}
8450
8451
		return YAHOO.widget.MenuManager.getMenuItem(next.id);
8452
		
8453
	},
8454
8455
8456
    /**
8457
    * @method getPreviousEnabledSibling
8458
    * @description Finds the menu item's previous enabled sibling.
8459
    * @return {YAHOO.widget.MenuItem}
8460
    */
8461
	getPreviousEnabledSibling: function () {
8462
		
8463
		var next = this.getPreviousSibling();
8464
		
8465
        return (next.cfg.getProperty(_DISABLED) || next.element.style.display == _NONE) ? next.getPreviousEnabledSibling() : next;
8466
		
8467
	},
8468
8469
8470
    /**
8471
    * @method focus
8472
    * @description Causes the menu item to receive the focus and fires the 
8473
    * focus event.
8474
    */
8475
    focus: function () {
8476
8477
        var oParent = this.parent,
8478
            oAnchor = this._oAnchor,
8479
            oActiveItem = oParent.activeItem;
8480
8481
8482
        function setFocus() {
8483
8484
            try {
8485
8486
                if (!(UA.ie && !document.hasFocus())) {
8487
                
8488
					if (oActiveItem) {
8489
		
8490
						oActiveItem.blurEvent.fire();
8491
		
8492
					}
8493
	
8494
					oAnchor.focus();
8495
					
8496
					this.focusEvent.fire();
8497
                
8498
                }
8499
8500
            }
8501
            catch(e) {
8502
            
8503
            }
8504
8505
        }
8506
8507
8508
        if (!this.cfg.getProperty(_DISABLED) && oParent && oParent.cfg.getProperty(_VISIBLE) && 
8509
            this.element.style.display != _NONE) {
8510
8511
8512
            /*
8513
                Setting focus via a timer fixes a race condition in Firefox, IE 
8514
                and Opera where the browser viewport jumps as it trys to 
8515
                position and focus the menu.
8516
            */
8517
8518
            Lang.later(0, this, setFocus);
8519
8520
        }
8521
8522
    },
8523
8524
8525
    /**
8526
    * @method blur
8527
    * @description Causes the menu item to lose focus and fires the 
8528
    * blur event.
8529
    */    
8530
    blur: function () {
8531
8532
        var oParent = this.parent;
8533
8534
        if (!this.cfg.getProperty(_DISABLED) && oParent && oParent.cfg.getProperty(_VISIBLE)) {
8535
8536
            Lang.later(0, this, function () {
8537
8538
                try {
8539
    
8540
                    this._oAnchor.blur();
8541
                    this.blurEvent.fire();    
8542
8543
                } 
8544
                catch (e) {
8545
                
8546
                }
8547
                
8548
            }, 0);
8549
8550
        }
8551
8552
    },
8553
8554
8555
    /**
8556
    * @method hasFocus
8557
    * @description Returns a boolean indicating whether or not the menu item
8558
    * has focus.
8559
    * @return {Boolean}
8560
    */
8561
    hasFocus: function () {
8562
    
8563
        return (YAHOO.widget.MenuManager.getFocusedMenuItem() == this);
8564
    
8565
    },
8566
8567
8568
	/**
8569
    * @method destroy
8570
	* @description Removes the menu item's <code>&#60;li&#62;</code> element 
8571
	* from its parent <code>&#60;ul&#62;</code> element.
8572
	*/
8573
    destroy: function () {
8574
8575
        var oEl = this.element,
8576
            oSubmenu,
8577
            oParentNode,
8578
            aEventData,
8579
            i;
8580
8581
8582
        if (oEl) {
8583
8584
8585
            // If the item has a submenu, destroy it first
8586
8587
            oSubmenu = this.cfg.getProperty(_SUBMENU);
8588
8589
            if (oSubmenu) {
8590
            
8591
                oSubmenu.destroy();
8592
            
8593
            }
8594
8595
8596
            // Remove the element from the parent node
8597
8598
            oParentNode = oEl.parentNode;
8599
8600
            if (oParentNode) {
8601
8602
                oParentNode.removeChild(oEl);
8603
8604
                this.destroyEvent.fire();
8605
8606
            }
8607
8608
8609
            // Remove CustomEvent listeners
8610
8611
			i = EVENT_TYPES.length - 1;
8612
8613
			do {
8614
8615
				aEventData = EVENT_TYPES[i];
8616
				
8617
				this[aEventData[0]].unsubscribeAll();
8618
8619
			}
8620
			while (i--);
8621
            
8622
            
8623
            this.cfg.configChangedEvent.unsubscribeAll();
8624
8625
        }
8626
8627
    },
8628
8629
8630
    /**
8631
    * @method toString
8632
    * @description Returns a string representing the menu item.
8633
    * @return {String}
8634
    */
8635
    toString: function () {
8636
8637
        var sReturnVal = _MENUITEM,
8638
            sId = this.id;
8639
8640
        if (sId) {
8641
    
8642
            sReturnVal += (_SPACE + sId);
8643
        
8644
        }
8645
8646
        return sReturnVal;
8647
    
8648
    }
8649
8650
};
8651
8652
Lang.augmentProto(MenuItem, YAHOO.util.EventProvider);
8653
8654
})();
8655
(function () {
8656
8657
	var _XY = "xy",
8658
		_MOUSEDOWN = "mousedown",
8659
		_CONTEXTMENU = "ContextMenu",
8660
		_SPACE = " ";
8661
8662
/**
8663
* Creates a list of options or commands which are made visible in response to 
8664
* an HTML element's "contextmenu" event ("mousedown" for Opera).
8665
*
8666
* @param {String} p_oElement String specifying the id attribute of the 
8667
* <code>&#60;div&#62;</code> element of the context menu.
8668
* @param {String} p_oElement String specifying the id attribute of the 
8669
* <code>&#60;select&#62;</code> element to be used as the data source for the 
8670
* context menu.
8671
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8672
* html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying the 
8673
* <code>&#60;div&#62;</code> element of the context menu.
8674
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8675
* html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object specifying 
8676
* the <code>&#60;select&#62;</code> element to be used as the data source for 
8677
* the context menu.
8678
* @param {Object} p_oConfig Optional. Object literal specifying the 
8679
* configuration for the context menu. See configuration class documentation 
8680
* for more details.
8681
* @class ContextMenu
8682
* @constructor
8683
* @extends YAHOO.widget.Menu
8684
* @namespace YAHOO.widget
8685
*/
8686
YAHOO.widget.ContextMenu = function(p_oElement, p_oConfig) {
8687
8688
    YAHOO.widget.ContextMenu.superclass.constructor.call(this, p_oElement, p_oConfig);
8689
8690
};
8691
8692
8693
var Event = YAHOO.util.Event,
8694
	UA = YAHOO.env.ua,
8695
    ContextMenu = YAHOO.widget.ContextMenu,
8696
8697
8698
8699
    /**
8700
    * Constant representing the name of the ContextMenu's events
8701
    * @property EVENT_TYPES
8702
    * @private
8703
    * @final
8704
    * @type Object
8705
    */
8706
    EVENT_TYPES = {
8707
8708
        "TRIGGER_CONTEXT_MENU": "triggerContextMenu",
8709
        "CONTEXT_MENU": (UA.opera ? _MOUSEDOWN : "contextmenu"),
8710
        "CLICK": "click"
8711
8712
    },
8713
    
8714
    
8715
    /**
8716
    * Constant representing the ContextMenu's configuration properties
8717
    * @property DEFAULT_CONFIG
8718
    * @private
8719
    * @final
8720
    * @type Object
8721
    */
8722
    TRIGGER_CONFIG = { 
8723
		key: "trigger",
8724
		suppressEvent: true
8725
    };
8726
8727
8728
/**
8729
* @method position
8730
* @description "beforeShow" event handler used to position the contextmenu.
8731
* @private
8732
* @param {String} p_sType String representing the name of the event that 
8733
* was fired.
8734
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
8735
* @param {Array} p_aPos Array representing the xy position for the context menu.
8736
*/
8737
function position(p_sType, p_aArgs, p_aPos) {
8738
8739
    this.cfg.setProperty(_XY, p_aPos);
8740
    
8741
    this.beforeShowEvent.unsubscribe(position, p_aPos);
8742
8743
}
8744
8745
8746
YAHOO.lang.extend(ContextMenu, YAHOO.widget.Menu, {
8747
8748
8749
8750
// Private properties
8751
8752
8753
/**
8754
* @property _oTrigger
8755
* @description Object reference to the current value of the "trigger" 
8756
* configuration property.
8757
* @default null
8758
* @private
8759
* @type String|<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/leve
8760
* l-one-html.html#ID-58190037">HTMLElement</a>|Array
8761
*/
8762
_oTrigger: null,
8763
8764
8765
/**
8766
* @property _bCancelled
8767
* @description Boolean indicating if the display of the context menu should 
8768
* be cancelled.
8769
* @default false
8770
* @private
8771
* @type Boolean
8772
*/
8773
_bCancelled: false,
8774
8775
8776
8777
// Public properties
8778
8779
8780
/**
8781
* @property contextEventTarget
8782
* @description Object reference for the HTML element that was the target of the
8783
* "contextmenu" DOM event ("mousedown" for Opera) that triggered the display of 
8784
* the context menu.
8785
* @default null
8786
* @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8787
* html.html#ID-58190037">HTMLElement</a>
8788
*/
8789
contextEventTarget: null,
8790
8791
8792
8793
// Events
8794
8795
8796
/**
8797
* @event triggerContextMenuEvent
8798
* @description Custom Event wrapper for the "contextmenu" DOM event 
8799
* ("mousedown" for Opera) fired by the element(s) that trigger the display of 
8800
* the context menu.
8801
*/
8802
triggerContextMenuEvent: null,
8803
8804
8805
8806
/**
8807
* @method init
8808
* @description The ContextMenu class's initialization method. This method is 
8809
* automatically called by the constructor, and sets up all DOM references for 
8810
* pre-existing markup, and creates required markup if it is not already present.
8811
* @param {String} p_oElement String specifying the id attribute of the 
8812
* <code>&#60;div&#62;</code> element of the context menu.
8813
* @param {String} p_oElement String specifying the id attribute of the 
8814
* <code>&#60;select&#62;</code> element to be used as the data source for 
8815
* the context menu.
8816
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8817
* html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying the 
8818
* <code>&#60;div&#62;</code> element of the context menu.
8819
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8820
* html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object specifying 
8821
* the <code>&#60;select&#62;</code> element to be used as the data source for 
8822
* the context menu.
8823
* @param {Object} p_oConfig Optional. Object literal specifying the 
8824
* configuration for the context menu. See configuration class documentation 
8825
* for more details.
8826
*/
8827
init: function(p_oElement, p_oConfig) {
8828
8829
8830
    // Call the init of the superclass (YAHOO.widget.Menu)
8831
8832
    ContextMenu.superclass.init.call(this, p_oElement);
8833
8834
8835
    this.beforeInitEvent.fire(ContextMenu);
8836
8837
8838
    if (p_oConfig) {
8839
8840
        this.cfg.applyConfig(p_oConfig, true);
8841
8842
    }
8843
    
8844
    this.initEvent.fire(ContextMenu);
8845
    
8846
},
8847
8848
8849
/**
8850
* @method initEvents
8851
* @description Initializes the custom events for the context menu.
8852
*/
8853
initEvents: function() {
8854
8855
	ContextMenu.superclass.initEvents.call(this);
8856
8857
    // Create custom events
8858
8859
    this.triggerContextMenuEvent = this.createEvent(EVENT_TYPES.TRIGGER_CONTEXT_MENU);
8860
8861
    this.triggerContextMenuEvent.signature = YAHOO.util.CustomEvent.LIST;
8862
8863
},
8864
8865
8866
/**
8867
* @method cancel
8868
* @description Cancels the display of the context menu.
8869
*/
8870
cancel: function() {
8871
8872
    this._bCancelled = true;
8873
8874
},
8875
8876
8877
8878
// Private methods
8879
8880
8881
/**
8882
* @method _removeEventHandlers
8883
* @description Removes all of the DOM event handlers from the HTML element(s) 
8884
* whose "context menu" event ("click" for Opera) trigger the display of 
8885
* the context menu.
8886
* @private
8887
*/
8888
_removeEventHandlers: function() {
8889
8890
    var oTrigger = this._oTrigger;
8891
8892
8893
    // Remove the event handlers from the trigger(s)
8894
8895
    if (oTrigger) {
8896
8897
        Event.removeListener(oTrigger, EVENT_TYPES.CONTEXT_MENU, this._onTriggerContextMenu);    
8898
        
8899
        if (UA.opera) {
8900
        
8901
            Event.removeListener(oTrigger, EVENT_TYPES.CLICK, this._onTriggerClick);
8902
    
8903
        }
8904
8905
    }
8906
8907
},
8908
8909
8910
8911
// Private event handlers
8912
8913
8914
8915
/**
8916
* @method _onTriggerClick
8917
* @description "click" event handler for the HTML element(s) identified as the 
8918
* "trigger" for the context menu.  Used to cancel default behaviors in Opera.
8919
* @private
8920
* @param {Event} p_oEvent Object representing the DOM event object passed back 
8921
* by the event utility (YAHOO.util.Event).
8922
* @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context 
8923
* menu that is handling the event.
8924
*/
8925
_onTriggerClick: function(p_oEvent, p_oMenu) {
8926
8927
    if (p_oEvent.ctrlKey) {
8928
    
8929
        Event.stopEvent(p_oEvent);
8930
8931
    }
8932
    
8933
},
8934
8935
8936
/**
8937
* @method _onTriggerContextMenu
8938
* @description "contextmenu" event handler ("mousedown" for Opera) for the HTML 
8939
* element(s) that trigger the display of the context menu.
8940
* @private
8941
* @param {Event} p_oEvent Object representing the DOM event object passed back 
8942
* by the event utility (YAHOO.util.Event).
8943
* @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context 
8944
* menu that is handling the event.
8945
*/
8946
_onTriggerContextMenu: function(p_oEvent, p_oMenu) {
8947
8948
    var aXY;
8949
8950
    if (!(p_oEvent.type == _MOUSEDOWN && !p_oEvent.ctrlKey)) {
8951
	
8952
		this.contextEventTarget = Event.getTarget(p_oEvent);
8953
	
8954
		this.triggerContextMenuEvent.fire(p_oEvent);
8955
		
8956
	
8957
		if (!this._bCancelled) {
8958
8959
			/*
8960
				Prevent the browser's default context menu from appearing and 
8961
				stop the propagation of the "contextmenu" event so that 
8962
				other ContextMenu instances are not displayed.
8963
			*/
8964
8965
			Event.stopEvent(p_oEvent);
8966
8967
8968
			// Hide any other Menu instances that might be visible
8969
8970
			YAHOO.widget.MenuManager.hideVisible();
8971
			
8972
	
8973
8974
			// Position and display the context menu
8975
	
8976
			aXY = Event.getXY(p_oEvent);
8977
	
8978
	
8979
			if (!YAHOO.util.Dom.inDocument(this.element)) {
8980
	
8981
				this.beforeShowEvent.subscribe(position, aXY);
8982
	
8983
			}
8984
			else {
8985
	
8986
				this.cfg.setProperty(_XY, aXY);
8987
			
8988
			}
8989
	
8990
	
8991
			this.show();
8992
	
8993
		}
8994
	
8995
		this._bCancelled = false;
8996
8997
    }
8998
8999
},
9000
9001
9002
9003
// Public methods
9004
9005
9006
/**
9007
* @method toString
9008
* @description Returns a string representing the context menu.
9009
* @return {String}
9010
*/
9011
toString: function() {
9012
9013
    var sReturnVal = _CONTEXTMENU,
9014
        sId = this.id;
9015
9016
    if (sId) {
9017
9018
        sReturnVal += (_SPACE + sId);
9019
    
9020
    }
9021
9022
    return sReturnVal;
9023
9024
},
9025
9026
9027
/**
9028
* @method initDefaultConfig
9029
* @description Initializes the class's configurable properties which can be 
9030
* changed using the context menu's Config object ("cfg").
9031
*/
9032
initDefaultConfig: function() {
9033
9034
    ContextMenu.superclass.initDefaultConfig.call(this);
9035
9036
    /**
9037
    * @config trigger
9038
    * @description The HTML element(s) whose "contextmenu" event ("mousedown" 
9039
    * for Opera) trigger the display of the context menu.  Can be a string 
9040
    * representing the id attribute of the HTML element, an object reference 
9041
    * for the HTML element, or an array of strings or HTML element references.
9042
    * @default null
9043
    * @type String|<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
9044
    * level-one-html.html#ID-58190037">HTMLElement</a>|Array
9045
    */
9046
    this.cfg.addProperty(TRIGGER_CONFIG.key, 
9047
        {
9048
            handler: this.configTrigger, 
9049
            suppressEvent: TRIGGER_CONFIG.suppressEvent 
9050
        }
9051
    );
9052
9053
},
9054
9055
9056
/**
9057
* @method destroy
9058
* @description Removes the context menu's <code>&#60;div&#62;</code> element 
9059
* (and accompanying child nodes) from the document.
9060
*/
9061
destroy: function() {
9062
9063
    // Remove the DOM event handlers from the current trigger(s)
9064
9065
    this._removeEventHandlers();
9066
9067
9068
    // Continue with the superclass implementation of this method
9069
9070
    ContextMenu.superclass.destroy.call(this);
9071
9072
},
9073
9074
9075
9076
// Public event handlers for configuration properties
9077
9078
9079
/**
9080
* @method configTrigger
9081
* @description Event handler for when the value of the "trigger" configuration 
9082
* property changes. 
9083
* @param {String} p_sType String representing the name of the event that 
9084
* was fired.
9085
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
9086
* @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context 
9087
* menu that fired the event.
9088
*/
9089
configTrigger: function(p_sType, p_aArgs, p_oMenu) {
9090
    
9091
    var oTrigger = p_aArgs[0];
9092
9093
    if (oTrigger) {
9094
9095
        /*
9096
            If there is a current "trigger" - remove the event handlers 
9097
            from that element(s) before assigning new ones
9098
        */
9099
9100
        if (this._oTrigger) {
9101
        
9102
            this._removeEventHandlers();
9103
9104
        }
9105
9106
        this._oTrigger = oTrigger;
9107
9108
9109
        /*
9110
            Listen for the "mousedown" event in Opera b/c it does not 
9111
            support the "contextmenu" event
9112
        */ 
9113
  
9114
        Event.on(oTrigger, EVENT_TYPES.CONTEXT_MENU, this._onTriggerContextMenu, this, true);
9115
9116
9117
        /*
9118
            Assign a "click" event handler to the trigger element(s) for
9119
            Opera to prevent default browser behaviors.
9120
        */
9121
9122
        if (UA.opera) {
9123
        
9124
            Event.on(oTrigger, EVENT_TYPES.CLICK, this._onTriggerClick, this, true);
9125
9126
        }
9127
9128
    }
9129
    else {
9130
   
9131
        this._removeEventHandlers();
9132
    
9133
    }
9134
    
9135
}
9136
9137
}); // END YAHOO.lang.extend
9138
9139
}());
9140
9141
9142
9143
/**
9144
* Creates an item for a context menu.
9145
* 
9146
* @param {String} p_oObject String specifying the text of the context menu item.
9147
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9148
* one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the 
9149
* <code>&#60;li&#62;</code> element of the context menu item.
9150
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9151
* one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object 
9152
* specifying the <code>&#60;optgroup&#62;</code> element of the context 
9153
* menu item.
9154
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9155
* one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying 
9156
* the <code>&#60;option&#62;</code> element of the context menu item.
9157
* @param {Object} p_oConfig Optional. Object literal specifying the 
9158
* configuration for the context menu item. See configuration class 
9159
* documentation for more details.
9160
* @class ContextMenuItem
9161
* @constructor
9162
* @extends YAHOO.widget.MenuItem
9163
* @deprecated As of version 2.4.0 items for YAHOO.widget.ContextMenu instances
9164
* are of type YAHOO.widget.MenuItem.
9165
*/
9166
YAHOO.widget.ContextMenuItem = YAHOO.widget.MenuItem;
9167
(function () {
9168
9169
	var Lang = YAHOO.lang,
9170
9171
		// String constants
9172
	
9173
		_STATIC = "static",
9174
		_DYNAMIC_STATIC = "dynamic," + _STATIC,
9175
		_DISABLED = "disabled",
9176
		_SELECTED = "selected",
9177
		_AUTO_SUBMENU_DISPLAY = "autosubmenudisplay",
9178
		_SUBMENU = "submenu",
9179
		_VISIBLE = "visible",
9180
		_SPACE = " ",
9181
		_SUBMENU_TOGGLE_REGION = "submenutoggleregion",
9182
		_MENUBAR = "MenuBar";
9183
9184
/**
9185
* Horizontal collection of items, each of which can contain a submenu.
9186
* 
9187
* @param {String} p_oElement String specifying the id attribute of the 
9188
* <code>&#60;div&#62;</code> element of the menu bar.
9189
* @param {String} p_oElement String specifying the id attribute of the 
9190
* <code>&#60;select&#62;</code> element to be used as the data source for the 
9191
* menu bar.
9192
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9193
* one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying 
9194
* the <code>&#60;div&#62;</code> element of the menu bar.
9195
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9196
* one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object 
9197
* specifying the <code>&#60;select&#62;</code> element to be used as the data 
9198
* source for the menu bar.
9199
* @param {Object} p_oConfig Optional. Object literal specifying the 
9200
* configuration for the menu bar. See configuration class documentation for
9201
* more details.
9202
* @class MenuBar
9203
* @constructor
9204
* @extends YAHOO.widget.Menu
9205
* @namespace YAHOO.widget
9206
*/
9207
YAHOO.widget.MenuBar = function(p_oElement, p_oConfig) {
9208
9209
    YAHOO.widget.MenuBar.superclass.constructor.call(this, p_oElement, p_oConfig);
9210
9211
};
9212
9213
9214
/**
9215
* @method checkPosition
9216
* @description Checks to make sure that the value of the "position" property 
9217
* is one of the supported strings. Returns true if the position is supported.
9218
* @private
9219
* @param {Object} p_sPosition String specifying the position of the menu.
9220
* @return {Boolean}
9221
*/
9222
function checkPosition(p_sPosition) {
9223
9224
	var returnVal = false;
9225
9226
    if (Lang.isString(p_sPosition)) {
9227
9228
        returnVal = (_DYNAMIC_STATIC.indexOf((p_sPosition.toLowerCase())) != -1);
9229
9230
    }
9231
    
9232
    return returnVal;
9233
9234
}
9235
9236
9237
var Event = YAHOO.util.Event,
9238
    MenuBar = YAHOO.widget.MenuBar,
9239
9240
    POSITION_CONFIG =  { 
9241
		key: "position", 
9242
		value: _STATIC, 
9243
		validator: checkPosition, 
9244
		supercedes: [_VISIBLE] 
9245
	}, 
9246
9247
	SUBMENU_ALIGNMENT_CONFIG =  { 
9248
		key: "submenualignment", 
9249
		value: ["tl","bl"]
9250
	},
9251
9252
	AUTO_SUBMENU_DISPLAY_CONFIG =  { 
9253
		key: _AUTO_SUBMENU_DISPLAY, 
9254
		value: false, 
9255
		validator: Lang.isBoolean,
9256
		suppressEvent: true
9257
	},
9258
	
9259
	SUBMENU_TOGGLE_REGION_CONFIG = {
9260
		key: _SUBMENU_TOGGLE_REGION, 
9261
		value: false, 
9262
		validator: Lang.isBoolean
9263
	};
9264
9265
9266
9267
Lang.extend(MenuBar, YAHOO.widget.Menu, {
9268
9269
/**
9270
* @method init
9271
* @description The MenuBar class's initialization method. This method is 
9272
* automatically called by the constructor, and sets up all DOM references for 
9273
* pre-existing markup, and creates required markup if it is not already present.
9274
* @param {String} p_oElement String specifying the id attribute of the 
9275
* <code>&#60;div&#62;</code> element of the menu bar.
9276
* @param {String} p_oElement String specifying the id attribute of the 
9277
* <code>&#60;select&#62;</code> element to be used as the data source for the 
9278
* menu bar.
9279
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9280
* one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying 
9281
* the <code>&#60;div&#62;</code> element of the menu bar.
9282
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9283
* one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object 
9284
* specifying the <code>&#60;select&#62;</code> element to be used as the data 
9285
* source for the menu bar.
9286
* @param {Object} p_oConfig Optional. Object literal specifying the 
9287
* configuration for the menu bar. See configuration class documentation for
9288
* more details.
9289
*/
9290
init: function(p_oElement, p_oConfig) {
9291
9292
    if(!this.ITEM_TYPE) {
9293
9294
        this.ITEM_TYPE = YAHOO.widget.MenuBarItem;
9295
9296
    }
9297
9298
9299
    // Call the init of the superclass (YAHOO.widget.Menu)
9300
9301
    MenuBar.superclass.init.call(this, p_oElement);
9302
9303
9304
    this.beforeInitEvent.fire(MenuBar);
9305
9306
9307
    if(p_oConfig) {
9308
9309
        this.cfg.applyConfig(p_oConfig, true);
9310
9311
    }
9312
9313
    this.initEvent.fire(MenuBar);
9314
9315
},
9316
9317
9318
9319
// Constants
9320
9321
9322
/**
9323
* @property CSS_CLASS_NAME
9324
* @description String representing the CSS class(es) to be applied to the menu 
9325
* bar's <code>&#60;div&#62;</code> element.
9326
* @default "yuimenubar"
9327
* @final
9328
* @type String
9329
*/
9330
CSS_CLASS_NAME: "yuimenubar",
9331
9332
9333
/**
9334
* @property SUBMENU_TOGGLE_REGION_WIDTH
9335
* @description Width (in pixels) of the area of a MenuBarItem that, when pressed, will toggle the
9336
* display of the MenuBarItem's submenu.
9337
* @default 20
9338
* @final
9339
* @type Number
9340
*/
9341
SUBMENU_TOGGLE_REGION_WIDTH: 20,
9342
9343
9344
// Protected event handlers
9345
9346
9347
/**
9348
* @method _onKeyDown
9349
* @description "keydown" Custom Event handler for the menu bar.
9350
* @private
9351
* @param {String} p_sType String representing the name of the event that 
9352
* was fired.
9353
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
9354
* @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar 
9355
* that fired the event.
9356
*/
9357
_onKeyDown: function(p_sType, p_aArgs, p_oMenuBar) {
9358
9359
    var oEvent = p_aArgs[0],
9360
        oItem = p_aArgs[1],
9361
        oSubmenu,
9362
        oItemCfg,
9363
        oNextItem;
9364
9365
9366
    if(oItem && !oItem.cfg.getProperty(_DISABLED)) {
9367
9368
        oItemCfg = oItem.cfg;
9369
9370
        switch(oEvent.keyCode) {
9371
    
9372
            case 37:    // Left arrow
9373
            case 39:    // Right arrow
9374
    
9375
                if(oItem == this.activeItem && !oItemCfg.getProperty(_SELECTED)) {
9376
    
9377
                    oItemCfg.setProperty(_SELECTED, true);
9378
    
9379
                }
9380
                else {
9381
    
9382
                    oNextItem = (oEvent.keyCode == 37) ? 
9383
                        oItem.getPreviousEnabledSibling() : 
9384
                        oItem.getNextEnabledSibling();
9385
            
9386
                    if(oNextItem) {
9387
    
9388
                        this.clearActiveItem();
9389
    
9390
                        oNextItem.cfg.setProperty(_SELECTED, true);
9391
                        
9392
						oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
9393
						
9394
						if(oSubmenu) {
9395
					
9396
							oSubmenu.show();
9397
							oSubmenu.setInitialFocus();
9398
						
9399
						}
9400
						else {
9401
							oNextItem.focus();  
9402
						}
9403
    
9404
                    }
9405
    
9406
                }
9407
    
9408
                Event.preventDefault(oEvent);
9409
    
9410
            break;
9411
    
9412
            case 40:    // Down arrow
9413
    
9414
                if(this.activeItem != oItem) {
9415
    
9416
                    this.clearActiveItem();
9417
    
9418
                    oItemCfg.setProperty(_SELECTED, true);
9419
                    oItem.focus();
9420
                
9421
                }
9422
    
9423
                oSubmenu = oItemCfg.getProperty(_SUBMENU);
9424
    
9425
                if(oSubmenu) {
9426
    
9427
                    if(oSubmenu.cfg.getProperty(_VISIBLE)) {
9428
    
9429
                        oSubmenu.setInitialSelection();
9430
                        oSubmenu.setInitialFocus();
9431
                    
9432
                    }
9433
                    else {
9434
    
9435
                        oSubmenu.show();
9436
                        oSubmenu.setInitialFocus();
9437
                    
9438
                    }
9439
    
9440
                }
9441
    
9442
                Event.preventDefault(oEvent);
9443
    
9444
            break;
9445
    
9446
        }
9447
9448
    }
9449
9450
9451
    if(oEvent.keyCode == 27 && this.activeItem) { // Esc key
9452
9453
        oSubmenu = this.activeItem.cfg.getProperty(_SUBMENU);
9454
9455
        if(oSubmenu && oSubmenu.cfg.getProperty(_VISIBLE)) {
9456
        
9457
            oSubmenu.hide();
9458
            this.activeItem.focus();
9459
        
9460
        }
9461
        else {
9462
9463
            this.activeItem.cfg.setProperty(_SELECTED, false);
9464
            this.activeItem.blur();
9465
    
9466
        }
9467
9468
        Event.preventDefault(oEvent);
9469
    
9470
    }
9471
9472
},
9473
9474
9475
/**
9476
* @method _onClick
9477
* @description "click" event handler for the menu bar.
9478
* @protected
9479
* @param {String} p_sType String representing the name of the event that 
9480
* was fired.
9481
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
9482
* @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar 
9483
* that fired the event.
9484
*/
9485
_onClick: function(p_sType, p_aArgs, p_oMenuBar) {
9486
9487
    MenuBar.superclass._onClick.call(this, p_sType, p_aArgs, p_oMenuBar);
9488
9489
    var oItem = p_aArgs[1],
9490
        bReturnVal = true,
9491
    	oItemEl,
9492
        oEvent,
9493
        oTarget,
9494
        oActiveItem,
9495
        oConfig,
9496
        oSubmenu,
9497
        nMenuItemX,
9498
        nToggleRegion;
9499
9500
9501
	var toggleSubmenuDisplay = function () {
9502
9503
		if(oSubmenu.cfg.getProperty(_VISIBLE)) {
9504
		
9505
			oSubmenu.hide();
9506
		
9507
		}
9508
		else {
9509
		
9510
			oSubmenu.show();                    
9511
		
9512
		}
9513
	
9514
	};
9515
    
9516
9517
    if(oItem && !oItem.cfg.getProperty(_DISABLED)) {
9518
9519
        oEvent = p_aArgs[0];
9520
        oTarget = Event.getTarget(oEvent);
9521
        oActiveItem = this.activeItem;
9522
        oConfig = this.cfg;
9523
9524
9525
        // Hide any other submenus that might be visible
9526
    
9527
        if(oActiveItem && oActiveItem != oItem) {
9528
    
9529
            this.clearActiveItem();
9530
    
9531
        }
9532
9533
    
9534
        oItem.cfg.setProperty(_SELECTED, true);
9535
    
9536
9537
        // Show the submenu for the item
9538
    
9539
        oSubmenu = oItem.cfg.getProperty(_SUBMENU);
9540
9541
9542
        if(oSubmenu) {
9543
9544
			oItemEl = oItem.element;
9545
			nMenuItemX = YAHOO.util.Dom.getX(oItemEl);
9546
			nToggleRegion = nMenuItemX + (oItemEl.offsetWidth - this.SUBMENU_TOGGLE_REGION_WIDTH);
9547
9548
			if (oConfig.getProperty(_SUBMENU_TOGGLE_REGION)) {
9549
9550
				if (Event.getPageX(oEvent) > nToggleRegion) {
9551
9552
					toggleSubmenuDisplay();
9553
9554
					Event.preventDefault(oEvent);
9555
9556
					/*
9557
						 Return false so that other click event handlers are not called when the 
9558
						 user clicks inside the toggle region.
9559
					*/
9560
					bReturnVal = false;
9561
				
9562
				}
9563
        
9564
        	}
9565
			else {
9566
9567
				toggleSubmenuDisplay();
9568
            
9569
            }
9570
        
9571
        }
9572
    
9573
    }
9574
9575
9576
	return bReturnVal;
9577
9578
},
9579
9580
9581
9582
// Public methods
9583
9584
/**
9585
* @method configSubmenuToggle
9586
* @description Event handler for when the "submenutoggleregion" configuration property of 
9587
* a MenuBar changes.
9588
* @param {String} p_sType The name of the event that was fired.
9589
* @param {Array} p_aArgs Collection of arguments sent when the event was fired.
9590
*/
9591
configSubmenuToggle: function (p_sType, p_aArgs) {
9592
9593
	var bSubmenuToggle = p_aArgs[0];
9594
	
9595
	if (bSubmenuToggle) {
9596
	
9597
		this.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, false);
9598
	
9599
	}
9600
9601
},
9602
9603
9604
/**
9605
* @method toString
9606
* @description Returns a string representing the menu bar.
9607
* @return {String}
9608
*/
9609
toString: function() {
9610
9611
    var sReturnVal = _MENUBAR,
9612
        sId = this.id;
9613
9614
    if(sId) {
9615
9616
        sReturnVal += (_SPACE + sId);
9617
    
9618
    }
9619
9620
    return sReturnVal;
9621
9622
},
9623
9624
9625
/**
9626
* @description Initializes the class's configurable properties which can be
9627
* changed using the menu bar's Config object ("cfg").
9628
* @method initDefaultConfig
9629
*/
9630
initDefaultConfig: function() {
9631
9632
    MenuBar.superclass.initDefaultConfig.call(this);
9633
9634
    var oConfig = this.cfg;
9635
9636
	// Add configuration properties
9637
9638
9639
    /*
9640
        Set the default value for the "position" configuration property
9641
        to "static" by re-adding the property.
9642
    */
9643
9644
9645
    /**
9646
    * @config position
9647
    * @description String indicating how a menu bar should be positioned on the 
9648
    * screen.  Possible values are "static" and "dynamic."  Static menu bars 
9649
    * are visible by default and reside in the normal flow of the document 
9650
    * (CSS position: static).  Dynamic menu bars are hidden by default, reside
9651
    * out of the normal flow of the document (CSS position: absolute), and can 
9652
    * overlay other elements on the screen.
9653
    * @default static
9654
    * @type String
9655
    */
9656
    oConfig.addProperty(
9657
        POSITION_CONFIG.key, 
9658
        {
9659
            handler: this.configPosition, 
9660
            value: POSITION_CONFIG.value, 
9661
            validator: POSITION_CONFIG.validator,
9662
            supercedes: POSITION_CONFIG.supercedes
9663
        }
9664
    );
9665
9666
9667
    /*
9668
        Set the default value for the "submenualignment" configuration property
9669
        to ["tl","bl"] by re-adding the property.
9670
    */
9671
9672
    /**
9673
    * @config submenualignment
9674
    * @description Array defining how submenus should be aligned to their 
9675
    * parent menu bar item. The format is: [itemCorner, submenuCorner].
9676
    * @default ["tl","bl"]
9677
    * @type Array
9678
    */
9679
    oConfig.addProperty(
9680
        SUBMENU_ALIGNMENT_CONFIG.key, 
9681
        {
9682
            value: SUBMENU_ALIGNMENT_CONFIG.value,
9683
            suppressEvent: SUBMENU_ALIGNMENT_CONFIG.suppressEvent
9684
        }
9685
    );
9686
9687
9688
    /*
9689
        Change the default value for the "autosubmenudisplay" configuration 
9690
        property to "false" by re-adding the property.
9691
    */
9692
9693
    /**
9694
    * @config autosubmenudisplay
9695
    * @description Boolean indicating if submenus are automatically made 
9696
    * visible when the user mouses over the menu bar's items.
9697
    * @default false
9698
    * @type Boolean
9699
    */
9700
	oConfig.addProperty(
9701
	   AUTO_SUBMENU_DISPLAY_CONFIG.key, 
9702
	   {
9703
	       value: AUTO_SUBMENU_DISPLAY_CONFIG.value, 
9704
	       validator: AUTO_SUBMENU_DISPLAY_CONFIG.validator,
9705
	       suppressEvent: AUTO_SUBMENU_DISPLAY_CONFIG.suppressEvent
9706
       } 
9707
    );
9708
9709
9710
    /**
9711
    * @config submenutoggleregion
9712
    * @description Boolean indicating if only a specific region of a MenuBarItem should toggle the 
9713
    * display of a submenu.  The default width of the region is determined by the value of the
9714
    * SUBMENU_TOGGLE_REGION_WIDTH property.  If set to true, the autosubmenudisplay 
9715
    * configuration property will be set to false, and any click event listeners will not be 
9716
    * called when the user clicks inside the submenu toggle region of a MenuBarItem.  If the 
9717
    * user clicks outside of the submenu toggle region, the MenuBarItem will maintain its 
9718
    * standard behavior.
9719
    * @default false
9720
    * @type Boolean
9721
    */
9722
	oConfig.addProperty(
9723
	   SUBMENU_TOGGLE_REGION_CONFIG.key, 
9724
	   {
9725
	       value: SUBMENU_TOGGLE_REGION_CONFIG.value, 
9726
	       validator: SUBMENU_TOGGLE_REGION_CONFIG.validator,
9727
	       handler: this.configSubmenuToggle
9728
       } 
9729
    );
9730
9731
}
9732
 
9733
}); // END YAHOO.lang.extend
9734
9735
}());
9736
9737
9738
9739
/**
9740
* Creates an item for a menu bar.
9741
* 
9742
* @param {String} p_oObject String specifying the text of the menu bar item.
9743
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9744
* one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the 
9745
* <code>&#60;li&#62;</code> element of the menu bar item.
9746
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9747
* one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object 
9748
* specifying the <code>&#60;optgroup&#62;</code> element of the menu bar item.
9749
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9750
* one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying 
9751
* the <code>&#60;option&#62;</code> element of the menu bar item.
9752
* @param {Object} p_oConfig Optional. Object literal specifying the 
9753
* configuration for the menu bar item. See configuration class documentation 
9754
* for more details.
9755
* @class MenuBarItem
9756
* @constructor
9757
* @extends YAHOO.widget.MenuItem
9758
*/
9759
YAHOO.widget.MenuBarItem = function(p_oObject, p_oConfig) {
9760
9761
    YAHOO.widget.MenuBarItem.superclass.constructor.call(this, p_oObject, p_oConfig);
9762
9763
};
9764
9765
YAHOO.lang.extend(YAHOO.widget.MenuBarItem, YAHOO.widget.MenuItem, {
9766
9767
9768
9769
/**
9770
* @method init
9771
* @description The MenuBarItem class's initialization method. This method is 
9772
* automatically called by the constructor, and sets up all DOM references for 
9773
* pre-existing markup, and creates required markup if it is not already present.
9774
* @param {String} p_oObject String specifying the text of the menu bar item.
9775
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9776
* one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the 
9777
* <code>&#60;li&#62;</code> element of the menu bar item.
9778
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9779
* one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object 
9780
* specifying the <code>&#60;optgroup&#62;</code> element of the menu bar item.
9781
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9782
* one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying 
9783
* the <code>&#60;option&#62;</code> element of the menu bar item.
9784
* @param {Object} p_oConfig Optional. Object literal specifying the 
9785
* configuration for the menu bar item. See configuration class documentation 
9786
* for more details.
9787
*/
9788
init: function(p_oObject, p_oConfig) {
9789
9790
    if(!this.SUBMENU_TYPE) {
9791
9792
        this.SUBMENU_TYPE = YAHOO.widget.Menu;
9793
9794
    }
9795
9796
9797
    /* 
9798
        Call the init of the superclass (YAHOO.widget.MenuItem)
9799
        Note: We don't pass the user config in here yet 
9800
        because we only want it executed once, at the lowest 
9801
        subclass level.
9802
    */ 
9803
9804
    YAHOO.widget.MenuBarItem.superclass.init.call(this, p_oObject);  
9805
9806
9807
    var oConfig = this.cfg;
9808
9809
    if(p_oConfig) {
9810
9811
        oConfig.applyConfig(p_oConfig, true);
9812
9813
    }
9814
9815
    oConfig.fireQueue();
9816
9817
},
9818
9819
9820
9821
// Constants
9822
9823
9824
/**
9825
* @property CSS_CLASS_NAME
9826
* @description String representing the CSS class(es) to be applied to the 
9827
* <code>&#60;li&#62;</code> element of the menu bar item.
9828
* @default "yuimenubaritem"
9829
* @final
9830
* @type String
9831
*/
9832
CSS_CLASS_NAME: "yuimenubaritem",
9833
9834
9835
/**
9836
* @property CSS_LABEL_CLASS_NAME
9837
* @description String representing the CSS class(es) to be applied to the 
9838
* menu bar item's <code>&#60;a&#62;</code> element.
9839
* @default "yuimenubaritemlabel"
9840
* @final
9841
* @type String
9842
*/
9843
CSS_LABEL_CLASS_NAME: "yuimenubaritemlabel",
9844
9845
9846
9847
// Public methods
9848
9849
9850
/**
9851
* @method toString
9852
* @description Returns a string representing the menu bar item.
9853
* @return {String}
9854
*/
9855
toString: function() {
9856
9857
    var sReturnVal = "MenuBarItem";
9858
9859
    if(this.cfg && this.cfg.getProperty("text")) {
9860
9861
        sReturnVal += (": " + this.cfg.getProperty("text"));
9862
9863
    }
9864
9865
    return sReturnVal;
9866
9867
}
9868
    
9869
}); // END YAHOO.lang.extend
9870
YAHOO.register("menu", YAHOO.widget.Menu, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/menu/menu-min.js (-16 lines)
Lines 1-16 Link Here
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.8.0r4
6
*/
7
(function(){var K=YAHOO.env.ua,C=YAHOO.util.Dom,Z=YAHOO.util.Event,H=YAHOO.lang,T="DIV",P="hd",M="bd",O="ft",X="LI",A="disabled",D="mouseover",F="mouseout",U="mousedown",G="mouseup",V="click",B="keydown",N="keyup",I="keypress",L="clicktohide",S="position",Q="dynamic",Y="showdelay",J="selected",E="visible",W="UL",R="MenuManager";YAHOO.widget.MenuManager=function(){var l=false,d={},o={},h={},c={"click":"clickEvent","mousedown":"mouseDownEvent","mouseup":"mouseUpEvent","mouseover":"mouseOverEvent","mouseout":"mouseOutEvent","keydown":"keyDownEvent","keyup":"keyUpEvent","keypress":"keyPressEvent","focus":"focusEvent","focusin":"focusEvent","blur":"blurEvent","focusout":"blurEvent"},i=null;function b(r){var p,q;if(r&&r.tagName){switch(r.tagName.toUpperCase()){case T:p=r.parentNode;if((C.hasClass(r,P)||C.hasClass(r,M)||C.hasClass(r,O))&&p&&p.tagName&&p.tagName.toUpperCase()==T){q=p;}else{q=r;}break;case X:q=r;break;default:p=r.parentNode;if(p){q=b(p);}break;}}return q;}function e(t){var p=Z.getTarget(t),q=b(p),u=true,w=t.type,x,r,s,z,y;if(q){r=q.tagName.toUpperCase();if(r==X){s=q.id;if(s&&h[s]){z=h[s];y=z.parent;}}else{if(r==T){if(q.id){y=d[q.id];}}}}if(y){x=c[w];if(w=="click"&&(K.gecko&&y.platform!="mac")&&t.button>0){u=false;}if(u&&z&&!z.cfg.getProperty(A)){z[x].fire(t);}if(u){y[x].fire(t,z);}}else{if(w==U){for(var v in o){if(H.hasOwnProperty(o,v)){y=o[v];if(y.cfg.getProperty(L)&&!(y instanceof YAHOO.widget.MenuBar)&&y.cfg.getProperty(S)==Q){y.hide();if(K.ie&&p.focus){p.setActive();}}else{if(y.cfg.getProperty(Y)>0){y._cancelShowDelay();}if(y.activeItem){y.activeItem.blur();y.activeItem.cfg.setProperty(J,false);y.activeItem=null;}}}}}}}function n(q,p,r){if(d[r.id]){this.removeMenu(r);}}function k(q,p){var r=p[1];if(r){i=r;}}function f(q,p){i=null;}function a(r,q){var p=q[0],s=this.id;if(p){o[s]=this;}else{if(o[s]){delete o[s];}}}function j(q,p){m(this);}function m(q){var p=q.id;if(p&&h[p]){if(i==q){i=null;}delete h[p];q.destroyEvent.unsubscribe(j);}}function g(q,p){var s=p[0],r;if(s instanceof YAHOO.widget.MenuItem){r=s.id;if(!h[r]){h[r]=s;s.destroyEvent.subscribe(j);}}}return{addMenu:function(q){var p;if(q instanceof YAHOO.widget.Menu&&q.id&&!d[q.id]){d[q.id]=q;if(!l){p=document;Z.on(p,D,e,this,true);Z.on(p,F,e,this,true);Z.on(p,U,e,this,true);Z.on(p,G,e,this,true);Z.on(p,V,e,this,true);Z.on(p,B,e,this,true);Z.on(p,N,e,this,true);Z.on(p,I,e,this,true);Z.onFocus(p,e,this,true);Z.onBlur(p,e,this,true);l=true;}q.cfg.subscribeToConfigEvent(E,a);q.destroyEvent.subscribe(n,q,this);q.itemAddedEvent.subscribe(g);q.focusEvent.subscribe(k);q.blurEvent.subscribe(f);}},removeMenu:function(s){var q,p,r;if(s){q=s.id;if((q in d)&&(d[q]==s)){p=s.getItems();if(p&&p.length>0){r=p.length-1;do{m(p[r]);}while(r--);}delete d[q];if((q in o)&&(o[q]==s)){delete o[q];}if(s.cfg){s.cfg.unsubscribeFromConfigEvent(E,a);}s.destroyEvent.unsubscribe(n,s);s.itemAddedEvent.unsubscribe(g);s.focusEvent.unsubscribe(k);s.blurEvent.unsubscribe(f);}}},hideVisible:function(){var p;for(var q in o){if(H.hasOwnProperty(o,q)){p=o[q];if(!(p instanceof YAHOO.widget.MenuBar)&&p.cfg.getProperty(S)==Q){p.hide();}}}},getVisible:function(){return o;},getMenus:function(){return d;},getMenu:function(q){var p;if(q in d){p=d[q];}return p;},getMenuItem:function(q){var p;if(q in h){p=h[q];}return p;},getMenuItemGroup:function(t){var q=C.get(t),p,v,u,r,s;if(q&&q.tagName&&q.tagName.toUpperCase()==W){v=q.firstChild;if(v){p=[];do{r=v.id;if(r){u=this.getMenuItem(r);if(u){p[p.length]=u;}}}while((v=v.nextSibling));if(p.length>0){s=p;}}}return s;},getFocusedMenuItem:function(){return i;},getFocusedMenu:function(){var p;if(i){p=i.parent.getRoot();}return p;},toString:function(){return R;}};}();})();(function(){var AM=YAHOO.lang,Aq="Menu",G="DIV",K="div",Am="id",AH="SELECT",e="xy",R="y",Ax="UL",L="ul",AJ="first-of-type",k="LI",h="OPTGROUP",Az="OPTION",Ah="disabled",AY="none",y="selected",At="groupindex",i="index",O="submenu",Au="visible",AX="hidedelay",Ac="position",AD="dynamic",C="static",An=AD+","+C,Q="url",M="#",V="target",AU="maxheight",T="topscrollbar",x="bottomscrollbar",d="_",P=T+d+Ah,E=x+d+Ah,b="mousemove",Av="showdelay",c="submenuhidedelay",AF="iframe",w="constraintoviewport",A4="preventcontextoverlap",AO="submenualignment",Z="autosubmenudisplay",AC="clicktohide",g="container",j="scrollincrement",Aj="minscrollheight",A2="classname",Ag="shadow",Ar="keepopen",A0="hd",D="hastitle",p="context",u="",Ak="mousedown",Ae="keydown",Ao="height",U="width",AQ="px",Ay="effect",AE="monitorresize",AW="display",AV="block",J="visibility",z="absolute",AS="zindex",l="yui-menu-body-scrolled",AK="&#32;",A1=" ",Ai="mouseover",H="mouseout",AR="itemAdded",n="itemRemoved",AL="hidden",s="yui-menu-shadow",AG=s+"-visible",m=s+A1+AG;YAHOO.widget.Menu=function(A6,A5){if(A5){this.parent=A5.parent;this.lazyLoad=A5.lazyLoad||A5.lazyload;this.itemData=A5.itemData||A5.itemdata;}YAHOO.widget.Menu.superclass.constructor.call(this,A6,A5);};function B(A6){var A5=false;if(AM.isString(A6)){A5=(An.indexOf((A6.toLowerCase()))!=-1);}return A5;}var f=YAHOO.util.Dom,AA=YAHOO.util.Event,Aw=YAHOO.widget.Module,AB=YAHOO.widget.Overlay,r=YAHOO.widget.Menu,A3=YAHOO.widget.MenuManager,F=YAHOO.util.CustomEvent,As=YAHOO.env.ua,Ap,AT=false,Ad,Ab=[["mouseOverEvent",Ai],["mouseOutEvent",H],["mouseDownEvent",Ak],["mouseUpEvent","mouseup"],["clickEvent","click"],["keyPressEvent","keypress"],["keyDownEvent",Ae],["keyUpEvent","keyup"],["focusEvent","focus"],["blurEvent","blur"],["itemAddedEvent",AR],["itemRemovedEvent",n]],AZ={key:Au,value:false,validator:AM.isBoolean},AP={key:w,value:true,validator:AM.isBoolean,supercedes:[AF,"x",R,e]},AI={key:A4,value:true,validator:AM.isBoolean,supercedes:[w]},S={key:Ac,value:AD,validator:B,supercedes:[Au,AF]},A={key:AO,value:["tl","tr"]},t={key:Z,value:true,validator:AM.isBoolean,suppressEvent:true},Y={key:Av,value:250,validator:AM.isNumber,suppressEvent:true},q={key:AX,value:0,validator:AM.isNumber,suppressEvent:true},v={key:c,value:250,validator:AM.isNumber,suppressEvent:true},o={key:AC,value:true,validator:AM.isBoolean,suppressEvent:true},AN={key:g,suppressEvent:true},Af={key:j,value:1,validator:AM.isNumber,supercedes:[AU],suppressEvent:true},N={key:Aj,value:90,validator:AM.isNumber,supercedes:[AU],suppressEvent:true},X={key:AU,value:0,validator:AM.isNumber,supercedes:[AF],suppressEvent:true},W={key:A2,value:null,validator:AM.isString,suppressEvent:true},a={key:Ah,value:false,validator:AM.isBoolean,suppressEvent:true},I={key:Ag,value:true,validator:AM.isBoolean,suppressEvent:true,supercedes:[Au]},Al={key:Ar,value:false,validator:AM.isBoolean};
8
function Aa(A5){Ad=AA.getTarget(A5);}YAHOO.lang.extend(r,AB,{CSS_CLASS_NAME:"yuimenu",ITEM_TYPE:null,GROUP_TITLE_TAG_NAME:"h6",OFF_SCREEN_POSITION:"-999em",_useHideDelay:false,_bHandledMouseOverEvent:false,_bHandledMouseOutEvent:false,_aGroupTitleElements:null,_aItemGroups:null,_aListElements:null,_nCurrentMouseX:0,_bStopMouseEventHandlers:false,_sClassName:null,lazyLoad:false,itemData:null,activeItem:null,parent:null,srcElement:null,init:function(A7,A6){this._aItemGroups=[];this._aListElements=[];this._aGroupTitleElements=[];if(!this.ITEM_TYPE){this.ITEM_TYPE=YAHOO.widget.MenuItem;}var A5;if(AM.isString(A7)){A5=f.get(A7);}else{if(A7.tagName){A5=A7;}}if(A5&&A5.tagName){switch(A5.tagName.toUpperCase()){case G:this.srcElement=A5;if(!A5.id){A5.setAttribute(Am,f.generateId());}r.superclass.init.call(this,A5);this.beforeInitEvent.fire(r);break;case AH:this.srcElement=A5;r.superclass.init.call(this,f.generateId());this.beforeInitEvent.fire(r);break;}}else{r.superclass.init.call(this,A7);this.beforeInitEvent.fire(r);}if(this.element){f.addClass(this.element,this.CSS_CLASS_NAME);this.initEvent.subscribe(this._onInit);this.beforeRenderEvent.subscribe(this._onBeforeRender);this.renderEvent.subscribe(this._onRender);this.beforeShowEvent.subscribe(this._onBeforeShow);this.hideEvent.subscribe(this._onHide);this.showEvent.subscribe(this._onShow);this.beforeHideEvent.subscribe(this._onBeforeHide);this.mouseOverEvent.subscribe(this._onMouseOver);this.mouseOutEvent.subscribe(this._onMouseOut);this.clickEvent.subscribe(this._onClick);this.keyDownEvent.subscribe(this._onKeyDown);this.keyPressEvent.subscribe(this._onKeyPress);this.blurEvent.subscribe(this._onBlur);if(!AT){AA.onFocus(document,Aa);AT=true;}if((As.gecko&&As.gecko<1.9)||As.webkit){this.cfg.subscribeToConfigEvent(R,this._onYChange);}if(A6){this.cfg.applyConfig(A6,true);}A3.addMenu(this);this.initEvent.fire(r);}},_initSubTree:function(){var A6=this.srcElement,A5,A8,BB,BC,BA,A9,A7;if(A6){A5=(A6.tagName&&A6.tagName.toUpperCase());if(A5==G){BC=this.body.firstChild;if(BC){A8=0;BB=this.GROUP_TITLE_TAG_NAME.toUpperCase();do{if(BC&&BC.tagName){switch(BC.tagName.toUpperCase()){case BB:this._aGroupTitleElements[A8]=BC;break;case Ax:this._aListElements[A8]=BC;this._aItemGroups[A8]=[];A8++;break;}}}while((BC=BC.nextSibling));if(this._aListElements[0]){f.addClass(this._aListElements[0],AJ);}}}BC=null;if(A5){switch(A5){case G:BA=this._aListElements;A9=BA.length;if(A9>0){A7=A9-1;do{BC=BA[A7].firstChild;if(BC){do{if(BC&&BC.tagName&&BC.tagName.toUpperCase()==k){this.addItem(new this.ITEM_TYPE(BC,{parent:this}),A7);}}while((BC=BC.nextSibling));}}while(A7--);}break;case AH:BC=A6.firstChild;do{if(BC&&BC.tagName){switch(BC.tagName.toUpperCase()){case h:case Az:this.addItem(new this.ITEM_TYPE(BC,{parent:this}));break;}}}while((BC=BC.nextSibling));break;}}}},_getFirstEnabledItem:function(){var A5=this.getItems(),A9=A5.length,A8,A7;for(var A6=0;A6<A9;A6++){A8=A5[A6];if(A8&&!A8.cfg.getProperty(Ah)&&A8.element.style.display!=AY){A7=A8;break;}}return A7;},_addItemToGroup:function(BA,BB,BF){var BD,BG,A8,BE,A9,A6,A7,BC;function A5(BH,BI){return(BH[BI]||A5(BH,(BI+1)));}if(BB instanceof this.ITEM_TYPE){BD=BB;BD.parent=this;}else{if(AM.isString(BB)){BD=new this.ITEM_TYPE(BB,{parent:this});}else{if(AM.isObject(BB)){BB.parent=this;BD=new this.ITEM_TYPE(BB.text,BB);}}}if(BD){if(BD.cfg.getProperty(y)){this.activeItem=BD;}BG=AM.isNumber(BA)?BA:0;A8=this._getItemGroup(BG);if(!A8){A8=this._createItemGroup(BG);}if(AM.isNumber(BF)){A9=(BF>=A8.length);if(A8[BF]){A8.splice(BF,0,BD);}else{A8[BF]=BD;}BE=A8[BF];if(BE){if(A9&&(!BE.element.parentNode||BE.element.parentNode.nodeType==11)){this._aListElements[BG].appendChild(BE.element);}else{A6=A5(A8,(BF+1));if(A6&&(!BE.element.parentNode||BE.element.parentNode.nodeType==11)){this._aListElements[BG].insertBefore(BE.element,A6.element);}}BE.parent=this;this._subscribeToItemEvents(BE);this._configureSubmenu(BE);this._updateItemProperties(BG);this.itemAddedEvent.fire(BE);this.changeContentEvent.fire();BC=BE;}}else{A7=A8.length;A8[A7]=BD;BE=A8[A7];if(BE){if(!f.isAncestor(this._aListElements[BG],BE.element)){this._aListElements[BG].appendChild(BE.element);}BE.element.setAttribute(At,BG);BE.element.setAttribute(i,A7);BE.parent=this;BE.index=A7;BE.groupIndex=BG;this._subscribeToItemEvents(BE);this._configureSubmenu(BE);if(A7===0){f.addClass(BE.element,AJ);}this.itemAddedEvent.fire(BE);this.changeContentEvent.fire();BC=BE;}}}return BC;},_removeItemFromGroupByIndex:function(A8,A6){var A7=AM.isNumber(A8)?A8:0,A9=this._getItemGroup(A7),BB,BA,A5;if(A9){BB=A9.splice(A6,1);BA=BB[0];if(BA){this._updateItemProperties(A7);if(A9.length===0){A5=this._aListElements[A7];if(this.body&&A5){this.body.removeChild(A5);}this._aItemGroups.splice(A7,1);this._aListElements.splice(A7,1);A5=this._aListElements[0];if(A5){f.addClass(A5,AJ);}}this.itemRemovedEvent.fire(BA);this.changeContentEvent.fire();}}return BA;},_removeItemFromGroupByValue:function(A8,A5){var BA=this._getItemGroup(A8),BB,A9,A7,A6;if(BA){BB=BA.length;A9=-1;if(BB>0){A6=BB-1;do{if(BA[A6]==A5){A9=A6;break;}}while(A6--);if(A9>-1){A7=this._removeItemFromGroupByIndex(A8,A9);}}}return A7;},_updateItemProperties:function(A6){var A7=this._getItemGroup(A6),BA=A7.length,A9,A8,A5;if(BA>0){A5=BA-1;do{A9=A7[A5];if(A9){A8=A9.element;A9.index=A5;A9.groupIndex=A6;A8.setAttribute(At,A6);A8.setAttribute(i,A5);f.removeClass(A8,AJ);}}while(A5--);if(A8){f.addClass(A8,AJ);}}},_createItemGroup:function(A7){var A5,A6;if(!this._aItemGroups[A7]){this._aItemGroups[A7]=[];A5=document.createElement(L);this._aListElements[A7]=A5;A6=this._aItemGroups[A7];}return A6;},_getItemGroup:function(A7){var A5=AM.isNumber(A7)?A7:0,A8=this._aItemGroups,A6;if(A5 in A8){A6=A8[A5];}return A6;},_configureSubmenu:function(A5){var A6=A5.cfg.getProperty(O);if(A6){this.cfg.configChangedEvent.subscribe(this._onParentMenuConfigChange,A6,true);this.renderEvent.subscribe(this._onParentMenuRender,A6,true);}},_subscribeToItemEvents:function(A5){A5.destroyEvent.subscribe(this._onMenuItemDestroy,A5,this);
9
A5.cfg.configChangedEvent.subscribe(this._onMenuItemConfigChange,A5,this);},_onVisibleChange:function(A7,A6){var A5=A6[0];if(A5){f.addClass(this.element,Au);}else{f.removeClass(this.element,Au);}},_cancelHideDelay:function(){var A5=this.getRoot()._hideDelayTimer;if(A5){A5.cancel();}},_execHideDelay:function(){this._cancelHideDelay();var A5=this.getRoot();A5._hideDelayTimer=AM.later(A5.cfg.getProperty(AX),this,function(){if(A5.activeItem){if(A5.hasFocus()){A5.activeItem.focus();}A5.clearActiveItem();}if(A5==this&&!(this instanceof YAHOO.widget.MenuBar)&&this.cfg.getProperty(Ac)==AD){this.hide();}});},_cancelShowDelay:function(){var A5=this.getRoot()._showDelayTimer;if(A5){A5.cancel();}},_execSubmenuHideDelay:function(A7,A6,A5){A7._submenuHideDelayTimer=AM.later(50,this,function(){if(this._nCurrentMouseX>(A6+10)){A7._submenuHideDelayTimer=AM.later(A5,A7,function(){this.hide();});}else{A7.hide();}});},_disableScrollHeader:function(){if(!this._bHeaderDisabled){f.addClass(this.header,P);this._bHeaderDisabled=true;}},_disableScrollFooter:function(){if(!this._bFooterDisabled){f.addClass(this.footer,E);this._bFooterDisabled=true;}},_enableScrollHeader:function(){if(this._bHeaderDisabled){f.removeClass(this.header,P);this._bHeaderDisabled=false;}},_enableScrollFooter:function(){if(this._bFooterDisabled){f.removeClass(this.footer,E);this._bFooterDisabled=false;}},_onMouseOver:function(BH,BA){var BI=BA[0],BE=BA[1],A5=AA.getTarget(BI),A9=this.getRoot(),BG=this._submenuHideDelayTimer,A6,A8,BD,A7,BC,BB;var BF=function(){if(this.parent.cfg.getProperty(y)){this.show();}};if(!this._bStopMouseEventHandlers){if(!this._bHandledMouseOverEvent&&(A5==this.element||f.isAncestor(this.element,A5))){if(this._useHideDelay){this._cancelHideDelay();}this._nCurrentMouseX=0;AA.on(this.element,b,this._onMouseMove,this,true);if(!(BE&&f.isAncestor(BE.element,AA.getRelatedTarget(BI)))){this.clearActiveItem();}if(this.parent&&BG){BG.cancel();this.parent.cfg.setProperty(y,true);A6=this.parent.parent;A6._bHandledMouseOutEvent=true;A6._bHandledMouseOverEvent=false;}this._bHandledMouseOverEvent=true;this._bHandledMouseOutEvent=false;}if(BE&&!BE.handledMouseOverEvent&&!BE.cfg.getProperty(Ah)&&(A5==BE.element||f.isAncestor(BE.element,A5))){A8=this.cfg.getProperty(Av);BD=(A8>0);if(BD){this._cancelShowDelay();}A7=this.activeItem;if(A7){A7.cfg.setProperty(y,false);}BC=BE.cfg;BC.setProperty(y,true);if(this.hasFocus()||A9._hasFocus){BE.focus();A9._hasFocus=false;}if(this.cfg.getProperty(Z)){BB=BC.getProperty(O);if(BB){if(BD){A9._showDelayTimer=AM.later(A9.cfg.getProperty(Av),BB,BF);}else{BB.show();}}}BE.handledMouseOverEvent=true;BE.handledMouseOutEvent=false;}}},_onMouseOut:function(BD,A7){var BE=A7[0],BB=A7[1],A8=AA.getRelatedTarget(BE),BC=false,BA,A9,A5,A6;if(!this._bStopMouseEventHandlers){if(BB&&!BB.cfg.getProperty(Ah)){BA=BB.cfg;A9=BA.getProperty(O);if(A9&&(A8==A9.element||f.isAncestor(A9.element,A8))){BC=true;}if(!BB.handledMouseOutEvent&&((A8!=BB.element&&!f.isAncestor(BB.element,A8))||BC)){if(!BC){BB.cfg.setProperty(y,false);if(A9){A5=this.cfg.getProperty(c);A6=this.cfg.getProperty(Av);if(!(this instanceof YAHOO.widget.MenuBar)&&A5>0&&A6>=A5){this._execSubmenuHideDelay(A9,AA.getPageX(BE),A5);}else{A9.hide();}}}BB.handledMouseOutEvent=true;BB.handledMouseOverEvent=false;}}if(!this._bHandledMouseOutEvent&&((A8!=this.element&&!f.isAncestor(this.element,A8))||BC)){if(this._useHideDelay){this._execHideDelay();}AA.removeListener(this.element,b,this._onMouseMove);this._nCurrentMouseX=AA.getPageX(BE);this._bHandledMouseOutEvent=true;this._bHandledMouseOverEvent=false;}}},_onMouseMove:function(A6,A5){if(!this._bStopMouseEventHandlers){this._nCurrentMouseX=AA.getPageX(A6);}},_onClick:function(BG,A7){var BH=A7[0],BB=A7[1],BD=false,A9,BE,A6,A5,BA,BC,BF;var A8=function(){A6=this.getRoot();if(A6 instanceof YAHOO.widget.MenuBar||A6.cfg.getProperty(Ac)==C){A6.clearActiveItem();}else{A6.hide();}};if(BB){if(BB.cfg.getProperty(Ah)){AA.preventDefault(BH);A8.call(this);}else{A9=BB.cfg.getProperty(O);BA=BB.cfg.getProperty(Q);if(BA){BC=BA.indexOf(M);BF=BA.length;if(BC!=-1){BA=BA.substr(BC,BF);BF=BA.length;if(BF>1){A5=BA.substr(1,BF);BE=YAHOO.widget.MenuManager.getMenu(A5);if(BE){BD=(this.getRoot()===BE.getRoot());}}else{if(BF===1){BD=true;}}}}if(BD&&!BB.cfg.getProperty(V)){AA.preventDefault(BH);if(As.webkit){BB.focus();}else{BB.focusEvent.fire();}}if(!A9&&!this.cfg.getProperty(Ar)){A8.call(this);}}}},_onKeyDown:function(BK,BE){var BH=BE[0],BG=BE[1],BD,BI,A6,BA,BL,A5,BO,A9,BJ,A8,BF,BN,BB,BC;if(this._useHideDelay){this._cancelHideDelay();}function A7(){this._bStopMouseEventHandlers=true;AM.later(10,this,function(){this._bStopMouseEventHandlers=false;});}if(BG&&!BG.cfg.getProperty(Ah)){BI=BG.cfg;A6=this.parent;switch(BH.keyCode){case 38:case 40:BL=(BH.keyCode==38)?BG.getPreviousEnabledSibling():BG.getNextEnabledSibling();if(BL){this.clearActiveItem();BL.cfg.setProperty(y,true);BL.focus();if(this.cfg.getProperty(AU)>0){A5=this.body;BO=A5.scrollTop;A9=A5.offsetHeight;BJ=this.getItems();A8=BJ.length-1;BF=BL.element.offsetTop;if(BH.keyCode==40){if(BF>=(A9+BO)){A5.scrollTop=BF-A9;}else{if(BF<=BO){A5.scrollTop=0;}}if(BL==BJ[A8]){A5.scrollTop=BL.element.offsetTop;}}else{if(BF<=BO){A5.scrollTop=BF-BL.element.offsetHeight;}else{if(BF>=(BO+A9)){A5.scrollTop=BF;}}if(BL==BJ[0]){A5.scrollTop=0;}}BO=A5.scrollTop;BN=A5.scrollHeight-A5.offsetHeight;if(BO===0){this._disableScrollHeader();this._enableScrollFooter();}else{if(BO==BN){this._enableScrollHeader();this._disableScrollFooter();}else{this._enableScrollHeader();this._enableScrollFooter();}}}}AA.preventDefault(BH);A7();break;case 39:BD=BI.getProperty(O);if(BD){if(!BI.getProperty(y)){BI.setProperty(y,true);}BD.show();BD.setInitialFocus();BD.setInitialSelection();}else{BA=this.getRoot();if(BA instanceof YAHOO.widget.MenuBar){BL=BA.activeItem.getNextEnabledSibling();if(BL){BA.clearActiveItem();BL.cfg.setProperty(y,true);BD=BL.cfg.getProperty(O);if(BD){BD.show();BD.setInitialFocus();}else{BL.focus();}}}}AA.preventDefault(BH);
10
A7();break;case 37:if(A6){BB=A6.parent;if(BB instanceof YAHOO.widget.MenuBar){BL=BB.activeItem.getPreviousEnabledSibling();if(BL){BB.clearActiveItem();BL.cfg.setProperty(y,true);BD=BL.cfg.getProperty(O);if(BD){BD.show();BD.setInitialFocus();}else{BL.focus();}}}else{this.hide();A6.focus();}}AA.preventDefault(BH);A7();break;}}if(BH.keyCode==27){if(this.cfg.getProperty(Ac)==AD){this.hide();if(this.parent){this.parent.focus();}else{BC=this._focusedElement;if(BC&&BC.focus){try{BC.focus();}catch(BM){}}}}else{if(this.activeItem){BD=this.activeItem.cfg.getProperty(O);if(BD&&BD.cfg.getProperty(Au)){BD.hide();this.activeItem.focus();}else{this.activeItem.blur();this.activeItem.cfg.setProperty(y,false);}}}AA.preventDefault(BH);}},_onKeyPress:function(A7,A6){var A5=A6[0];if(A5.keyCode==40||A5.keyCode==38){AA.preventDefault(A5);}},_onBlur:function(A6,A5){if(this._hasFocus){this._hasFocus=false;}},_onYChange:function(A6,A5){var A8=this.parent,BA,A7,A9;if(A8){BA=A8.parent.body.scrollTop;if(BA>0){A9=(this.cfg.getProperty(R)-BA);f.setY(this.element,A9);A7=this.iframe;if(A7){f.setY(A7,A9);}this.cfg.setProperty(R,A9,true);}}},_onScrollTargetMouseOver:function(BB,BE){var BD=this._bodyScrollTimer;if(BD){BD.cancel();}this._cancelHideDelay();var A7=AA.getTarget(BB),A9=this.body,A8=this.cfg.getProperty(j),A5,A6;function BC(){var BF=A9.scrollTop;if(BF<A5){A9.scrollTop=(BF+A8);this._enableScrollHeader();}else{A9.scrollTop=A5;this._bodyScrollTimer.cancel();this._disableScrollFooter();}}function BA(){var BF=A9.scrollTop;if(BF>0){A9.scrollTop=(BF-A8);this._enableScrollFooter();}else{A9.scrollTop=0;this._bodyScrollTimer.cancel();this._disableScrollHeader();}}if(f.hasClass(A7,A0)){A6=BA;}else{A5=A9.scrollHeight-A9.offsetHeight;A6=BC;}this._bodyScrollTimer=AM.later(10,this,A6,null,true);},_onScrollTargetMouseOut:function(A7,A5){var A6=this._bodyScrollTimer;if(A6){A6.cancel();}this._cancelHideDelay();},_onInit:function(A6,A5){this.cfg.subscribeToConfigEvent(Au,this._onVisibleChange);var A7=!this.parent,A8=this.lazyLoad;if(((A7&&!A8)||(A7&&(this.cfg.getProperty(Au)||this.cfg.getProperty(Ac)==C))||(!A7&&!A8))&&this.getItemGroups().length===0){if(this.srcElement){this._initSubTree();}if(this.itemData){this.addItems(this.itemData);}}else{if(A8){this.cfg.fireQueue();}}},_onBeforeRender:function(A8,A7){var A9=this.element,BC=this._aListElements.length,A6=true,BB=0,A5,BA;if(BC>0){do{A5=this._aListElements[BB];if(A5){if(A6){f.addClass(A5,AJ);A6=false;}if(!f.isAncestor(A9,A5)){this.appendToBody(A5);}BA=this._aGroupTitleElements[BB];if(BA){if(!f.isAncestor(A9,BA)){A5.parentNode.insertBefore(BA,A5);}f.addClass(A5,D);}}BB++;}while(BB<BC);}},_onRender:function(A6,A5){if(this.cfg.getProperty(Ac)==AD){if(!this.cfg.getProperty(Au)){this.positionOffScreen();}}},_onBeforeShow:function(A7,A6){var A9,BC,A8,BA=this.cfg.getProperty(g);if(this.lazyLoad&&this.getItemGroups().length===0){if(this.srcElement){this._initSubTree();}if(this.itemData){if(this.parent&&this.parent.parent&&this.parent.parent.srcElement&&this.parent.parent.srcElement.tagName.toUpperCase()==AH){A9=this.itemData.length;for(BC=0;BC<A9;BC++){if(this.itemData[BC].tagName){this.addItem((new this.ITEM_TYPE(this.itemData[BC])));}}}else{this.addItems(this.itemData);}}A8=this.srcElement;if(A8){if(A8.tagName.toUpperCase()==AH){if(f.inDocument(A8)){this.render(A8.parentNode);}else{this.render(BA);}}else{this.render();}}else{if(this.parent){this.render(this.parent.element);}else{this.render(BA);}}}var BB=this.parent,A5;if(!BB&&this.cfg.getProperty(Ac)==AD){this.cfg.refireEvent(e);}if(BB){A5=BB.parent.cfg.getProperty(AO);this.cfg.setProperty(p,[BB.element,A5[0],A5[1]]);this.align();}},getConstrainedY:function(BH){var BS=this,BO=BS.cfg.getProperty(p),BV=BS.cfg.getProperty(AU),BR,BG={"trbr":true,"tlbl":true,"bltl":true,"brtr":true},BA=(BO&&BG[BO[1]+BO[2]]),BC=BS.element,BW=BC.offsetHeight,BQ=AB.VIEWPORT_OFFSET,BL=f.getViewportHeight(),BP=f.getDocumentScrollTop(),BM=(BS.cfg.getProperty(Aj)+BQ<BL),BU,BD,BJ,BK,BF=false,BE,A7,BI=BP+BQ,A9=BP+BL-BW-BQ,A5=BH;var BB=function(){var BX;if((BS.cfg.getProperty(R)-BP)>BJ){BX=(BJ-BW);}else{BX=(BJ+BK);}BS.cfg.setProperty(R,(BX+BP),true);return BX;};var A8=function(){if((BS.cfg.getProperty(R)-BP)>BJ){return(A7-BQ);}else{return(BE-BQ);}};var BN=function(){var BX;if((BS.cfg.getProperty(R)-BP)>BJ){BX=(BJ+BK);}else{BX=(BJ-BC.offsetHeight);}BS.cfg.setProperty(R,(BX+BP),true);};var A6=function(){BS._setScrollHeight(this.cfg.getProperty(AU));BS.hideEvent.unsubscribe(A6);};var BT=function(){var Ba=A8(),BX=(BS.getItems().length>0),BZ,BY;if(BW>Ba){BZ=BX?BS.cfg.getProperty(Aj):BW;if((Ba>BZ)&&BX){BR=Ba;}else{BR=BV;}BS._setScrollHeight(BR);BS.hideEvent.subscribe(A6);BN();if(Ba<BZ){if(BF){BB();}else{BB();BF=true;BY=BT();}}}else{if(BR&&(BR!==BV)){BS._setScrollHeight(BV);BS.hideEvent.subscribe(A6);BN();}}return BY;};if(BH<BI||BH>A9){if(BM){if(BS.cfg.getProperty(A4)&&BA){BD=BO[0];BK=BD.offsetHeight;BJ=(f.getY(BD)-BP);BE=BJ;A7=(BL-(BJ+BK));BT();A5=BS.cfg.getProperty(R);}else{if(!(BS instanceof YAHOO.widget.MenuBar)&&BW>=BL){BU=(BL-(BQ*2));if(BU>BS.cfg.getProperty(Aj)){BS._setScrollHeight(BU);BS.hideEvent.subscribe(A6);BN();A5=BS.cfg.getProperty(R);}}else{if(BH<BI){A5=BI;}else{if(BH>A9){A5=A9;}}}}}else{A5=BQ+BP;}}return A5;},_onHide:function(A6,A5){if(this.cfg.getProperty(Ac)===AD){this.positionOffScreen();}},_onShow:function(BD,BB){var A5=this.parent,A7,A8,BA,A6;function A9(BF){var BE;if(BF.type==Ak||(BF.type==Ae&&BF.keyCode==27)){BE=AA.getTarget(BF);if(BE!=A7.element||!f.isAncestor(A7.element,BE)){A7.cfg.setProperty(Z,false);AA.removeListener(document,Ak,A9);AA.removeListener(document,Ae,A9);}}}function BC(BF,BE,BG){this.cfg.setProperty(U,u);this.hideEvent.unsubscribe(BC,BG);}if(A5){A7=A5.parent;if(!A7.cfg.getProperty(Z)&&(A7 instanceof YAHOO.widget.MenuBar||A7.cfg.getProperty(Ac)==C)){A7.cfg.setProperty(Z,true);AA.on(document,Ak,A9);AA.on(document,Ae,A9);}if((this.cfg.getProperty("x")<A7.cfg.getProperty("x"))&&(As.gecko&&As.gecko<1.9)&&!this.cfg.getProperty(U)){A8=this.element;
11
BA=A8.offsetWidth;A8.style.width=BA+AQ;A6=(BA-(A8.offsetWidth-BA))+AQ;this.cfg.setProperty(U,A6);this.hideEvent.subscribe(BC,A6);}}if(this===this.getRoot()&&this.cfg.getProperty(Ac)===AD){this._focusedElement=Ad;this.focus();}},_onBeforeHide:function(A7,A6){var A5=this.activeItem,A9=this.getRoot(),BA,A8;if(A5){BA=A5.cfg;BA.setProperty(y,false);A8=BA.getProperty(O);if(A8){A8.hide();}}if(As.ie&&this.cfg.getProperty(Ac)===AD&&this.parent){A9._hasFocus=this.hasFocus();}if(A9==this){A9.blur();}},_onParentMenuConfigChange:function(A6,A5,A9){var A7=A5[0][0],A8=A5[0][1];switch(A7){case AF:case w:case AX:case Av:case c:case AC:case Ay:case A2:case j:case AU:case Aj:case AE:case Ag:case A4:case Ar:A9.cfg.setProperty(A7,A8);break;case AO:if(!(this.parent.parent instanceof YAHOO.widget.MenuBar)){A9.cfg.setProperty(A7,A8);}break;}},_onParentMenuRender:function(A6,A5,BB){var A8=BB.parent.parent,A7=A8.cfg,A9={constraintoviewport:A7.getProperty(w),xy:[0,0],clicktohide:A7.getProperty(AC),effect:A7.getProperty(Ay),showdelay:A7.getProperty(Av),hidedelay:A7.getProperty(AX),submenuhidedelay:A7.getProperty(c),classname:A7.getProperty(A2),scrollincrement:A7.getProperty(j),maxheight:A7.getProperty(AU),minscrollheight:A7.getProperty(Aj),iframe:A7.getProperty(AF),shadow:A7.getProperty(Ag),preventcontextoverlap:A7.getProperty(A4),monitorresize:A7.getProperty(AE),keepopen:A7.getProperty(Ar)},BA;if(!(A8 instanceof YAHOO.widget.MenuBar)){A9[AO]=A7.getProperty(AO);}BB.cfg.applyConfig(A9);if(!this.lazyLoad){BA=this.parent.element;if(this.element.parentNode==BA){this.render();}else{this.render(BA);}}},_onMenuItemDestroy:function(A7,A6,A5){this._removeItemFromGroupByValue(A5.groupIndex,A5);},_onMenuItemConfigChange:function(A7,A6,A5){var A9=A6[0][0],BA=A6[0][1],A8;switch(A9){case y:if(BA===true){this.activeItem=A5;}break;case O:A8=A6[0][1];if(A8){this._configureSubmenu(A5);}break;}},configVisible:function(A7,A6,A8){var A5,A9;if(this.cfg.getProperty(Ac)==AD){r.superclass.configVisible.call(this,A7,A6,A8);}else{A5=A6[0];A9=f.getStyle(this.element,AW);f.setStyle(this.element,J,Au);if(A5){if(A9!=AV){this.beforeShowEvent.fire();f.setStyle(this.element,AW,AV);this.showEvent.fire();}}else{if(A9==AV){this.beforeHideEvent.fire();f.setStyle(this.element,AW,AY);this.hideEvent.fire();}}}},configPosition:function(A7,A6,BA){var A9=this.element,A8=A6[0]==C?C:z,BB=this.cfg,A5;f.setStyle(A9,Ac,A8);if(A8==C){f.setStyle(A9,AW,AV);BB.setProperty(Au,true);}else{f.setStyle(A9,J,AL);}if(A8==z){A5=BB.getProperty(AS);if(!A5||A5===0){BB.setProperty(AS,1);}}},configIframe:function(A6,A5,A7){if(this.cfg.getProperty(Ac)==AD){r.superclass.configIframe.call(this,A6,A5,A7);}},configHideDelay:function(A6,A5,A7){var A8=A5[0];this._useHideDelay=(A8>0);},configContainer:function(A6,A5,A8){var A7=A5[0];if(AM.isString(A7)){this.cfg.setProperty(g,f.get(A7),true);}},_clearSetWidthFlag:function(){this._widthSetForScroll=false;this.cfg.unsubscribeFromConfigEvent(U,this._clearSetWidthFlag);},_setScrollHeight:function(BG){var BC=BG,BB=false,BH=false,A8,A9,BF,A6,BE,BI,A5,BD,BA,A7;if(this.getItems().length>0){A8=this.element;A9=this.body;BF=this.header;A6=this.footer;BE=this._onScrollTargetMouseOver;BI=this._onScrollTargetMouseOut;A5=this.cfg.getProperty(Aj);if(BC>0&&BC<A5){BC=A5;}f.setStyle(A9,Ao,u);f.removeClass(A9,l);A9.scrollTop=0;BH=((As.gecko&&As.gecko<1.9)||As.ie);if(BC>0&&BH&&!this.cfg.getProperty(U)){BA=A8.offsetWidth;A8.style.width=BA+AQ;A7=(BA-(A8.offsetWidth-BA))+AQ;this.cfg.unsubscribeFromConfigEvent(U,this._clearSetWidthFlag);this.cfg.setProperty(U,A7);this._widthSetForScroll=true;this.cfg.subscribeToConfigEvent(U,this._clearSetWidthFlag);}if(BC>0&&(!BF&&!A6)){this.setHeader(AK);this.setFooter(AK);BF=this.header;A6=this.footer;f.addClass(BF,T);f.addClass(A6,x);A8.insertBefore(BF,A9);A8.appendChild(A6);}BD=BC;if(BF&&A6){BD=(BD-(BF.offsetHeight+A6.offsetHeight));}if((BD>0)&&(A9.offsetHeight>BC)){f.addClass(A9,l);f.setStyle(A9,Ao,(BD+AQ));if(!this._hasScrollEventHandlers){AA.on(BF,Ai,BE,this,true);AA.on(BF,H,BI,this,true);AA.on(A6,Ai,BE,this,true);AA.on(A6,H,BI,this,true);this._hasScrollEventHandlers=true;}this._disableScrollHeader();this._enableScrollFooter();BB=true;}else{if(BF&&A6){if(this._widthSetForScroll){this._widthSetForScroll=false;this.cfg.unsubscribeFromConfigEvent(U,this._clearSetWidthFlag);this.cfg.setProperty(U,u);}this._enableScrollHeader();this._enableScrollFooter();if(this._hasScrollEventHandlers){AA.removeListener(BF,Ai,BE);AA.removeListener(BF,H,BI);AA.removeListener(A6,Ai,BE);AA.removeListener(A6,H,BI);this._hasScrollEventHandlers=false;}A8.removeChild(BF);A8.removeChild(A6);this.header=null;this.footer=null;BB=true;}}if(BB){this.cfg.refireEvent(AF);this.cfg.refireEvent(Ag);}}},_setMaxHeight:function(A6,A5,A7){this._setScrollHeight(A7);this.renderEvent.unsubscribe(this._setMaxHeight);},configMaxHeight:function(A6,A5,A7){var A8=A5[0];if(this.lazyLoad&&!this.body&&A8>0){this.renderEvent.subscribe(this._setMaxHeight,A8,this);}else{this._setScrollHeight(A8);}},configClassName:function(A7,A6,A8){var A5=A6[0];if(this._sClassName){f.removeClass(this.element,this._sClassName);}f.addClass(this.element,A5);this._sClassName=A5;},_onItemAdded:function(A6,A5){var A7=A5[0];if(A7){A7.cfg.setProperty(Ah,true);}},configDisabled:function(A7,A6,BA){var A9=A6[0],A5=this.getItems(),BB,A8;if(AM.isArray(A5)){BB=A5.length;if(BB>0){A8=BB-1;do{A5[A8].cfg.setProperty(Ah,A9);}while(A8--);}if(A9){this.clearActiveItem(true);f.addClass(this.element,Ah);this.itemAddedEvent.subscribe(this._onItemAdded);}else{f.removeClass(this.element,Ah);this.itemAddedEvent.unsubscribe(this._onItemAdded);}}},configShadow:function(BD,A7,BC){var BB=function(){var BG=this.element,BF=this._shadow;if(BF&&BG){if(BF.style.width&&BF.style.height){BF.style.width=u;BF.style.height=u;}BF.style.width=(BG.offsetWidth+6)+AQ;BF.style.height=(BG.offsetHeight+1)+AQ;}};var BE=function(){this.element.appendChild(this._shadow);};var A9=function(){f.addClass(this._shadow,AG);};var BA=function(){f.removeClass(this._shadow,AG);
12
};var A6=function(){var BG=this._shadow,BF;if(!BG){BF=this.element;if(!Ap){Ap=document.createElement(K);Ap.className=m;}BG=Ap.cloneNode(false);BF.appendChild(BG);this._shadow=BG;this.beforeShowEvent.subscribe(A9);this.beforeHideEvent.subscribe(BA);if(As.ie){AM.later(0,this,function(){BB.call(this);this.syncIframe();});this.cfg.subscribeToConfigEvent(U,BB);this.cfg.subscribeToConfigEvent(Ao,BB);this.cfg.subscribeToConfigEvent(AU,BB);this.changeContentEvent.subscribe(BB);Aw.textResizeEvent.subscribe(BB,this,true);this.destroyEvent.subscribe(function(){Aw.textResizeEvent.unsubscribe(BB,this);});}this.cfg.subscribeToConfigEvent(AU,BE);}};var A8=function(){if(this._shadow){BE.call(this);if(As.ie){BB.call(this);}}else{A6.call(this);}this.beforeShowEvent.unsubscribe(A8);};var A5=A7[0];if(A5&&this.cfg.getProperty(Ac)==AD){if(this.cfg.getProperty(Au)){if(this._shadow){BE.call(this);if(As.ie){BB.call(this);}}else{A6.call(this);}}else{this.beforeShowEvent.subscribe(A8);}}},initEvents:function(){r.superclass.initEvents.call(this);var A6=Ab.length-1,A7,A5;do{A7=Ab[A6];A5=this.createEvent(A7[1]);A5.signature=F.LIST;this[A7[0]]=A5;}while(A6--);},positionOffScreen:function(){var A6=this.iframe,A7=this.element,A5=this.OFF_SCREEN_POSITION;A7.style.top=u;A7.style.left=u;if(A6){A6.style.top=A5;A6.style.left=A5;}},getRoot:function(){var A7=this.parent,A6,A5;if(A7){A6=A7.parent;A5=A6?A6.getRoot():this;}else{A5=this;}return A5;},toString:function(){var A6=Aq,A5=this.id;if(A5){A6+=(A1+A5);}return A6;},setItemGroupTitle:function(BA,A9){var A8,A7,A6,A5;if(AM.isString(BA)&&BA.length>0){A8=AM.isNumber(A9)?A9:0;A7=this._aGroupTitleElements[A8];if(A7){A7.innerHTML=BA;}else{A7=document.createElement(this.GROUP_TITLE_TAG_NAME);A7.innerHTML=BA;this._aGroupTitleElements[A8]=A7;}A6=this._aGroupTitleElements.length-1;do{if(this._aGroupTitleElements[A6]){f.removeClass(this._aGroupTitleElements[A6],AJ);A5=A6;}}while(A6--);if(A5!==null){f.addClass(this._aGroupTitleElements[A5],AJ);}this.changeContentEvent.fire();}},addItem:function(A5,A6){return this._addItemToGroup(A6,A5);},addItems:function(A9,A8){var BB,A5,BA,A6,A7;if(AM.isArray(A9)){BB=A9.length;A5=[];for(A6=0;A6<BB;A6++){BA=A9[A6];if(BA){if(AM.isArray(BA)){A5[A5.length]=this.addItems(BA,A6);}else{A5[A5.length]=this._addItemToGroup(A8,BA);}}}if(A5.length){A7=A5;}}return A7;},insertItem:function(A5,A6,A7){return this._addItemToGroup(A7,A5,A6);},removeItem:function(A5,A7){var A8,A6;if(!AM.isUndefined(A5)){if(A5 instanceof YAHOO.widget.MenuItem){A8=this._removeItemFromGroupByValue(A7,A5);}else{if(AM.isNumber(A5)){A8=this._removeItemFromGroupByIndex(A7,A5);}}if(A8){A8.destroy();A6=A8;}}return A6;},getItems:function(){var A8=this._aItemGroups,A6,A7,A5=[];if(AM.isArray(A8)){A6=A8.length;A7=((A6==1)?A8[0]:(Array.prototype.concat.apply(A5,A8)));}return A7;},getItemGroups:function(){return this._aItemGroups;},getItem:function(A6,A7){var A8,A5;if(AM.isNumber(A6)){A8=this._getItemGroup(A7);if(A8){A5=A8[A6];}}return A5;},getSubmenus:function(){var A6=this.getItems(),BA=A6.length,A5,A7,A9,A8;if(BA>0){A5=[];for(A8=0;A8<BA;A8++){A9=A6[A8];if(A9){A7=A9.cfg.getProperty(O);if(A7){A5[A5.length]=A7;}}}}return A5;},clearContent:function(){var A9=this.getItems(),A6=A9.length,A7=this.element,A8=this.body,BD=this.header,A5=this.footer,BC,BB,BA;if(A6>0){BA=A6-1;do{BC=A9[BA];if(BC){BB=BC.cfg.getProperty(O);if(BB){this.cfg.configChangedEvent.unsubscribe(this._onParentMenuConfigChange,BB);this.renderEvent.unsubscribe(this._onParentMenuRender,BB);}this.removeItem(BC,BC.groupIndex);}}while(BA--);}if(BD){AA.purgeElement(BD);A7.removeChild(BD);}if(A5){AA.purgeElement(A5);A7.removeChild(A5);}if(A8){AA.purgeElement(A8);A8.innerHTML=u;}this.activeItem=null;this._aItemGroups=[];this._aListElements=[];this._aGroupTitleElements=[];this.cfg.setProperty(U,null);},destroy:function(){this.clearContent();this._aItemGroups=null;this._aListElements=null;this._aGroupTitleElements=null;r.superclass.destroy.call(this);},setInitialFocus:function(){var A5=this._getFirstEnabledItem();if(A5){A5.focus();}},setInitialSelection:function(){var A5=this._getFirstEnabledItem();if(A5){A5.cfg.setProperty(y,true);}},clearActiveItem:function(A7){if(this.cfg.getProperty(Av)>0){this._cancelShowDelay();}var A5=this.activeItem,A8,A6;if(A5){A8=A5.cfg;if(A7){A5.blur();this.getRoot()._hasFocus=true;}A8.setProperty(y,false);A6=A8.getProperty(O);if(A6){A6.hide();}this.activeItem=null;}},focus:function(){if(!this.hasFocus()){this.setInitialFocus();}},blur:function(){var A5;if(this.hasFocus()){A5=A3.getFocusedMenuItem();if(A5){A5.blur();}}},hasFocus:function(){return(A3.getFocusedMenu()==this.getRoot());},_doItemSubmenuSubscribe:function(A6,A5,A8){var A9=A5[0],A7=A9.cfg.getProperty(O);if(A7){A7.subscribe.apply(A7,A8);}},_doSubmenuSubscribe:function(A6,A5,A8){var A7=this.cfg.getProperty(O);if(A7){A7.subscribe.apply(A7,A8);}},subscribe:function(){r.superclass.subscribe.apply(this,arguments);r.superclass.subscribe.call(this,AR,this._doItemSubmenuSubscribe,arguments);var A5=this.getItems(),A9,A8,A6,A7;if(A5){A9=A5.length;if(A9>0){A7=A9-1;do{A8=A5[A7];A6=A8.cfg.getProperty(O);if(A6){A6.subscribe.apply(A6,arguments);}else{A8.cfg.subscribeToConfigEvent(O,this._doSubmenuSubscribe,arguments);}}while(A7--);}}},unsubscribe:function(){r.superclass.unsubscribe.apply(this,arguments);r.superclass.unsubscribe.call(this,AR,this._doItemSubmenuSubscribe,arguments);var A5=this.getItems(),A9,A8,A6,A7;if(A5){A9=A5.length;if(A9>0){A7=A9-1;do{A8=A5[A7];A6=A8.cfg.getProperty(O);if(A6){A6.unsubscribe.apply(A6,arguments);}else{A8.cfg.unsubscribeFromConfigEvent(O,this._doSubmenuSubscribe,arguments);}}while(A7--);}}},initDefaultConfig:function(){r.superclass.initDefaultConfig.call(this);var A5=this.cfg;A5.addProperty(AZ.key,{handler:this.configVisible,value:AZ.value,validator:AZ.validator});A5.addProperty(AP.key,{handler:this.configConstrainToViewport,value:AP.value,validator:AP.validator,supercedes:AP.supercedes});A5.addProperty(AI.key,{value:AI.value,validator:AI.validator,supercedes:AI.supercedes});
13
A5.addProperty(S.key,{handler:this.configPosition,value:S.value,validator:S.validator,supercedes:S.supercedes});A5.addProperty(A.key,{value:A.value,suppressEvent:A.suppressEvent});A5.addProperty(t.key,{value:t.value,validator:t.validator,suppressEvent:t.suppressEvent});A5.addProperty(Y.key,{value:Y.value,validator:Y.validator,suppressEvent:Y.suppressEvent});A5.addProperty(q.key,{handler:this.configHideDelay,value:q.value,validator:q.validator,suppressEvent:q.suppressEvent});A5.addProperty(v.key,{value:v.value,validator:v.validator,suppressEvent:v.suppressEvent});A5.addProperty(o.key,{value:o.value,validator:o.validator,suppressEvent:o.suppressEvent});A5.addProperty(AN.key,{handler:this.configContainer,value:document.body,suppressEvent:AN.suppressEvent});A5.addProperty(Af.key,{value:Af.value,validator:Af.validator,supercedes:Af.supercedes,suppressEvent:Af.suppressEvent});A5.addProperty(N.key,{value:N.value,validator:N.validator,supercedes:N.supercedes,suppressEvent:N.suppressEvent});A5.addProperty(X.key,{handler:this.configMaxHeight,value:X.value,validator:X.validator,suppressEvent:X.suppressEvent,supercedes:X.supercedes});A5.addProperty(W.key,{handler:this.configClassName,value:W.value,validator:W.validator,supercedes:W.supercedes});A5.addProperty(a.key,{handler:this.configDisabled,value:a.value,validator:a.validator,suppressEvent:a.suppressEvent});A5.addProperty(I.key,{handler:this.configShadow,value:I.value,validator:I.validator});A5.addProperty(Al.key,{value:Al.value,validator:Al.validator});}});})();(function(){YAHOO.widget.MenuItem=function(AS,AR){if(AS){if(AR){this.parent=AR.parent;this.value=AR.value;this.id=AR.id;}this.init(AS,AR);}};var x=YAHOO.util.Dom,j=YAHOO.widget.Module,AB=YAHOO.widget.Menu,c=YAHOO.widget.MenuItem,AK=YAHOO.util.CustomEvent,k=YAHOO.env.ua,AQ=YAHOO.lang,AL="text",O="#",Q="-",L="helptext",n="url",AH="target",A="emphasis",N="strongemphasis",b="checked",w="submenu",H="disabled",B="selected",P="hassubmenu",U="checked-disabled",AI="hassubmenu-disabled",AD="hassubmenu-selected",T="checked-selected",q="onclick",J="classname",AJ="",i="OPTION",v="OPTGROUP",K="LI",AE="href",r="SELECT",X="DIV",AN='<em class="helptext">',a="<em>",I="</em>",W="<strong>",y="</strong>",Y="preventcontextoverlap",h="obj",AG="scope",t="none",V="visible",E=" ",m="MenuItem",AA="click",D="show",M="hide",S="li",AF='<a href="#"></a>',p=[["mouseOverEvent","mouseover"],["mouseOutEvent","mouseout"],["mouseDownEvent","mousedown"],["mouseUpEvent","mouseup"],["clickEvent",AA],["keyPressEvent","keypress"],["keyDownEvent","keydown"],["keyUpEvent","keyup"],["focusEvent","focus"],["blurEvent","blur"],["destroyEvent","destroy"]],o={key:AL,value:AJ,validator:AQ.isString,suppressEvent:true},s={key:L,supercedes:[AL],suppressEvent:true},G={key:n,value:O,suppressEvent:true},AO={key:AH,suppressEvent:true},AP={key:A,value:false,validator:AQ.isBoolean,suppressEvent:true,supercedes:[AL]},d={key:N,value:false,validator:AQ.isBoolean,suppressEvent:true,supercedes:[AL]},l={key:b,value:false,validator:AQ.isBoolean,suppressEvent:true,supercedes:[H,B]},F={key:w,suppressEvent:true,supercedes:[H,B]},AM={key:H,value:false,validator:AQ.isBoolean,suppressEvent:true,supercedes:[AL,B]},f={key:B,value:false,validator:AQ.isBoolean,suppressEvent:true},u={key:q,suppressEvent:true},AC={key:J,value:null,validator:AQ.isString,suppressEvent:true},z={key:"keylistener",value:null,suppressEvent:true},C=null,e={};var Z=function(AU,AT){var AR=e[AU];if(!AR){e[AU]={};AR=e[AU];}var AS=AR[AT];if(!AS){AS=AU+Q+AT;AR[AT]=AS;}return AS;};var g=function(AR){x.addClass(this.element,Z(this.CSS_CLASS_NAME,AR));x.addClass(this._oAnchor,Z(this.CSS_LABEL_CLASS_NAME,AR));};var R=function(AR){x.removeClass(this.element,Z(this.CSS_CLASS_NAME,AR));x.removeClass(this._oAnchor,Z(this.CSS_LABEL_CLASS_NAME,AR));};c.prototype={CSS_CLASS_NAME:"yuimenuitem",CSS_LABEL_CLASS_NAME:"yuimenuitemlabel",SUBMENU_TYPE:null,_oAnchor:null,_oHelpTextEM:null,_oSubmenu:null,_oOnclickAttributeValue:null,_sClassName:null,constructor:c,index:null,groupIndex:null,parent:null,element:null,srcElement:null,value:null,browser:j.prototype.browser,id:null,init:function(AR,Ab){if(!this.SUBMENU_TYPE){this.SUBMENU_TYPE=AB;}this.cfg=new YAHOO.util.Config(this);this.initDefaultConfig();var AX=this.cfg,AY=O,AT,Aa,AZ,AS,AV,AU,AW;if(AQ.isString(AR)){this._createRootNodeStructure();AX.queueProperty(AL,AR);}else{if(AR&&AR.tagName){switch(AR.tagName.toUpperCase()){case i:this._createRootNodeStructure();AX.queueProperty(AL,AR.text);AX.queueProperty(H,AR.disabled);this.value=AR.value;this.srcElement=AR;break;case v:this._createRootNodeStructure();AX.queueProperty(AL,AR.label);AX.queueProperty(H,AR.disabled);this.srcElement=AR;this._initSubTree();break;case K:AZ=x.getFirstChild(AR);if(AZ){AY=AZ.getAttribute(AE,2);AS=AZ.getAttribute(AH);AV=AZ.innerHTML;}this.srcElement=AR;this.element=AR;this._oAnchor=AZ;AX.setProperty(AL,AV,true);AX.setProperty(n,AY,true);AX.setProperty(AH,AS,true);this._initSubTree();break;}}}if(this.element){AU=(this.srcElement||this.element).id;if(!AU){AU=this.id||x.generateId();this.element.id=AU;}this.id=AU;x.addClass(this.element,this.CSS_CLASS_NAME);x.addClass(this._oAnchor,this.CSS_LABEL_CLASS_NAME);AW=p.length-1;do{Aa=p[AW];AT=this.createEvent(Aa[1]);AT.signature=AK.LIST;this[Aa[0]]=AT;}while(AW--);if(Ab){AX.applyConfig(Ab);}AX.fireQueue();}},_createRootNodeStructure:function(){var AR,AS;if(!C){C=document.createElement(S);C.innerHTML=AF;}AR=C.cloneNode(true);AR.className=this.CSS_CLASS_NAME;AS=AR.firstChild;AS.className=this.CSS_LABEL_CLASS_NAME;this.element=AR;this._oAnchor=AS;},_initSubTree:function(){var AX=this.srcElement,AT=this.cfg,AV,AU,AS,AR,AW;if(AX.childNodes.length>0){if(this.parent.lazyLoad&&this.parent.srcElement&&this.parent.srcElement.tagName.toUpperCase()==r){AT.setProperty(w,{id:x.generateId(),itemdata:AX.childNodes});}else{AV=AX.firstChild;AU=[];do{if(AV&&AV.tagName){switch(AV.tagName.toUpperCase()){case X:AT.setProperty(w,AV);break;case i:AU[AU.length]=AV;break;}}}while((AV=AV.nextSibling));
14
AS=AU.length;if(AS>0){AR=new this.SUBMENU_TYPE(x.generateId());AT.setProperty(w,AR);for(AW=0;AW<AS;AW++){AR.addItem((new AR.ITEM_TYPE(AU[AW])));}}}}},configText:function(Aa,AT,AV){var AS=AT[0],AU=this.cfg,AY=this._oAnchor,AR=AU.getProperty(L),AZ=AJ,AW=AJ,AX=AJ;if(AS){if(AR){AZ=AN+AR+I;}if(AU.getProperty(A)){AW=a;AX=I;}if(AU.getProperty(N)){AW=W;AX=y;}AY.innerHTML=(AW+AS+AX+AZ);}},configHelpText:function(AT,AS,AR){this.cfg.refireEvent(AL);},configURL:function(AT,AS,AR){var AV=AS[0];if(!AV){AV=O;}var AU=this._oAnchor;if(k.opera){AU.removeAttribute(AE);}AU.setAttribute(AE,AV);},configTarget:function(AU,AT,AS){var AR=AT[0],AV=this._oAnchor;if(AR&&AR.length>0){AV.setAttribute(AH,AR);}else{AV.removeAttribute(AH);}},configEmphasis:function(AT,AS,AR){var AV=AS[0],AU=this.cfg;if(AV&&AU.getProperty(N)){AU.setProperty(N,false);}AU.refireEvent(AL);},configStrongEmphasis:function(AU,AT,AS){var AR=AT[0],AV=this.cfg;if(AR&&AV.getProperty(A)){AV.setProperty(A,false);}AV.refireEvent(AL);},configChecked:function(AT,AS,AR){var AV=AS[0],AU=this.cfg;if(AV){g.call(this,b);}else{R.call(this,b);}AU.refireEvent(AL);if(AU.getProperty(H)){AU.refireEvent(H);}if(AU.getProperty(B)){AU.refireEvent(B);}},configDisabled:function(AT,AS,AR){var AV=AS[0],AW=this.cfg,AU=AW.getProperty(w),AX=AW.getProperty(b);if(AV){if(AW.getProperty(B)){AW.setProperty(B,false);}g.call(this,H);if(AU){g.call(this,AI);}if(AX){g.call(this,U);}}else{R.call(this,H);if(AU){R.call(this,AI);}if(AX){R.call(this,U);}}},configSelected:function(AT,AS,AR){var AX=this.cfg,AW=this._oAnchor,AV=AS[0],AY=AX.getProperty(b),AU=AX.getProperty(w);if(k.opera){AW.blur();}if(AV&&!AX.getProperty(H)){g.call(this,B);if(AU){g.call(this,AD);}if(AY){g.call(this,T);}}else{R.call(this,B);if(AU){R.call(this,AD);}if(AY){R.call(this,T);}}if(this.hasFocus()&&k.opera){AW.focus();}},_onSubmenuBeforeHide:function(AU,AT){var AV=this.parent,AR;function AS(){AV._oAnchor.blur();AR.beforeHideEvent.unsubscribe(AS);}if(AV.hasFocus()){AR=AV.parent;AR.beforeHideEvent.subscribe(AS);}},configSubmenu:function(AY,AT,AW){var AV=AT[0],AU=this.cfg,AS=this.parent&&this.parent.lazyLoad,AX,AZ,AR;if(AV){if(AV instanceof AB){AX=AV;AX.parent=this;AX.lazyLoad=AS;}else{if(AQ.isObject(AV)&&AV.id&&!AV.nodeType){AZ=AV.id;AR=AV;AR.lazyload=AS;AR.parent=this;AX=new this.SUBMENU_TYPE(AZ,AR);AU.setProperty(w,AX,true);}else{AX=new this.SUBMENU_TYPE(AV,{lazyload:AS,parent:this});AU.setProperty(w,AX,true);}}if(AX){AX.cfg.setProperty(Y,true);g.call(this,P);if(AU.getProperty(n)===O){AU.setProperty(n,(O+AX.id));}this._oSubmenu=AX;if(k.opera){AX.beforeHideEvent.subscribe(this._onSubmenuBeforeHide);}}}else{R.call(this,P);if(this._oSubmenu){this._oSubmenu.destroy();}}if(AU.getProperty(H)){AU.refireEvent(H);}if(AU.getProperty(B)){AU.refireEvent(B);}},configOnClick:function(AT,AS,AR){var AU=AS[0];if(this._oOnclickAttributeValue&&(this._oOnclickAttributeValue!=AU)){this.clickEvent.unsubscribe(this._oOnclickAttributeValue.fn,this._oOnclickAttributeValue.obj);this._oOnclickAttributeValue=null;}if(!this._oOnclickAttributeValue&&AQ.isObject(AU)&&AQ.isFunction(AU.fn)){this.clickEvent.subscribe(AU.fn,((h in AU)?AU.obj:this),((AG in AU)?AU.scope:null));this._oOnclickAttributeValue=AU;}},configClassName:function(AU,AT,AS){var AR=AT[0];if(this._sClassName){x.removeClass(this.element,this._sClassName);}x.addClass(this.element,AR);this._sClassName=AR;},_dispatchClickEvent:function(){var AT=this,AS,AR;if(!AT.cfg.getProperty(H)){AS=x.getFirstChild(AT.element);if(k.ie){AS.fireEvent(q);}else{if((k.gecko&&k.gecko>=1.9)||k.opera||k.webkit){AR=document.createEvent("HTMLEvents");AR.initEvent(AA,true,true);}else{AR=document.createEvent("MouseEvents");AR.initMouseEvent(AA,true,true,window,0,0,0,0,0,false,false,false,false,0,null);}AS.dispatchEvent(AR);}}},_createKeyListener:function(AU,AT,AW){var AV=this,AS=AV.parent;var AR=new YAHOO.util.KeyListener(AS.element.ownerDocument,AW,{fn:AV._dispatchClickEvent,scope:AV,correctScope:true});if(AS.cfg.getProperty(V)){AR.enable();}AS.subscribe(D,AR.enable,null,AR);AS.subscribe(M,AR.disable,null,AR);AV._keyListener=AR;AS.unsubscribe(D,AV._createKeyListener,AW);},configKeyListener:function(AT,AS){var AV=AS[0],AU=this,AR=AU.parent;if(AU._keyData){AR.unsubscribe(D,AU._createKeyListener,AU._keyData);AU._keyData=null;}if(AU._keyListener){AR.unsubscribe(D,AU._keyListener.enable);AR.unsubscribe(M,AU._keyListener.disable);AU._keyListener.disable();AU._keyListener=null;}if(AV){AU._keyData=AV;AR.subscribe(D,AU._createKeyListener,AV,AU);}},initDefaultConfig:function(){var AR=this.cfg;AR.addProperty(o.key,{handler:this.configText,value:o.value,validator:o.validator,suppressEvent:o.suppressEvent});AR.addProperty(s.key,{handler:this.configHelpText,supercedes:s.supercedes,suppressEvent:s.suppressEvent});AR.addProperty(G.key,{handler:this.configURL,value:G.value,suppressEvent:G.suppressEvent});AR.addProperty(AO.key,{handler:this.configTarget,suppressEvent:AO.suppressEvent});AR.addProperty(AP.key,{handler:this.configEmphasis,value:AP.value,validator:AP.validator,suppressEvent:AP.suppressEvent,supercedes:AP.supercedes});AR.addProperty(d.key,{handler:this.configStrongEmphasis,value:d.value,validator:d.validator,suppressEvent:d.suppressEvent,supercedes:d.supercedes});AR.addProperty(l.key,{handler:this.configChecked,value:l.value,validator:l.validator,suppressEvent:l.suppressEvent,supercedes:l.supercedes});AR.addProperty(AM.key,{handler:this.configDisabled,value:AM.value,validator:AM.validator,suppressEvent:AM.suppressEvent});AR.addProperty(f.key,{handler:this.configSelected,value:f.value,validator:f.validator,suppressEvent:f.suppressEvent});AR.addProperty(F.key,{handler:this.configSubmenu,supercedes:F.supercedes,suppressEvent:F.suppressEvent});AR.addProperty(u.key,{handler:this.configOnClick,suppressEvent:u.suppressEvent});AR.addProperty(AC.key,{handler:this.configClassName,value:AC.value,validator:AC.validator,suppressEvent:AC.suppressEvent});AR.addProperty(z.key,{handler:this.configKeyListener,value:z.value,suppressEvent:z.suppressEvent});
15
},getNextSibling:function(){var AR=function(AX){return(AX.nodeName.toLowerCase()==="ul");},AV=this.element,AU=x.getNextSibling(AV),AT,AS,AW;if(!AU){AT=AV.parentNode;AS=x.getNextSiblingBy(AT,AR);if(AS){AW=AS;}else{AW=x.getFirstChildBy(AT.parentNode,AR);}AU=x.getFirstChild(AW);}return YAHOO.widget.MenuManager.getMenuItem(AU.id);},getNextEnabledSibling:function(){var AR=this.getNextSibling();return(AR.cfg.getProperty(H)||AR.element.style.display==t)?AR.getNextEnabledSibling():AR;},getPreviousSibling:function(){var AR=function(AX){return(AX.nodeName.toLowerCase()==="ul");},AV=this.element,AU=x.getPreviousSibling(AV),AT,AS,AW;if(!AU){AT=AV.parentNode;AS=x.getPreviousSiblingBy(AT,AR);if(AS){AW=AS;}else{AW=x.getLastChildBy(AT.parentNode,AR);}AU=x.getLastChild(AW);}return YAHOO.widget.MenuManager.getMenuItem(AU.id);},getPreviousEnabledSibling:function(){var AR=this.getPreviousSibling();return(AR.cfg.getProperty(H)||AR.element.style.display==t)?AR.getPreviousEnabledSibling():AR;},focus:function(){var AU=this.parent,AT=this._oAnchor,AR=AU.activeItem;function AS(){try{if(!(k.ie&&!document.hasFocus())){if(AR){AR.blurEvent.fire();}AT.focus();this.focusEvent.fire();}}catch(AV){}}if(!this.cfg.getProperty(H)&&AU&&AU.cfg.getProperty(V)&&this.element.style.display!=t){AQ.later(0,this,AS);}},blur:function(){var AR=this.parent;if(!this.cfg.getProperty(H)&&AR&&AR.cfg.getProperty(V)){AQ.later(0,this,function(){try{this._oAnchor.blur();this.blurEvent.fire();}catch(AS){}},0);}},hasFocus:function(){return(YAHOO.widget.MenuManager.getFocusedMenuItem()==this);},destroy:function(){var AT=this.element,AS,AR,AV,AU;if(AT){AS=this.cfg.getProperty(w);if(AS){AS.destroy();}AR=AT.parentNode;if(AR){AR.removeChild(AT);this.destroyEvent.fire();}AU=p.length-1;do{AV=p[AU];this[AV[0]].unsubscribeAll();}while(AU--);this.cfg.configChangedEvent.unsubscribeAll();}},toString:function(){var AS=m,AR=this.id;if(AR){AS+=(E+AR);}return AS;}};AQ.augmentProto(c,YAHOO.util.EventProvider);})();(function(){var B="xy",C="mousedown",F="ContextMenu",J=" ";YAHOO.widget.ContextMenu=function(L,K){YAHOO.widget.ContextMenu.superclass.constructor.call(this,L,K);};var I=YAHOO.util.Event,E=YAHOO.env.ua,G=YAHOO.widget.ContextMenu,A={"TRIGGER_CONTEXT_MENU":"triggerContextMenu","CONTEXT_MENU":(E.opera?C:"contextmenu"),"CLICK":"click"},H={key:"trigger",suppressEvent:true};function D(L,K,M){this.cfg.setProperty(B,M);this.beforeShowEvent.unsubscribe(D,M);}YAHOO.lang.extend(G,YAHOO.widget.Menu,{_oTrigger:null,_bCancelled:false,contextEventTarget:null,triggerContextMenuEvent:null,init:function(L,K){G.superclass.init.call(this,L);this.beforeInitEvent.fire(G);if(K){this.cfg.applyConfig(K,true);}this.initEvent.fire(G);},initEvents:function(){G.superclass.initEvents.call(this);this.triggerContextMenuEvent=this.createEvent(A.TRIGGER_CONTEXT_MENU);this.triggerContextMenuEvent.signature=YAHOO.util.CustomEvent.LIST;},cancel:function(){this._bCancelled=true;},_removeEventHandlers:function(){var K=this._oTrigger;if(K){I.removeListener(K,A.CONTEXT_MENU,this._onTriggerContextMenu);if(E.opera){I.removeListener(K,A.CLICK,this._onTriggerClick);}}},_onTriggerClick:function(L,K){if(L.ctrlKey){I.stopEvent(L);}},_onTriggerContextMenu:function(M,K){var L;if(!(M.type==C&&!M.ctrlKey)){this.contextEventTarget=I.getTarget(M);this.triggerContextMenuEvent.fire(M);if(!this._bCancelled){I.stopEvent(M);YAHOO.widget.MenuManager.hideVisible();L=I.getXY(M);if(!YAHOO.util.Dom.inDocument(this.element)){this.beforeShowEvent.subscribe(D,L);}else{this.cfg.setProperty(B,L);}this.show();}this._bCancelled=false;}},toString:function(){var L=F,K=this.id;if(K){L+=(J+K);}return L;},initDefaultConfig:function(){G.superclass.initDefaultConfig.call(this);this.cfg.addProperty(H.key,{handler:this.configTrigger,suppressEvent:H.suppressEvent});},destroy:function(){this._removeEventHandlers();G.superclass.destroy.call(this);},configTrigger:function(L,K,N){var M=K[0];if(M){if(this._oTrigger){this._removeEventHandlers();}this._oTrigger=M;I.on(M,A.CONTEXT_MENU,this._onTriggerContextMenu,this,true);if(E.opera){I.on(M,A.CLICK,this._onTriggerClick,this,true);}}else{this._removeEventHandlers();}}});}());YAHOO.widget.ContextMenuItem=YAHOO.widget.MenuItem;(function(){var D=YAHOO.lang,N="static",M="dynamic,"+N,A="disabled",F="selected",B="autosubmenudisplay",G="submenu",C="visible",Q=" ",H="submenutoggleregion",P="MenuBar";YAHOO.widget.MenuBar=function(T,S){YAHOO.widget.MenuBar.superclass.constructor.call(this,T,S);};function O(T){var S=false;if(D.isString(T)){S=(M.indexOf((T.toLowerCase()))!=-1);}return S;}var R=YAHOO.util.Event,L=YAHOO.widget.MenuBar,K={key:"position",value:N,validator:O,supercedes:[C]},E={key:"submenualignment",value:["tl","bl"]},J={key:B,value:false,validator:D.isBoolean,suppressEvent:true},I={key:H,value:false,validator:D.isBoolean};D.extend(L,YAHOO.widget.Menu,{init:function(T,S){if(!this.ITEM_TYPE){this.ITEM_TYPE=YAHOO.widget.MenuBarItem;}L.superclass.init.call(this,T);this.beforeInitEvent.fire(L);if(S){this.cfg.applyConfig(S,true);}this.initEvent.fire(L);},CSS_CLASS_NAME:"yuimenubar",SUBMENU_TOGGLE_REGION_WIDTH:20,_onKeyDown:function(U,T,Y){var S=T[0],Z=T[1],W,X,V;if(Z&&!Z.cfg.getProperty(A)){X=Z.cfg;switch(S.keyCode){case 37:case 39:if(Z==this.activeItem&&!X.getProperty(F)){X.setProperty(F,true);}else{V=(S.keyCode==37)?Z.getPreviousEnabledSibling():Z.getNextEnabledSibling();if(V){this.clearActiveItem();V.cfg.setProperty(F,true);W=V.cfg.getProperty(G);if(W){W.show();W.setInitialFocus();}else{V.focus();}}}R.preventDefault(S);break;case 40:if(this.activeItem!=Z){this.clearActiveItem();X.setProperty(F,true);Z.focus();}W=X.getProperty(G);if(W){if(W.cfg.getProperty(C)){W.setInitialSelection();W.setInitialFocus();}else{W.show();W.setInitialFocus();}}R.preventDefault(S);break;}}if(S.keyCode==27&&this.activeItem){W=this.activeItem.cfg.getProperty(G);if(W&&W.cfg.getProperty(C)){W.hide();this.activeItem.focus();}else{this.activeItem.cfg.setProperty(F,false);this.activeItem.blur();}R.preventDefault(S);}},_onClick:function(e,Y,b){L.superclass._onClick.call(this,e,Y,b);
16
var d=Y[1],T=true,S,f,U,W,Z,a,c,V;var X=function(){if(a.cfg.getProperty(C)){a.hide();}else{a.show();}};if(d&&!d.cfg.getProperty(A)){f=Y[0];U=R.getTarget(f);W=this.activeItem;Z=this.cfg;if(W&&W!=d){this.clearActiveItem();}d.cfg.setProperty(F,true);a=d.cfg.getProperty(G);if(a){S=d.element;c=YAHOO.util.Dom.getX(S);V=c+(S.offsetWidth-this.SUBMENU_TOGGLE_REGION_WIDTH);if(Z.getProperty(H)){if(R.getPageX(f)>V){X();R.preventDefault(f);T=false;}}else{X();}}}return T;},configSubmenuToggle:function(U,T){var S=T[0];if(S){this.cfg.setProperty(B,false);}},toString:function(){var T=P,S=this.id;if(S){T+=(Q+S);}return T;},initDefaultConfig:function(){L.superclass.initDefaultConfig.call(this);var S=this.cfg;S.addProperty(K.key,{handler:this.configPosition,value:K.value,validator:K.validator,supercedes:K.supercedes});S.addProperty(E.key,{value:E.value,suppressEvent:E.suppressEvent});S.addProperty(J.key,{value:J.value,validator:J.validator,suppressEvent:J.suppressEvent});S.addProperty(I.key,{value:I.value,validator:I.validator,handler:this.configSubmenuToggle});}});}());YAHOO.widget.MenuBarItem=function(B,A){YAHOO.widget.MenuBarItem.superclass.constructor.call(this,B,A);};YAHOO.lang.extend(YAHOO.widget.MenuBarItem,YAHOO.widget.MenuItem,{init:function(B,A){if(!this.SUBMENU_TYPE){this.SUBMENU_TYPE=YAHOO.widget.Menu;}YAHOO.widget.MenuBarItem.superclass.init.call(this,B);var C=this.cfg;if(A){C.applyConfig(A,true);}C.fireQueue();},CSS_CLASS_NAME:"yuimenubaritem",CSS_LABEL_CLASS_NAME:"yuimenubaritemlabel",toString:function(){var A="MenuBarItem";if(this.cfg&&this.cfg.getProperty("text")){A+=(": "+this.cfg.getProperty("text"));}return A;}});YAHOO.register("menu",YAHOO.widget.Menu,{version:"2.8.0r4",build:"2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/menu/menu.js (-9823 lines)
Lines 1-9823 Link Here
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.8.0r4
6
*/
7
8
9
/**
10
* @module menu
11
* @description <p>The Menu family of components features a collection of 
12
* controls that make it easy to add menus to your website or web application.  
13
* With the Menu Controls you can create website fly-out menus, customized 
14
* context menus, or application-style menu bars with just a small amount of 
15
* scripting.</p><p>The Menu family of controls features:</p>
16
* <ul>
17
*    <li>Keyboard and mouse navigation.</li>
18
*    <li>A rich event model that provides access to all of a menu's 
19
*    interesting moments.</li>
20
*    <li>Support for 
21
*    <a href="http://en.wikipedia.org/wiki/Progressive_Enhancement">Progressive
22
*    Enhancement</a>; Menus can be created from simple, 
23
*    semantic markup on the page or purely through JavaScript.</li>
24
* </ul>
25
* @title Menu
26
* @namespace YAHOO.widget
27
* @requires Event, Dom, Container
28
*/
29
(function () {
30
31
    var UA = YAHOO.env.ua,
32
		Dom = YAHOO.util.Dom,
33
	    Event = YAHOO.util.Event,
34
	    Lang = YAHOO.lang,
35
36
		_DIV = "DIV",
37
    	_HD = "hd",
38
    	_BD = "bd",
39
    	_FT = "ft",
40
    	_LI = "LI",
41
    	_DISABLED = "disabled",
42
		_MOUSEOVER = "mouseover",
43
		_MOUSEOUT = "mouseout",
44
		_MOUSEDOWN = "mousedown",
45
		_MOUSEUP = "mouseup",
46
		_CLICK = "click",
47
		_KEYDOWN = "keydown",
48
		_KEYUP = "keyup",
49
		_KEYPRESS = "keypress",
50
		_CLICK_TO_HIDE = "clicktohide",
51
		_POSITION = "position", 
52
		_DYNAMIC = "dynamic",
53
		_SHOW_DELAY = "showdelay",
54
		_SELECTED = "selected",
55
		_VISIBLE = "visible",
56
		_UL = "UL",
57
		_MENUMANAGER = "MenuManager";
58
59
60
    /**
61
    * Singleton that manages a collection of all menus and menu items.  Listens 
62
    * for DOM events at the document level and dispatches the events to the 
63
    * corresponding menu or menu item.
64
    *
65
    * @namespace YAHOO.widget
66
    * @class MenuManager
67
    * @static
68
    */
69
    YAHOO.widget.MenuManager = function () {
70
    
71
        // Private member variables
72
    
73
    
74
        // Flag indicating if the DOM event handlers have been attached
75
    
76
        var m_bInitializedEventHandlers = false,
77
    
78
    
79
        // Collection of menus
80
81
        m_oMenus = {},
82
83
84
        // Collection of visible menus
85
    
86
        m_oVisibleMenus = {},
87
    
88
    
89
        //  Collection of menu items 
90
91
        m_oItems = {},
92
93
94
        // Map of DOM event types to their equivalent CustomEvent types
95
        
96
        m_oEventTypes = {
97
            "click": "clickEvent",
98
            "mousedown": "mouseDownEvent",
99
            "mouseup": "mouseUpEvent",
100
            "mouseover": "mouseOverEvent",
101
            "mouseout": "mouseOutEvent",
102
            "keydown": "keyDownEvent",
103
            "keyup": "keyUpEvent",
104
            "keypress": "keyPressEvent",
105
            "focus": "focusEvent",
106
            "focusin": "focusEvent",
107
            "blur": "blurEvent",
108
            "focusout": "blurEvent"
109
        },
110
    
111
    
112
        m_oFocusedMenuItem = null;
113
    
114
    
115
    
116
        // Private methods
117
    
118
    
119
        /**
120
        * @method getMenuRootElement
121
        * @description Finds the root DIV node of a menu or the root LI node of 
122
        * a menu item.
123
        * @private
124
        * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
125
        * level-one-html.html#ID-58190037">HTMLElement</a>} p_oElement Object 
126
        * specifying an HTML element.
127
        */
128
        function getMenuRootElement(p_oElement) {
129
        
130
            var oParentNode,
131
            	returnVal;
132
    
133
            if (p_oElement && p_oElement.tagName) {
134
            
135
                switch (p_oElement.tagName.toUpperCase()) {
136
                        
137
                case _DIV:
138
    
139
                    oParentNode = p_oElement.parentNode;
140
    
141
                    // Check if the DIV is the inner "body" node of a menu
142
143
                    if ((
144
                            Dom.hasClass(p_oElement, _HD) ||
145
                            Dom.hasClass(p_oElement, _BD) ||
146
                            Dom.hasClass(p_oElement, _FT)
147
                        ) && 
148
                        oParentNode && 
149
                        oParentNode.tagName && 
150
                        oParentNode.tagName.toUpperCase() == _DIV) {
151
                    
152
                        returnVal = oParentNode;
153
                    
154
                    }
155
                    else {
156
                    
157
                        returnVal = p_oElement;
158
                    
159
                    }
160
                
161
                    break;
162
163
                case _LI:
164
    
165
                    returnVal = p_oElement;
166
                    
167
                    break;
168
169
                default:
170
    
171
                    oParentNode = p_oElement.parentNode;
172
    
173
                    if (oParentNode) {
174
                    
175
                        returnVal = getMenuRootElement(oParentNode);
176
                    
177
                    }
178
                
179
                    break;
180
                
181
                }
182
    
183
            }
184
            
185
            return returnVal;
186
            
187
        }
188
    
189
    
190
    
191
        // Private event handlers
192
    
193
    
194
        /**
195
        * @method onDOMEvent
196
        * @description Generic, global event handler for all of a menu's 
197
        * DOM-based events.  This listens for events against the document 
198
        * object.  If the target of a given event is a member of a menu or 
199
        * menu item's DOM, the instance's corresponding Custom Event is fired.
200
        * @private
201
        * @param {Event} p_oEvent Object representing the DOM event object  
202
        * passed back by the event utility (YAHOO.util.Event).
203
        */
204
        function onDOMEvent(p_oEvent) {
205
    
206
            // Get the target node of the DOM event
207
        
208
            var oTarget = Event.getTarget(p_oEvent),
209
                
210
            // See if the target of the event was a menu, or a menu item
211
    
212
            oElement = getMenuRootElement(oTarget),
213
			bFireEvent = true,
214
			sEventType = p_oEvent.type,
215
            sCustomEventType,
216
            sTagName,
217
            sId,
218
            oMenuItem,
219
            oMenu; 
220
    
221
    
222
            if (oElement) {
223
    
224
                sTagName = oElement.tagName.toUpperCase();
225
        
226
                if (sTagName == _LI) {
227
            
228
                    sId = oElement.id;
229
            
230
                    if (sId && m_oItems[sId]) {
231
            
232
                        oMenuItem = m_oItems[sId];
233
                        oMenu = oMenuItem.parent;
234
            
235
                    }
236
                
237
                }
238
                else if (sTagName == _DIV) {
239
                
240
                    if (oElement.id) {
241
                    
242
                        oMenu = m_oMenus[oElement.id];
243
                    
244
                    }
245
                
246
                }
247
    
248
            }
249
    
250
    
251
            if (oMenu) {
252
    
253
                sCustomEventType = m_oEventTypes[sEventType];
254
255
				/*
256
					There is an inconsistency between Firefox for Mac OS X and 
257
					Firefox Windows & Linux regarding the triggering of the 
258
					display of the browser's context menu and the subsequent 
259
					firing of the "click" event. In Firefox for Windows & Linux, 
260
					when the user triggers the display of the browser's context 
261
					menu the "click" event also fires for the document object, 
262
					even though the "click" event did not fire for the element 
263
					that was the original target of the "contextmenu" event. 
264
					This is unique to Firefox on Windows & Linux.  For all 
265
					other A-Grade browsers, including Firefox for Mac OS X, the 
266
					"click" event doesn't fire for the document object. 
267
268
					This bug in Firefox for Windows affects Menu, as Menu 
269
					instances listen for events at the document level and 
270
					dispatches Custom Events of the same name.  Therefore users
271
					of Menu will get an unwanted firing of the "click" 
272
					custom event.  The following line fixes this bug.
273
				*/
274
				
275
276
277
				if (sEventType == "click" && 
278
					(UA.gecko && oMenu.platform != "mac") && 
279
					p_oEvent.button > 0) {
280
281
					bFireEvent = false;
282
283
				}
284
    
285
                // Fire the Custom Event that corresponds the current DOM event    
286
        
287
                if (bFireEvent && oMenuItem && !oMenuItem.cfg.getProperty(_DISABLED)) {
288
                    oMenuItem[sCustomEventType].fire(p_oEvent);                   
289
                }
290
        
291
				if (bFireEvent) {
292
                	oMenu[sCustomEventType].fire(p_oEvent, oMenuItem);
293
				}
294
            
295
            }
296
            else if (sEventType == _MOUSEDOWN) {
297
    
298
                /*
299
                    If the target of the event wasn't a menu, hide all 
300
                    dynamically positioned menus
301
                */
302
                
303
                for (var i in m_oVisibleMenus) {
304
        
305
                    if (Lang.hasOwnProperty(m_oVisibleMenus, i)) {
306
        
307
                        oMenu = m_oVisibleMenus[i];
308
309
                        if (oMenu.cfg.getProperty(_CLICK_TO_HIDE) && 
310
                            !(oMenu instanceof YAHOO.widget.MenuBar) && 
311
                            oMenu.cfg.getProperty(_POSITION) == _DYNAMIC) {
312
313
                            oMenu.hide();
314
315
							//	In IE when the user mouses down on a focusable 
316
							//	element that element will be focused and become 
317
							//	the "activeElement".
318
							//	(http://msdn.microsoft.com/en-us/library/ms533065(VS.85).aspx)
319
							//	However, there is a bug in IE where if there is 
320
							//	a positioned element with a focused descendant 
321
							//	that is hidden in response to the mousedown 
322
							//	event, the target of the mousedown event will 
323
							//	appear to have focus, but will not be set as 
324
							//	the activeElement.  This will result in the 
325
							//	element not firing key events, even though it
326
							//	appears to have focus.  The following call to 
327
							//	"setActive" fixes this bug.
328
329
							if (UA.ie && oTarget.focus) {
330
								oTarget.setActive();
331
							}
332
        
333
                        }
334
                        else {
335
                            
336
							if (oMenu.cfg.getProperty(_SHOW_DELAY) > 0) {
337
							
338
								oMenu._cancelShowDelay();
339
							
340
							}
341
342
343
							if (oMenu.activeItem) {
344
						
345
								oMenu.activeItem.blur();
346
								oMenu.activeItem.cfg.setProperty(_SELECTED, false);
347
						
348
								oMenu.activeItem = null;            
349
						
350
							}
351
        
352
                        }
353
        
354
                    }
355
        
356
                } 
357
    
358
            }
359
            
360
        }
361
    
362
    
363
        /**
364
        * @method onMenuDestroy
365
        * @description "destroy" event handler for a menu.
366
        * @private
367
        * @param {String} p_sType String representing the name of the event 
368
        * that was fired.
369
        * @param {Array} p_aArgs Array of arguments sent when the event 
370
        * was fired.
371
        * @param {YAHOO.widget.Menu} p_oMenu The menu that fired the event.
372
        */
373
        function onMenuDestroy(p_sType, p_aArgs, p_oMenu) {
374
    
375
            if (m_oMenus[p_oMenu.id]) {
376
    
377
                this.removeMenu(p_oMenu);
378
    
379
            }
380
    
381
        }
382
    
383
    
384
        /**
385
        * @method onMenuFocus
386
        * @description "focus" event handler for a MenuItem instance.
387
        * @private
388
        * @param {String} p_sType String representing the name of the event 
389
        * that was fired.
390
        * @param {Array} p_aArgs Array of arguments sent when the event 
391
        * was fired.
392
        */
393
        function onMenuFocus(p_sType, p_aArgs) {
394
    
395
            var oItem = p_aArgs[1];
396
    
397
            if (oItem) {
398
    
399
                m_oFocusedMenuItem = oItem;
400
            
401
            }
402
    
403
        }
404
    
405
    
406
        /**
407
        * @method onMenuBlur
408
        * @description "blur" event handler for a MenuItem instance.
409
        * @private
410
        * @param {String} p_sType String representing the name of the event  
411
        * that was fired.
412
        * @param {Array} p_aArgs Array of arguments sent when the event 
413
        * was fired.
414
        */
415
        function onMenuBlur(p_sType, p_aArgs) {
416
    
417
            m_oFocusedMenuItem = null;
418
    
419
        }
420
421
    
422
        /**
423
        * @method onMenuVisibleConfigChange
424
        * @description Event handler for when the "visible" configuration  
425
        * property of a Menu instance changes.
426
        * @private
427
        * @param {String} p_sType String representing the name of the event  
428
        * that was fired.
429
        * @param {Array} p_aArgs Array of arguments sent when the event 
430
        * was fired.
431
        */
432
        function onMenuVisibleConfigChange(p_sType, p_aArgs) {
433
    
434
            var bVisible = p_aArgs[0],
435
                sId = this.id;
436
            
437
            if (bVisible) {
438
    
439
                m_oVisibleMenus[sId] = this;
440
                
441
            
442
            }
443
            else if (m_oVisibleMenus[sId]) {
444
            
445
                delete m_oVisibleMenus[sId];
446
                
447
            
448
            }
449
        
450
        }
451
    
452
    
453
        /**
454
        * @method onItemDestroy
455
        * @description "destroy" event handler for a MenuItem instance.
456
        * @private
457
        * @param {String} p_sType String representing the name of the event  
458
        * that was fired.
459
        * @param {Array} p_aArgs Array of arguments sent when the event 
460
        * was fired.
461
        */
462
        function onItemDestroy(p_sType, p_aArgs) {
463
    
464
            removeItem(this);
465
    
466
        }
467
468
469
        /**
470
        * @method removeItem
471
        * @description Removes a MenuItem instance from the MenuManager's collection of MenuItems.
472
        * @private
473
        * @param {MenuItem} p_oMenuItem The MenuItem instance to be removed.
474
        */    
475
        function removeItem(p_oMenuItem) {
476
477
            var sId = p_oMenuItem.id;
478
    
479
            if (sId && m_oItems[sId]) {
480
    
481
                if (m_oFocusedMenuItem == p_oMenuItem) {
482
    
483
                    m_oFocusedMenuItem = null;
484
    
485
                }
486
    
487
                delete m_oItems[sId];
488
                
489
                p_oMenuItem.destroyEvent.unsubscribe(onItemDestroy);
490
    
491
    
492
            }
493
494
        }
495
    
496
    
497
        /**
498
        * @method onItemAdded
499
        * @description "itemadded" event handler for a Menu instance.
500
        * @private
501
        * @param {String} p_sType String representing the name of the event  
502
        * that was fired.
503
        * @param {Array} p_aArgs Array of arguments sent when the event 
504
        * was fired.
505
        */
506
        function onItemAdded(p_sType, p_aArgs) {
507
    
508
            var oItem = p_aArgs[0],
509
                sId;
510
    
511
            if (oItem instanceof YAHOO.widget.MenuItem) { 
512
    
513
                sId = oItem.id;
514
        
515
                if (!m_oItems[sId]) {
516
            
517
                    m_oItems[sId] = oItem;
518
        
519
                    oItem.destroyEvent.subscribe(onItemDestroy);
520
        
521
        
522
                }
523
    
524
            }
525
        
526
        }
527
    
528
    
529
        return {
530
    
531
            // Privileged methods
532
    
533
    
534
            /**
535
            * @method addMenu
536
            * @description Adds a menu to the collection of known menus.
537
            * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu  
538
            * instance to be added.
539
            */
540
            addMenu: function (p_oMenu) {
541
    
542
                var oDoc;
543
    
544
                if (p_oMenu instanceof YAHOO.widget.Menu && p_oMenu.id && 
545
                    !m_oMenus[p_oMenu.id]) {
546
        
547
                    m_oMenus[p_oMenu.id] = p_oMenu;
548
                
549
            
550
                    if (!m_bInitializedEventHandlers) {
551
            
552
                        oDoc = document;
553
                
554
                        Event.on(oDoc, _MOUSEOVER, onDOMEvent, this, true);
555
                        Event.on(oDoc, _MOUSEOUT, onDOMEvent, this, true);
556
                        Event.on(oDoc, _MOUSEDOWN, onDOMEvent, this, true);
557
                        Event.on(oDoc, _MOUSEUP, onDOMEvent, this, true);
558
                        Event.on(oDoc, _CLICK, onDOMEvent, this, true);
559
                        Event.on(oDoc, _KEYDOWN, onDOMEvent, this, true);
560
                        Event.on(oDoc, _KEYUP, onDOMEvent, this, true);
561
                        Event.on(oDoc, _KEYPRESS, onDOMEvent, this, true);
562
    
563
						Event.onFocus(oDoc, onDOMEvent, this, true);
564
						Event.onBlur(oDoc, onDOMEvent, this, true);						
565
    
566
                        m_bInitializedEventHandlers = true;
567
                        
568
            
569
                    }
570
            
571
                    p_oMenu.cfg.subscribeToConfigEvent(_VISIBLE, onMenuVisibleConfigChange);
572
                    p_oMenu.destroyEvent.subscribe(onMenuDestroy, p_oMenu, this);
573
                    p_oMenu.itemAddedEvent.subscribe(onItemAdded);
574
                    p_oMenu.focusEvent.subscribe(onMenuFocus);
575
                    p_oMenu.blurEvent.subscribe(onMenuBlur);
576
        
577
        
578
                }
579
        
580
            },
581
    
582
        
583
            /**
584
            * @method removeMenu
585
            * @description Removes a menu from the collection of known menus.
586
            * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu  
587
            * instance to be removed.
588
            */
589
            removeMenu: function (p_oMenu) {
590
    
591
                var sId,
592
                    aItems,
593
                    i;
594
        
595
                if (p_oMenu) {
596
    
597
                    sId = p_oMenu.id;
598
        
599
                    if ((sId in m_oMenus) && (m_oMenus[sId] == p_oMenu)) {
600
601
                        // Unregister each menu item
602
603
                        aItems = p_oMenu.getItems();
604
605
                        if (aItems && aItems.length > 0) {
606
607
                            i = aItems.length - 1;
608
609
                            do {
610
611
                                removeItem(aItems[i]);
612
613
                            }
614
                            while (i--);
615
616
                        }
617
618
619
                        // Unregister the menu
620
621
                        delete m_oMenus[sId];
622
            
623
        
624
625
                        /*
626
                             Unregister the menu from the collection of 
627
                             visible menus
628
                        */
629
630
                        if ((sId in m_oVisibleMenus) && (m_oVisibleMenus[sId] == p_oMenu)) {
631
            
632
                            delete m_oVisibleMenus[sId];
633
                            
634
       
635
                        }
636
637
638
                        // Unsubscribe event listeners
639
640
                        if (p_oMenu.cfg) {
641
642
                            p_oMenu.cfg.unsubscribeFromConfigEvent(_VISIBLE, 
643
                                onMenuVisibleConfigChange);
644
                            
645
                        }
646
647
                        p_oMenu.destroyEvent.unsubscribe(onMenuDestroy, 
648
                            p_oMenu);
649
                
650
                        p_oMenu.itemAddedEvent.unsubscribe(onItemAdded);
651
                        p_oMenu.focusEvent.unsubscribe(onMenuFocus);
652
                        p_oMenu.blurEvent.unsubscribe(onMenuBlur);
653
654
                    }
655
                
656
                }
657
    
658
            },
659
        
660
        
661
            /**
662
            * @method hideVisible
663
            * @description Hides all visible, dynamically positioned menus 
664
            * (excluding instances of YAHOO.widget.MenuBar).
665
            */
666
            hideVisible: function () {
667
        
668
                var oMenu;
669
        
670
                for (var i in m_oVisibleMenus) {
671
        
672
                    if (Lang.hasOwnProperty(m_oVisibleMenus, i)) {
673
        
674
                        oMenu = m_oVisibleMenus[i];
675
        
676
                        if (!(oMenu instanceof YAHOO.widget.MenuBar) && 
677
                            oMenu.cfg.getProperty(_POSITION) == _DYNAMIC) {
678
        
679
                            oMenu.hide();
680
        
681
                        }
682
        
683
                    }
684
        
685
                }        
686
    
687
            },
688
689
690
            /**
691
            * @method getVisible
692
            * @description Returns a collection of all visible menus registered
693
            * with the menu manger.
694
            * @return {Object}
695
            */
696
            getVisible: function () {
697
            
698
                return m_oVisibleMenus;
699
            
700
            },
701
702
    
703
            /**
704
            * @method getMenus
705
            * @description Returns a collection of all menus registered with the 
706
            * menu manger.
707
            * @return {Object}
708
            */
709
            getMenus: function () {
710
    
711
                return m_oMenus;
712
            
713
            },
714
    
715
    
716
            /**
717
            * @method getMenu
718
            * @description Returns a menu with the specified id.
719
            * @param {String} p_sId String specifying the id of the 
720
            * <code>&#60;div&#62;</code> element representing the menu to
721
            * be retrieved.
722
            * @return {YAHOO.widget.Menu}
723
            */
724
            getMenu: function (p_sId) {
725
                
726
                var returnVal;
727
                
728
                if (p_sId in m_oMenus) {
729
                
730
					returnVal = m_oMenus[p_sId];
731
				
732
				}
733
            
734
            	return returnVal;
735
            
736
            },
737
    
738
    
739
            /**
740
            * @method getMenuItem
741
            * @description Returns a menu item with the specified id.
742
            * @param {String} p_sId String specifying the id of the 
743
            * <code>&#60;li&#62;</code> element representing the menu item to
744
            * be retrieved.
745
            * @return {YAHOO.widget.MenuItem}
746
            */
747
            getMenuItem: function (p_sId) {
748
    
749
    			var returnVal;
750
    
751
    			if (p_sId in m_oItems) {
752
    
753
					returnVal = m_oItems[p_sId];
754
				
755
				}
756
				
757
				return returnVal;
758
            
759
            },
760
761
762
            /**
763
            * @method getMenuItemGroup
764
            * @description Returns an array of menu item instances whose 
765
            * corresponding <code>&#60;li&#62;</code> elements are child 
766
            * nodes of the <code>&#60;ul&#62;</code> element with the 
767
            * specified id.
768
            * @param {String} p_sId String specifying the id of the 
769
            * <code>&#60;ul&#62;</code> element representing the group of 
770
            * menu items to be retrieved.
771
            * @return {Array}
772
            */
773
            getMenuItemGroup: function (p_sId) {
774
775
                var oUL = Dom.get(p_sId),
776
                    aItems,
777
                    oNode,
778
                    oItem,
779
                    sId,
780
                    returnVal;
781
    
782
783
                if (oUL && oUL.tagName && oUL.tagName.toUpperCase() == _UL) {
784
785
                    oNode = oUL.firstChild;
786
787
                    if (oNode) {
788
789
                        aItems = [];
790
                        
791
                        do {
792
793
                            sId = oNode.id;
794
795
                            if (sId) {
796
                            
797
                                oItem = this.getMenuItem(sId);
798
                                
799
                                if (oItem) {
800
                                
801
                                    aItems[aItems.length] = oItem;
802
                                
803
                                }
804
                            
805
                            }
806
                        
807
                        }
808
                        while ((oNode = oNode.nextSibling));
809
810
811
                        if (aItems.length > 0) {
812
813
                            returnVal = aItems;
814
                        
815
                        }
816
817
                    }
818
                
819
                }
820
821
				return returnVal;
822
            
823
            },
824
825
    
826
            /**
827
            * @method getFocusedMenuItem
828
            * @description Returns a reference to the menu item that currently 
829
            * has focus.
830
            * @return {YAHOO.widget.MenuItem}
831
            */
832
            getFocusedMenuItem: function () {
833
    
834
                return m_oFocusedMenuItem;
835
    
836
            },
837
    
838
    
839
            /**
840
            * @method getFocusedMenu
841
            * @description Returns a reference to the menu that currently 
842
            * has focus.
843
            * @return {YAHOO.widget.Menu}
844
            */
845
            getFocusedMenu: function () {
846
847
				var returnVal;
848
    
849
                if (m_oFocusedMenuItem) {
850
    
851
                    returnVal = m_oFocusedMenuItem.parent.getRoot();
852
                
853
                }
854
    
855
    			return returnVal;
856
    
857
            },
858
    
859
        
860
            /**
861
            * @method toString
862
            * @description Returns a string representing the menu manager.
863
            * @return {String}
864
            */
865
            toString: function () {
866
            
867
                return _MENUMANAGER;
868
            
869
            }
870
    
871
        };
872
    
873
    }();
874
875
})();
876
877
878
879
(function () {
880
881
	var Lang = YAHOO.lang,
882
883
	// String constants
884
	
885
		_MENU = "Menu",
886
		_DIV_UPPERCASE = "DIV",
887
		_DIV_LOWERCASE = "div",
888
		_ID = "id",
889
		_SELECT = "SELECT",
890
		_XY = "xy",
891
		_Y = "y",
892
		_UL_UPPERCASE = "UL",
893
		_UL_LOWERCASE = "ul",
894
		_FIRST_OF_TYPE = "first-of-type",
895
		_LI = "LI",
896
		_OPTGROUP = "OPTGROUP",
897
		_OPTION = "OPTION",
898
		_DISABLED = "disabled",
899
		_NONE = "none",
900
		_SELECTED = "selected",
901
		_GROUP_INDEX = "groupindex",
902
		_INDEX = "index",
903
		_SUBMENU = "submenu",
904
		_VISIBLE = "visible",
905
		_HIDE_DELAY = "hidedelay",
906
		_POSITION = "position",
907
		_DYNAMIC = "dynamic",
908
		_STATIC = "static",
909
		_DYNAMIC_STATIC = _DYNAMIC + "," + _STATIC,
910
		_URL = "url",
911
		_HASH = "#",
912
		_TARGET = "target",
913
		_MAX_HEIGHT = "maxheight",
914
        _TOP_SCROLLBAR = "topscrollbar",
915
        _BOTTOM_SCROLLBAR = "bottomscrollbar",
916
        _UNDERSCORE = "_",
917
		_TOP_SCROLLBAR_DISABLED = _TOP_SCROLLBAR + _UNDERSCORE + _DISABLED,
918
		_BOTTOM_SCROLLBAR_DISABLED = _BOTTOM_SCROLLBAR + _UNDERSCORE + _DISABLED,
919
		_MOUSEMOVE = "mousemove",
920
		_SHOW_DELAY = "showdelay",
921
		_SUBMENU_HIDE_DELAY = "submenuhidedelay",
922
		_IFRAME = "iframe",
923
		_CONSTRAIN_TO_VIEWPORT = "constraintoviewport",
924
		_PREVENT_CONTEXT_OVERLAP = "preventcontextoverlap",
925
		_SUBMENU_ALIGNMENT = "submenualignment",
926
		_AUTO_SUBMENU_DISPLAY = "autosubmenudisplay",
927
		_CLICK_TO_HIDE = "clicktohide",
928
		_CONTAINER = "container",
929
		_SCROLL_INCREMENT = "scrollincrement",
930
		_MIN_SCROLL_HEIGHT = "minscrollheight",
931
		_CLASSNAME = "classname",
932
		_SHADOW = "shadow",
933
		_KEEP_OPEN = "keepopen",
934
		_HD = "hd",
935
		_HAS_TITLE = "hastitle",
936
		_CONTEXT = "context",
937
		_EMPTY_STRING = "",
938
		_MOUSEDOWN = "mousedown",
939
		_KEYDOWN = "keydown",
940
		_HEIGHT = "height",
941
		_WIDTH = "width",
942
		_PX = "px",
943
		_EFFECT = "effect",
944
		_MONITOR_RESIZE = "monitorresize",
945
		_DISPLAY = "display",
946
		_BLOCK = "block",
947
		_VISIBILITY = "visibility",
948
		_ABSOLUTE = "absolute",
949
		_ZINDEX = "zindex",
950
		_YUI_MENU_BODY_SCROLLED = "yui-menu-body-scrolled",
951
		_NON_BREAKING_SPACE = "&#32;",
952
		_SPACE = " ",
953
		_MOUSEOVER = "mouseover",
954
		_MOUSEOUT = "mouseout",
955
        _ITEM_ADDED = "itemAdded",
956
        _ITEM_REMOVED = "itemRemoved",
957
        _HIDDEN = "hidden",
958
        _YUI_MENU_SHADOW = "yui-menu-shadow",
959
        _YUI_MENU_SHADOW_VISIBLE = _YUI_MENU_SHADOW + "-visible",
960
        _YUI_MENU_SHADOW_YUI_MENU_SHADOW_VISIBLE = _YUI_MENU_SHADOW + _SPACE + _YUI_MENU_SHADOW_VISIBLE;
961
962
963
/**
964
* The Menu class creates a container that holds a vertical list representing 
965
* a set of options or commands.  Menu is the base class for all 
966
* menu containers. 
967
* @param {String} p_oElement String specifying the id attribute of the 
968
* <code>&#60;div&#62;</code> element of the menu.
969
* @param {String} p_oElement String specifying the id attribute of the 
970
* <code>&#60;select&#62;</code> element to be used as the data source 
971
* for the menu.
972
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
973
* level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object 
974
* specifying the <code>&#60;div&#62;</code> element of the menu.
975
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
976
* level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement 
977
* Object specifying the <code>&#60;select&#62;</code> element to be used as 
978
* the data source for the menu.
979
* @param {Object} p_oConfig Optional. Object literal specifying the 
980
* configuration for the menu. See configuration class documentation for 
981
* more details.
982
* @namespace YAHOO.widget
983
* @class Menu
984
* @constructor
985
* @extends YAHOO.widget.Overlay
986
*/
987
YAHOO.widget.Menu = function (p_oElement, p_oConfig) {
988
989
    if (p_oConfig) {
990
991
        this.parent = p_oConfig.parent;
992
        this.lazyLoad = p_oConfig.lazyLoad || p_oConfig.lazyload;
993
        this.itemData = p_oConfig.itemData || p_oConfig.itemdata;
994
995
    }
996
997
998
    YAHOO.widget.Menu.superclass.constructor.call(this, p_oElement, p_oConfig);
999
1000
};
1001
1002
1003
1004
/**
1005
* @method checkPosition
1006
* @description Checks to make sure that the value of the "position" property 
1007
* is one of the supported strings. Returns true if the position is supported.
1008
* @private
1009
* @param {Object} p_sPosition String specifying the position of the menu.
1010
* @return {Boolean}
1011
*/
1012
function checkPosition(p_sPosition) {
1013
1014
	var returnVal = false;
1015
1016
    if (Lang.isString(p_sPosition)) {
1017
1018
        returnVal = (_DYNAMIC_STATIC.indexOf((p_sPosition.toLowerCase())) != -1);
1019
1020
    }
1021
1022
	return returnVal;
1023
1024
}
1025
1026
1027
var Dom = YAHOO.util.Dom,
1028
    Event = YAHOO.util.Event,
1029
    Module = YAHOO.widget.Module,
1030
    Overlay = YAHOO.widget.Overlay,
1031
    Menu = YAHOO.widget.Menu,
1032
    MenuManager = YAHOO.widget.MenuManager,
1033
    CustomEvent = YAHOO.util.CustomEvent,
1034
    UA = YAHOO.env.ua,
1035
    
1036
    m_oShadowTemplate,
1037
1038
	bFocusListenerInitialized = false,
1039
1040
	oFocusedElement,
1041
1042
	EVENT_TYPES = [
1043
    
1044
		["mouseOverEvent", _MOUSEOVER],
1045
		["mouseOutEvent", _MOUSEOUT],
1046
		["mouseDownEvent", _MOUSEDOWN],
1047
		["mouseUpEvent", "mouseup"],
1048
		["clickEvent", "click"],
1049
		["keyPressEvent", "keypress"],
1050
		["keyDownEvent", _KEYDOWN],
1051
		["keyUpEvent", "keyup"],
1052
		["focusEvent", "focus"],
1053
		["blurEvent", "blur"],
1054
		["itemAddedEvent", _ITEM_ADDED],
1055
		["itemRemovedEvent", _ITEM_REMOVED]
1056
1057
	],
1058
1059
	VISIBLE_CONFIG =  { 
1060
		key: _VISIBLE, 
1061
		value: false, 
1062
		validator: Lang.isBoolean
1063
	}, 
1064
1065
	CONSTRAIN_TO_VIEWPORT_CONFIG =  {
1066
		key: _CONSTRAIN_TO_VIEWPORT, 
1067
		value: true, 
1068
		validator: Lang.isBoolean, 
1069
		supercedes: [_IFRAME,"x",_Y,_XY]
1070
	}, 
1071
1072
	PREVENT_CONTEXT_OVERLAP_CONFIG =  {
1073
		key: _PREVENT_CONTEXT_OVERLAP,
1074
		value: true,
1075
		validator: Lang.isBoolean,  
1076
		supercedes: [_CONSTRAIN_TO_VIEWPORT]
1077
	},
1078
1079
	POSITION_CONFIG =  { 
1080
		key: _POSITION, 
1081
		value: _DYNAMIC, 
1082
		validator: checkPosition, 
1083
		supercedes: [_VISIBLE, _IFRAME]
1084
	}, 
1085
1086
	SUBMENU_ALIGNMENT_CONFIG =  { 
1087
		key: _SUBMENU_ALIGNMENT, 
1088
		value: ["tl","tr"]
1089
	},
1090
1091
	AUTO_SUBMENU_DISPLAY_CONFIG =  { 
1092
		key: _AUTO_SUBMENU_DISPLAY, 
1093
		value: true, 
1094
		validator: Lang.isBoolean,
1095
		suppressEvent: true
1096
	}, 
1097
1098
	SHOW_DELAY_CONFIG =  { 
1099
		key: _SHOW_DELAY, 
1100
		value: 250, 
1101
		validator: Lang.isNumber, 
1102
		suppressEvent: true
1103
	}, 
1104
1105
	HIDE_DELAY_CONFIG =  { 
1106
		key: _HIDE_DELAY, 
1107
		value: 0, 
1108
		validator: Lang.isNumber, 
1109
		suppressEvent: true
1110
	}, 
1111
1112
	SUBMENU_HIDE_DELAY_CONFIG =  { 
1113
		key: _SUBMENU_HIDE_DELAY, 
1114
		value: 250, 
1115
		validator: Lang.isNumber,
1116
		suppressEvent: true
1117
	}, 
1118
1119
	CLICK_TO_HIDE_CONFIG =  { 
1120
		key: _CLICK_TO_HIDE, 
1121
		value: true, 
1122
		validator: Lang.isBoolean,
1123
		suppressEvent: true
1124
	},
1125
1126
	CONTAINER_CONFIG =  { 
1127
		key: _CONTAINER,
1128
		suppressEvent: true
1129
	}, 
1130
1131
	SCROLL_INCREMENT_CONFIG =  { 
1132
		key: _SCROLL_INCREMENT, 
1133
		value: 1, 
1134
		validator: Lang.isNumber,
1135
		supercedes: [_MAX_HEIGHT],
1136
		suppressEvent: true
1137
	},
1138
1139
	MIN_SCROLL_HEIGHT_CONFIG =  { 
1140
		key: _MIN_SCROLL_HEIGHT, 
1141
		value: 90, 
1142
		validator: Lang.isNumber,
1143
		supercedes: [_MAX_HEIGHT],
1144
		suppressEvent: true
1145
	},    
1146
1147
	MAX_HEIGHT_CONFIG =  { 
1148
		key: _MAX_HEIGHT, 
1149
		value: 0, 
1150
		validator: Lang.isNumber,
1151
		supercedes: [_IFRAME],
1152
		suppressEvent: true
1153
	}, 
1154
1155
	CLASS_NAME_CONFIG =  { 
1156
		key: _CLASSNAME, 
1157
		value: null, 
1158
		validator: Lang.isString,
1159
		suppressEvent: true
1160
	}, 
1161
1162
	DISABLED_CONFIG =  { 
1163
		key: _DISABLED, 
1164
		value: false, 
1165
		validator: Lang.isBoolean,
1166
		suppressEvent: true
1167
	},
1168
	
1169
	SHADOW_CONFIG =  { 
1170
		key: _SHADOW, 
1171
		value: true, 
1172
		validator: Lang.isBoolean,
1173
		suppressEvent: true,
1174
		supercedes: [_VISIBLE]
1175
	},
1176
	
1177
	KEEP_OPEN_CONFIG = {
1178
		key: _KEEP_OPEN, 
1179
		value: false, 
1180
		validator: Lang.isBoolean
1181
	};
1182
1183
1184
function onDocFocus(event) {
1185
1186
	oFocusedElement = Event.getTarget(event);
1187
1188
}
1189
1190
1191
1192
YAHOO.lang.extend(Menu, Overlay, {
1193
1194
1195
// Constants
1196
1197
1198
/**
1199
* @property CSS_CLASS_NAME
1200
* @description String representing the CSS class(es) to be applied to the 
1201
* menu's <code>&#60;div&#62;</code> element.
1202
* @default "yuimenu"
1203
* @final
1204
* @type String
1205
*/
1206
CSS_CLASS_NAME: "yuimenu",
1207
1208
1209
/**
1210
* @property ITEM_TYPE
1211
* @description Object representing the type of menu item to instantiate and 
1212
* add when parsing the child nodes (either <code>&#60;li&#62;</code> element, 
1213
* <code>&#60;optgroup&#62;</code> element or <code>&#60;option&#62;</code>) 
1214
* of the menu's source HTML element.
1215
* @default YAHOO.widget.MenuItem
1216
* @final
1217
* @type YAHOO.widget.MenuItem
1218
*/
1219
ITEM_TYPE: null,
1220
1221
1222
/**
1223
* @property GROUP_TITLE_TAG_NAME
1224
* @description String representing the tagname of the HTML element used to 
1225
* title the menu's item groups.
1226
* @default H6
1227
* @final
1228
* @type String
1229
*/
1230
GROUP_TITLE_TAG_NAME: "h6",
1231
1232
1233
/**
1234
* @property OFF_SCREEN_POSITION
1235
* @description Array representing the default x and y position that a menu 
1236
* should have when it is positioned outside the viewport by the 
1237
* "poistionOffScreen" method.
1238
* @default "-999em"
1239
* @final
1240
* @type String
1241
*/
1242
OFF_SCREEN_POSITION: "-999em",
1243
1244
1245
// Private properties
1246
1247
1248
/** 
1249
* @property _useHideDelay
1250
* @description Boolean indicating if the "mouseover" and "mouseout" event 
1251
* handlers used for hiding the menu via a call to "YAHOO.lang.later" have 
1252
* already been assigned.
1253
* @default false
1254
* @private
1255
* @type Boolean
1256
*/
1257
_useHideDelay: false,
1258
1259
1260
/**
1261
* @property _bHandledMouseOverEvent
1262
* @description Boolean indicating the current state of the menu's 
1263
* "mouseover" event.
1264
* @default false
1265
* @private
1266
* @type Boolean
1267
*/
1268
_bHandledMouseOverEvent: false,
1269
1270
1271
/**
1272
* @property _bHandledMouseOutEvent
1273
* @description Boolean indicating the current state of the menu's
1274
* "mouseout" event.
1275
* @default false
1276
* @private
1277
* @type Boolean
1278
*/
1279
_bHandledMouseOutEvent: false,
1280
1281
1282
/**
1283
* @property _aGroupTitleElements
1284
* @description Array of HTML element used to title groups of menu items.
1285
* @default []
1286
* @private
1287
* @type Array
1288
*/
1289
_aGroupTitleElements: null,
1290
1291
1292
/**
1293
* @property _aItemGroups
1294
* @description Multi-dimensional Array representing the menu items as they
1295
* are grouped in the menu.
1296
* @default []
1297
* @private
1298
* @type Array
1299
*/
1300
_aItemGroups: null,
1301
1302
1303
/**
1304
* @property _aListElements
1305
* @description Array of <code>&#60;ul&#62;</code> elements, each of which is 
1306
* the parent node for each item's <code>&#60;li&#62;</code> element.
1307
* @default []
1308
* @private
1309
* @type Array
1310
*/
1311
_aListElements: null,
1312
1313
1314
/**
1315
* @property _nCurrentMouseX
1316
* @description The current x coordinate of the mouse inside the area of 
1317
* the menu.
1318
* @default 0
1319
* @private
1320
* @type Number
1321
*/
1322
_nCurrentMouseX: 0,
1323
1324
1325
/**
1326
* @property _bStopMouseEventHandlers
1327
* @description Stops "mouseover," "mouseout," and "mousemove" event handlers 
1328
* from executing.
1329
* @default false
1330
* @private
1331
* @type Boolean
1332
*/
1333
_bStopMouseEventHandlers: false,
1334
1335
1336
/**
1337
* @property _sClassName
1338
* @description The current value of the "classname" configuration attribute.
1339
* @default null
1340
* @private
1341
* @type String
1342
*/
1343
_sClassName: null,
1344
1345
1346
1347
// Public properties
1348
1349
1350
/**
1351
* @property lazyLoad
1352
* @description Boolean indicating if the menu's "lazy load" feature is 
1353
* enabled.  If set to "true," initialization and rendering of the menu's 
1354
* items will be deferred until the first time it is made visible.  This 
1355
* property should be set via the constructor using the configuration 
1356
* object literal.
1357
* @default false
1358
* @type Boolean
1359
*/
1360
lazyLoad: false,
1361
1362
1363
/**
1364
* @property itemData
1365
* @description Array of items to be added to the menu.  The array can contain 
1366
* strings representing the text for each item to be created, object literals 
1367
* representing the menu item configuration properties, or MenuItem instances.  
1368
* This property should be set via the constructor using the configuration 
1369
* object literal.
1370
* @default null
1371
* @type Array
1372
*/
1373
itemData: null,
1374
1375
1376
/**
1377
* @property activeItem
1378
* @description Object reference to the item in the menu that has is selected.
1379
* @default null
1380
* @type YAHOO.widget.MenuItem
1381
*/
1382
activeItem: null,
1383
1384
1385
/**
1386
* @property parent
1387
* @description Object reference to the menu's parent menu or menu item.  
1388
* This property can be set via the constructor using the configuration 
1389
* object literal.
1390
* @default null
1391
* @type YAHOO.widget.MenuItem
1392
*/
1393
parent: null,
1394
1395
1396
/**
1397
* @property srcElement
1398
* @description Object reference to the HTML element (either 
1399
* <code>&#60;select&#62;</code> or <code>&#60;div&#62;</code>) used to 
1400
* create the menu.
1401
* @default null
1402
* @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1403
* level-one-html.html#ID-94282980">HTMLSelectElement</a>|<a 
1404
* href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.
1405
* html#ID-22445964">HTMLDivElement</a>
1406
*/
1407
srcElement: null,
1408
1409
1410
1411
// Events
1412
1413
1414
/**
1415
* @event mouseOverEvent
1416
* @description Fires when the mouse has entered the menu.  Passes back 
1417
* the DOM Event object as an argument.
1418
*/
1419
1420
1421
/**
1422
* @event mouseOutEvent
1423
* @description Fires when the mouse has left the menu.  Passes back the DOM 
1424
* Event object as an argument.
1425
* @type YAHOO.util.CustomEvent
1426
*/
1427
1428
1429
/**
1430
* @event mouseDownEvent
1431
* @description Fires when the user mouses down on the menu.  Passes back the 
1432
* DOM Event object as an argument.
1433
* @type YAHOO.util.CustomEvent
1434
*/
1435
1436
1437
/**
1438
* @event mouseUpEvent
1439
* @description Fires when the user releases a mouse button while the mouse is 
1440
* over the menu.  Passes back the DOM Event object as an argument.
1441
* @type YAHOO.util.CustomEvent
1442
*/
1443
1444
1445
/**
1446
* @event clickEvent
1447
* @description Fires when the user clicks the on the menu.  Passes back the 
1448
* DOM Event object as an argument.
1449
* @type YAHOO.util.CustomEvent
1450
*/
1451
1452
1453
/**
1454
* @event keyPressEvent
1455
* @description Fires when the user presses an alphanumeric key when one of the
1456
* menu's items has focus.  Passes back the DOM Event object as an argument.
1457
* @type YAHOO.util.CustomEvent
1458
*/
1459
1460
1461
/**
1462
* @event keyDownEvent
1463
* @description Fires when the user presses a key when one of the menu's items 
1464
* has focus.  Passes back the DOM Event object as an argument.
1465
* @type YAHOO.util.CustomEvent
1466
*/
1467
1468
1469
/**
1470
* @event keyUpEvent
1471
* @description Fires when the user releases a key when one of the menu's items 
1472
* has focus.  Passes back the DOM Event object as an argument.
1473
* @type YAHOO.util.CustomEvent
1474
*/
1475
1476
1477
/**
1478
* @event itemAddedEvent
1479
* @description Fires when an item is added to the menu.
1480
* @type YAHOO.util.CustomEvent
1481
*/
1482
1483
1484
/**
1485
* @event itemRemovedEvent
1486
* @description Fires when an item is removed to the menu.
1487
* @type YAHOO.util.CustomEvent
1488
*/
1489
1490
1491
/**
1492
* @method init
1493
* @description The Menu class's initialization method. This method is 
1494
* automatically called by the constructor, and sets up all DOM references 
1495
* for pre-existing markup, and creates required markup if it is not 
1496
* already present.
1497
* @param {String} p_oElement String specifying the id attribute of the 
1498
* <code>&#60;div&#62;</code> element of the menu.
1499
* @param {String} p_oElement String specifying the id attribute of the 
1500
* <code>&#60;select&#62;</code> element to be used as the data source 
1501
* for the menu.
1502
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1503
* level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object 
1504
* specifying the <code>&#60;div&#62;</code> element of the menu.
1505
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1506
* level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement 
1507
* Object specifying the <code>&#60;select&#62;</code> element to be used as 
1508
* the data source for the menu.
1509
* @param {Object} p_oConfig Optional. Object literal specifying the 
1510
* configuration for the menu. See configuration class documentation for 
1511
* more details.
1512
*/
1513
init: function (p_oElement, p_oConfig) {
1514
1515
    this._aItemGroups = [];
1516
    this._aListElements = [];
1517
    this._aGroupTitleElements = [];
1518
1519
    if (!this.ITEM_TYPE) {
1520
1521
        this.ITEM_TYPE = YAHOO.widget.MenuItem;
1522
1523
    }
1524
1525
1526
    var oElement;
1527
1528
    if (Lang.isString(p_oElement)) {
1529
1530
        oElement = Dom.get(p_oElement);
1531
1532
    }
1533
    else if (p_oElement.tagName) {
1534
1535
        oElement = p_oElement;
1536
1537
    }
1538
1539
1540
    if (oElement && oElement.tagName) {
1541
1542
        switch(oElement.tagName.toUpperCase()) {
1543
    
1544
            case _DIV_UPPERCASE:
1545
1546
                this.srcElement = oElement;
1547
1548
                if (!oElement.id) {
1549
1550
                    oElement.setAttribute(_ID, Dom.generateId());
1551
1552
                }
1553
1554
1555
                /* 
1556
                    Note: we don't pass the user config in here yet 
1557
                    because we only want it executed once, at the lowest 
1558
                    subclass level.
1559
                */ 
1560
            
1561
                Menu.superclass.init.call(this, oElement);
1562
1563
                this.beforeInitEvent.fire(Menu);
1564
1565
    
1566
            break;
1567
    
1568
            case _SELECT:
1569
    
1570
                this.srcElement = oElement;
1571
1572
    
1573
                /*
1574
                    The source element is not something that we can use 
1575
                    outright, so we need to create a new Overlay
1576
1577
                    Note: we don't pass the user config in here yet 
1578
                    because we only want it executed once, at the lowest 
1579
                    subclass level.
1580
                */ 
1581
1582
                Menu.superclass.init.call(this, Dom.generateId());
1583
1584
                this.beforeInitEvent.fire(Menu);
1585
1586
1587
            break;
1588
1589
        }
1590
1591
    }
1592
    else {
1593
1594
        /* 
1595
            Note: we don't pass the user config in here yet 
1596
            because we only want it executed once, at the lowest 
1597
            subclass level.
1598
        */ 
1599
    
1600
        Menu.superclass.init.call(this, p_oElement);
1601
1602
        this.beforeInitEvent.fire(Menu);
1603
1604
1605
    }
1606
1607
1608
    if (this.element) {
1609
1610
        Dom.addClass(this.element, this.CSS_CLASS_NAME);
1611
1612
1613
        // Subscribe to Custom Events
1614
1615
        this.initEvent.subscribe(this._onInit);
1616
        this.beforeRenderEvent.subscribe(this._onBeforeRender);
1617
        this.renderEvent.subscribe(this._onRender);
1618
        this.beforeShowEvent.subscribe(this._onBeforeShow);
1619
		this.hideEvent.subscribe(this._onHide);
1620
        this.showEvent.subscribe(this._onShow);
1621
		this.beforeHideEvent.subscribe(this._onBeforeHide);
1622
        this.mouseOverEvent.subscribe(this._onMouseOver);
1623
        this.mouseOutEvent.subscribe(this._onMouseOut);
1624
        this.clickEvent.subscribe(this._onClick);
1625
        this.keyDownEvent.subscribe(this._onKeyDown);
1626
        this.keyPressEvent.subscribe(this._onKeyPress);
1627
        this.blurEvent.subscribe(this._onBlur);
1628
1629
1630
		if (!bFocusListenerInitialized) {
1631
			Event.onFocus(document, onDocFocus);
1632
			bFocusListenerInitialized = true;
1633
		}
1634
1635
1636
		//	Fixes an issue in Firefox 2 and Webkit where Dom's "getX" and "getY" 
1637
		//	methods return values that don't take scrollTop into consideration 
1638
1639
        if ((UA.gecko && UA.gecko < 1.9) || UA.webkit) {
1640
1641
            this.cfg.subscribeToConfigEvent(_Y, this._onYChange);
1642
1643
        }
1644
1645
1646
        if (p_oConfig) {
1647
    
1648
            this.cfg.applyConfig(p_oConfig, true);
1649
    
1650
        }
1651
1652
1653
        // Register the Menu instance with the MenuManager
1654
1655
        MenuManager.addMenu(this);
1656
1657
1658
        this.initEvent.fire(Menu);
1659
1660
    }
1661
1662
},
1663
1664
1665
1666
// Private methods
1667
1668
1669
/**
1670
* @method _initSubTree
1671
* @description Iterates the childNodes of the source element to find nodes 
1672
* used to instantiate menu and menu items.
1673
* @private
1674
*/
1675
_initSubTree: function () {
1676
1677
    var oSrcElement = this.srcElement,
1678
        sSrcElementTagName,
1679
        nGroup,
1680
        sGroupTitleTagName,
1681
        oNode,
1682
        aListElements,
1683
        nListElements,
1684
        i;
1685
1686
1687
    if (oSrcElement) {
1688
    
1689
        sSrcElementTagName = 
1690
            (oSrcElement.tagName && oSrcElement.tagName.toUpperCase());
1691
1692
1693
        if (sSrcElementTagName == _DIV_UPPERCASE) {
1694
    
1695
            //  Populate the collection of item groups and item group titles
1696
    
1697
            oNode = this.body.firstChild;
1698
    
1699
1700
            if (oNode) {
1701
    
1702
                nGroup = 0;
1703
                sGroupTitleTagName = this.GROUP_TITLE_TAG_NAME.toUpperCase();
1704
        
1705
                do {
1706
        
1707
1708
                    if (oNode && oNode.tagName) {
1709
        
1710
                        switch (oNode.tagName.toUpperCase()) {
1711
        
1712
                            case sGroupTitleTagName:
1713
                            
1714
                                this._aGroupTitleElements[nGroup] = oNode;
1715
        
1716
                            break;
1717
        
1718
                            case _UL_UPPERCASE:
1719
        
1720
                                this._aListElements[nGroup] = oNode;
1721
                                this._aItemGroups[nGroup] = [];
1722
                                nGroup++;
1723
        
1724
                            break;
1725
        
1726
                        }
1727
                    
1728
                    }
1729
        
1730
                }
1731
                while ((oNode = oNode.nextSibling));
1732
        
1733
        
1734
                /*
1735
                    Apply the "first-of-type" class to the first UL to mimic 
1736
                    the ":first-of-type" CSS3 psuedo class.
1737
                */
1738
        
1739
                if (this._aListElements[0]) {
1740
        
1741
                    Dom.addClass(this._aListElements[0], _FIRST_OF_TYPE);
1742
        
1743
                }
1744
            
1745
            }
1746
    
1747
        }
1748
    
1749
    
1750
        oNode = null;
1751
    
1752
    
1753
1754
        if (sSrcElementTagName) {
1755
    
1756
            switch (sSrcElementTagName) {
1757
        
1758
                case _DIV_UPPERCASE:
1759
1760
                    aListElements = this._aListElements;
1761
                    nListElements = aListElements.length;
1762
        
1763
                    if (nListElements > 0) {
1764
        
1765
        
1766
                        i = nListElements - 1;
1767
        
1768
                        do {
1769
        
1770
                            oNode = aListElements[i].firstChild;
1771
            
1772
                            if (oNode) {
1773
1774
            
1775
                                do {
1776
                
1777
                                    if (oNode && oNode.tagName && 
1778
                                        oNode.tagName.toUpperCase() == _LI) {
1779
                
1780
        
1781
                                        this.addItem(new this.ITEM_TYPE(oNode, 
1782
                                                    { parent: this }), i);
1783
            
1784
                                    }
1785
                        
1786
                                }
1787
                                while ((oNode = oNode.nextSibling));
1788
                            
1789
                            }
1790
                    
1791
                        }
1792
                        while (i--);
1793
        
1794
                    }
1795
        
1796
                break;
1797
        
1798
                case _SELECT:
1799
        
1800
        
1801
                    oNode = oSrcElement.firstChild;
1802
        
1803
                    do {
1804
        
1805
                        if (oNode && oNode.tagName) {
1806
                        
1807
                            switch (oNode.tagName.toUpperCase()) {
1808
            
1809
                                case _OPTGROUP:
1810
                                case _OPTION:
1811
            
1812
            
1813
                                    this.addItem(
1814
                                            new this.ITEM_TYPE(
1815
                                                    oNode, 
1816
                                                    { parent: this }
1817
                                                )
1818
                                            );
1819
            
1820
                                break;
1821
            
1822
                            }
1823
    
1824
                        }
1825
        
1826
                    }
1827
                    while ((oNode = oNode.nextSibling));
1828
        
1829
                break;
1830
        
1831
            }
1832
    
1833
        }    
1834
    
1835
    }
1836
1837
},
1838
1839
1840
/**
1841
* @method _getFirstEnabledItem
1842
* @description Returns the first enabled item in the menu.
1843
* @return {YAHOO.widget.MenuItem}
1844
* @private
1845
*/
1846
_getFirstEnabledItem: function () {
1847
1848
    var aItems = this.getItems(),
1849
        nItems = aItems.length,
1850
        oItem,
1851
        returnVal;
1852
    
1853
1854
    for(var i=0; i<nItems; i++) {
1855
1856
        oItem = aItems[i];
1857
1858
        if (oItem && !oItem.cfg.getProperty(_DISABLED) && oItem.element.style.display != _NONE) {
1859
1860
            returnVal = oItem;
1861
            break;
1862
1863
        }
1864
    
1865
    }
1866
    
1867
    return returnVal;
1868
    
1869
},
1870
1871
1872
/**
1873
* @method _addItemToGroup
1874
* @description Adds a menu item to a group.
1875
* @private
1876
* @param {Number} p_nGroupIndex Number indicating the group to which the 
1877
* item belongs.
1878
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem 
1879
* instance to be added to the menu.
1880
* @param {String} p_oItem String specifying the text of the item to be added 
1881
* to the menu.
1882
* @param {Object} p_oItem Object literal containing a set of menu item 
1883
* configuration properties.
1884
* @param {Number} p_nItemIndex Optional. Number indicating the index at 
1885
* which the menu item should be added.
1886
* @return {YAHOO.widget.MenuItem}
1887
*/
1888
_addItemToGroup: function (p_nGroupIndex, p_oItem, p_nItemIndex) {
1889
1890
    var oItem,
1891
        nGroupIndex,
1892
        aGroup,
1893
        oGroupItem,
1894
        bAppend,
1895
        oNextItemSibling,
1896
        nItemIndex,
1897
        returnVal;
1898
1899
1900
    function getNextItemSibling(p_aArray, p_nStartIndex) {
1901
1902
        return (p_aArray[p_nStartIndex] || getNextItemSibling(p_aArray, (p_nStartIndex+1)));
1903
1904
    }
1905
1906
1907
    if (p_oItem instanceof this.ITEM_TYPE) {
1908
1909
        oItem = p_oItem;
1910
        oItem.parent = this;
1911
1912
    }
1913
    else if (Lang.isString(p_oItem)) {
1914
1915
        oItem = new this.ITEM_TYPE(p_oItem, { parent: this });
1916
    
1917
    }
1918
    else if (Lang.isObject(p_oItem)) {
1919
1920
        p_oItem.parent = this;
1921
1922
        oItem = new this.ITEM_TYPE(p_oItem.text, p_oItem);
1923
1924
    }
1925
1926
1927
    if (oItem) {
1928
1929
        if (oItem.cfg.getProperty(_SELECTED)) {
1930
1931
            this.activeItem = oItem;
1932
        
1933
        }
1934
1935
1936
        nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0;
1937
        aGroup = this._getItemGroup(nGroupIndex);
1938
1939
1940
1941
        if (!aGroup) {
1942
1943
            aGroup = this._createItemGroup(nGroupIndex);
1944
1945
        }
1946
1947
1948
        if (Lang.isNumber(p_nItemIndex)) {
1949
1950
            bAppend = (p_nItemIndex >= aGroup.length);            
1951
1952
1953
            if (aGroup[p_nItemIndex]) {
1954
    
1955
                aGroup.splice(p_nItemIndex, 0, oItem);
1956
    
1957
            }
1958
            else {
1959
    
1960
                aGroup[p_nItemIndex] = oItem;
1961
    
1962
            }
1963
1964
1965
            oGroupItem = aGroup[p_nItemIndex];
1966
1967
            if (oGroupItem) {
1968
1969
                if (bAppend && (!oGroupItem.element.parentNode || 
1970
                        oGroupItem.element.parentNode.nodeType == 11)) {
1971
        
1972
                    this._aListElements[nGroupIndex].appendChild(oGroupItem.element);
1973
    
1974
                }
1975
                else {
1976
    
1977
                    oNextItemSibling = getNextItemSibling(aGroup, (p_nItemIndex+1));
1978
    
1979
                    if (oNextItemSibling && (!oGroupItem.element.parentNode || 
1980
                            oGroupItem.element.parentNode.nodeType == 11)) {
1981
            
1982
                        this._aListElements[nGroupIndex].insertBefore(
1983
                                oGroupItem.element, oNextItemSibling.element);
1984
        
1985
                    }
1986
    
1987
                }
1988
    
1989
1990
                oGroupItem.parent = this;
1991
        
1992
                this._subscribeToItemEvents(oGroupItem);
1993
    
1994
                this._configureSubmenu(oGroupItem);
1995
                
1996
                this._updateItemProperties(nGroupIndex);
1997
        
1998
1999
                this.itemAddedEvent.fire(oGroupItem);
2000
                this.changeContentEvent.fire();
2001
2002
                returnVal = oGroupItem;
2003
    
2004
            }
2005
2006
        }
2007
        else {
2008
    
2009
            nItemIndex = aGroup.length;
2010
    
2011
            aGroup[nItemIndex] = oItem;
2012
2013
            oGroupItem = aGroup[nItemIndex];
2014
    
2015
2016
            if (oGroupItem) {
2017
    
2018
                if (!Dom.isAncestor(this._aListElements[nGroupIndex], oGroupItem.element)) {
2019
    
2020
                    this._aListElements[nGroupIndex].appendChild(oGroupItem.element);
2021
    
2022
                }
2023
    
2024
                oGroupItem.element.setAttribute(_GROUP_INDEX, nGroupIndex);
2025
                oGroupItem.element.setAttribute(_INDEX, nItemIndex);
2026
        
2027
                oGroupItem.parent = this;
2028
    
2029
                oGroupItem.index = nItemIndex;
2030
                oGroupItem.groupIndex = nGroupIndex;
2031
        
2032
                this._subscribeToItemEvents(oGroupItem);
2033
    
2034
                this._configureSubmenu(oGroupItem);
2035
    
2036
                if (nItemIndex === 0) {
2037
        
2038
                    Dom.addClass(oGroupItem.element, _FIRST_OF_TYPE);
2039
        
2040
                }
2041
2042
        
2043
2044
                this.itemAddedEvent.fire(oGroupItem);
2045
                this.changeContentEvent.fire();
2046
2047
                returnVal = oGroupItem;
2048
    
2049
            }
2050
    
2051
        }
2052
2053
    }
2054
    
2055
    return returnVal;
2056
    
2057
},
2058
2059
2060
/**
2061
* @method _removeItemFromGroupByIndex
2062
* @description Removes a menu item from a group by index.  Returns the menu 
2063
* item that was removed.
2064
* @private
2065
* @param {Number} p_nGroupIndex Number indicating the group to which the menu 
2066
* item belongs.
2067
* @param {Number} p_nItemIndex Number indicating the index of the menu item 
2068
* to be removed.
2069
* @return {YAHOO.widget.MenuItem}
2070
*/
2071
_removeItemFromGroupByIndex: function (p_nGroupIndex, p_nItemIndex) {
2072
2073
    var nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0,
2074
        aGroup = this._getItemGroup(nGroupIndex),
2075
        aArray,
2076
        oItem,
2077
        oUL;
2078
2079
    if (aGroup) {
2080
2081
        aArray = aGroup.splice(p_nItemIndex, 1);
2082
        oItem = aArray[0];
2083
    
2084
        if (oItem) {
2085
    
2086
            // Update the index and className properties of each member        
2087
            
2088
            this._updateItemProperties(nGroupIndex);
2089
    
2090
            if (aGroup.length === 0) {
2091
    
2092
                // Remove the UL
2093
    
2094
                oUL = this._aListElements[nGroupIndex];
2095
    
2096
                if (this.body && oUL) {
2097
    
2098
                    this.body.removeChild(oUL);
2099
    
2100
                }
2101
    
2102
                // Remove the group from the array of items
2103
    
2104
                this._aItemGroups.splice(nGroupIndex, 1);
2105
    
2106
    
2107
                // Remove the UL from the array of ULs
2108
    
2109
                this._aListElements.splice(nGroupIndex, 1);
2110
    
2111
    
2112
                /*
2113
                     Assign the "first-of-type" class to the new first UL 
2114
                     in the collection
2115
                */
2116
    
2117
                oUL = this._aListElements[0];
2118
    
2119
                if (oUL) {
2120
    
2121
                    Dom.addClass(oUL, _FIRST_OF_TYPE);
2122
    
2123
                }            
2124
    
2125
            }
2126
    
2127
2128
            this.itemRemovedEvent.fire(oItem);
2129
            this.changeContentEvent.fire();
2130
    
2131
        }
2132
2133
    }
2134
2135
	// Return a reference to the item that was removed
2136
2137
	return oItem;
2138
    
2139
},
2140
2141
2142
/**
2143
* @method _removeItemFromGroupByValue
2144
* @description Removes a menu item from a group by reference.  Returns the 
2145
* menu item that was removed.
2146
* @private
2147
* @param {Number} p_nGroupIndex Number indicating the group to which the
2148
* menu item belongs.
2149
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem 
2150
* instance to be removed.
2151
* @return {YAHOO.widget.MenuItem}
2152
*/    
2153
_removeItemFromGroupByValue: function (p_nGroupIndex, p_oItem) {
2154
2155
    var aGroup = this._getItemGroup(p_nGroupIndex),
2156
        nItems,
2157
        nItemIndex,
2158
        returnVal,
2159
        i;
2160
2161
    if (aGroup) {
2162
2163
        nItems = aGroup.length;
2164
        nItemIndex = -1;
2165
    
2166
        if (nItems > 0) {
2167
    
2168
            i = nItems-1;
2169
        
2170
            do {
2171
        
2172
                if (aGroup[i] == p_oItem) {
2173
        
2174
                    nItemIndex = i;
2175
                    break;    
2176
        
2177
                }
2178
        
2179
            }
2180
            while (i--);
2181
        
2182
            if (nItemIndex > -1) {
2183
        
2184
                returnVal = this._removeItemFromGroupByIndex(p_nGroupIndex, nItemIndex);
2185
        
2186
            }
2187
    
2188
        }
2189
    
2190
    }
2191
    
2192
    return returnVal;
2193
2194
},
2195
2196
2197
/**
2198
* @method _updateItemProperties
2199
* @description Updates the "index," "groupindex," and "className" properties 
2200
* of the menu items in the specified group. 
2201
* @private
2202
* @param {Number} p_nGroupIndex Number indicating the group of items to update.
2203
*/
2204
_updateItemProperties: function (p_nGroupIndex) {
2205
2206
    var aGroup = this._getItemGroup(p_nGroupIndex),
2207
        nItems = aGroup.length,
2208
        oItem,
2209
        oLI,
2210
        i;
2211
2212
2213
    if (nItems > 0) {
2214
2215
        i = nItems - 1;
2216
2217
        // Update the index and className properties of each member
2218
    
2219
        do {
2220
2221
            oItem = aGroup[i];
2222
2223
            if (oItem) {
2224
    
2225
                oLI = oItem.element;
2226
2227
                oItem.index = i;
2228
                oItem.groupIndex = p_nGroupIndex;
2229
2230
                oLI.setAttribute(_GROUP_INDEX, p_nGroupIndex);
2231
                oLI.setAttribute(_INDEX, i);
2232
2233
                Dom.removeClass(oLI, _FIRST_OF_TYPE);
2234
2235
            }
2236
    
2237
        }
2238
        while (i--);
2239
2240
2241
        if (oLI) {
2242
2243
            Dom.addClass(oLI, _FIRST_OF_TYPE);
2244
2245
        }
2246
2247
    }
2248
2249
},
2250
2251
2252
/**
2253
* @method _createItemGroup
2254
* @description Creates a new menu item group (array) and its associated 
2255
* <code>&#60;ul&#62;</code> element. Returns an aray of menu item groups.
2256
* @private
2257
* @param {Number} p_nIndex Number indicating the group to create.
2258
* @return {Array}
2259
*/
2260
_createItemGroup: function (p_nIndex) {
2261
2262
    var oUL,
2263
    	returnVal;
2264
2265
    if (!this._aItemGroups[p_nIndex]) {
2266
2267
        this._aItemGroups[p_nIndex] = [];
2268
2269
        oUL = document.createElement(_UL_LOWERCASE);
2270
2271
        this._aListElements[p_nIndex] = oUL;
2272
2273
        returnVal = this._aItemGroups[p_nIndex];
2274
2275
    }
2276
    
2277
    return returnVal;
2278
2279
},
2280
2281
2282
/**
2283
* @method _getItemGroup
2284
* @description Returns the menu item group at the specified index.
2285
* @private
2286
* @param {Number} p_nIndex Number indicating the index of the menu item group 
2287
* to be retrieved.
2288
* @return {Array}
2289
*/
2290
_getItemGroup: function (p_nIndex) {
2291
2292
    var nIndex = Lang.isNumber(p_nIndex) ? p_nIndex : 0,
2293
    	aGroups = this._aItemGroups,
2294
    	returnVal;
2295
2296
	if (nIndex in aGroups) {
2297
2298
	    returnVal = aGroups[nIndex];
2299
2300
	}
2301
	
2302
	return returnVal;
2303
2304
},
2305
2306
2307
/**
2308
* @method _configureSubmenu
2309
* @description Subscribes the menu item's submenu to its parent menu's events.
2310
* @private
2311
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem 
2312
* instance with the submenu to be configured.
2313
*/
2314
_configureSubmenu: function (p_oItem) {
2315
2316
    var oSubmenu = p_oItem.cfg.getProperty(_SUBMENU);
2317
2318
    if (oSubmenu) {
2319
            
2320
        /*
2321
            Listen for configuration changes to the parent menu 
2322
            so they they can be applied to the submenu.
2323
        */
2324
2325
        this.cfg.configChangedEvent.subscribe(this._onParentMenuConfigChange, oSubmenu, true);
2326
2327
        this.renderEvent.subscribe(this._onParentMenuRender, oSubmenu, true);
2328
2329
    }
2330
2331
},
2332
2333
2334
2335
2336
/**
2337
* @method _subscribeToItemEvents
2338
* @description Subscribes a menu to a menu item's event.
2339
* @private
2340
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem 
2341
* instance whose events should be subscribed to.
2342
*/
2343
_subscribeToItemEvents: function (p_oItem) {
2344
2345
    p_oItem.destroyEvent.subscribe(this._onMenuItemDestroy, p_oItem, this);
2346
    p_oItem.cfg.configChangedEvent.subscribe(this._onMenuItemConfigChange, p_oItem, this);
2347
2348
},
2349
2350
2351
/**
2352
* @method _onVisibleChange
2353
* @description Change event handler for the menu's "visible" configuration
2354
* property.
2355
* @private
2356
* @param {String} p_sType String representing the name of the event that 
2357
* was fired.
2358
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
2359
*/
2360
_onVisibleChange: function (p_sType, p_aArgs) {
2361
2362
    var bVisible = p_aArgs[0];
2363
    
2364
    if (bVisible) {
2365
2366
        Dom.addClass(this.element, _VISIBLE);
2367
2368
    }
2369
    else {
2370
2371
        Dom.removeClass(this.element, _VISIBLE);
2372
2373
    }
2374
2375
},
2376
2377
2378
/**
2379
* @method _cancelHideDelay
2380
* @description Cancels the call to "hideMenu."
2381
* @private
2382
*/
2383
_cancelHideDelay: function () {
2384
2385
    var oTimer = this.getRoot()._hideDelayTimer;
2386
2387
    if (oTimer) {
2388
2389
		oTimer.cancel();
2390
2391
    }
2392
2393
},
2394
2395
2396
/**
2397
* @method _execHideDelay
2398
* @description Hides the menu after the number of milliseconds specified by 
2399
* the "hidedelay" configuration property.
2400
* @private
2401
*/
2402
_execHideDelay: function () {
2403
2404
    this._cancelHideDelay();
2405
2406
    var oRoot = this.getRoot();
2407
        
2408
	oRoot._hideDelayTimer = Lang.later(oRoot.cfg.getProperty(_HIDE_DELAY), this, function () {
2409
    
2410
        if (oRoot.activeItem) {
2411
2412
			if (oRoot.hasFocus()) {
2413
2414
				oRoot.activeItem.focus();
2415
			
2416
			}
2417
			
2418
            oRoot.clearActiveItem();
2419
2420
        }
2421
2422
        if (oRoot == this && !(this instanceof YAHOO.widget.MenuBar) && 
2423
            this.cfg.getProperty(_POSITION) == _DYNAMIC) {
2424
2425
            this.hide();
2426
        
2427
        }
2428
    
2429
    });
2430
2431
},
2432
2433
2434
/**
2435
* @method _cancelShowDelay
2436
* @description Cancels the call to the "showMenu."
2437
* @private
2438
*/
2439
_cancelShowDelay: function () {
2440
2441
    var oTimer = this.getRoot()._showDelayTimer;
2442
2443
    if (oTimer) {
2444
2445
        oTimer.cancel();
2446
2447
    }
2448
2449
},
2450
2451
2452
/**
2453
* @method _execSubmenuHideDelay
2454
* @description Hides a submenu after the number of milliseconds specified by 
2455
* the "submenuhidedelay" configuration property have ellapsed.
2456
* @private
2457
* @param {YAHOO.widget.Menu} p_oSubmenu Object specifying the submenu that  
2458
* should be hidden.
2459
* @param {Number} p_nMouseX The x coordinate of the mouse when it left 
2460
* the specified submenu's parent menu item.
2461
* @param {Number} p_nHideDelay The number of milliseconds that should ellapse
2462
* before the submenu is hidden.
2463
*/
2464
_execSubmenuHideDelay: function (p_oSubmenu, p_nMouseX, p_nHideDelay) {
2465
2466
	p_oSubmenu._submenuHideDelayTimer = Lang.later(50, this, function () {
2467
2468
        if (this._nCurrentMouseX > (p_nMouseX + 10)) {
2469
2470
            p_oSubmenu._submenuHideDelayTimer = Lang.later(p_nHideDelay, p_oSubmenu, function () {
2471
        
2472
                this.hide();
2473
2474
            });
2475
2476
        }
2477
        else {
2478
2479
            p_oSubmenu.hide();
2480
        
2481
        }
2482
	
2483
	});
2484
2485
},
2486
2487
2488
2489
// Protected methods
2490
2491
2492
/**
2493
* @method _disableScrollHeader
2494
* @description Disables the header used for scrolling the body of the menu.
2495
* @protected
2496
*/
2497
_disableScrollHeader: function () {
2498
2499
    if (!this._bHeaderDisabled) {
2500
2501
        Dom.addClass(this.header, _TOP_SCROLLBAR_DISABLED);
2502
        this._bHeaderDisabled = true;
2503
2504
    }
2505
2506
},
2507
2508
2509
/**
2510
* @method _disableScrollFooter
2511
* @description Disables the footer used for scrolling the body of the menu.
2512
* @protected
2513
*/
2514
_disableScrollFooter: function () {
2515
2516
    if (!this._bFooterDisabled) {
2517
2518
        Dom.addClass(this.footer, _BOTTOM_SCROLLBAR_DISABLED);
2519
        this._bFooterDisabled = true;
2520
2521
    }
2522
2523
},
2524
2525
2526
/**
2527
* @method _enableScrollHeader
2528
* @description Enables the header used for scrolling the body of the menu.
2529
* @protected
2530
*/
2531
_enableScrollHeader: function () {
2532
2533
    if (this._bHeaderDisabled) {
2534
2535
        Dom.removeClass(this.header, _TOP_SCROLLBAR_DISABLED);
2536
        this._bHeaderDisabled = false;
2537
2538
    }
2539
2540
},
2541
2542
2543
/**
2544
* @method _enableScrollFooter
2545
* @description Enables the footer used for scrolling the body of the menu.
2546
* @protected
2547
*/
2548
_enableScrollFooter: function () {
2549
2550
    if (this._bFooterDisabled) {
2551
2552
        Dom.removeClass(this.footer, _BOTTOM_SCROLLBAR_DISABLED);
2553
        this._bFooterDisabled = false;
2554
2555
    }
2556
2557
},
2558
2559
2560
/**
2561
* @method _onMouseOver
2562
* @description "mouseover" event handler for the menu.
2563
* @protected
2564
* @param {String} p_sType String representing the name of the event that 
2565
* was fired.
2566
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
2567
*/
2568
_onMouseOver: function (p_sType, p_aArgs) {
2569
2570
    var oEvent = p_aArgs[0],
2571
        oItem = p_aArgs[1],
2572
        oTarget = Event.getTarget(oEvent),
2573
        oRoot = this.getRoot(),
2574
        oSubmenuHideDelayTimer = this._submenuHideDelayTimer,
2575
        oParentMenu,
2576
        nShowDelay,
2577
        bShowDelay,
2578
        oActiveItem,
2579
        oItemCfg,
2580
        oSubmenu;
2581
2582
2583
    var showSubmenu = function () {
2584
2585
        if (this.parent.cfg.getProperty(_SELECTED)) {
2586
2587
            this.show();
2588
2589
        }
2590
2591
    };
2592
2593
2594
    if (!this._bStopMouseEventHandlers) {
2595
    
2596
		if (!this._bHandledMouseOverEvent && (oTarget == this.element || 
2597
				Dom.isAncestor(this.element, oTarget))) {
2598
	
2599
			// Menu mouseover logic
2600
2601
	        if (this._useHideDelay) {
2602
	        	this._cancelHideDelay();
2603
	        }
2604
	
2605
			this._nCurrentMouseX = 0;
2606
	
2607
			Event.on(this.element, _MOUSEMOVE, this._onMouseMove, this, true);
2608
2609
2610
			/*
2611
				If the mouse is moving from the submenu back to its corresponding menu item, 
2612
				don't hide the submenu or clear the active MenuItem.
2613
			*/
2614
2615
			if (!(oItem && Dom.isAncestor(oItem.element, Event.getRelatedTarget(oEvent)))) {
2616
2617
				this.clearActiveItem();
2618
2619
			}
2620
	
2621
2622
			if (this.parent && oSubmenuHideDelayTimer) {
2623
	
2624
				oSubmenuHideDelayTimer.cancel();
2625
	
2626
				this.parent.cfg.setProperty(_SELECTED, true);
2627
	
2628
				oParentMenu = this.parent.parent;
2629
	
2630
				oParentMenu._bHandledMouseOutEvent = true;
2631
				oParentMenu._bHandledMouseOverEvent = false;
2632
	
2633
			}
2634
	
2635
	
2636
			this._bHandledMouseOverEvent = true;
2637
			this._bHandledMouseOutEvent = false;
2638
		
2639
		}
2640
	
2641
	
2642
		if (oItem && !oItem.handledMouseOverEvent && !oItem.cfg.getProperty(_DISABLED) && 
2643
			(oTarget == oItem.element || Dom.isAncestor(oItem.element, oTarget))) {
2644
	
2645
			// Menu Item mouseover logic
2646
	
2647
			nShowDelay = this.cfg.getProperty(_SHOW_DELAY);
2648
			bShowDelay = (nShowDelay > 0);
2649
	
2650
	
2651
			if (bShowDelay) {
2652
			
2653
				this._cancelShowDelay();
2654
			
2655
			}
2656
	
2657
	
2658
			oActiveItem = this.activeItem;
2659
		
2660
			if (oActiveItem) {
2661
		
2662
				oActiveItem.cfg.setProperty(_SELECTED, false);
2663
		
2664
			}
2665
	
2666
	
2667
			oItemCfg = oItem.cfg;
2668
		
2669
			// Select and focus the current menu item
2670
		
2671
			oItemCfg.setProperty(_SELECTED, true);
2672
	
2673
	
2674
			if (this.hasFocus() || oRoot._hasFocus) {
2675
			
2676
				oItem.focus();
2677
				
2678
				oRoot._hasFocus = false;
2679
			
2680
			}
2681
	
2682
	
2683
			if (this.cfg.getProperty(_AUTO_SUBMENU_DISPLAY)) {
2684
	
2685
				// Show the submenu this menu item
2686
	
2687
				oSubmenu = oItemCfg.getProperty(_SUBMENU);
2688
			
2689
				if (oSubmenu) {
2690
			
2691
					if (bShowDelay) {
2692
	
2693
						oRoot._showDelayTimer = 
2694
							Lang.later(oRoot.cfg.getProperty(_SHOW_DELAY), oSubmenu, showSubmenu);
2695
			
2696
					}
2697
					else {
2698
	
2699
						oSubmenu.show();
2700
	
2701
					}
2702
	
2703
				}
2704
	
2705
			}                        
2706
	
2707
			oItem.handledMouseOverEvent = true;
2708
			oItem.handledMouseOutEvent = false;
2709
	
2710
		}
2711
    
2712
    }
2713
2714
},
2715
2716
2717
/**
2718
* @method _onMouseOut
2719
* @description "mouseout" event handler for the menu.
2720
* @protected
2721
* @param {String} p_sType String representing the name of the event that 
2722
* was fired.
2723
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
2724
*/
2725
_onMouseOut: function (p_sType, p_aArgs) {
2726
2727
    var oEvent = p_aArgs[0],
2728
        oItem = p_aArgs[1],
2729
        oRelatedTarget = Event.getRelatedTarget(oEvent),
2730
        bMovingToSubmenu = false,
2731
        oItemCfg,
2732
        oSubmenu,
2733
        nSubmenuHideDelay,
2734
        nShowDelay;
2735
2736
2737
    if (!this._bStopMouseEventHandlers) {
2738
    
2739
		if (oItem && !oItem.cfg.getProperty(_DISABLED)) {
2740
	
2741
			oItemCfg = oItem.cfg;
2742
			oSubmenu = oItemCfg.getProperty(_SUBMENU);
2743
	
2744
	
2745
			if (oSubmenu && (oRelatedTarget == oSubmenu.element ||
2746
					Dom.isAncestor(oSubmenu.element, oRelatedTarget))) {
2747
	
2748
				bMovingToSubmenu = true;
2749
	
2750
			}
2751
	
2752
	
2753
			if (!oItem.handledMouseOutEvent && ((oRelatedTarget != oItem.element &&  
2754
				!Dom.isAncestor(oItem.element, oRelatedTarget)) || bMovingToSubmenu)) {
2755
	
2756
				// Menu Item mouseout logic
2757
	
2758
				if (!bMovingToSubmenu) {
2759
	
2760
					oItem.cfg.setProperty(_SELECTED, false);
2761
	
2762
	
2763
					if (oSubmenu) {
2764
	
2765
						nSubmenuHideDelay = this.cfg.getProperty(_SUBMENU_HIDE_DELAY);
2766
	
2767
						nShowDelay = this.cfg.getProperty(_SHOW_DELAY);
2768
	
2769
						if (!(this instanceof YAHOO.widget.MenuBar) && nSubmenuHideDelay > 0 && 
2770
							nShowDelay >= nSubmenuHideDelay) {
2771
	
2772
							this._execSubmenuHideDelay(oSubmenu, Event.getPageX(oEvent),
2773
									nSubmenuHideDelay);
2774
	
2775
						}
2776
						else {
2777
	
2778
							oSubmenu.hide();
2779
	
2780
						}
2781
	
2782
					}
2783
	
2784
				}
2785
	
2786
	
2787
				oItem.handledMouseOutEvent = true;
2788
				oItem.handledMouseOverEvent = false;
2789
		
2790
			}
2791
	
2792
		}
2793
2794
2795
		if (!this._bHandledMouseOutEvent && ((oRelatedTarget != this.element &&  
2796
			!Dom.isAncestor(this.element, oRelatedTarget)) || bMovingToSubmenu)) {
2797
	
2798
			// Menu mouseout logic
2799
2800
	        if (this._useHideDelay) {
2801
	        	this._execHideDelay();
2802
	        }
2803
2804
			Event.removeListener(this.element, _MOUSEMOVE, this._onMouseMove);
2805
	
2806
			this._nCurrentMouseX = Event.getPageX(oEvent);
2807
	
2808
			this._bHandledMouseOutEvent = true;
2809
			this._bHandledMouseOverEvent = false;
2810
	
2811
		}
2812
    
2813
    }
2814
2815
},
2816
2817
2818
/**
2819
* @method _onMouseMove
2820
* @description "click" event handler for the menu.
2821
* @protected
2822
* @param {Event} p_oEvent Object representing the DOM event object passed 
2823
* back by the event utility (YAHOO.util.Event).
2824
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
2825
* fired the event.
2826
*/
2827
_onMouseMove: function (p_oEvent, p_oMenu) {
2828
2829
    if (!this._bStopMouseEventHandlers) {
2830
    
2831
	    this._nCurrentMouseX = Event.getPageX(p_oEvent);
2832
    
2833
    }
2834
2835
},
2836
2837
2838
/**
2839
* @method _onClick
2840
* @description "click" event handler for the menu.
2841
* @protected
2842
* @param {String} p_sType String representing the name of the event that 
2843
* was fired.
2844
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
2845
*/
2846
_onClick: function (p_sType, p_aArgs) {
2847
2848
	var oEvent = p_aArgs[0],
2849
		oItem = p_aArgs[1],
2850
		bInMenuAnchor = false,
2851
		oSubmenu,
2852
		oMenu,
2853
		oRoot,
2854
		sId,
2855
		sURL,
2856
		nHashPos,
2857
		nLen;
2858
2859
2860
	var hide = function () {
2861
		
2862
		oRoot = this.getRoot();
2863
2864
		if (oRoot instanceof YAHOO.widget.MenuBar || 
2865
			oRoot.cfg.getProperty(_POSITION) == _STATIC) {
2866
2867
			oRoot.clearActiveItem();
2868
2869
		}
2870
		else {
2871
2872
			oRoot.hide();
2873
		
2874
		}
2875
	
2876
	};
2877
2878
2879
	if (oItem) {
2880
	
2881
		if (oItem.cfg.getProperty(_DISABLED)) {
2882
		
2883
			Event.preventDefault(oEvent);
2884
2885
			hide.call(this);
2886
2887
		}
2888
		else {
2889
2890
			oSubmenu = oItem.cfg.getProperty(_SUBMENU);
2891
	
2892
			
2893
			/*
2894
				 Check if the URL of the anchor is pointing to an element that is 
2895
				 a child of the menu.
2896
			*/
2897
			
2898
			sURL = oItem.cfg.getProperty(_URL);
2899
2900
		
2901
			if (sURL) {
2902
	
2903
				nHashPos = sURL.indexOf(_HASH);
2904
	
2905
				nLen = sURL.length;
2906
	
2907
	
2908
				if (nHashPos != -1) {
2909
	
2910
					sURL = sURL.substr(nHashPos, nLen);
2911
		
2912
					nLen = sURL.length;
2913
	
2914
	
2915
					if (nLen > 1) {
2916
	
2917
						sId = sURL.substr(1, nLen);
2918
	
2919
						oMenu = YAHOO.widget.MenuManager.getMenu(sId);
2920
						
2921
						if (oMenu) {
2922
2923
							bInMenuAnchor = 
2924
								(this.getRoot() === oMenu.getRoot());
2925
2926
						}
2927
						
2928
					}
2929
					else if (nLen === 1) {
2930
	
2931
						bInMenuAnchor = true;
2932
					
2933
					}
2934
	
2935
				}
2936
			
2937
			}
2938
2939
	
2940
			if (bInMenuAnchor && !oItem.cfg.getProperty(_TARGET)) {
2941
	
2942
				Event.preventDefault(oEvent);
2943
				
2944
2945
				if (UA.webkit) {
2946
				
2947
					oItem.focus();
2948
				
2949
				}
2950
				else {
2951
2952
					oItem.focusEvent.fire();
2953
				
2954
				}
2955
			
2956
			}
2957
	
2958
	
2959
			if (!oSubmenu && !this.cfg.getProperty(_KEEP_OPEN)) {
2960
	
2961
				hide.call(this);
2962
	
2963
			}
2964
			
2965
		}
2966
	
2967
	}
2968
2969
},
2970
2971
2972
/**
2973
* @method _onKeyDown
2974
* @description "keydown" event handler for the menu.
2975
* @protected
2976
* @param {String} p_sType String representing the name of the event that 
2977
* was fired.
2978
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
2979
*/
2980
_onKeyDown: function (p_sType, p_aArgs) {
2981
2982
    var oEvent = p_aArgs[0],
2983
        oItem = p_aArgs[1],
2984
        oSubmenu,
2985
        oItemCfg,
2986
        oParentItem,
2987
        oRoot,
2988
        oNextItem,
2989
        oBody,
2990
        nBodyScrollTop,
2991
        nBodyOffsetHeight,
2992
        aItems,
2993
        nItems,
2994
        nNextItemOffsetTop,
2995
        nScrollTarget,
2996
        oParentMenu,
2997
		oFocusedEl;
2998
2999
3000
	if (this._useHideDelay) {
3001
		this._cancelHideDelay();
3002
	}
3003
3004
3005
    /*
3006
        This function is called to prevent a bug in Firefox.  In Firefox,
3007
        moving a DOM element into a stationary mouse pointer will cause the 
3008
        browser to fire mouse events.  This can result in the menu mouse
3009
        event handlers being called uncessarily, especially when menus are 
3010
        moved into a stationary mouse pointer as a result of a 
3011
        key event handler.
3012
    */
3013
    function stopMouseEventHandlers() {
3014
3015
        this._bStopMouseEventHandlers = true;
3016
        
3017
        Lang.later(10, this, function () {
3018
3019
            this._bStopMouseEventHandlers = false;
3020
        
3021
        });
3022
3023
    }
3024
3025
3026
    if (oItem && !oItem.cfg.getProperty(_DISABLED)) {
3027
3028
        oItemCfg = oItem.cfg;
3029
        oParentItem = this.parent;
3030
3031
        switch(oEvent.keyCode) {
3032
    
3033
            case 38:    // Up arrow
3034
            case 40:    // Down arrow
3035
    
3036
                oNextItem = (oEvent.keyCode == 38) ? 
3037
                    oItem.getPreviousEnabledSibling() : 
3038
                    oItem.getNextEnabledSibling();
3039
        
3040
                if (oNextItem) {
3041
3042
                    this.clearActiveItem();
3043
3044
                    oNextItem.cfg.setProperty(_SELECTED, true);
3045
                    oNextItem.focus();
3046
3047
3048
                    if (this.cfg.getProperty(_MAX_HEIGHT) > 0) {
3049
3050
                        oBody = this.body;
3051
                        nBodyScrollTop = oBody.scrollTop;
3052
                        nBodyOffsetHeight = oBody.offsetHeight;
3053
                        aItems = this.getItems();
3054
                        nItems = aItems.length - 1;
3055
                        nNextItemOffsetTop = oNextItem.element.offsetTop;
3056
3057
3058
                        if (oEvent.keyCode == 40 ) {    // Down
3059
                       
3060
                            if (nNextItemOffsetTop >= (nBodyOffsetHeight + nBodyScrollTop)) {
3061
3062
                                oBody.scrollTop = nNextItemOffsetTop - nBodyOffsetHeight;
3063
3064
                            }
3065
                            else if (nNextItemOffsetTop <= nBodyScrollTop) {
3066
                            
3067
                                oBody.scrollTop = 0;
3068
                            
3069
                            }
3070
3071
3072
                            if (oNextItem == aItems[nItems]) {
3073
3074
                                oBody.scrollTop = oNextItem.element.offsetTop;
3075
3076
                            }
3077
3078
                        }
3079
                        else {  // Up
3080
3081
                            if (nNextItemOffsetTop <= nBodyScrollTop) {
3082
3083
                                oBody.scrollTop = nNextItemOffsetTop - oNextItem.element.offsetHeight;
3084
                            
3085
                            }
3086
                            else if (nNextItemOffsetTop >= (nBodyScrollTop + nBodyOffsetHeight)) {
3087
                            
3088
                                oBody.scrollTop = nNextItemOffsetTop;
3089
                            
3090
                            }
3091
3092
3093
                            if (oNextItem == aItems[0]) {
3094
                            
3095
                                oBody.scrollTop = 0;
3096
                            
3097
                            }
3098
3099
                        }
3100
3101
3102
                        nBodyScrollTop = oBody.scrollTop;
3103
                        nScrollTarget = oBody.scrollHeight - oBody.offsetHeight;
3104
3105
                        if (nBodyScrollTop === 0) {
3106
3107
                            this._disableScrollHeader();
3108
                            this._enableScrollFooter();
3109
3110
                        }
3111
                        else if (nBodyScrollTop == nScrollTarget) {
3112
3113
                             this._enableScrollHeader();
3114
                             this._disableScrollFooter();
3115
3116
                        }
3117
                        else {
3118
3119
                            this._enableScrollHeader();
3120
                            this._enableScrollFooter();
3121
3122
                        }
3123
3124
                    }
3125
3126
                }
3127
3128
    
3129
                Event.preventDefault(oEvent);
3130
3131
                stopMouseEventHandlers();
3132
    
3133
            break;
3134
            
3135
    
3136
            case 39:    // Right arrow
3137
    
3138
                oSubmenu = oItemCfg.getProperty(_SUBMENU);
3139
    
3140
                if (oSubmenu) {
3141
    
3142
                    if (!oItemCfg.getProperty(_SELECTED)) {
3143
        
3144
                        oItemCfg.setProperty(_SELECTED, true);
3145
        
3146
                    }
3147
    
3148
                    oSubmenu.show();
3149
                    oSubmenu.setInitialFocus();
3150
                    oSubmenu.setInitialSelection();
3151
    
3152
                }
3153
                else {
3154
    
3155
                    oRoot = this.getRoot();
3156
                    
3157
                    if (oRoot instanceof YAHOO.widget.MenuBar) {
3158
    
3159
                        oNextItem = oRoot.activeItem.getNextEnabledSibling();
3160
    
3161
                        if (oNextItem) {
3162
                        
3163
                            oRoot.clearActiveItem();
3164
    
3165
                            oNextItem.cfg.setProperty(_SELECTED, true);
3166
    
3167
                            oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
3168
    
3169
                            if (oSubmenu) {
3170
    
3171
                                oSubmenu.show();
3172
                                oSubmenu.setInitialFocus();
3173
                            
3174
                            }
3175
                            else {
3176
    
3177
                            	oNextItem.focus();
3178
                            
3179
                            }
3180
                        
3181
                        }
3182
                    
3183
                    }
3184
                
3185
                }
3186
    
3187
    
3188
                Event.preventDefault(oEvent);
3189
3190
                stopMouseEventHandlers();
3191
3192
            break;
3193
    
3194
    
3195
            case 37:    // Left arrow
3196
    
3197
                if (oParentItem) {
3198
    
3199
                    oParentMenu = oParentItem.parent;
3200
    
3201
                    if (oParentMenu instanceof YAHOO.widget.MenuBar) {
3202
    
3203
                        oNextItem = 
3204
                            oParentMenu.activeItem.getPreviousEnabledSibling();
3205
    
3206
                        if (oNextItem) {
3207
                        
3208
                            oParentMenu.clearActiveItem();
3209
    
3210
                            oNextItem.cfg.setProperty(_SELECTED, true);
3211
    
3212
                            oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
3213
    
3214
                            if (oSubmenu) {
3215
                            
3216
                                oSubmenu.show();
3217
								oSubmenu.setInitialFocus();                                
3218
                            
3219
                            }
3220
                            else {
3221
    
3222
                            	oNextItem.focus();
3223
                            
3224
                            }
3225
                        
3226
                        } 
3227
                    
3228
                    }
3229
                    else {
3230
    
3231
                        this.hide();
3232
    
3233
                        oParentItem.focus();
3234
                    
3235
                    }
3236
    
3237
                }
3238
    
3239
                Event.preventDefault(oEvent);
3240
3241
                stopMouseEventHandlers();
3242
3243
            break;        
3244
    
3245
        }
3246
3247
3248
    }
3249
3250
3251
    if (oEvent.keyCode == 27) { // Esc key
3252
3253
        if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3254
        
3255
            this.hide();
3256
3257
            if (this.parent) {
3258
3259
                this.parent.focus();
3260
            
3261
            }
3262
			else {
3263
				// Focus the element that previously had focus
3264
3265
				oFocusedEl = this._focusedElement;
3266
3267
				if (oFocusedEl && oFocusedEl.focus) {
3268
3269
					try {
3270
						oFocusedEl.focus();
3271
					}
3272
					catch(ex) {
3273
					}
3274
3275
				}
3276
				
3277
			}
3278
3279
        }
3280
        else if (this.activeItem) {
3281
3282
            oSubmenu = this.activeItem.cfg.getProperty(_SUBMENU);
3283
3284
            if (oSubmenu && oSubmenu.cfg.getProperty(_VISIBLE)) {
3285
            
3286
                oSubmenu.hide();
3287
                this.activeItem.focus();
3288
            
3289
            }
3290
            else {
3291
3292
                this.activeItem.blur();
3293
                this.activeItem.cfg.setProperty(_SELECTED, false);
3294
        
3295
            }
3296
        
3297
        }
3298
3299
3300
        Event.preventDefault(oEvent);
3301
    
3302
    }
3303
    
3304
},
3305
3306
3307
/**
3308
* @method _onKeyPress
3309
* @description "keypress" event handler for a Menu instance.
3310
* @protected
3311
* @param {String} p_sType The name of the event that was fired.
3312
* @param {Array} p_aArgs Collection of arguments sent when the event 
3313
* was fired.
3314
*/
3315
_onKeyPress: function (p_sType, p_aArgs) {
3316
    
3317
    var oEvent = p_aArgs[0];
3318
3319
3320
    if (oEvent.keyCode == 40 || oEvent.keyCode == 38) {
3321
3322
        Event.preventDefault(oEvent);
3323
3324
    }
3325
3326
},
3327
3328
3329
/**
3330
* @method _onBlur
3331
* @description "blur" event handler for a Menu instance.
3332
* @protected
3333
* @param {String} p_sType The name of the event that was fired.
3334
* @param {Array} p_aArgs Collection of arguments sent when the event 
3335
* was fired.
3336
*/
3337
_onBlur: function (p_sType, p_aArgs) {
3338
        
3339
	if (this._hasFocus) {
3340
		this._hasFocus = false;
3341
	}
3342
3343
},
3344
3345
/**
3346
* @method _onYChange
3347
* @description "y" event handler for a Menu instance.
3348
* @protected
3349
* @param {String} p_sType The name of the event that was fired.
3350
* @param {Array} p_aArgs Collection of arguments sent when the event 
3351
* was fired.
3352
*/
3353
_onYChange: function (p_sType, p_aArgs) {
3354
3355
    var oParent = this.parent,
3356
        nScrollTop,
3357
        oIFrame,
3358
        nY;
3359
3360
3361
    if (oParent) {
3362
3363
        nScrollTop = oParent.parent.body.scrollTop;
3364
3365
3366
        if (nScrollTop > 0) {
3367
    
3368
            nY = (this.cfg.getProperty(_Y) - nScrollTop);
3369
            
3370
            Dom.setY(this.element, nY);
3371
3372
            oIFrame = this.iframe;            
3373
    
3374
3375
            if (oIFrame) {
3376
    
3377
                Dom.setY(oIFrame, nY);
3378
    
3379
            }
3380
            
3381
            this.cfg.setProperty(_Y, nY, true);
3382
        
3383
        }
3384
    
3385
    }
3386
3387
},
3388
3389
3390
/**
3391
* @method _onScrollTargetMouseOver
3392
* @description "mouseover" event handler for the menu's "header" and "footer" 
3393
* elements.  Used to scroll the body of the menu up and down when the 
3394
* menu's "maxheight" configuration property is set to a value greater than 0.
3395
* @protected
3396
* @param {Event} p_oEvent Object representing the DOM event object passed 
3397
* back by the event utility (YAHOO.util.Event).
3398
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
3399
* fired the event.
3400
*/
3401
_onScrollTargetMouseOver: function (p_oEvent, p_oMenu) {
3402
3403
	var oBodyScrollTimer = this._bodyScrollTimer;
3404
3405
3406
	if (oBodyScrollTimer) {
3407
3408
		oBodyScrollTimer.cancel();
3409
3410
	}
3411
3412
3413
	this._cancelHideDelay();
3414
3415
3416
    var oTarget = Event.getTarget(p_oEvent),
3417
        oBody = this.body,
3418
        nScrollIncrement = this.cfg.getProperty(_SCROLL_INCREMENT),
3419
        nScrollTarget,
3420
        fnScrollFunction;
3421
3422
3423
    function scrollBodyDown() {
3424
3425
        var nScrollTop = oBody.scrollTop;
3426
3427
3428
        if (nScrollTop < nScrollTarget) {
3429
3430
            oBody.scrollTop = (nScrollTop + nScrollIncrement);
3431
3432
            this._enableScrollHeader();
3433
3434
        }
3435
        else {
3436
3437
            oBody.scrollTop = nScrollTarget;
3438
3439
            this._bodyScrollTimer.cancel();
3440
3441
            this._disableScrollFooter();
3442
3443
        }
3444
3445
    }
3446
3447
3448
    function scrollBodyUp() {
3449
3450
        var nScrollTop = oBody.scrollTop;
3451
3452
3453
        if (nScrollTop > 0) {
3454
3455
            oBody.scrollTop = (nScrollTop - nScrollIncrement);
3456
3457
            this._enableScrollFooter();
3458
3459
        }
3460
        else {
3461
3462
            oBody.scrollTop = 0;
3463
3464
			this._bodyScrollTimer.cancel();
3465
3466
            this._disableScrollHeader();
3467
3468
        }
3469
3470
    }
3471
3472
    
3473
    if (Dom.hasClass(oTarget, _HD)) {
3474
3475
        fnScrollFunction = scrollBodyUp;
3476
    
3477
    }
3478
    else {
3479
3480
        nScrollTarget = oBody.scrollHeight - oBody.offsetHeight;
3481
3482
        fnScrollFunction = scrollBodyDown;
3483
    
3484
    }
3485
    
3486
3487
    this._bodyScrollTimer = Lang.later(10, this, fnScrollFunction, null, true);
3488
3489
},
3490
3491
3492
/**
3493
* @method _onScrollTargetMouseOut
3494
* @description "mouseout" event handler for the menu's "header" and "footer" 
3495
* elements.  Used to stop scrolling the body of the menu up and down when the 
3496
* menu's "maxheight" configuration property is set to a value greater than 0.
3497
* @protected
3498
* @param {Event} p_oEvent Object representing the DOM event object passed 
3499
* back by the event utility (YAHOO.util.Event).
3500
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
3501
* fired the event.
3502
*/
3503
_onScrollTargetMouseOut: function (p_oEvent, p_oMenu) {
3504
3505
	var oBodyScrollTimer = this._bodyScrollTimer;
3506
3507
	if (oBodyScrollTimer) {
3508
3509
		oBodyScrollTimer.cancel();
3510
3511
	}
3512
	
3513
    this._cancelHideDelay();
3514
3515
},
3516
3517
3518
3519
// Private methods
3520
3521
3522
/**
3523
* @method _onInit
3524
* @description "init" event handler for the menu.
3525
* @private
3526
* @param {String} p_sType String representing the name of the event that 
3527
* was fired.
3528
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
3529
*/
3530
_onInit: function (p_sType, p_aArgs) {
3531
3532
    this.cfg.subscribeToConfigEvent(_VISIBLE, this._onVisibleChange);
3533
3534
    var bRootMenu = !this.parent,
3535
        bLazyLoad = this.lazyLoad;
3536
3537
3538
    /*
3539
        Automatically initialize a menu's subtree if:
3540
3541
        1) This is the root menu and lazyload is off
3542
        
3543
        2) This is the root menu, lazyload is on, but the menu is 
3544
           already visible
3545
3546
        3) This menu is a submenu and lazyload is off
3547
    */
3548
3549
3550
3551
    if (((bRootMenu && !bLazyLoad) || 
3552
        (bRootMenu && (this.cfg.getProperty(_VISIBLE) || 
3553
        this.cfg.getProperty(_POSITION) == _STATIC)) || 
3554
        (!bRootMenu && !bLazyLoad)) && this.getItemGroups().length === 0) {
3555
3556
        if (this.srcElement) {
3557
3558
            this._initSubTree();
3559
        
3560
        }
3561
3562
3563
        if (this.itemData) {
3564
3565
            this.addItems(this.itemData);
3566
3567
        }
3568
    
3569
    }
3570
    else if (bLazyLoad) {
3571
3572
        this.cfg.fireQueue();
3573
    
3574
    }
3575
3576
},
3577
3578
3579
/**
3580
* @method _onBeforeRender
3581
* @description "beforerender" event handler for the menu.  Appends all of the 
3582
* <code>&#60;ul&#62;</code>, <code>&#60;li&#62;</code> and their accompanying 
3583
* title elements to the body element of the menu.
3584
* @private
3585
* @param {String} p_sType String representing the name of the event that 
3586
* was fired.
3587
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
3588
*/
3589
_onBeforeRender: function (p_sType, p_aArgs) {
3590
3591
    var oEl = this.element,
3592
        nListElements = this._aListElements.length,
3593
        bFirstList = true,
3594
        i = 0,
3595
        oUL,
3596
        oGroupTitle;
3597
3598
    if (nListElements > 0) {
3599
3600
        do {
3601
3602
            oUL = this._aListElements[i];
3603
3604
            if (oUL) {
3605
3606
                if (bFirstList) {
3607
        
3608
                    Dom.addClass(oUL, _FIRST_OF_TYPE);
3609
                    bFirstList = false;
3610
        
3611
                }
3612
3613
3614
                if (!Dom.isAncestor(oEl, oUL)) {
3615
3616
                    this.appendToBody(oUL);
3617
3618
                }
3619
3620
3621
                oGroupTitle = this._aGroupTitleElements[i];
3622
3623
                if (oGroupTitle) {
3624
3625
                    if (!Dom.isAncestor(oEl, oGroupTitle)) {
3626
3627
                        oUL.parentNode.insertBefore(oGroupTitle, oUL);
3628
3629
                    }
3630
3631
3632
                    Dom.addClass(oUL, _HAS_TITLE);
3633
3634
                }
3635
3636
            }
3637
3638
            i++;
3639
3640
        }
3641
        while (i < nListElements);
3642
3643
    }
3644
3645
},
3646
3647
3648
/**
3649
* @method _onRender
3650
* @description "render" event handler for the menu.
3651
* @private
3652
* @param {String} p_sType String representing the name of the event that 
3653
* was fired.
3654
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
3655
*/
3656
_onRender: function (p_sType, p_aArgs) {
3657
3658
    if (this.cfg.getProperty(_POSITION) == _DYNAMIC) { 
3659
3660
        if (!this.cfg.getProperty(_VISIBLE)) {
3661
3662
            this.positionOffScreen();
3663
3664
        }
3665
    
3666
    }
3667
3668
},
3669
3670
3671
3672
3673
3674
/**
3675
* @method _onBeforeShow
3676
* @description "beforeshow" event handler for the menu.
3677
* @private
3678
* @param {String} p_sType String representing the name of the event that 
3679
* was fired.
3680
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
3681
*/
3682
_onBeforeShow: function (p_sType, p_aArgs) {
3683
3684
    var nOptions,
3685
        n,
3686
        oSrcElement,
3687
        oContainer = this.cfg.getProperty(_CONTAINER);
3688
3689
3690
    if (this.lazyLoad && this.getItemGroups().length === 0) {
3691
3692
        if (this.srcElement) {
3693
        
3694
            this._initSubTree();
3695
3696
        }
3697
3698
3699
        if (this.itemData) {
3700
3701
            if (this.parent && this.parent.parent && 
3702
                this.parent.parent.srcElement && 
3703
                this.parent.parent.srcElement.tagName.toUpperCase() == 
3704
                _SELECT) {
3705
3706
                nOptions = this.itemData.length;
3707
    
3708
                for(n=0; n<nOptions; n++) {
3709
3710
                    if (this.itemData[n].tagName) {
3711
3712
                        this.addItem((new this.ITEM_TYPE(this.itemData[n])));
3713
    
3714
                    }
3715
    
3716
                }
3717
            
3718
            }
3719
            else {
3720
3721
                this.addItems(this.itemData);
3722
            
3723
            }
3724
        
3725
        }
3726
3727
3728
        oSrcElement = this.srcElement;
3729
3730
        if (oSrcElement) {
3731
3732
            if (oSrcElement.tagName.toUpperCase() == _SELECT) {
3733
3734
                if (Dom.inDocument(oSrcElement)) {
3735
3736
                    this.render(oSrcElement.parentNode);
3737
                
3738
                }
3739
                else {
3740
                
3741
                    this.render(oContainer);
3742
                
3743
                }
3744
3745
            }
3746
            else {
3747
3748
                this.render();
3749
3750
            }
3751
3752
        }
3753
        else {
3754
3755
            if (this.parent) {
3756
3757
                this.render(this.parent.element);     
3758
3759
            }
3760
            else {
3761
3762
                this.render(oContainer);
3763
3764
            }                
3765
3766
        }
3767
3768
    }
3769
3770
3771
3772
    var oParent = this.parent,
3773
		aAlignment;
3774
3775
3776
    if (!oParent && this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3777
3778
        this.cfg.refireEvent(_XY);
3779
   
3780
    }
3781
3782
3783
	if (oParent) {
3784
3785
		aAlignment = oParent.parent.cfg.getProperty(_SUBMENU_ALIGNMENT);
3786
		
3787
		this.cfg.setProperty(_CONTEXT, [oParent.element, aAlignment[0], aAlignment[1]]);
3788
		this.align();
3789
	
3790
	}
3791
3792
},
3793
3794
3795
getConstrainedY: function (y) {
3796
3797
	var oMenu = this,
3798
	
3799
		aContext = oMenu.cfg.getProperty(_CONTEXT),
3800
		nInitialMaxHeight = oMenu.cfg.getProperty(_MAX_HEIGHT),
3801
3802
		nMaxHeight,
3803
3804
		oOverlapPositions = {
3805
3806
			"trbr": true,
3807
			"tlbl": true,
3808
			"bltl": true,
3809
			"brtr": true
3810
3811
		},
3812
3813
		bPotentialContextOverlap = (aContext && oOverlapPositions[aContext[1] + aContext[2]]),
3814
	
3815
		oMenuEl = oMenu.element,
3816
		nMenuOffsetHeight = oMenuEl.offsetHeight,
3817
	
3818
		nViewportOffset = Overlay.VIEWPORT_OFFSET,
3819
		viewPortHeight = Dom.getViewportHeight(),
3820
		scrollY = Dom.getDocumentScrollTop(),
3821
3822
		bCanConstrain = 
3823
			(oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT) + nViewportOffset < viewPortHeight),
3824
3825
		nAvailableHeight,
3826
3827
		oContextEl,
3828
		nContextElY,
3829
		nContextElHeight,
3830
3831
		bFlipped = false,
3832
3833
		nTopRegionHeight,
3834
		nBottomRegionHeight,
3835
3836
		topConstraint = scrollY + nViewportOffset,
3837
		bottomConstraint = scrollY + viewPortHeight - nMenuOffsetHeight - nViewportOffset,
3838
3839
		yNew = y;
3840
		
3841
3842
	var flipVertical = function () {
3843
3844
		var nNewY;
3845
	
3846
		// The Menu is below the context element, flip it above
3847
		if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) { 
3848
			nNewY = (nContextElY - nMenuOffsetHeight);
3849
		}
3850
		else {	// The Menu is above the context element, flip it below
3851
			nNewY = (nContextElY + nContextElHeight);
3852
		}
3853
3854
		oMenu.cfg.setProperty(_Y, (nNewY + scrollY), true);
3855
		
3856
		return nNewY;
3857
	
3858
	};
3859
3860
3861
	/*
3862
		 Uses the context element's position to calculate the availble height 
3863
		 above and below it to display its corresponding Menu.
3864
	*/
3865
3866
	var getDisplayRegionHeight = function () {
3867
3868
		// The Menu is below the context element
3869
		if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
3870
			return (nBottomRegionHeight - nViewportOffset);				
3871
		}
3872
		else {	// The Menu is above the context element
3873
			return (nTopRegionHeight - nViewportOffset);				
3874
		}
3875
3876
	};
3877
3878
3879
	/*
3880
		Sets the Menu's "y" configuration property to the correct value based on its
3881
		current orientation.
3882
	*/ 
3883
3884
	var alignY = function () {
3885
3886
		var nNewY;
3887
3888
		if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) { 
3889
			nNewY = (nContextElY + nContextElHeight);
3890
		}
3891
		else {	
3892
			nNewY = (nContextElY - oMenuEl.offsetHeight);
3893
		}
3894
3895
		oMenu.cfg.setProperty(_Y, (nNewY + scrollY), true);
3896
	
3897
	};
3898
3899
3900
	//	Resets the maxheight of the Menu to the value set by the user
3901
3902
	var resetMaxHeight = function () {
3903
3904
		oMenu._setScrollHeight(this.cfg.getProperty(_MAX_HEIGHT));
3905
3906
		oMenu.hideEvent.unsubscribe(resetMaxHeight);
3907
	
3908
	};
3909
3910
3911
	/*
3912
		Trys to place the Menu in the best possible position (either above or 
3913
		below its corresponding context element).
3914
	*/
3915
3916
	var setVerticalPosition = function () {
3917
3918
		var nDisplayRegionHeight = getDisplayRegionHeight(),
3919
			bMenuHasItems = (oMenu.getItems().length > 0),
3920
			nMenuMinScrollHeight,
3921
			fnReturnVal;
3922
3923
3924
		if (nMenuOffsetHeight > nDisplayRegionHeight) {
3925
3926
			nMenuMinScrollHeight = 
3927
				bMenuHasItems ? oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT) : nMenuOffsetHeight;
3928
3929
3930
			if ((nDisplayRegionHeight > nMenuMinScrollHeight) && bMenuHasItems) {
3931
				nMaxHeight = nDisplayRegionHeight;
3932
			}
3933
			else {
3934
				nMaxHeight = nInitialMaxHeight;
3935
			}
3936
3937
3938
			oMenu._setScrollHeight(nMaxHeight);
3939
			oMenu.hideEvent.subscribe(resetMaxHeight);
3940
			
3941
3942
			// Re-align the Menu since its height has just changed
3943
			// as a result of the setting of the maxheight property.
3944
3945
			alignY();
3946
			
3947
3948
			if (nDisplayRegionHeight < nMenuMinScrollHeight) {
3949
3950
				if (bFlipped) {
3951
	
3952
					/*
3953
						 All possible positions and values for the "maxheight" 
3954
						 configuration property have been tried, but none were 
3955
						 successful, so fall back to the original size and position.
3956
					*/
3957
3958
					flipVertical();
3959
					
3960
				}
3961
				else {
3962
	
3963
					flipVertical();
3964
3965
					bFlipped = true;
3966
	
3967
					fnReturnVal = setVerticalPosition();
3968
	
3969
				}
3970
				
3971
			}
3972
		
3973
		}
3974
		else if (nMaxHeight && (nMaxHeight !== nInitialMaxHeight)) {
3975
		
3976
			oMenu._setScrollHeight(nInitialMaxHeight);
3977
			oMenu.hideEvent.subscribe(resetMaxHeight);
3978
3979
			// Re-align the Menu since its height has just changed
3980
			// as a result of the setting of the maxheight property.
3981
3982
			alignY();
3983
		
3984
		}
3985
3986
		return fnReturnVal;
3987
3988
	};
3989
3990
3991
	// Determine if the current value for the Menu's "y" configuration property will
3992
	// result in the Menu being positioned outside the boundaries of the viewport
3993
3994
	if (y < topConstraint || y  > bottomConstraint) {
3995
3996
		// The current value for the Menu's "y" configuration property WILL
3997
		// result in the Menu being positioned outside the boundaries of the viewport
3998
3999
		if (bCanConstrain) {
4000
4001
			if (oMenu.cfg.getProperty(_PREVENT_CONTEXT_OVERLAP) && bPotentialContextOverlap) {
4002
		
4003
				//	SOLUTION #1:
4004
				//	If the "preventcontextoverlap" configuration property is set to "true", 
4005
				//	try to flip and/or scroll the Menu to both keep it inside the boundaries of the 
4006
				//	viewport AND from overlaping its context element (MenuItem or MenuBarItem).
4007
4008
				oContextEl = aContext[0];
4009
				nContextElHeight = oContextEl.offsetHeight;
4010
				nContextElY = (Dom.getY(oContextEl) - scrollY);
4011
	
4012
				nTopRegionHeight = nContextElY;
4013
				nBottomRegionHeight = (viewPortHeight - (nContextElY + nContextElHeight));
4014
	
4015
				setVerticalPosition();
4016
				
4017
				yNew = oMenu.cfg.getProperty(_Y);
4018
		
4019
			}
4020
			else if (!(oMenu instanceof YAHOO.widget.MenuBar) && 
4021
				nMenuOffsetHeight >= viewPortHeight) {
4022
4023
				//	SOLUTION #2:
4024
				//	If the Menu exceeds the height of the viewport, introduce scroll bars
4025
				//	to keep the Menu inside the boundaries of the viewport
4026
4027
				nAvailableHeight = (viewPortHeight - (nViewportOffset * 2));
4028
		
4029
				if (nAvailableHeight > oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT)) {
4030
		
4031
					oMenu._setScrollHeight(nAvailableHeight);
4032
					oMenu.hideEvent.subscribe(resetMaxHeight);
4033
		
4034
					alignY();
4035
					
4036
					yNew = oMenu.cfg.getProperty(_Y);
4037
				
4038
				}
4039
		
4040
			}	
4041
			else {
4042
4043
				//	SOLUTION #3:
4044
			
4045
				if (y < topConstraint) {
4046
					yNew  = topConstraint;
4047
				} else if (y  > bottomConstraint) {
4048
					yNew  = bottomConstraint;
4049
				}				
4050
			
4051
			}
4052
4053
		}
4054
		else {
4055
			//	The "y" configuration property cannot be set to a value that will keep
4056
			//	entire Menu inside the boundary of the viewport.  Therefore, set  
4057
			//	the "y" configuration property to scrollY to keep as much of the 
4058
			//	Menu inside the viewport as possible.
4059
			yNew = nViewportOffset + scrollY;
4060
		}	
4061
4062
	}
4063
4064
	return yNew;
4065
4066
},
4067
4068
4069
/**
4070
* @method _onHide
4071
* @description "hide" event handler for the menu.
4072
* @private
4073
* @param {String} p_sType String representing the name of the event that 
4074
* was fired.
4075
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4076
*/
4077
_onHide: function (p_sType, p_aArgs) {
4078
4079
	if (this.cfg.getProperty(_POSITION) === _DYNAMIC) {
4080
	
4081
		this.positionOffScreen();
4082
	
4083
	}
4084
4085
},
4086
4087
4088
/**
4089
* @method _onShow
4090
* @description "show" event handler for the menu.
4091
* @private
4092
* @param {String} p_sType String representing the name of the event that 
4093
* was fired.
4094
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4095
*/
4096
_onShow: function (p_sType, p_aArgs) {
4097
4098
    var oParent = this.parent,
4099
        oParentMenu,
4100
		oElement,
4101
		nOffsetWidth,
4102
		sWidth;        
4103
4104
4105
    function disableAutoSubmenuDisplay(p_oEvent) {
4106
4107
        var oTarget;
4108
4109
        if (p_oEvent.type == _MOUSEDOWN || (p_oEvent.type == _KEYDOWN && p_oEvent.keyCode == 27)) {
4110
4111
            /*  
4112
                Set the "autosubmenudisplay" to "false" if the user
4113
                clicks outside the menu bar.
4114
            */
4115
4116
            oTarget = Event.getTarget(p_oEvent);
4117
4118
            if (oTarget != oParentMenu.element || !Dom.isAncestor(oParentMenu.element, oTarget)) {
4119
4120
                oParentMenu.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, false);
4121
4122
                Event.removeListener(document, _MOUSEDOWN, disableAutoSubmenuDisplay);
4123
                Event.removeListener(document, _KEYDOWN, disableAutoSubmenuDisplay);
4124
4125
            }
4126
        
4127
        }
4128
4129
    }
4130
4131
4132
	function onSubmenuHide(p_sType, p_aArgs, p_sWidth) {
4133
	
4134
		this.cfg.setProperty(_WIDTH, _EMPTY_STRING);
4135
		this.hideEvent.unsubscribe(onSubmenuHide, p_sWidth);
4136
	
4137
	}
4138
4139
4140
    if (oParent) {
4141
4142
        oParentMenu = oParent.parent;
4143
4144
4145
        if (!oParentMenu.cfg.getProperty(_AUTO_SUBMENU_DISPLAY) && 
4146
            (oParentMenu instanceof YAHOO.widget.MenuBar || 
4147
            oParentMenu.cfg.getProperty(_POSITION) == _STATIC)) {
4148
4149
            oParentMenu.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, true);
4150
4151
            Event.on(document, _MOUSEDOWN, disableAutoSubmenuDisplay);                             
4152
            Event.on(document, _KEYDOWN, disableAutoSubmenuDisplay);
4153
4154
        }
4155
4156
4157
		//	The following fixes an issue with the selected state of a MenuItem 
4158
		//	not rendering correctly when a submenu is aligned to the left of
4159
		//	its parent Menu instance.
4160
4161
		if ((this.cfg.getProperty("x") < oParentMenu.cfg.getProperty("x")) && 
4162
			(UA.gecko && UA.gecko < 1.9) && !this.cfg.getProperty(_WIDTH)) {
4163
4164
			oElement = this.element;
4165
			nOffsetWidth = oElement.offsetWidth;
4166
			
4167
			/*
4168
				Measuring the difference of the offsetWidth before and after
4169
				setting the "width" style attribute allows us to compute the 
4170
				about of padding and borders applied to the element, which in 
4171
				turn allows us to set the "width" property correctly.
4172
			*/
4173
			
4174
			oElement.style.width = nOffsetWidth + _PX;
4175
			
4176
			sWidth = (nOffsetWidth - (oElement.offsetWidth - nOffsetWidth)) + _PX;
4177
			
4178
			this.cfg.setProperty(_WIDTH, sWidth);
4179
		
4180
			this.hideEvent.subscribe(onSubmenuHide, sWidth);
4181
		
4182
		}
4183
4184
    }
4185
4186
4187
	/*
4188
		Dynamically positioned, root Menus focus themselves when visible, and 
4189
		will then, when hidden, restore focus to the UI control that had focus 
4190
		before the Menu was made visible.
4191
	*/ 
4192
4193
	if (this === this.getRoot() && this.cfg.getProperty(_POSITION) === _DYNAMIC) {
4194
4195
		this._focusedElement = oFocusedElement;
4196
		
4197
		this.focus();
4198
	
4199
	}
4200
4201
4202
},
4203
4204
4205
/**
4206
* @method _onBeforeHide
4207
* @description "beforehide" event handler for the menu.
4208
* @private
4209
* @param {String} p_sType String representing the name of the event that 
4210
* was fired.
4211
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4212
*/
4213
_onBeforeHide: function (p_sType, p_aArgs) {
4214
4215
    var oActiveItem = this.activeItem,
4216
        oRoot = this.getRoot(),
4217
        oConfig,
4218
        oSubmenu;
4219
4220
4221
    if (oActiveItem) {
4222
4223
        oConfig = oActiveItem.cfg;
4224
4225
        oConfig.setProperty(_SELECTED, false);
4226
4227
        oSubmenu = oConfig.getProperty(_SUBMENU);
4228
4229
        if (oSubmenu) {
4230
4231
            oSubmenu.hide();
4232
4233
        }
4234
4235
    }
4236
4237
4238
	/*
4239
		Focus can get lost in IE when the mouse is moving from a submenu back to its parent Menu.  
4240
		For this reason, it is necessary to maintain the focused state in a private property 
4241
		so that the _onMouseOver event handler is able to determined whether or not to set focus
4242
		to MenuItems as the user is moving the mouse.
4243
	*/ 
4244
4245
	if (UA.ie && this.cfg.getProperty(_POSITION) === _DYNAMIC && this.parent) {
4246
4247
		oRoot._hasFocus = this.hasFocus();
4248
	
4249
	}
4250
4251
4252
    if (oRoot == this) {
4253
4254
        oRoot.blur();
4255
    
4256
    }
4257
4258
},
4259
4260
4261
/**
4262
* @method _onParentMenuConfigChange
4263
* @description "configchange" event handler for a submenu.
4264
* @private
4265
* @param {String} p_sType String representing the name of the event that 
4266
* was fired.
4267
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4268
* @param {YAHOO.widget.Menu} p_oSubmenu Object representing the submenu that 
4269
* subscribed to the event.
4270
*/
4271
_onParentMenuConfigChange: function (p_sType, p_aArgs, p_oSubmenu) {
4272
    
4273
    var sPropertyName = p_aArgs[0][0],
4274
        oPropertyValue = p_aArgs[0][1];
4275
4276
    switch(sPropertyName) {
4277
4278
        case _IFRAME:
4279
        case _CONSTRAIN_TO_VIEWPORT:
4280
        case _HIDE_DELAY:
4281
        case _SHOW_DELAY:
4282
        case _SUBMENU_HIDE_DELAY:
4283
        case _CLICK_TO_HIDE:
4284
        case _EFFECT:
4285
        case _CLASSNAME:
4286
        case _SCROLL_INCREMENT:
4287
        case _MAX_HEIGHT:
4288
        case _MIN_SCROLL_HEIGHT:
4289
        case _MONITOR_RESIZE:
4290
        case _SHADOW:
4291
        case _PREVENT_CONTEXT_OVERLAP:
4292
		case _KEEP_OPEN:
4293
4294
            p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue);
4295
                
4296
        break;
4297
        
4298
        case _SUBMENU_ALIGNMENT:
4299
4300
			if (!(this.parent.parent instanceof YAHOO.widget.MenuBar)) {
4301
		
4302
				p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue);
4303
		
4304
			}
4305
        
4306
        break;
4307
        
4308
    }
4309
    
4310
},
4311
4312
4313
/**
4314
* @method _onParentMenuRender
4315
* @description "render" event handler for a submenu.  Renders a  
4316
* submenu in response to the firing of its parent's "render" event.
4317
* @private
4318
* @param {String} p_sType String representing the name of the event that 
4319
* was fired.
4320
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4321
* @param {YAHOO.widget.Menu} p_oSubmenu Object representing the submenu that 
4322
* subscribed to the event.
4323
*/
4324
_onParentMenuRender: function (p_sType, p_aArgs, p_oSubmenu) {
4325
4326
    var oParentMenu = p_oSubmenu.parent.parent,
4327
    	oParentCfg = oParentMenu.cfg,
4328
4329
        oConfig = {
4330
4331
            constraintoviewport: oParentCfg.getProperty(_CONSTRAIN_TO_VIEWPORT),
4332
4333
            xy: [0,0],
4334
4335
            clicktohide: oParentCfg.getProperty(_CLICK_TO_HIDE),
4336
                
4337
            effect: oParentCfg.getProperty(_EFFECT),
4338
4339
            showdelay: oParentCfg.getProperty(_SHOW_DELAY),
4340
            
4341
            hidedelay: oParentCfg.getProperty(_HIDE_DELAY),
4342
4343
            submenuhidedelay: oParentCfg.getProperty(_SUBMENU_HIDE_DELAY),
4344
4345
            classname: oParentCfg.getProperty(_CLASSNAME),
4346
            
4347
            scrollincrement: oParentCfg.getProperty(_SCROLL_INCREMENT),
4348
            
4349
			maxheight: oParentCfg.getProperty(_MAX_HEIGHT),
4350
4351
            minscrollheight: oParentCfg.getProperty(_MIN_SCROLL_HEIGHT),
4352
            
4353
            iframe: oParentCfg.getProperty(_IFRAME),
4354
            
4355
            shadow: oParentCfg.getProperty(_SHADOW),
4356
4357
			preventcontextoverlap: oParentCfg.getProperty(_PREVENT_CONTEXT_OVERLAP),
4358
            
4359
            monitorresize: oParentCfg.getProperty(_MONITOR_RESIZE),
4360
4361
			keepopen: oParentCfg.getProperty(_KEEP_OPEN)
4362
4363
        },
4364
        
4365
        oLI;
4366
4367
4368
	
4369
	if (!(oParentMenu instanceof YAHOO.widget.MenuBar)) {
4370
4371
		oConfig[_SUBMENU_ALIGNMENT] = oParentCfg.getProperty(_SUBMENU_ALIGNMENT);
4372
4373
	}
4374
4375
4376
    p_oSubmenu.cfg.applyConfig(oConfig);
4377
4378
4379
    if (!this.lazyLoad) {
4380
4381
        oLI = this.parent.element;
4382
4383
        if (this.element.parentNode == oLI) {
4384
    
4385
            this.render();
4386
    
4387
        }
4388
        else {
4389
4390
            this.render(oLI);
4391
    
4392
        }
4393
4394
    }
4395
    
4396
},
4397
4398
4399
/**
4400
* @method _onMenuItemDestroy
4401
* @description "destroy" event handler for the menu's items.
4402
* @private
4403
* @param {String} p_sType String representing the name of the event 
4404
* that was fired.
4405
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4406
* @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item 
4407
* that fired the event.
4408
*/
4409
_onMenuItemDestroy: function (p_sType, p_aArgs, p_oItem) {
4410
4411
    this._removeItemFromGroupByValue(p_oItem.groupIndex, p_oItem);
4412
4413
},
4414
4415
4416
/**
4417
* @method _onMenuItemConfigChange
4418
* @description "configchange" event handler for the menu's items.
4419
* @private
4420
* @param {String} p_sType String representing the name of the event that 
4421
* was fired.
4422
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4423
* @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item 
4424
* that fired the event.
4425
*/
4426
_onMenuItemConfigChange: function (p_sType, p_aArgs, p_oItem) {
4427
4428
    var sPropertyName = p_aArgs[0][0],
4429
        oPropertyValue = p_aArgs[0][1],
4430
        oSubmenu;
4431
4432
4433
    switch(sPropertyName) {
4434
4435
        case _SELECTED:
4436
4437
            if (oPropertyValue === true) {
4438
4439
                this.activeItem = p_oItem;
4440
            
4441
            }
4442
4443
        break;
4444
4445
        case _SUBMENU:
4446
4447
            oSubmenu = p_aArgs[0][1];
4448
4449
            if (oSubmenu) {
4450
4451
                this._configureSubmenu(p_oItem);
4452
4453
            }
4454
4455
        break;
4456
4457
    }
4458
4459
},
4460
4461
4462
4463
// Public event handlers for configuration properties
4464
4465
4466
/**
4467
* @method configVisible
4468
* @description Event handler for when the "visible" configuration property 
4469
* the menu changes.
4470
* @param {String} p_sType String representing the name of the event that 
4471
* was fired.
4472
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4473
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
4474
* fired the event.
4475
*/
4476
configVisible: function (p_sType, p_aArgs, p_oMenu) {
4477
4478
    var bVisible,
4479
        sDisplay;
4480
4481
    if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
4482
4483
        Menu.superclass.configVisible.call(this, p_sType, p_aArgs, p_oMenu);
4484
4485
    }
4486
    else {
4487
4488
        bVisible = p_aArgs[0];
4489
        sDisplay = Dom.getStyle(this.element, _DISPLAY);
4490
4491
        Dom.setStyle(this.element, _VISIBILITY, _VISIBLE);
4492
4493
        if (bVisible) {
4494
4495
            if (sDisplay != _BLOCK) {
4496
                this.beforeShowEvent.fire();
4497
                Dom.setStyle(this.element, _DISPLAY, _BLOCK);
4498
                this.showEvent.fire();
4499
            }
4500
        
4501
        }
4502
        else {
4503
4504
			if (sDisplay == _BLOCK) {
4505
				this.beforeHideEvent.fire();
4506
				Dom.setStyle(this.element, _DISPLAY, _NONE);
4507
				this.hideEvent.fire();
4508
			}
4509
        
4510
        }
4511
4512
    }
4513
4514
},
4515
4516
4517
/**
4518
* @method configPosition
4519
* @description Event handler for when the "position" configuration property 
4520
* of the menu changes.
4521
* @param {String} p_sType String representing the name of the event that 
4522
* was fired.
4523
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4524
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
4525
* fired the event.
4526
*/
4527
configPosition: function (p_sType, p_aArgs, p_oMenu) {
4528
4529
    var oElement = this.element,
4530
        sCSSPosition = p_aArgs[0] == _STATIC ? _STATIC : _ABSOLUTE,
4531
        oCfg = this.cfg,
4532
        nZIndex;
4533
4534
4535
    Dom.setStyle(oElement, _POSITION, sCSSPosition);
4536
4537
4538
    if (sCSSPosition == _STATIC) {
4539
4540
        // Statically positioned menus are visible by default
4541
        
4542
        Dom.setStyle(oElement, _DISPLAY, _BLOCK);
4543
4544
        oCfg.setProperty(_VISIBLE, true);
4545
4546
    }
4547
    else {
4548
4549
        /*
4550
            Even though the "visible" property is queued to 
4551
            "false" by default, we need to set the "visibility" property to 
4552
            "hidden" since Overlay's "configVisible" implementation checks the 
4553
            element's "visibility" style property before deciding whether 
4554
            or not to show an Overlay instance.
4555
        */
4556
4557
        Dom.setStyle(oElement, _VISIBILITY, _HIDDEN);
4558
    
4559
    }
4560
4561
  	 
4562
     if (sCSSPosition == _ABSOLUTE) { 	 
4563
  	 
4564
         nZIndex = oCfg.getProperty(_ZINDEX);
4565
  	 
4566
         if (!nZIndex || nZIndex === 0) { 	 
4567
  	 
4568
             oCfg.setProperty(_ZINDEX, 1); 	 
4569
  	 
4570
         } 	 
4571
  	 
4572
     }
4573
4574
},
4575
4576
4577
/**
4578
* @method configIframe
4579
* @description Event handler for when the "iframe" configuration property of 
4580
* the menu changes.
4581
* @param {String} p_sType String representing the name of the event that 
4582
* was fired.
4583
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4584
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
4585
* fired the event.
4586
*/
4587
configIframe: function (p_sType, p_aArgs, p_oMenu) {    
4588
4589
    if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
4590
4591
        Menu.superclass.configIframe.call(this, p_sType, p_aArgs, p_oMenu);
4592
4593
    }
4594
4595
},
4596
4597
4598
/**
4599
* @method configHideDelay
4600
* @description Event handler for when the "hidedelay" configuration property 
4601
* of the menu changes.
4602
* @param {String} p_sType String representing the name of the event that 
4603
* was fired.
4604
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4605
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
4606
* fired the event.
4607
*/
4608
configHideDelay: function (p_sType, p_aArgs, p_oMenu) {
4609
4610
    var nHideDelay = p_aArgs[0];
4611
4612
	this._useHideDelay = (nHideDelay > 0);
4613
4614
},
4615
4616
4617
/**
4618
* @method configContainer
4619
* @description Event handler for when the "container" configuration property 
4620
* of the menu changes.
4621
* @param {String} p_sType String representing the name of the event that 
4622
* was fired.
4623
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4624
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that 
4625
* fired the event.
4626
*/
4627
configContainer: function (p_sType, p_aArgs, p_oMenu) {
4628
4629
	var oElement = p_aArgs[0];
4630
4631
	if (Lang.isString(oElement)) {
4632
4633
        this.cfg.setProperty(_CONTAINER, Dom.get(oElement), true);
4634
4635
	}
4636
4637
},
4638
4639
4640
/**
4641
* @method _clearSetWidthFlag
4642
* @description Change event listener for the "width" configuration property.  This listener is 
4643
* added when a Menu's "width" configuration property is set by the "_setScrollHeight" method, and 
4644
* is used to set the "_widthSetForScroll" property to "false" if the "width" configuration property 
4645
* is changed after it was set by the "_setScrollHeight" method.  If the "_widthSetForScroll" 
4646
* property is set to "false", and the "_setScrollHeight" method is in the process of tearing down 
4647
* scrolling functionality, it will maintain the Menu's new width rather than reseting it.
4648
* @private
4649
*/
4650
_clearSetWidthFlag: function () {
4651
4652
	this._widthSetForScroll = false;
4653
	
4654
	this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4655
4656
},
4657
4658
4659
/**
4660
* @method _setScrollHeight
4661
* @description 
4662
* @param {String} p_nScrollHeight Number representing the scrolling height of the Menu.
4663
* @private
4664
*/
4665
_setScrollHeight: function (p_nScrollHeight) {
4666
4667
    var nScrollHeight = p_nScrollHeight,
4668
		bRefireIFrameAndShadow = false,
4669
		bSetWidth = false,
4670
        oElement,
4671
        oBody,
4672
        oHeader,
4673
        oFooter,
4674
        fnMouseOver,
4675
        fnMouseOut,
4676
        nMinScrollHeight,
4677
        nHeight,
4678
        nOffsetWidth,
4679
        sWidth;
4680
4681
4682
	if (this.getItems().length > 0) {
4683
	
4684
        oElement = this.element;
4685
        oBody = this.body;
4686
        oHeader = this.header;
4687
        oFooter = this.footer;
4688
        fnMouseOver = this._onScrollTargetMouseOver;
4689
        fnMouseOut = this._onScrollTargetMouseOut;
4690
        nMinScrollHeight = this.cfg.getProperty(_MIN_SCROLL_HEIGHT);
4691
4692
4693
		if (nScrollHeight > 0 && nScrollHeight < nMinScrollHeight) {
4694
		
4695
			nScrollHeight = nMinScrollHeight;
4696
		
4697
		}
4698
4699
4700
		Dom.setStyle(oBody, _HEIGHT, _EMPTY_STRING);
4701
		Dom.removeClass(oBody, _YUI_MENU_BODY_SCROLLED);
4702
		oBody.scrollTop = 0;
4703
4704
4705
		//	Need to set a width for the Menu to fix the following problems in 
4706
		//	Firefox 2 and IE:
4707
4708
		//	#1) Scrolled Menus will render at 1px wide in Firefox 2
4709
4710
		//	#2) There is a bug in gecko-based browsers where an element whose 
4711
		//	"position" property is set to "absolute" and "overflow" property is 
4712
		//	set to "hidden" will not render at the correct width when its 
4713
		//	offsetParent's "position" property is also set to "absolute."  It is 
4714
		//	possible to work around this bug by specifying a value for the width 
4715
		//	property in addition to overflow.
4716
4717
		//	#3) In IE it is necessary to give the Menu a width before the 
4718
		//	scrollbars are rendered to prevent the Menu from rendering with a 
4719
		//	width that is 100% of the browser viewport.
4720
	
4721
		bSetWidth = ((UA.gecko && UA.gecko < 1.9) || UA.ie);
4722
4723
		if (nScrollHeight > 0 && bSetWidth && !this.cfg.getProperty(_WIDTH)) {
4724
4725
			nOffsetWidth = oElement.offsetWidth;
4726
	
4727
			/*
4728
				Measuring the difference of the offsetWidth before and after
4729
				setting the "width" style attribute allows us to compute the 
4730
				about of padding and borders applied to the element, which in 
4731
				turn allows us to set the "width" property correctly.
4732
			*/
4733
			
4734
			oElement.style.width = nOffsetWidth + _PX;
4735
	
4736
			sWidth = (nOffsetWidth - (oElement.offsetWidth - nOffsetWidth)) + _PX;
4737
4738
4739
			this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4740
4741
4742
			this.cfg.setProperty(_WIDTH, sWidth);
4743
4744
4745
			/*
4746
				Set a flag (_widthSetForScroll) to maintain some history regarding how the 
4747
				"width" configuration property was set.  If the "width" configuration property 
4748
				is set by something other than the "_setScrollHeight" method, it will be 
4749
				necessary to maintain that new value and not clear the width if scrolling 
4750
				is turned off.
4751
			*/
4752
4753
			this._widthSetForScroll = true;
4754
4755
			this.cfg.subscribeToConfigEvent(_WIDTH, this._clearSetWidthFlag);
4756
	
4757
		}
4758
	
4759
	
4760
		if (nScrollHeight > 0 && (!oHeader && !oFooter)) {
4761
	
4762
	
4763
			this.setHeader(_NON_BREAKING_SPACE);
4764
			this.setFooter(_NON_BREAKING_SPACE);
4765
	
4766
			oHeader = this.header;
4767
			oFooter = this.footer;
4768
	
4769
			Dom.addClass(oHeader, _TOP_SCROLLBAR);
4770
			Dom.addClass(oFooter, _BOTTOM_SCROLLBAR);
4771
			
4772
			oElement.insertBefore(oHeader, oBody);
4773
			oElement.appendChild(oFooter);
4774
		
4775
		}
4776
	
4777
	
4778
		nHeight = nScrollHeight;
4779
	
4780
	
4781
		if (oHeader && oFooter) {
4782
			nHeight = (nHeight - (oHeader.offsetHeight + oFooter.offsetHeight));
4783
		}
4784
	
4785
	
4786
		if ((nHeight > 0) && (oBody.offsetHeight > nScrollHeight)) {
4787
4788
	
4789
			Dom.addClass(oBody, _YUI_MENU_BODY_SCROLLED);
4790
			Dom.setStyle(oBody, _HEIGHT, (nHeight + _PX));
4791
4792
			if (!this._hasScrollEventHandlers) {
4793
	
4794
				Event.on(oHeader, _MOUSEOVER, fnMouseOver, this, true);
4795
				Event.on(oHeader, _MOUSEOUT, fnMouseOut, this, true);
4796
				Event.on(oFooter, _MOUSEOVER, fnMouseOver, this, true);
4797
				Event.on(oFooter, _MOUSEOUT, fnMouseOut, this, true);
4798
	
4799
				this._hasScrollEventHandlers = true;
4800
	
4801
			}
4802
	
4803
			this._disableScrollHeader();
4804
			this._enableScrollFooter();
4805
			
4806
			bRefireIFrameAndShadow = true;			
4807
	
4808
		}
4809
		else if (oHeader && oFooter) {
4810
4811
	
4812
4813
			/*
4814
				Only clear the "width" configuration property if it was set the
4815
				"_setScrollHeight" method and wasn't changed by some other means after it was set.
4816
			*/	
4817
	
4818
			if (this._widthSetForScroll) {
4819
	
4820
4821
				this._widthSetForScroll = false;
4822
4823
				this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4824
	
4825
				this.cfg.setProperty(_WIDTH, _EMPTY_STRING);
4826
			
4827
			}
4828
	
4829
	
4830
			this._enableScrollHeader();
4831
			this._enableScrollFooter();
4832
	
4833
			if (this._hasScrollEventHandlers) {
4834
	
4835
				Event.removeListener(oHeader, _MOUSEOVER, fnMouseOver);
4836
				Event.removeListener(oHeader, _MOUSEOUT, fnMouseOut);
4837
				Event.removeListener(oFooter, _MOUSEOVER, fnMouseOver);
4838
				Event.removeListener(oFooter, _MOUSEOUT, fnMouseOut);
4839
4840
				this._hasScrollEventHandlers = false;
4841
	
4842
			}
4843
4844
			oElement.removeChild(oHeader);
4845
			oElement.removeChild(oFooter);
4846
	
4847
			this.header = null;
4848
			this.footer = null;
4849
			
4850
			bRefireIFrameAndShadow = true;
4851
		
4852
		}
4853
4854
4855
		if (bRefireIFrameAndShadow) {
4856
	
4857
			this.cfg.refireEvent(_IFRAME);
4858
			this.cfg.refireEvent(_SHADOW);
4859
		
4860
		}
4861
	
4862
	}
4863
4864
},
4865
4866
4867
/**
4868
* @method _setMaxHeight
4869
* @description "renderEvent" handler used to defer the setting of the 
4870
* "maxheight" configuration property until the menu is rendered in lazy 
4871
* load scenarios.
4872
* @param {String} p_sType The name of the event that was fired.
4873
* @param {Array} p_aArgs Collection of arguments sent when the event 
4874
* was fired.
4875
* @param {Number} p_nMaxHeight Number representing the value to set for the 
4876
* "maxheight" configuration property.
4877
* @private
4878
*/
4879
_setMaxHeight: function (p_sType, p_aArgs, p_nMaxHeight) {
4880
4881
    this._setScrollHeight(p_nMaxHeight);
4882
    this.renderEvent.unsubscribe(this._setMaxHeight);
4883
4884
},
4885
4886
4887
/**
4888
* @method configMaxHeight
4889
* @description Event handler for when the "maxheight" configuration property of 
4890
* a Menu changes.
4891
* @param {String} p_sType The name of the event that was fired.
4892
* @param {Array} p_aArgs Collection of arguments sent when the event 
4893
* was fired.
4894
* @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired
4895
* the event.
4896
*/
4897
configMaxHeight: function (p_sType, p_aArgs, p_oMenu) {
4898
4899
	var nMaxHeight = p_aArgs[0];
4900
4901
	if (this.lazyLoad && !this.body && nMaxHeight > 0) {
4902
	
4903
		this.renderEvent.subscribe(this._setMaxHeight, nMaxHeight, this);
4904
4905
	}
4906
	else {
4907
4908
		this._setScrollHeight(nMaxHeight);
4909
	
4910
	}
4911
4912
},
4913
4914
4915
/**
4916
* @method configClassName
4917
* @description Event handler for when the "classname" configuration property of 
4918
* a menu changes.
4919
* @param {String} p_sType The name of the event that was fired.
4920
* @param {Array} p_aArgs Collection of arguments sent when the event was fired.
4921
* @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
4922
*/
4923
configClassName: function (p_sType, p_aArgs, p_oMenu) {
4924
4925
    var sClassName = p_aArgs[0];
4926
4927
    if (this._sClassName) {
4928
4929
        Dom.removeClass(this.element, this._sClassName);
4930
4931
    }
4932
4933
    Dom.addClass(this.element, sClassName);
4934
    this._sClassName = sClassName;
4935
4936
},
4937
4938
4939
/**
4940
* @method _onItemAdded
4941
* @description "itemadded" event handler for a Menu instance.
4942
* @private
4943
* @param {String} p_sType The name of the event that was fired.
4944
* @param {Array} p_aArgs Collection of arguments sent when the event 
4945
* was fired.
4946
*/
4947
_onItemAdded: function (p_sType, p_aArgs) {
4948
4949
    var oItem = p_aArgs[0];
4950
    
4951
    if (oItem) {
4952
4953
        oItem.cfg.setProperty(_DISABLED, true);
4954
    
4955
    }
4956
4957
},
4958
4959
4960
/**
4961
* @method configDisabled
4962
* @description Event handler for when the "disabled" configuration property of 
4963
* a menu changes.
4964
* @param {String} p_sType The name of the event that was fired.
4965
* @param {Array} p_aArgs Collection of arguments sent when the event was fired.
4966
* @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
4967
*/
4968
configDisabled: function (p_sType, p_aArgs, p_oMenu) {
4969
4970
    var bDisabled = p_aArgs[0],
4971
        aItems = this.getItems(),
4972
        nItems,
4973
        i;
4974
4975
    if (Lang.isArray(aItems)) {
4976
4977
        nItems = aItems.length;
4978
    
4979
        if (nItems > 0) {
4980
        
4981
            i = nItems - 1;
4982
    
4983
            do {
4984
    
4985
                aItems[i].cfg.setProperty(_DISABLED, bDisabled);
4986
            
4987
            }
4988
            while (i--);
4989
        
4990
        }
4991
4992
4993
        if (bDisabled) {
4994
4995
            this.clearActiveItem(true);
4996
4997
            Dom.addClass(this.element, _DISABLED);
4998
4999
            this.itemAddedEvent.subscribe(this._onItemAdded);
5000
5001
        }
5002
        else {
5003
5004
            Dom.removeClass(this.element, _DISABLED);
5005
5006
            this.itemAddedEvent.unsubscribe(this._onItemAdded);
5007
5008
        }
5009
        
5010
    }
5011
5012
},
5013
5014
5015
/**
5016
* @method configShadow
5017
* @description Event handler for when the "shadow" configuration property of 
5018
* a menu changes.
5019
* @param {String} p_sType The name of the event that was fired.
5020
* @param {Array} p_aArgs Collection of arguments sent when the event was fired.
5021
* @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
5022
*/
5023
configShadow: function (p_sType, p_aArgs, p_oMenu) {
5024
5025
    var sizeShadow = function () {
5026
5027
        var oElement = this.element,
5028
            oShadow = this._shadow;
5029
    
5030
        if (oShadow && oElement) {
5031
5032
			// Clear the previous width
5033
5034
			if (oShadow.style.width && oShadow.style.height) {
5035
			
5036
				oShadow.style.width = _EMPTY_STRING;
5037
				oShadow.style.height = _EMPTY_STRING;
5038
			
5039
			}
5040
5041
            oShadow.style.width = (oElement.offsetWidth + 6) + _PX;
5042
            oShadow.style.height = (oElement.offsetHeight + 1) + _PX;
5043
            
5044
        }
5045
    
5046
    };
5047
5048
5049
    var replaceShadow = function () {
5050
5051
        this.element.appendChild(this._shadow);
5052
5053
    };
5054
5055
5056
    var addShadowVisibleClass = function () {
5057
    
5058
        Dom.addClass(this._shadow, _YUI_MENU_SHADOW_VISIBLE);
5059
    
5060
    };
5061
    
5062
5063
    var removeShadowVisibleClass = function () {
5064
5065
        Dom.removeClass(this._shadow, _YUI_MENU_SHADOW_VISIBLE);
5066
    
5067
    };
5068
5069
5070
    var createShadow = function () {
5071
5072
        var oShadow = this._shadow,
5073
            oElement;
5074
5075
        if (!oShadow) {
5076
5077
            oElement = this.element;
5078
5079
5080
            if (!m_oShadowTemplate) {
5081
5082
                m_oShadowTemplate = document.createElement(_DIV_LOWERCASE);
5083
                m_oShadowTemplate.className = _YUI_MENU_SHADOW_YUI_MENU_SHADOW_VISIBLE;
5084
            
5085
            }
5086
5087
            oShadow = m_oShadowTemplate.cloneNode(false);
5088
5089
            oElement.appendChild(oShadow);
5090
            
5091
            this._shadow = oShadow;
5092
5093
            this.beforeShowEvent.subscribe(addShadowVisibleClass);
5094
            this.beforeHideEvent.subscribe(removeShadowVisibleClass);
5095
5096
5097
            if (UA.ie) {
5098
        
5099
                /*
5100
                     Need to call sizeShadow & syncIframe via setTimeout for 
5101
                     IE 7 Quirks Mode and IE 6 Standards Mode and Quirks Mode 
5102
                     or the shadow and iframe shim will not be sized and 
5103
                     positioned properly.
5104
                */
5105
        
5106
				Lang.later(0, this, function () {
5107
5108
                    sizeShadow.call(this); 
5109
                    this.syncIframe();
5110
				
5111
				});
5112
5113
5114
                this.cfg.subscribeToConfigEvent(_WIDTH, sizeShadow);
5115
                this.cfg.subscribeToConfigEvent(_HEIGHT, sizeShadow);
5116
                this.cfg.subscribeToConfigEvent(_MAX_HEIGHT, sizeShadow);
5117
                this.changeContentEvent.subscribe(sizeShadow);
5118
5119
                Module.textResizeEvent.subscribe(sizeShadow, this, true);
5120
                
5121
                this.destroyEvent.subscribe(function () {
5122
                
5123
                    Module.textResizeEvent.unsubscribe(sizeShadow, this);
5124
                
5125
                });
5126
        
5127
            }
5128
5129
            this.cfg.subscribeToConfigEvent(_MAX_HEIGHT, replaceShadow);
5130
5131
        }
5132
5133
    };
5134
5135
5136
    var onBeforeShow = function () {
5137
5138
    	if (this._shadow) {
5139
5140
			// If called because the "shadow" event was refired - just append again and resize
5141
			
5142
			replaceShadow.call(this);
5143
			
5144
			if (UA.ie) {
5145
				sizeShadow.call(this);
5146
			}
5147
    	
5148
    	}
5149
    	else {
5150
    
5151
        	createShadow.call(this);
5152
        
5153
        }
5154
5155
        this.beforeShowEvent.unsubscribe(onBeforeShow);
5156
    
5157
    };
5158
5159
5160
	var bShadow = p_aArgs[0];
5161
5162
5163
    if (bShadow && this.cfg.getProperty(_POSITION) == _DYNAMIC) {
5164
5165
        if (this.cfg.getProperty(_VISIBLE)) {
5166
5167
			if (this._shadow) {
5168
5169
				// If the "shadow" event was refired - just append again and resize
5170
				
5171
				replaceShadow.call(this);
5172
				
5173
				if (UA.ie) {
5174
					sizeShadow.call(this);
5175
				}
5176
				
5177
			} 
5178
			else {
5179
            	createShadow.call(this);
5180
            }
5181
        
5182
        }
5183
        else {
5184
5185
            this.beforeShowEvent.subscribe(onBeforeShow);
5186
        
5187
        }
5188
    
5189
    }
5190
    
5191
},
5192
5193
5194
5195
// Public methods
5196
5197
5198
/**
5199
* @method initEvents
5200
* @description Initializes the custom events for the menu.
5201
*/
5202
initEvents: function () {
5203
5204
	Menu.superclass.initEvents.call(this);
5205
5206
    // Create custom events
5207
5208
	var i = EVENT_TYPES.length - 1,
5209
		aEventData,
5210
		oCustomEvent;
5211
5212
5213
	do {
5214
5215
		aEventData = EVENT_TYPES[i];
5216
5217
		oCustomEvent = this.createEvent(aEventData[1]);
5218
		oCustomEvent.signature = CustomEvent.LIST;
5219
		
5220
		this[aEventData[0]] = oCustomEvent;
5221
5222
	}
5223
	while (i--);
5224
5225
},
5226
5227
5228
/**
5229
* @method positionOffScreen
5230
* @description Positions the menu outside of the boundaries of the browser's 
5231
* viewport.  Called automatically when a menu is hidden to ensure that 
5232
* it doesn't force the browser to render uncessary scrollbars.
5233
*/
5234
positionOffScreen: function () {
5235
5236
    var oIFrame = this.iframe,
5237
    	oElement = this.element,
5238
        sPos = this.OFF_SCREEN_POSITION;
5239
    
5240
    oElement.style.top = _EMPTY_STRING;
5241
    oElement.style.left = _EMPTY_STRING;
5242
    
5243
    if (oIFrame) {
5244
5245
		oIFrame.style.top = sPos;
5246
		oIFrame.style.left = sPos;
5247
    
5248
    }
5249
5250
},
5251
5252
5253
/**
5254
* @method getRoot
5255
* @description Finds the menu's root menu.
5256
*/
5257
getRoot: function () {
5258
5259
    var oItem = this.parent,
5260
        oParentMenu,
5261
        returnVal;
5262
5263
    if (oItem) {
5264
5265
        oParentMenu = oItem.parent;
5266
5267
        returnVal = oParentMenu ? oParentMenu.getRoot() : this;
5268
5269
    }
5270
    else {
5271
    
5272
        returnVal = this;
5273
    
5274
    }
5275
    
5276
    return returnVal;
5277
5278
},
5279
5280
5281
/**
5282
* @method toString
5283
* @description Returns a string representing the menu.
5284
* @return {String}
5285
*/
5286
toString: function () {
5287
5288
    var sReturnVal = _MENU,
5289
        sId = this.id;
5290
5291
    if (sId) {
5292
5293
        sReturnVal += (_SPACE + sId);
5294
    
5295
    }
5296
5297
    return sReturnVal;
5298
5299
},
5300
5301
5302
/**
5303
* @method setItemGroupTitle
5304
* @description Sets the title of a group of menu items.
5305
* @param {String} p_sGroupTitle String specifying the title of the group.
5306
* @param {Number} p_nGroupIndex Optional. Number specifying the group to which
5307
* the title belongs.
5308
*/
5309
setItemGroupTitle: function (p_sGroupTitle, p_nGroupIndex) {
5310
5311
    var nGroupIndex,
5312
        oTitle,
5313
        i,
5314
        nFirstIndex;
5315
        
5316
    if (Lang.isString(p_sGroupTitle) && p_sGroupTitle.length > 0) {
5317
5318
        nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0;
5319
        oTitle = this._aGroupTitleElements[nGroupIndex];
5320
5321
5322
        if (oTitle) {
5323
5324
            oTitle.innerHTML = p_sGroupTitle;
5325
            
5326
        }
5327
        else {
5328
5329
            oTitle = document.createElement(this.GROUP_TITLE_TAG_NAME);
5330
                    
5331
            oTitle.innerHTML = p_sGroupTitle;
5332
5333
            this._aGroupTitleElements[nGroupIndex] = oTitle;
5334
5335
        }
5336
5337
5338
        i = this._aGroupTitleElements.length - 1;
5339
5340
        do {
5341
5342
            if (this._aGroupTitleElements[i]) {
5343
5344
                Dom.removeClass(this._aGroupTitleElements[i], _FIRST_OF_TYPE);
5345
5346
                nFirstIndex = i;
5347
5348
            }
5349
5350
        }
5351
        while (i--);
5352
5353
5354
        if (nFirstIndex !== null) {
5355
5356
            Dom.addClass(this._aGroupTitleElements[nFirstIndex], 
5357
                _FIRST_OF_TYPE);
5358
5359
        }
5360
5361
        this.changeContentEvent.fire();
5362
5363
    }
5364
5365
},
5366
5367
5368
5369
/**
5370
* @method addItem
5371
* @description Appends an item to the menu.
5372
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem 
5373
* instance to be added to the menu.
5374
* @param {String} p_oItem String specifying the text of the item to be added 
5375
* to the menu.
5376
* @param {Object} p_oItem Object literal containing a set of menu item 
5377
* configuration properties.
5378
* @param {Number} p_nGroupIndex Optional. Number indicating the group to
5379
* which the item belongs.
5380
* @return {YAHOO.widget.MenuItem}
5381
*/
5382
addItem: function (p_oItem, p_nGroupIndex) {
5383
5384
	return this._addItemToGroup(p_nGroupIndex, p_oItem);
5385
5386
},
5387
5388
5389
/**
5390
* @method addItems
5391
* @description Adds an array of items to the menu.
5392
* @param {Array} p_aItems Array of items to be added to the menu.  The array 
5393
* can contain strings specifying the text for each item to be created, object
5394
* literals specifying each of the menu item configuration properties, 
5395
* or MenuItem instances.
5396
* @param {Number} p_nGroupIndex Optional. Number specifying the group to 
5397
* which the items belongs.
5398
* @return {Array}
5399
*/
5400
addItems: function (p_aItems, p_nGroupIndex) {
5401
5402
    var nItems,
5403
        aItems,
5404
        oItem,
5405
        i,
5406
        returnVal;
5407
5408
5409
    if (Lang.isArray(p_aItems)) {
5410
5411
        nItems = p_aItems.length;
5412
        aItems = [];
5413
5414
        for(i=0; i<nItems; i++) {
5415
5416
            oItem = p_aItems[i];
5417
5418
            if (oItem) {
5419
5420
                if (Lang.isArray(oItem)) {
5421
    
5422
                    aItems[aItems.length] = this.addItems(oItem, i);
5423
    
5424
                }
5425
                else {
5426
    
5427
                    aItems[aItems.length] = this._addItemToGroup(p_nGroupIndex, oItem);
5428
                
5429
                }
5430
5431
            }
5432
    
5433
        }
5434
5435
5436
        if (aItems.length) {
5437
        
5438
            returnVal = aItems;
5439
        
5440
        }
5441
5442
    }
5443
5444
	return returnVal;
5445
5446
},
5447
5448
5449
/**
5450
* @method insertItem
5451
* @description Inserts an item into the menu at the specified index.
5452
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem 
5453
* instance to be added to the menu.
5454
* @param {String} p_oItem String specifying the text of the item to be added 
5455
* to the menu.
5456
* @param {Object} p_oItem Object literal containing a set of menu item 
5457
* configuration properties.
5458
* @param {Number} p_nItemIndex Number indicating the ordinal position at which
5459
* the item should be added.
5460
* @param {Number} p_nGroupIndex Optional. Number indicating the group to which 
5461
* the item belongs.
5462
* @return {YAHOO.widget.MenuItem}
5463
*/
5464
insertItem: function (p_oItem, p_nItemIndex, p_nGroupIndex) {
5465
    
5466
	return this._addItemToGroup(p_nGroupIndex, p_oItem, p_nItemIndex);
5467
5468
},
5469
5470
5471
/**
5472
* @method removeItem
5473
* @description Removes the specified item from the menu.
5474
* @param {YAHOO.widget.MenuItem} p_oObject Object reference for the MenuItem 
5475
* instance to be removed from the menu.
5476
* @param {Number} p_oObject Number specifying the index of the item 
5477
* to be removed.
5478
* @param {Number} p_nGroupIndex Optional. Number specifying the group to 
5479
* which the item belongs.
5480
* @return {YAHOO.widget.MenuItem}
5481
*/
5482
removeItem: function (p_oObject, p_nGroupIndex) {
5483
5484
    var oItem,
5485
    	returnVal;
5486
    
5487
    if (!Lang.isUndefined(p_oObject)) {
5488
5489
        if (p_oObject instanceof YAHOO.widget.MenuItem) {
5490
5491
            oItem = this._removeItemFromGroupByValue(p_nGroupIndex, p_oObject);           
5492
5493
        }
5494
        else if (Lang.isNumber(p_oObject)) {
5495
5496
            oItem = this._removeItemFromGroupByIndex(p_nGroupIndex, p_oObject);
5497
5498
        }
5499
5500
        if (oItem) {
5501
5502
            oItem.destroy();
5503
5504
5505
            returnVal = oItem;
5506
5507
        }
5508
5509
    }
5510
5511
	return returnVal;
5512
5513
},
5514
5515
5516
/**
5517
* @method getItems
5518
* @description Returns an array of all of the items in the menu.
5519
* @return {Array}
5520
*/
5521
getItems: function () {
5522
5523
    var aGroups = this._aItemGroups,
5524
        nGroups,
5525
        returnVal,
5526
        aItems = [];
5527
5528
5529
    if (Lang.isArray(aGroups)) {
5530
5531
        nGroups = aGroups.length;
5532
5533
        returnVal = ((nGroups == 1) ? aGroups[0] : (Array.prototype.concat.apply(aItems, aGroups)));
5534
5535
    }
5536
5537
	return returnVal;
5538
5539
},
5540
5541
5542
/**
5543
* @method getItemGroups
5544
* @description Multi-dimensional Array representing the menu items as they 
5545
* are grouped in the menu.
5546
* @return {Array}
5547
*/        
5548
getItemGroups: function () {
5549
5550
    return this._aItemGroups;
5551
5552
},
5553
5554
5555
/**
5556
* @method getItem
5557
* @description Returns the item at the specified index.
5558
* @param {Number} p_nItemIndex Number indicating the ordinal position of the 
5559
* item to be retrieved.
5560
* @param {Number} p_nGroupIndex Optional. Number indicating the group to which 
5561
* the item belongs.
5562
* @return {YAHOO.widget.MenuItem}
5563
*/
5564
getItem: function (p_nItemIndex, p_nGroupIndex) {
5565
    
5566
    var aGroup,
5567
    	returnVal;
5568
    
5569
    if (Lang.isNumber(p_nItemIndex)) {
5570
5571
        aGroup = this._getItemGroup(p_nGroupIndex);
5572
5573
        if (aGroup) {
5574
5575
            returnVal = aGroup[p_nItemIndex];
5576
        
5577
        }
5578
5579
    }
5580
    
5581
    return returnVal;
5582
    
5583
},
5584
5585
5586
/**
5587
* @method getSubmenus
5588
* @description Returns an array of all of the submenus that are immediate 
5589
* children of the menu.
5590
* @return {Array}
5591
*/
5592
getSubmenus: function () {
5593
5594
    var aItems = this.getItems(),
5595
        nItems = aItems.length,
5596
        aSubmenus,
5597
        oSubmenu,
5598
        oItem,
5599
        i;
5600
5601
5602
    if (nItems > 0) {
5603
        
5604
        aSubmenus = [];
5605
5606
        for(i=0; i<nItems; i++) {
5607
5608
            oItem = aItems[i];
5609
            
5610
            if (oItem) {
5611
5612
                oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5613
                
5614
                if (oSubmenu) {
5615
5616
                    aSubmenus[aSubmenus.length] = oSubmenu;
5617
5618
                }
5619
            
5620
            }
5621
        
5622
        }
5623
    
5624
    }
5625
5626
    return aSubmenus;
5627
5628
},
5629
5630
5631
/**
5632
* @method clearContent
5633
* @description Removes all of the content from the menu, including the menu 
5634
* items, group titles, header and footer.
5635
*/
5636
clearContent: function () {
5637
5638
    var aItems = this.getItems(),
5639
        nItems = aItems.length,
5640
        oElement = this.element,
5641
        oBody = this.body,
5642
        oHeader = this.header,
5643
        oFooter = this.footer,
5644
        oItem,
5645
        oSubmenu,
5646
        i;
5647
5648
5649
    if (nItems > 0) {
5650
5651
        i = nItems - 1;
5652
5653
        do {
5654
5655
            oItem = aItems[i];
5656
5657
            if (oItem) {
5658
5659
                oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5660
5661
                if (oSubmenu) {
5662
5663
                    this.cfg.configChangedEvent.unsubscribe(
5664
                        this._onParentMenuConfigChange, oSubmenu);
5665
5666
                    this.renderEvent.unsubscribe(this._onParentMenuRender, 
5667
                        oSubmenu);
5668
5669
                }
5670
                
5671
                this.removeItem(oItem, oItem.groupIndex);
5672
5673
            }
5674
        
5675
        }
5676
        while (i--);
5677
5678
    }
5679
5680
5681
    if (oHeader) {
5682
5683
        Event.purgeElement(oHeader);
5684
        oElement.removeChild(oHeader);
5685
5686
    }
5687
    
5688
5689
    if (oFooter) {
5690
5691
        Event.purgeElement(oFooter);
5692
        oElement.removeChild(oFooter);
5693
    }
5694
5695
5696
    if (oBody) {
5697
5698
        Event.purgeElement(oBody);
5699
5700
        oBody.innerHTML = _EMPTY_STRING;
5701
5702
    }
5703
5704
    this.activeItem = null;
5705
5706
    this._aItemGroups = [];
5707
    this._aListElements = [];
5708
    this._aGroupTitleElements = [];
5709
5710
    this.cfg.setProperty(_WIDTH, null);
5711
5712
},
5713
5714
5715
/**
5716
* @method destroy
5717
* @description Removes the menu's <code>&#60;div&#62;</code> element 
5718
* (and accompanying child nodes) from the document.
5719
*/
5720
destroy: function () {
5721
5722
    // Remove all items
5723
5724
    this.clearContent();
5725
5726
    this._aItemGroups = null;
5727
    this._aListElements = null;
5728
    this._aGroupTitleElements = null;
5729
5730
5731
    // Continue with the superclass implementation of this method
5732
5733
    Menu.superclass.destroy.call(this);
5734
    
5735
5736
},
5737
5738
5739
/**
5740
* @method setInitialFocus
5741
* @description Sets focus to the menu's first enabled item.
5742
*/
5743
setInitialFocus: function () {
5744
5745
    var oItem = this._getFirstEnabledItem();
5746
    
5747
    if (oItem) {
5748
5749
        oItem.focus();
5750
5751
    }
5752
    
5753
},
5754
5755
5756
/**
5757
* @method setInitialSelection
5758
* @description Sets the "selected" configuration property of the menu's first 
5759
* enabled item to "true."
5760
*/
5761
setInitialSelection: function () {
5762
5763
    var oItem = this._getFirstEnabledItem();
5764
    
5765
    if (oItem) {
5766
    
5767
        oItem.cfg.setProperty(_SELECTED, true);
5768
    }        
5769
5770
},
5771
5772
5773
/**
5774
* @method clearActiveItem
5775
* @description Sets the "selected" configuration property of the menu's active
5776
* item to "false" and hides the item's submenu.
5777
* @param {Boolean} p_bBlur Boolean indicating if the menu's active item 
5778
* should be blurred.  
5779
*/
5780
clearActiveItem: function (p_bBlur) {
5781
5782
    if (this.cfg.getProperty(_SHOW_DELAY) > 0) {
5783
    
5784
        this._cancelShowDelay();
5785
    
5786
    }
5787
5788
5789
    var oActiveItem = this.activeItem,
5790
        oConfig,
5791
        oSubmenu;
5792
5793
    if (oActiveItem) {
5794
5795
        oConfig = oActiveItem.cfg;
5796
5797
        if (p_bBlur) {
5798
5799
            oActiveItem.blur();
5800
            
5801
            this.getRoot()._hasFocus = true;
5802
        
5803
        }
5804
5805
        oConfig.setProperty(_SELECTED, false);
5806
5807
        oSubmenu = oConfig.getProperty(_SUBMENU);
5808
5809
5810
        if (oSubmenu) {
5811
5812
            oSubmenu.hide();
5813
5814
        }
5815
5816
        this.activeItem = null;  
5817
5818
    }
5819
5820
},
5821
5822
5823
/**
5824
* @method focus
5825
* @description Causes the menu to receive focus and fires the "focus" event.
5826
*/
5827
focus: function () {
5828
5829
    if (!this.hasFocus()) {
5830
5831
        this.setInitialFocus();
5832
    
5833
    }
5834
5835
},
5836
5837
5838
/**
5839
* @method blur
5840
* @description Causes the menu to lose focus and fires the "blur" event.
5841
*/    
5842
blur: function () {
5843
5844
    var oItem;
5845
5846
    if (this.hasFocus()) {
5847
    
5848
        oItem = MenuManager.getFocusedMenuItem();
5849
        
5850
        if (oItem) {
5851
5852
            oItem.blur();
5853
5854
        }
5855
5856
    }
5857
5858
},
5859
5860
5861
/**
5862
* @method hasFocus
5863
* @description Returns a boolean indicating whether or not the menu has focus.
5864
* @return {Boolean}
5865
*/
5866
hasFocus: function () {
5867
5868
    return (MenuManager.getFocusedMenu() == this.getRoot());
5869
5870
},
5871
5872
5873
_doItemSubmenuSubscribe: function (p_sType, p_aArgs, p_oObject) {
5874
5875
    var oItem = p_aArgs[0],
5876
        oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5877
5878
    if (oSubmenu) {
5879
        oSubmenu.subscribe.apply(oSubmenu, p_oObject);
5880
    }
5881
5882
},
5883
5884
5885
_doSubmenuSubscribe: function (p_sType, p_aArgs, p_oObject) { 
5886
5887
    var oSubmenu = this.cfg.getProperty(_SUBMENU);
5888
    
5889
    if (oSubmenu) {
5890
        oSubmenu.subscribe.apply(oSubmenu, p_oObject);
5891
    }
5892
5893
},
5894
5895
5896
/**
5897
* Adds the specified CustomEvent subscriber to the menu and each of 
5898
* its submenus.
5899
* @method subscribe
5900
* @param p_type     {string}   the type, or name of the event
5901
* @param p_fn       {function} the function to exectute when the event fires
5902
* @param p_obj      {Object}   An object to be passed along when the event 
5903
*                              fires
5904
* @param p_override {boolean}  If true, the obj passed in becomes the 
5905
*                              execution scope of the listener
5906
*/
5907
subscribe: function () {
5908
5909
	//	Subscribe to the event for this Menu instance
5910
    Menu.superclass.subscribe.apply(this, arguments);
5911
5912
	//	Subscribe to the "itemAdded" event so that all future submenus
5913
	//	also subscribe to this event
5914
    Menu.superclass.subscribe.call(this, _ITEM_ADDED, this._doItemSubmenuSubscribe, arguments);
5915
5916
5917
    var aItems = this.getItems(),
5918
        nItems,
5919
        oItem,
5920
        oSubmenu,
5921
        i;
5922
        
5923
5924
    if (aItems) {
5925
5926
        nItems = aItems.length;
5927
        
5928
        if (nItems > 0) {
5929
        
5930
            i = nItems - 1;
5931
            
5932
            do {
5933
5934
                oItem = aItems[i];
5935
                oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5936
                
5937
                if (oSubmenu) {
5938
                    oSubmenu.subscribe.apply(oSubmenu, arguments);
5939
                }
5940
                else {
5941
                    oItem.cfg.subscribeToConfigEvent(_SUBMENU, this._doSubmenuSubscribe, arguments);
5942
                }
5943
5944
            }
5945
            while (i--);
5946
        
5947
        }
5948
5949
    }
5950
5951
},
5952
5953
5954
unsubscribe: function () {
5955
5956
	//	Remove the event for this Menu instance
5957
    Menu.superclass.unsubscribe.apply(this, arguments);
5958
5959
	//	Remove the "itemAdded" event so that all future submenus don't have 
5960
	//	the event handler
5961
    Menu.superclass.unsubscribe.call(this, _ITEM_ADDED, this._doItemSubmenuSubscribe, arguments);
5962
5963
5964
    var aItems = this.getItems(),
5965
        nItems,
5966
        oItem,
5967
        oSubmenu,
5968
        i;
5969
        
5970
5971
    if (aItems) {
5972
5973
        nItems = aItems.length;
5974
        
5975
        if (nItems > 0) {
5976
        
5977
            i = nItems - 1;
5978
            
5979
            do {
5980
5981
                oItem = aItems[i];
5982
                oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5983
                
5984
                if (oSubmenu) {
5985
                    oSubmenu.unsubscribe.apply(oSubmenu, arguments);
5986
                }
5987
                else {
5988
                    oItem.cfg.unsubscribeFromConfigEvent(_SUBMENU, this._doSubmenuSubscribe, arguments);
5989
                }
5990
5991
            }
5992
            while (i--);
5993
        
5994
        }
5995
5996
    }
5997
5998
},
5999
6000
6001
/**
6002
* @description Initializes the class's configurable properties which can be
6003
* changed using the menu's Config object ("cfg").
6004
* @method initDefaultConfig
6005
*/
6006
initDefaultConfig: function () {
6007
6008
    Menu.superclass.initDefaultConfig.call(this);
6009
6010
    var oConfig = this.cfg;
6011
6012
6013
    // Module documentation overrides
6014
6015
    /**
6016
    * @config effect
6017
    * @description Object or array of objects representing the ContainerEffect 
6018
    * classes that are active for animating the container.  When set this 
6019
    * property is automatically applied to all submenus.
6020
    * @type Object
6021
    * @default null
6022
    */
6023
6024
    // Overlay documentation overrides
6025
6026
6027
    /**
6028
    * @config x
6029
    * @description Number representing the absolute x-coordinate position of 
6030
    * the Menu.  This property is only applied when the "position" 
6031
    * configuration property is set to dynamic.
6032
    * @type Number
6033
    * @default null
6034
    */
6035
    
6036
6037
    /**
6038
    * @config y
6039
    * @description Number representing the absolute y-coordinate position of 
6040
    * the Menu.  This property is only applied when the "position" 
6041
    * configuration property is set to dynamic.
6042
    * @type Number
6043
    * @default null
6044
    */
6045
6046
6047
    /**
6048
    * @description Array of the absolute x and y positions of the Menu.  This 
6049
    * property is only applied when the "position" configuration property is 
6050
    * set to dynamic.
6051
    * @config xy
6052
    * @type Number[]
6053
    * @default null
6054
    */
6055
    
6056
6057
    /**
6058
    * @config context
6059
    * @description Array of context arguments for context-sensitive positioning.  
6060
    * The format is: [id or element, element corner, context corner]. 
6061
    * For example, setting this property to ["img1", "tl", "bl"] would 
6062
    * align the Menu's top left corner to the context element's 
6063
    * bottom left corner.  This property is only applied when the "position" 
6064
    * configuration property is set to dynamic.
6065
    * @type Array
6066
    * @default null
6067
    */
6068
    
6069
    
6070
    /**
6071
    * @config fixedcenter
6072
    * @description Boolean indicating if the Menu should be anchored to the 
6073
    * center of the viewport.  This property is only applied when the 
6074
    * "position" configuration property is set to dynamic.
6075
    * @type Boolean
6076
    * @default false
6077
    */
6078
    
6079
    
6080
    /**
6081
    * @config iframe
6082
    * @description Boolean indicating whether or not the Menu should 
6083
    * have an IFRAME shim; used to prevent SELECT elements from 
6084
    * poking through an Overlay instance in IE6.  When set to "true", 
6085
    * the iframe shim is created when the Menu instance is intially
6086
    * made visible.  This property is only applied when the "position" 
6087
    * configuration property is set to dynamic and is automatically applied 
6088
    * to all submenus.
6089
    * @type Boolean
6090
    * @default true for IE6 and below, false for all other browsers.
6091
    */
6092
6093
6094
	// Add configuration attributes
6095
6096
    /*
6097
        Change the default value for the "visible" configuration 
6098
        property to "false" by re-adding the property.
6099
    */
6100
6101
    /**
6102
    * @config visible
6103
    * @description Boolean indicating whether or not the menu is visible.  If 
6104
    * the menu's "position" configuration property is set to "dynamic" (the 
6105
    * default), this property toggles the menu's <code>&#60;div&#62;</code> 
6106
    * element's "visibility" style property between "visible" (true) or 
6107
    * "hidden" (false).  If the menu's "position" configuration property is 
6108
    * set to "static" this property toggles the menu's 
6109
    * <code>&#60;div&#62;</code> element's "display" style property 
6110
    * between "block" (true) or "none" (false).
6111
    * @default false
6112
    * @type Boolean
6113
    */
6114
    oConfig.addProperty(
6115
        VISIBLE_CONFIG.key, 
6116
        {
6117
            handler: this.configVisible, 
6118
            value: VISIBLE_CONFIG.value, 
6119
            validator: VISIBLE_CONFIG.validator
6120
        }
6121
     );
6122
6123
6124
    /*
6125
        Change the default value for the "constraintoviewport" configuration 
6126
        property (inherited by YAHOO.widget.Overlay) to "true" by re-adding the property.
6127
    */
6128
6129
    /**
6130
    * @config constraintoviewport
6131
    * @description Boolean indicating if the menu will try to remain inside 
6132
    * the boundaries of the size of viewport.  This property is only applied 
6133
    * when the "position" configuration property is set to dynamic and is 
6134
    * automatically applied to all submenus.
6135
    * @default true
6136
    * @type Boolean
6137
    */
6138
    oConfig.addProperty(
6139
        CONSTRAIN_TO_VIEWPORT_CONFIG.key, 
6140
        {
6141
            handler: this.configConstrainToViewport, 
6142
            value: CONSTRAIN_TO_VIEWPORT_CONFIG.value, 
6143
            validator: CONSTRAIN_TO_VIEWPORT_CONFIG.validator, 
6144
            supercedes: CONSTRAIN_TO_VIEWPORT_CONFIG.supercedes 
6145
        } 
6146
    );
6147
6148
6149
    /*
6150
        Change the default value for the "preventcontextoverlap" configuration 
6151
        property (inherited by YAHOO.widget.Overlay) to "true" by re-adding the property.
6152
    */
6153
6154
	/**
6155
	* @config preventcontextoverlap
6156
	* @description Boolean indicating whether or not a submenu should overlap its parent MenuItem 
6157
	* when the "constraintoviewport" configuration property is set to "true".
6158
	* @type Boolean
6159
	* @default true
6160
	*/
6161
	oConfig.addProperty(PREVENT_CONTEXT_OVERLAP_CONFIG.key, {
6162
6163
		value: PREVENT_CONTEXT_OVERLAP_CONFIG.value, 
6164
		validator: PREVENT_CONTEXT_OVERLAP_CONFIG.validator, 
6165
		supercedes: PREVENT_CONTEXT_OVERLAP_CONFIG.supercedes
6166
6167
	});
6168
6169
6170
    /**
6171
    * @config position
6172
    * @description String indicating how a menu should be positioned on the 
6173
    * screen.  Possible values are "static" and "dynamic."  Static menus are 
6174
    * visible by default and reside in the normal flow of the document 
6175
    * (CSS position: static).  Dynamic menus are hidden by default, reside 
6176
    * out of the normal flow of the document (CSS position: absolute), and 
6177
    * can overlay other elements on the screen.
6178
    * @default dynamic
6179
    * @type String
6180
    */
6181
    oConfig.addProperty(
6182
        POSITION_CONFIG.key, 
6183
        {
6184
            handler: this.configPosition,
6185
            value: POSITION_CONFIG.value, 
6186
            validator: POSITION_CONFIG.validator,
6187
            supercedes: POSITION_CONFIG.supercedes
6188
        }
6189
    );
6190
6191
6192
    /**
6193
    * @config submenualignment
6194
    * @description Array defining how submenus should be aligned to their 
6195
    * parent menu item. The format is: [itemCorner, submenuCorner]. By default
6196
    * a submenu's top left corner is aligned to its parent menu item's top 
6197
    * right corner.
6198
    * @default ["tl","tr"]
6199
    * @type Array
6200
    */
6201
    oConfig.addProperty(
6202
        SUBMENU_ALIGNMENT_CONFIG.key, 
6203
        { 
6204
            value: SUBMENU_ALIGNMENT_CONFIG.value,
6205
            suppressEvent: SUBMENU_ALIGNMENT_CONFIG.suppressEvent
6206
        }
6207
    );
6208
6209
6210
    /**
6211
    * @config autosubmenudisplay
6212
    * @description Boolean indicating if submenus are automatically made 
6213
    * visible when the user mouses over the menu's items.
6214
    * @default true
6215
    * @type Boolean
6216
    */
6217
	oConfig.addProperty(
6218
	   AUTO_SUBMENU_DISPLAY_CONFIG.key, 
6219
	   { 
6220
	       value: AUTO_SUBMENU_DISPLAY_CONFIG.value, 
6221
	       validator: AUTO_SUBMENU_DISPLAY_CONFIG.validator,
6222
	       suppressEvent: AUTO_SUBMENU_DISPLAY_CONFIG.suppressEvent
6223
       } 
6224
    );
6225
6226
6227
    /**
6228
    * @config showdelay
6229
    * @description Number indicating the time (in milliseconds) that should 
6230
    * expire before a submenu is made visible when the user mouses over 
6231
    * the menu's items.  This property is only applied when the "position" 
6232
    * configuration property is set to dynamic and is automatically applied 
6233
    * to all submenus.
6234
    * @default 250
6235
    * @type Number
6236
    */
6237
	oConfig.addProperty(
6238
	   SHOW_DELAY_CONFIG.key, 
6239
	   { 
6240
	       value: SHOW_DELAY_CONFIG.value, 
6241
	       validator: SHOW_DELAY_CONFIG.validator,
6242
	       suppressEvent: SHOW_DELAY_CONFIG.suppressEvent
6243
       } 
6244
    );
6245
6246
6247
    /**
6248
    * @config hidedelay
6249
    * @description Number indicating the time (in milliseconds) that should 
6250
    * expire before the menu is hidden.  This property is only applied when 
6251
    * the "position" configuration property is set to dynamic and is 
6252
    * automatically applied to all submenus.
6253
    * @default 0
6254
    * @type Number
6255
    */
6256
	oConfig.addProperty(
6257
	   HIDE_DELAY_CONFIG.key, 
6258
	   { 
6259
	       handler: this.configHideDelay,
6260
	       value: HIDE_DELAY_CONFIG.value, 
6261
	       validator: HIDE_DELAY_CONFIG.validator, 
6262
	       suppressEvent: HIDE_DELAY_CONFIG.suppressEvent
6263
       } 
6264
    );
6265
6266
6267
    /**
6268
    * @config submenuhidedelay
6269
    * @description Number indicating the time (in milliseconds) that should 
6270
    * expire before a submenu is hidden when the user mouses out of a menu item 
6271
    * heading in the direction of a submenu.  The value must be greater than or 
6272
    * equal to the value specified for the "showdelay" configuration property.
6273
    * This property is only applied when the "position" configuration property 
6274
    * is set to dynamic and is automatically applied to all submenus.
6275
    * @default 250
6276
    * @type Number
6277
    */
6278
	oConfig.addProperty(
6279
	   SUBMENU_HIDE_DELAY_CONFIG.key, 
6280
	   { 
6281
	       value: SUBMENU_HIDE_DELAY_CONFIG.value, 
6282
	       validator: SUBMENU_HIDE_DELAY_CONFIG.validator,
6283
	       suppressEvent: SUBMENU_HIDE_DELAY_CONFIG.suppressEvent
6284
       } 
6285
    );
6286
6287
6288
    /**
6289
    * @config clicktohide
6290
    * @description Boolean indicating if the menu will automatically be 
6291
    * hidden if the user clicks outside of it.  This property is only 
6292
    * applied when the "position" configuration property is set to dynamic 
6293
    * and is automatically applied to all submenus.
6294
    * @default true
6295
    * @type Boolean
6296
    */
6297
    oConfig.addProperty(
6298
        CLICK_TO_HIDE_CONFIG.key,
6299
        {
6300
            value: CLICK_TO_HIDE_CONFIG.value,
6301
            validator: CLICK_TO_HIDE_CONFIG.validator,
6302
            suppressEvent: CLICK_TO_HIDE_CONFIG.suppressEvent
6303
        }
6304
    );
6305
6306
6307
	/**
6308
	* @config container
6309
	* @description HTML element reference or string specifying the id 
6310
	* attribute of the HTML element that the menu's markup should be 
6311
	* rendered into.
6312
	* @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
6313
	* level-one-html.html#ID-58190037">HTMLElement</a>|String
6314
	* @default document.body
6315
	*/
6316
	oConfig.addProperty(
6317
	   CONTAINER_CONFIG.key, 
6318
	   { 
6319
	       handler: this.configContainer,
6320
	       value: document.body,
6321
           suppressEvent: CONTAINER_CONFIG.suppressEvent
6322
       } 
6323
   );
6324
6325
6326
    /**
6327
    * @config scrollincrement
6328
    * @description Number used to control the scroll speed of a menu.  Used to 
6329
    * increment the "scrollTop" property of the menu's body by when a menu's 
6330
    * content is scrolling.  When set this property is automatically applied 
6331
    * to all submenus.
6332
    * @default 1
6333
    * @type Number
6334
    */
6335
    oConfig.addProperty(
6336
        SCROLL_INCREMENT_CONFIG.key, 
6337
        { 
6338
            value: SCROLL_INCREMENT_CONFIG.value, 
6339
            validator: SCROLL_INCREMENT_CONFIG.validator,
6340
            supercedes: SCROLL_INCREMENT_CONFIG.supercedes,
6341
            suppressEvent: SCROLL_INCREMENT_CONFIG.suppressEvent
6342
        }
6343
    );
6344
6345
6346
    /**
6347
    * @config minscrollheight
6348
    * @description Number defining the minimum threshold for the "maxheight" 
6349
    * configuration property.  When set this property is automatically applied 
6350
    * to all submenus.
6351
    * @default 90
6352
    * @type Number
6353
    */
6354
    oConfig.addProperty(
6355
        MIN_SCROLL_HEIGHT_CONFIG.key, 
6356
        { 
6357
            value: MIN_SCROLL_HEIGHT_CONFIG.value, 
6358
            validator: MIN_SCROLL_HEIGHT_CONFIG.validator,
6359
            supercedes: MIN_SCROLL_HEIGHT_CONFIG.supercedes,
6360
            suppressEvent: MIN_SCROLL_HEIGHT_CONFIG.suppressEvent
6361
        }
6362
    );
6363
6364
6365
    /**
6366
    * @config maxheight
6367
    * @description Number defining the maximum height (in pixels) for a menu's 
6368
    * body element (<code>&#60;div class="bd"&#62;</code>).  Once a menu's body 
6369
    * exceeds this height, the contents of the body are scrolled to maintain 
6370
    * this value.  This value cannot be set lower than the value of the 
6371
    * "minscrollheight" configuration property.
6372
    * @default 0
6373
    * @type Number
6374
    */
6375
    oConfig.addProperty(
6376
       MAX_HEIGHT_CONFIG.key, 
6377
       {
6378
            handler: this.configMaxHeight,
6379
            value: MAX_HEIGHT_CONFIG.value,
6380
            validator: MAX_HEIGHT_CONFIG.validator,
6381
            suppressEvent: MAX_HEIGHT_CONFIG.suppressEvent,
6382
            supercedes: MAX_HEIGHT_CONFIG.supercedes            
6383
       } 
6384
    );
6385
6386
6387
    /**
6388
    * @config classname
6389
    * @description String representing the CSS class to be applied to the 
6390
    * menu's root <code>&#60;div&#62;</code> element.  The specified class(es)  
6391
    * are appended in addition to the default class as specified by the menu's
6392
    * CSS_CLASS_NAME constant. When set this property is automatically 
6393
    * applied to all submenus.
6394
    * @default null
6395
    * @type String
6396
    */
6397
    oConfig.addProperty(
6398
        CLASS_NAME_CONFIG.key, 
6399
        { 
6400
            handler: this.configClassName,
6401
            value: CLASS_NAME_CONFIG.value, 
6402
            validator: CLASS_NAME_CONFIG.validator,
6403
            supercedes: CLASS_NAME_CONFIG.supercedes      
6404
        }
6405
    );
6406
6407
6408
    /**
6409
    * @config disabled
6410
    * @description Boolean indicating if the menu should be disabled.  
6411
    * Disabling a menu disables each of its items.  (Disabled menu items are 
6412
    * dimmed and will not respond to user input or fire events.)  Disabled
6413
    * menus have a corresponding "disabled" CSS class applied to their root
6414
    * <code>&#60;div&#62;</code> element.
6415
    * @default false
6416
    * @type Boolean
6417
    */
6418
    oConfig.addProperty(
6419
        DISABLED_CONFIG.key, 
6420
        { 
6421
            handler: this.configDisabled,
6422
            value: DISABLED_CONFIG.value, 
6423
            validator: DISABLED_CONFIG.validator,
6424
            suppressEvent: DISABLED_CONFIG.suppressEvent
6425
        }
6426
    );
6427
6428
6429
    /**
6430
    * @config shadow
6431
    * @description Boolean indicating if the menu should have a shadow.
6432
    * @default true
6433
    * @type Boolean
6434
    */
6435
    oConfig.addProperty(
6436
        SHADOW_CONFIG.key, 
6437
        { 
6438
            handler: this.configShadow,
6439
            value: SHADOW_CONFIG.value, 
6440
            validator: SHADOW_CONFIG.validator
6441
        }
6442
    );
6443
6444
6445
    /**
6446
    * @config keepopen
6447
    * @description Boolean indicating if the menu should remain open when clicked.
6448
    * @default false
6449
    * @type Boolean
6450
    */
6451
    oConfig.addProperty(
6452
        KEEP_OPEN_CONFIG.key, 
6453
        { 
6454
            value: KEEP_OPEN_CONFIG.value, 
6455
            validator: KEEP_OPEN_CONFIG.validator
6456
        }
6457
    );
6458
6459
}
6460
6461
}); // END YAHOO.lang.extend
6462
6463
})();
6464
6465
6466
6467
(function () {
6468
6469
/**
6470
* Creates an item for a menu.
6471
* 
6472
* @param {String} p_oObject String specifying the text of the menu item.
6473
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6474
* one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying 
6475
* the <code>&#60;li&#62;</code> element of the menu item.
6476
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6477
* one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object 
6478
* specifying the <code>&#60;optgroup&#62;</code> element of the menu item.
6479
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6480
* one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object 
6481
* specifying the <code>&#60;option&#62;</code> element of the menu item.
6482
* @param {Object} p_oConfig Optional. Object literal specifying the 
6483
* configuration for the menu item. See configuration class documentation 
6484
* for more details.
6485
* @class MenuItem
6486
* @constructor
6487
*/
6488
YAHOO.widget.MenuItem = function (p_oObject, p_oConfig) {
6489
6490
    if (p_oObject) {
6491
6492
        if (p_oConfig) {
6493
    
6494
            this.parent = p_oConfig.parent;
6495
            this.value = p_oConfig.value;
6496
            this.id = p_oConfig.id;
6497
6498
        }
6499
6500
        this.init(p_oObject, p_oConfig);
6501
6502
    }
6503
6504
};
6505
6506
6507
var Dom = YAHOO.util.Dom,
6508
    Module = YAHOO.widget.Module,
6509
    Menu = YAHOO.widget.Menu,
6510
    MenuItem = YAHOO.widget.MenuItem,
6511
    CustomEvent = YAHOO.util.CustomEvent,
6512
    UA = YAHOO.env.ua,
6513
    Lang = YAHOO.lang,
6514
6515
	// Private string constants
6516
6517
	_TEXT = "text",
6518
	_HASH = "#",
6519
	_HYPHEN = "-",
6520
	_HELP_TEXT = "helptext",
6521
	_URL = "url",
6522
	_TARGET = "target",
6523
	_EMPHASIS = "emphasis",
6524
	_STRONG_EMPHASIS = "strongemphasis",
6525
	_CHECKED = "checked",
6526
	_SUBMENU = "submenu",
6527
	_DISABLED = "disabled",
6528
	_SELECTED = "selected",
6529
	_HAS_SUBMENU = "hassubmenu",
6530
	_CHECKED_DISABLED = "checked-disabled",
6531
	_HAS_SUBMENU_DISABLED = "hassubmenu-disabled",
6532
	_HAS_SUBMENU_SELECTED = "hassubmenu-selected",
6533
	_CHECKED_SELECTED = "checked-selected",
6534
	_ONCLICK = "onclick",
6535
	_CLASSNAME = "classname",
6536
	_EMPTY_STRING = "",
6537
	_OPTION = "OPTION",
6538
	_OPTGROUP = "OPTGROUP",
6539
	_LI_UPPERCASE = "LI",
6540
	_HREF = "href",
6541
	_SELECT = "SELECT",
6542
	_DIV = "DIV",
6543
	_START_HELP_TEXT = "<em class=\"helptext\">",
6544
	_START_EM = "<em>",
6545
	_END_EM = "</em>",
6546
	_START_STRONG = "<strong>",
6547
	_END_STRONG = "</strong>",
6548
	_PREVENT_CONTEXT_OVERLAP = "preventcontextoverlap",
6549
	_OBJ = "obj",
6550
	_SCOPE = "scope",
6551
	_NONE = "none",
6552
	_VISIBLE = "visible",
6553
	_SPACE = " ",
6554
	_MENUITEM = "MenuItem",
6555
	_CLICK = "click",
6556
	_SHOW = "show",
6557
	_HIDE = "hide",
6558
	_LI_LOWERCASE = "li",
6559
	_ANCHOR_TEMPLATE = "<a href=\"#\"></a>",
6560
6561
    EVENT_TYPES = [
6562
    
6563
        ["mouseOverEvent", "mouseover"],
6564
        ["mouseOutEvent", "mouseout"],
6565
        ["mouseDownEvent", "mousedown"],
6566
        ["mouseUpEvent", "mouseup"],
6567
        ["clickEvent", _CLICK],
6568
        ["keyPressEvent", "keypress"],
6569
        ["keyDownEvent", "keydown"],
6570
        ["keyUpEvent", "keyup"],
6571
        ["focusEvent", "focus"],
6572
        ["blurEvent", "blur"],
6573
        ["destroyEvent", "destroy"]
6574
    
6575
    ],
6576
6577
	TEXT_CONFIG = { 
6578
		key: _TEXT, 
6579
		value: _EMPTY_STRING, 
6580
		validator: Lang.isString, 
6581
		suppressEvent: true 
6582
	}, 
6583
6584
	HELP_TEXT_CONFIG = { 
6585
		key: _HELP_TEXT,
6586
		supercedes: [_TEXT], 
6587
		suppressEvent: true 
6588
	},
6589
6590
	URL_CONFIG = { 
6591
		key: _URL, 
6592
		value: _HASH, 
6593
		suppressEvent: true 
6594
	}, 
6595
6596
	TARGET_CONFIG = { 
6597
		key: _TARGET, 
6598
		suppressEvent: true 
6599
	}, 
6600
6601
	EMPHASIS_CONFIG = { 
6602
		key: _EMPHASIS, 
6603
		value: false, 
6604
		validator: Lang.isBoolean, 
6605
		suppressEvent: true, 
6606
		supercedes: [_TEXT]
6607
	}, 
6608
6609
	STRONG_EMPHASIS_CONFIG = { 
6610
		key: _STRONG_EMPHASIS, 
6611
		value: false, 
6612
		validator: Lang.isBoolean, 
6613
		suppressEvent: true,
6614
		supercedes: [_TEXT]
6615
	},
6616
6617
	CHECKED_CONFIG = { 
6618
		key: _CHECKED, 
6619
		value: false, 
6620
		validator: Lang.isBoolean, 
6621
		suppressEvent: true, 
6622
		supercedes: [_DISABLED, _SELECTED]
6623
	}, 
6624
6625
	SUBMENU_CONFIG = { 
6626
		key: _SUBMENU,
6627
		suppressEvent: true,
6628
		supercedes: [_DISABLED, _SELECTED]
6629
	},
6630
6631
	DISABLED_CONFIG = { 
6632
		key: _DISABLED, 
6633
		value: false, 
6634
		validator: Lang.isBoolean, 
6635
		suppressEvent: true,
6636
		supercedes: [_TEXT, _SELECTED]
6637
	},
6638
6639
	SELECTED_CONFIG = { 
6640
		key: _SELECTED, 
6641
		value: false, 
6642
		validator: Lang.isBoolean, 
6643
		suppressEvent: true
6644
	},
6645
6646
	ONCLICK_CONFIG = { 
6647
		key: _ONCLICK,
6648
		suppressEvent: true
6649
	},
6650
6651
	CLASS_NAME_CONFIG = { 
6652
		key: _CLASSNAME, 
6653
		value: null, 
6654
		validator: Lang.isString,
6655
		suppressEvent: true
6656
	},
6657
    
6658
	KEY_LISTENER_CONFIG = {
6659
		key: "keylistener", 
6660
		value: null, 
6661
		suppressEvent: true
6662
	},
6663
6664
	m_oMenuItemTemplate = null,
6665
6666
    CLASS_NAMES = {};
6667
6668
6669
/**
6670
* @method getClassNameForState
6671
* @description Returns a class name for the specified prefix and state.  If the class name does not 
6672
* yet exist, it is created and stored in the CLASS_NAMES object to increase performance.
6673
* @private
6674
* @param {String} prefix String representing the prefix for the class name
6675
* @param {String} state String representing a state - "disabled," "checked," etc.
6676
*/  
6677
var getClassNameForState = function (prefix, state) {
6678
6679
	var oClassNames = CLASS_NAMES[prefix];
6680
	
6681
	if (!oClassNames) {
6682
		CLASS_NAMES[prefix] = {};
6683
		oClassNames = CLASS_NAMES[prefix];
6684
	}
6685
6686
6687
	var sClassName = oClassNames[state];
6688
6689
	if (!sClassName) {
6690
		sClassName = prefix + _HYPHEN + state;
6691
		oClassNames[state] = sClassName;
6692
	}
6693
6694
	return sClassName;
6695
	
6696
};
6697
6698
6699
/**
6700
* @method addClassNameForState
6701
* @description Applies a class name to a MenuItem instance's &#60;LI&#62; and &#60;A&#62; elements
6702
* that represents a MenuItem's state - "disabled," "checked," etc.
6703
* @private
6704
* @param {String} state String representing a state - "disabled," "checked," etc.
6705
*/  
6706
var addClassNameForState = function (state) {
6707
6708
	Dom.addClass(this.element, getClassNameForState(this.CSS_CLASS_NAME, state));
6709
	Dom.addClass(this._oAnchor, getClassNameForState(this.CSS_LABEL_CLASS_NAME, state));
6710
6711
};
6712
6713
/**
6714
* @method removeClassNameForState
6715
* @description Removes a class name from a MenuItem instance's &#60;LI&#62; and &#60;A&#62; elements
6716
* that represents a MenuItem's state - "disabled," "checked," etc.
6717
* @private
6718
* @param {String} state String representing a state - "disabled," "checked," etc.
6719
*/  
6720
var removeClassNameForState = function (state) {
6721
6722
	Dom.removeClass(this.element, getClassNameForState(this.CSS_CLASS_NAME, state));
6723
	Dom.removeClass(this._oAnchor, getClassNameForState(this.CSS_LABEL_CLASS_NAME, state));
6724
6725
};
6726
6727
6728
MenuItem.prototype = {
6729
6730
    /**
6731
    * @property CSS_CLASS_NAME
6732
    * @description String representing the CSS class(es) to be applied to the 
6733
    * <code>&#60;li&#62;</code> element of the menu item.
6734
    * @default "yuimenuitem"
6735
    * @final
6736
    * @type String
6737
    */
6738
    CSS_CLASS_NAME: "yuimenuitem",
6739
6740
6741
    /**
6742
    * @property CSS_LABEL_CLASS_NAME
6743
    * @description String representing the CSS class(es) to be applied to the 
6744
    * menu item's <code>&#60;a&#62;</code> element.
6745
    * @default "yuimenuitemlabel"
6746
    * @final
6747
    * @type String
6748
    */
6749
    CSS_LABEL_CLASS_NAME: "yuimenuitemlabel",
6750
6751
6752
    /**
6753
    * @property SUBMENU_TYPE
6754
    * @description Object representing the type of menu to instantiate and 
6755
    * add when parsing the child nodes of the menu item's source HTML element.
6756
    * @final
6757
    * @type YAHOO.widget.Menu
6758
    */
6759
    SUBMENU_TYPE: null,
6760
6761
6762
6763
    // Private member variables
6764
    
6765
6766
    /**
6767
    * @property _oAnchor
6768
    * @description Object reference to the menu item's 
6769
    * <code>&#60;a&#62;</code> element.
6770
    * @default null 
6771
    * @private
6772
    * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6773
    * one-html.html#ID-48250443">HTMLAnchorElement</a>
6774
    */
6775
    _oAnchor: null,
6776
    
6777
    
6778
    /**
6779
    * @property _oHelpTextEM
6780
    * @description Object reference to the menu item's help text 
6781
    * <code>&#60;em&#62;</code> element.
6782
    * @default null
6783
    * @private
6784
    * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6785
    * one-html.html#ID-58190037">HTMLElement</a>
6786
    */
6787
    _oHelpTextEM: null,
6788
    
6789
    
6790
    /**
6791
    * @property _oSubmenu
6792
    * @description Object reference to the menu item's submenu.
6793
    * @default null
6794
    * @private
6795
    * @type YAHOO.widget.Menu
6796
    */
6797
    _oSubmenu: null,
6798
6799
6800
    /** 
6801
    * @property _oOnclickAttributeValue
6802
    * @description Object reference to the menu item's current value for the 
6803
    * "onclick" configuration attribute.
6804
    * @default null
6805
    * @private
6806
    * @type Object
6807
    */
6808
    _oOnclickAttributeValue: null,
6809
6810
6811
    /**
6812
    * @property _sClassName
6813
    * @description The current value of the "classname" configuration attribute.
6814
    * @default null
6815
    * @private
6816
    * @type String
6817
    */
6818
    _sClassName: null,
6819
6820
6821
6822
    // Public properties
6823
6824
6825
	/**
6826
    * @property constructor
6827
	* @description Object reference to the menu item's constructor function.
6828
    * @default YAHOO.widget.MenuItem
6829
	* @type YAHOO.widget.MenuItem
6830
	*/
6831
	constructor: MenuItem,
6832
6833
6834
    /**
6835
    * @property index
6836
    * @description Number indicating the ordinal position of the menu item in 
6837
    * its group.
6838
    * @default null
6839
    * @type Number
6840
    */
6841
    index: null,
6842
6843
6844
    /**
6845
    * @property groupIndex
6846
    * @description Number indicating the index of the group to which the menu 
6847
    * item belongs.
6848
    * @default null
6849
    * @type Number
6850
    */
6851
    groupIndex: null,
6852
6853
6854
    /**
6855
    * @property parent
6856
    * @description Object reference to the menu item's parent menu.
6857
    * @default null
6858
    * @type YAHOO.widget.Menu
6859
    */
6860
    parent: null,
6861
6862
6863
    /**
6864
    * @property element
6865
    * @description Object reference to the menu item's 
6866
    * <code>&#60;li&#62;</code> element.
6867
    * @default <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level
6868
    * -one-html.html#ID-74680021">HTMLLIElement</a>
6869
    * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6870
    * one-html.html#ID-74680021">HTMLLIElement</a>
6871
    */
6872
    element: null,
6873
6874
6875
    /**
6876
    * @property srcElement
6877
    * @description Object reference to the HTML element (either 
6878
    * <code>&#60;li&#62;</code>, <code>&#60;optgroup&#62;</code> or 
6879
    * <code>&#60;option&#62;</code>) used create the menu item.
6880
    * @default <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
6881
    * level-one-html.html#ID-74680021">HTMLLIElement</a>|<a href="http://www.
6882
    * w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-38450247"
6883
    * >HTMLOptGroupElement</a>|<a href="http://www.w3.org/TR/2000/WD-DOM-
6884
    * Level-1-20000929/level-one-html.html#ID-70901257">HTMLOptionElement</a>
6885
    * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6886
    * one-html.html#ID-74680021">HTMLLIElement</a>|<a href="http://www.w3.
6887
    * org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-38450247">
6888
    * HTMLOptGroupElement</a>|<a href="http://www.w3.org/TR/2000/WD-DOM-
6889
    * Level-1-20000929/level-one-html.html#ID-70901257">HTMLOptionElement</a>
6890
    */
6891
    srcElement: null,
6892
6893
6894
    /**
6895
    * @property value
6896
    * @description Object reference to the menu item's value.
6897
    * @default null
6898
    * @type Object
6899
    */
6900
    value: null,
6901
6902
6903
	/**
6904
    * @property browser
6905
    * @deprecated Use YAHOO.env.ua
6906
	* @description String representing the browser.
6907
	* @type String
6908
	*/
6909
	browser: Module.prototype.browser,
6910
6911
6912
    /**
6913
    * @property id
6914
    * @description Id of the menu item's root <code>&#60;li&#62;</code> 
6915
    * element.  This property should be set via the constructor using the 
6916
    * configuration object literal.  If an id is not specified, then one will 
6917
    * be created using the "generateId" method of the Dom utility.
6918
    * @default null
6919
    * @type String
6920
    */
6921
    id: null,
6922
6923
6924
6925
    // Events
6926
6927
6928
    /**
6929
    * @event destroyEvent
6930
    * @description Fires when the menu item's <code>&#60;li&#62;</code> 
6931
    * element is removed from its parent <code>&#60;ul&#62;</code> element.
6932
    * @type YAHOO.util.CustomEvent
6933
    */
6934
6935
6936
    /**
6937
    * @event mouseOverEvent
6938
    * @description Fires when the mouse has entered the menu item.  Passes 
6939
    * back the DOM Event object as an argument.
6940
    * @type YAHOO.util.CustomEvent
6941
    */
6942
6943
6944
    /**
6945
    * @event mouseOutEvent
6946
    * @description Fires when the mouse has left the menu item.  Passes back 
6947
    * the DOM Event object as an argument.
6948
    * @type YAHOO.util.CustomEvent
6949
    */
6950
6951
6952
    /**
6953
    * @event mouseDownEvent
6954
    * @description Fires when the user mouses down on the menu item.  Passes 
6955
    * back the DOM Event object as an argument.
6956
    * @type YAHOO.util.CustomEvent
6957
    */
6958
6959
6960
    /**
6961
    * @event mouseUpEvent
6962
    * @description Fires when the user releases a mouse button while the mouse 
6963
    * is over the menu item.  Passes back the DOM Event object as an argument.
6964
    * @type YAHOO.util.CustomEvent
6965
    */
6966
6967
6968
    /**
6969
    * @event clickEvent
6970
    * @description Fires when the user clicks the on the menu item.  Passes 
6971
    * back the DOM Event object as an argument.
6972
    * @type YAHOO.util.CustomEvent
6973
    */
6974
6975
6976
    /**
6977
    * @event keyPressEvent
6978
    * @description Fires when the user presses an alphanumeric key when the 
6979
    * menu item has focus.  Passes back the DOM Event object as an argument.
6980
    * @type YAHOO.util.CustomEvent
6981
    */
6982
6983
6984
    /**
6985
    * @event keyDownEvent
6986
    * @description Fires when the user presses a key when the menu item has 
6987
    * focus.  Passes back the DOM Event object as an argument.
6988
    * @type YAHOO.util.CustomEvent
6989
    */
6990
6991
6992
    /**
6993
    * @event keyUpEvent
6994
    * @description Fires when the user releases a key when the menu item has 
6995
    * focus.  Passes back the DOM Event object as an argument.
6996
    * @type YAHOO.util.CustomEvent
6997
    */
6998
6999
7000
    /**
7001
    * @event focusEvent
7002
    * @description Fires when the menu item receives focus.
7003
    * @type YAHOO.util.CustomEvent
7004
    */
7005
7006
7007
    /**
7008
    * @event blurEvent
7009
    * @description Fires when the menu item loses the input focus.
7010
    * @type YAHOO.util.CustomEvent
7011
    */
7012
7013
7014
    /**
7015
    * @method init
7016
    * @description The MenuItem class's initialization method. This method is 
7017
    * automatically called by the constructor, and sets up all DOM references 
7018
    * for pre-existing markup, and creates required markup if it is not 
7019
    * already present.
7020
    * @param {String} p_oObject String specifying the text of the menu item.
7021
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
7022
    * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying 
7023
    * the <code>&#60;li&#62;</code> element of the menu item.
7024
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
7025
    * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object 
7026
    * specifying the <code>&#60;optgroup&#62;</code> element of the menu item.
7027
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
7028
    * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object 
7029
    * specifying the <code>&#60;option&#62;</code> element of the menu item.
7030
    * @param {Object} p_oConfig Optional. Object literal specifying the 
7031
    * configuration for the menu item. See configuration class documentation 
7032
    * for more details.
7033
    */
7034
    init: function (p_oObject, p_oConfig) {
7035
7036
7037
        if (!this.SUBMENU_TYPE) {
7038
    
7039
            this.SUBMENU_TYPE = Menu;
7040
    
7041
        }
7042
7043
7044
        // Create the config object
7045
7046
        this.cfg = new YAHOO.util.Config(this);
7047
7048
        this.initDefaultConfig();
7049
7050
        var oConfig = this.cfg,
7051
            sURL = _HASH,
7052
            oCustomEvent,
7053
			aEventData,
7054
            oAnchor,
7055
            sTarget,
7056
            sText,
7057
            sId,
7058
            i;
7059
7060
7061
        if (Lang.isString(p_oObject)) {
7062
7063
            this._createRootNodeStructure();
7064
7065
            oConfig.queueProperty(_TEXT, p_oObject);
7066
7067
        }
7068
        else if (p_oObject && p_oObject.tagName) {
7069
7070
            switch(p_oObject.tagName.toUpperCase()) {
7071
7072
                case _OPTION:
7073
7074
                    this._createRootNodeStructure();
7075
7076
                    oConfig.queueProperty(_TEXT, p_oObject.text);
7077
                    oConfig.queueProperty(_DISABLED, p_oObject.disabled);
7078
7079
                    this.value = p_oObject.value;
7080
7081
                    this.srcElement = p_oObject;
7082
7083
                break;
7084
7085
                case _OPTGROUP:
7086
7087
                    this._createRootNodeStructure();
7088
7089
                    oConfig.queueProperty(_TEXT, p_oObject.label);
7090
                    oConfig.queueProperty(_DISABLED, p_oObject.disabled);
7091
7092
                    this.srcElement = p_oObject;
7093
7094
                    this._initSubTree();
7095
7096
                break;
7097
7098
                case _LI_UPPERCASE:
7099
7100
                    // Get the anchor node (if it exists)
7101
                    
7102
                    oAnchor = Dom.getFirstChild(p_oObject);
7103
7104
7105
                    // Capture the "text" and/or the "URL"
7106
7107
                    if (oAnchor) {
7108
7109
                        sURL = oAnchor.getAttribute(_HREF, 2);
7110
                        sTarget = oAnchor.getAttribute(_TARGET);
7111
7112
                        sText = oAnchor.innerHTML;
7113
7114
                    }
7115
7116
                    this.srcElement = p_oObject;
7117
                    this.element = p_oObject;
7118
                    this._oAnchor = oAnchor;
7119
7120
                    /*
7121
                        Set these properties silently to sync up the 
7122
                        configuration object without making changes to the 
7123
                        element's DOM
7124
                    */ 
7125
7126
                    oConfig.setProperty(_TEXT, sText, true);
7127
                    oConfig.setProperty(_URL, sURL, true);
7128
                    oConfig.setProperty(_TARGET, sTarget, true);
7129
7130
                    this._initSubTree();
7131
7132
                break;
7133
7134
            }            
7135
7136
        }
7137
7138
7139
        if (this.element) {
7140
7141
            sId = (this.srcElement || this.element).id;
7142
7143
            if (!sId) {
7144
7145
                sId = this.id || Dom.generateId();
7146
7147
                this.element.id = sId;
7148
7149
            }
7150
7151
            this.id = sId;
7152
7153
7154
            Dom.addClass(this.element, this.CSS_CLASS_NAME);
7155
            Dom.addClass(this._oAnchor, this.CSS_LABEL_CLASS_NAME);
7156
7157
7158
			i = EVENT_TYPES.length - 1;
7159
7160
			do {
7161
7162
				aEventData = EVENT_TYPES[i];
7163
7164
				oCustomEvent = this.createEvent(aEventData[1]);
7165
				oCustomEvent.signature = CustomEvent.LIST;
7166
				
7167
				this[aEventData[0]] = oCustomEvent;
7168
7169
			}
7170
			while (i--);
7171
7172
7173
            if (p_oConfig) {
7174
    
7175
                oConfig.applyConfig(p_oConfig);
7176
    
7177
            }        
7178
7179
            oConfig.fireQueue();
7180
7181
        }
7182
7183
    },
7184
7185
7186
7187
    // Private methods
7188
7189
    /**
7190
    * @method _createRootNodeStructure
7191
    * @description Creates the core DOM structure for the menu item.
7192
    * @private
7193
    */
7194
    _createRootNodeStructure: function () {
7195
7196
        var oElement,
7197
            oAnchor;
7198
7199
        if (!m_oMenuItemTemplate) {
7200
7201
            m_oMenuItemTemplate = document.createElement(_LI_LOWERCASE);
7202
            m_oMenuItemTemplate.innerHTML = _ANCHOR_TEMPLATE;
7203
7204
        }
7205
7206
        oElement = m_oMenuItemTemplate.cloneNode(true);
7207
        oElement.className = this.CSS_CLASS_NAME;
7208
7209
        oAnchor = oElement.firstChild;
7210
        oAnchor.className = this.CSS_LABEL_CLASS_NAME;
7211
7212
        this.element = oElement;
7213
        this._oAnchor = oAnchor;
7214
7215
    },
7216
7217
7218
    /**
7219
    * @method _initSubTree
7220
    * @description Iterates the source element's childNodes collection and uses 
7221
    * the child nodes to instantiate other menus.
7222
    * @private
7223
    */
7224
    _initSubTree: function () {
7225
7226
        var oSrcEl = this.srcElement,
7227
            oConfig = this.cfg,
7228
            oNode,
7229
            aOptions,
7230
            nOptions,
7231
            oMenu,
7232
            n;
7233
7234
7235
        if (oSrcEl.childNodes.length > 0) {
7236
7237
            if (this.parent.lazyLoad && this.parent.srcElement && 
7238
                this.parent.srcElement.tagName.toUpperCase() == _SELECT) {
7239
7240
                oConfig.setProperty(
7241
                        _SUBMENU, 
7242
                        { id: Dom.generateId(), itemdata: oSrcEl.childNodes }
7243
                    );
7244
7245
            }
7246
            else {
7247
7248
                oNode = oSrcEl.firstChild;
7249
                aOptions = [];
7250
    
7251
                do {
7252
    
7253
                    if (oNode && oNode.tagName) {
7254
    
7255
                        switch(oNode.tagName.toUpperCase()) {
7256
                
7257
                            case _DIV:
7258
                
7259
                                oConfig.setProperty(_SUBMENU, oNode);
7260
                
7261
                            break;
7262
         
7263
                            case _OPTION:
7264
        
7265
                                aOptions[aOptions.length] = oNode;
7266
        
7267
                            break;
7268
               
7269
                        }
7270
                    
7271
                    }
7272
                
7273
                }        
7274
                while((oNode = oNode.nextSibling));
7275
    
7276
    
7277
                nOptions = aOptions.length;
7278
    
7279
                if (nOptions > 0) {
7280
    
7281
                    oMenu = new this.SUBMENU_TYPE(Dom.generateId());
7282
                    
7283
                    oConfig.setProperty(_SUBMENU, oMenu);
7284
    
7285
                    for(n=0; n<nOptions; n++) {
7286
        
7287
                        oMenu.addItem((new oMenu.ITEM_TYPE(aOptions[n])));
7288
        
7289
                    }
7290
        
7291
                }
7292
            
7293
            }
7294
7295
        }
7296
7297
    },
7298
7299
7300
7301
    // Event handlers for configuration properties
7302
7303
7304
    /**
7305
    * @method configText
7306
    * @description Event handler for when the "text" configuration property of 
7307
    * the menu item changes.
7308
    * @param {String} p_sType String representing the name of the event that 
7309
    * was fired.
7310
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7311
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7312
    * that fired the event.
7313
    */
7314
    configText: function (p_sType, p_aArgs, p_oItem) {
7315
7316
        var sText = p_aArgs[0],
7317
            oConfig = this.cfg,
7318
            oAnchor = this._oAnchor,
7319
            sHelpText = oConfig.getProperty(_HELP_TEXT),
7320
            sHelpTextHTML = _EMPTY_STRING,
7321
            sEmphasisStartTag = _EMPTY_STRING,
7322
            sEmphasisEndTag = _EMPTY_STRING;
7323
7324
7325
        if (sText) {
7326
7327
7328
            if (sHelpText) {
7329
                    
7330
                sHelpTextHTML = _START_HELP_TEXT + sHelpText + _END_EM;
7331
            
7332
            }
7333
7334
7335
            if (oConfig.getProperty(_EMPHASIS)) {
7336
7337
                sEmphasisStartTag = _START_EM;
7338
                sEmphasisEndTag = _END_EM;
7339
7340
            }
7341
7342
7343
            if (oConfig.getProperty(_STRONG_EMPHASIS)) {
7344
7345
                sEmphasisStartTag = _START_STRONG;
7346
                sEmphasisEndTag = _END_STRONG;
7347
            
7348
            }
7349
7350
7351
            oAnchor.innerHTML = (sEmphasisStartTag + sText + sEmphasisEndTag + sHelpTextHTML);
7352
7353
        }
7354
7355
    },
7356
7357
7358
    /**
7359
    * @method configHelpText
7360
    * @description Event handler for when the "helptext" configuration property 
7361
    * of the menu item changes.
7362
    * @param {String} p_sType String representing the name of the event that 
7363
    * was fired.
7364
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7365
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7366
    * that fired the event.
7367
    */    
7368
    configHelpText: function (p_sType, p_aArgs, p_oItem) {
7369
7370
        this.cfg.refireEvent(_TEXT);
7371
7372
    },
7373
7374
7375
    /**
7376
    * @method configURL
7377
    * @description Event handler for when the "url" configuration property of 
7378
    * the menu item changes.
7379
    * @param {String} p_sType String representing the name of the event that 
7380
    * was fired.
7381
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7382
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7383
    * that fired the event.
7384
    */    
7385
    configURL: function (p_sType, p_aArgs, p_oItem) {
7386
7387
        var sURL = p_aArgs[0];
7388
7389
        if (!sURL) {
7390
7391
            sURL = _HASH;
7392
7393
        }
7394
7395
        var oAnchor = this._oAnchor;
7396
7397
        if (UA.opera) {
7398
7399
            oAnchor.removeAttribute(_HREF);
7400
        
7401
        }
7402
7403
        oAnchor.setAttribute(_HREF, sURL);
7404
7405
    },
7406
7407
7408
    /**
7409
    * @method configTarget
7410
    * @description Event handler for when the "target" configuration property 
7411
    * of the menu item changes.  
7412
    * @param {String} p_sType String representing the name of the event that 
7413
    * was fired.
7414
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7415
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7416
    * that fired the event.
7417
    */    
7418
    configTarget: function (p_sType, p_aArgs, p_oItem) {
7419
7420
        var sTarget = p_aArgs[0],
7421
            oAnchor = this._oAnchor;
7422
7423
        if (sTarget && sTarget.length > 0) {
7424
7425
            oAnchor.setAttribute(_TARGET, sTarget);
7426
7427
        }
7428
        else {
7429
7430
            oAnchor.removeAttribute(_TARGET);
7431
        
7432
        }
7433
7434
    },
7435
7436
7437
    /**
7438
    * @method configEmphasis
7439
    * @description Event handler for when the "emphasis" configuration property
7440
    * of the menu item changes.
7441
    * @param {String} p_sType String representing the name of the event that 
7442
    * was fired.
7443
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7444
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7445
    * that fired the event.
7446
    */    
7447
    configEmphasis: function (p_sType, p_aArgs, p_oItem) {
7448
7449
        var bEmphasis = p_aArgs[0],
7450
            oConfig = this.cfg;
7451
7452
7453
        if (bEmphasis && oConfig.getProperty(_STRONG_EMPHASIS)) {
7454
7455
            oConfig.setProperty(_STRONG_EMPHASIS, false);
7456
7457
        }
7458
7459
7460
        oConfig.refireEvent(_TEXT);
7461
7462
    },
7463
7464
7465
    /**
7466
    * @method configStrongEmphasis
7467
    * @description Event handler for when the "strongemphasis" configuration 
7468
    * property of the menu item changes.
7469
    * @param {String} p_sType String representing the name of the event that 
7470
    * was fired.
7471
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7472
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7473
    * that fired the event.
7474
    */    
7475
    configStrongEmphasis: function (p_sType, p_aArgs, p_oItem) {
7476
7477
        var bStrongEmphasis = p_aArgs[0],
7478
            oConfig = this.cfg;
7479
7480
7481
        if (bStrongEmphasis && oConfig.getProperty(_EMPHASIS)) {
7482
7483
            oConfig.setProperty(_EMPHASIS, false);
7484
7485
        }
7486
7487
        oConfig.refireEvent(_TEXT);
7488
7489
    },
7490
7491
7492
    /**
7493
    * @method configChecked
7494
    * @description Event handler for when the "checked" configuration property 
7495
    * of the menu item changes. 
7496
    * @param {String} p_sType String representing the name of the event that 
7497
    * was fired.
7498
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7499
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7500
    * that fired the event.
7501
    */    
7502
    configChecked: function (p_sType, p_aArgs, p_oItem) {
7503
7504
        var bChecked = p_aArgs[0],
7505
            oConfig = this.cfg;
7506
7507
7508
        if (bChecked) {
7509
7510
            addClassNameForState.call(this, _CHECKED);
7511
7512
        }
7513
        else {
7514
7515
            removeClassNameForState.call(this, _CHECKED);
7516
        }
7517
7518
7519
        oConfig.refireEvent(_TEXT);
7520
7521
7522
        if (oConfig.getProperty(_DISABLED)) {
7523
7524
            oConfig.refireEvent(_DISABLED);
7525
7526
        }
7527
7528
7529
        if (oConfig.getProperty(_SELECTED)) {
7530
7531
            oConfig.refireEvent(_SELECTED);
7532
7533
        }
7534
7535
    },
7536
7537
7538
7539
    /**
7540
    * @method configDisabled
7541
    * @description Event handler for when the "disabled" configuration property 
7542
    * of the menu item changes. 
7543
    * @param {String} p_sType String representing the name of the event that 
7544
    * was fired.
7545
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7546
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7547
    * that fired the event.
7548
    */    
7549
    configDisabled: function (p_sType, p_aArgs, p_oItem) {
7550
7551
        var bDisabled = p_aArgs[0],
7552
            oConfig = this.cfg,
7553
            oSubmenu = oConfig.getProperty(_SUBMENU),
7554
            bChecked = oConfig.getProperty(_CHECKED);
7555
7556
7557
        if (bDisabled) {
7558
7559
            if (oConfig.getProperty(_SELECTED)) {
7560
7561
                oConfig.setProperty(_SELECTED, false);
7562
7563
            }
7564
7565
7566
			addClassNameForState.call(this, _DISABLED);
7567
7568
7569
            if (oSubmenu) {
7570
7571
				addClassNameForState.call(this, _HAS_SUBMENU_DISABLED);
7572
            
7573
            }
7574
            
7575
7576
            if (bChecked) {
7577
7578
				addClassNameForState.call(this, _CHECKED_DISABLED);
7579
7580
            }
7581
7582
        }
7583
        else {
7584
7585
			removeClassNameForState.call(this, _DISABLED);
7586
7587
7588
            if (oSubmenu) {
7589
7590
				removeClassNameForState.call(this, _HAS_SUBMENU_DISABLED);
7591
            
7592
            }
7593
            
7594
7595
            if (bChecked) {
7596
7597
				removeClassNameForState.call(this, _CHECKED_DISABLED);
7598
7599
            }
7600
7601
        }
7602
7603
    },
7604
7605
7606
    /**
7607
    * @method configSelected
7608
    * @description Event handler for when the "selected" configuration property 
7609
    * of the menu item changes. 
7610
    * @param {String} p_sType String representing the name of the event that 
7611
    * was fired.
7612
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7613
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7614
    * that fired the event.
7615
    */    
7616
    configSelected: function (p_sType, p_aArgs, p_oItem) {
7617
7618
        var oConfig = this.cfg,
7619
        	oAnchor = this._oAnchor,
7620
        	
7621
            bSelected = p_aArgs[0],
7622
            bChecked = oConfig.getProperty(_CHECKED),
7623
            oSubmenu = oConfig.getProperty(_SUBMENU);
7624
7625
7626
        if (UA.opera) {
7627
7628
            oAnchor.blur();
7629
        
7630
        }
7631
7632
7633
        if (bSelected && !oConfig.getProperty(_DISABLED)) {
7634
7635
			addClassNameForState.call(this, _SELECTED);
7636
7637
7638
            if (oSubmenu) {
7639
7640
				addClassNameForState.call(this, _HAS_SUBMENU_SELECTED);
7641
            
7642
            }
7643
7644
7645
            if (bChecked) {
7646
7647
				addClassNameForState.call(this, _CHECKED_SELECTED);
7648
7649
            }
7650
7651
        }
7652
        else {
7653
7654
			removeClassNameForState.call(this, _SELECTED);
7655
7656
7657
            if (oSubmenu) {
7658
7659
				removeClassNameForState.call(this, _HAS_SUBMENU_SELECTED);
7660
            
7661
            }
7662
7663
7664
            if (bChecked) {
7665
7666
				removeClassNameForState.call(this, _CHECKED_SELECTED);
7667
7668
            }
7669
7670
        }
7671
7672
7673
        if (this.hasFocus() && UA.opera) {
7674
        
7675
            oAnchor.focus();
7676
        
7677
        }
7678
7679
    },
7680
7681
7682
    /**
7683
    * @method _onSubmenuBeforeHide
7684
    * @description "beforehide" Custom Event handler for a submenu.
7685
    * @private
7686
    * @param {String} p_sType String representing the name of the event that 
7687
    * was fired.
7688
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7689
    */
7690
    _onSubmenuBeforeHide: function (p_sType, p_aArgs) {
7691
7692
        var oItem = this.parent,
7693
            oMenu;
7694
7695
        function onHide() {
7696
7697
            oItem._oAnchor.blur();
7698
            oMenu.beforeHideEvent.unsubscribe(onHide);
7699
        
7700
        }
7701
7702
7703
        if (oItem.hasFocus()) {
7704
7705
            oMenu = oItem.parent;
7706
7707
            oMenu.beforeHideEvent.subscribe(onHide);
7708
        
7709
        }
7710
    
7711
    },
7712
7713
7714
    /**
7715
    * @method configSubmenu
7716
    * @description Event handler for when the "submenu" configuration property 
7717
    * of the menu item changes. 
7718
    * @param {String} p_sType String representing the name of the event that 
7719
    * was fired.
7720
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7721
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7722
    * that fired the event.
7723
    */
7724
    configSubmenu: function (p_sType, p_aArgs, p_oItem) {
7725
7726
        var oSubmenu = p_aArgs[0],
7727
            oConfig = this.cfg,
7728
            bLazyLoad = this.parent && this.parent.lazyLoad,
7729
            oMenu,
7730
            sSubmenuId,
7731
            oSubmenuConfig;
7732
7733
7734
        if (oSubmenu) {
7735
7736
            if (oSubmenu instanceof Menu) {
7737
7738
                oMenu = oSubmenu;
7739
                oMenu.parent = this;
7740
                oMenu.lazyLoad = bLazyLoad;
7741
7742
            }
7743
            else if (Lang.isObject(oSubmenu) && oSubmenu.id && !oSubmenu.nodeType) {
7744
7745
                sSubmenuId = oSubmenu.id;
7746
                oSubmenuConfig = oSubmenu;
7747
7748
                oSubmenuConfig.lazyload = bLazyLoad;
7749
                oSubmenuConfig.parent = this;
7750
7751
                oMenu = new this.SUBMENU_TYPE(sSubmenuId, oSubmenuConfig);
7752
7753
7754
                // Set the value of the property to the Menu instance
7755
7756
                oConfig.setProperty(_SUBMENU, oMenu, true);
7757
7758
            }
7759
            else {
7760
7761
                oMenu = new this.SUBMENU_TYPE(oSubmenu, { lazyload: bLazyLoad, parent: this });
7762
7763
7764
                // Set the value of the property to the Menu instance
7765
                
7766
                oConfig.setProperty(_SUBMENU, oMenu, true);
7767
7768
            }
7769
7770
7771
            if (oMenu) {
7772
7773
				oMenu.cfg.setProperty(_PREVENT_CONTEXT_OVERLAP, true);
7774
7775
                addClassNameForState.call(this, _HAS_SUBMENU);
7776
7777
7778
				if (oConfig.getProperty(_URL) === _HASH) {
7779
				
7780
					oConfig.setProperty(_URL, (_HASH + oMenu.id));
7781
				
7782
				}
7783
7784
7785
                this._oSubmenu = oMenu;
7786
7787
7788
                if (UA.opera) {
7789
                
7790
                    oMenu.beforeHideEvent.subscribe(this._onSubmenuBeforeHide);               
7791
                
7792
                }
7793
            
7794
            }
7795
7796
        }
7797
        else {
7798
7799
			removeClassNameForState.call(this, _HAS_SUBMENU);
7800
7801
            if (this._oSubmenu) {
7802
7803
                this._oSubmenu.destroy();
7804
7805
            }
7806
7807
        }
7808
7809
7810
        if (oConfig.getProperty(_DISABLED)) {
7811
7812
            oConfig.refireEvent(_DISABLED);
7813
7814
        }
7815
7816
7817
        if (oConfig.getProperty(_SELECTED)) {
7818
7819
            oConfig.refireEvent(_SELECTED);
7820
7821
        }
7822
7823
    },
7824
7825
7826
    /**
7827
    * @method configOnClick
7828
    * @description Event handler for when the "onclick" configuration property 
7829
    * of the menu item changes. 
7830
    * @param {String} p_sType String representing the name of the event that 
7831
    * was fired.
7832
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7833
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7834
    * that fired the event.
7835
    */
7836
    configOnClick: function (p_sType, p_aArgs, p_oItem) {
7837
7838
        var oObject = p_aArgs[0];
7839
7840
        /*
7841
            Remove any existing listeners if a "click" event handler has 
7842
            already been specified.
7843
        */
7844
7845
        if (this._oOnclickAttributeValue && (this._oOnclickAttributeValue != oObject)) {
7846
7847
            this.clickEvent.unsubscribe(this._oOnclickAttributeValue.fn, 
7848
                                this._oOnclickAttributeValue.obj);
7849
7850
            this._oOnclickAttributeValue = null;
7851
7852
        }
7853
7854
7855
        if (!this._oOnclickAttributeValue && Lang.isObject(oObject) && 
7856
            Lang.isFunction(oObject.fn)) {
7857
            
7858
            this.clickEvent.subscribe(oObject.fn, 
7859
                ((_OBJ in oObject) ? oObject.obj : this), 
7860
                ((_SCOPE in oObject) ? oObject.scope : null) );
7861
7862
            this._oOnclickAttributeValue = oObject;
7863
7864
        }
7865
    
7866
    },
7867
7868
7869
    /**
7870
    * @method configClassName
7871
    * @description Event handler for when the "classname" configuration 
7872
    * property of a menu item changes.
7873
    * @param {String} p_sType String representing the name of the event that 
7874
    * was fired.
7875
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7876
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7877
    * that fired the event.
7878
    */
7879
    configClassName: function (p_sType, p_aArgs, p_oItem) {
7880
    
7881
        var sClassName = p_aArgs[0];
7882
    
7883
        if (this._sClassName) {
7884
    
7885
            Dom.removeClass(this.element, this._sClassName);
7886
    
7887
        }
7888
    
7889
        Dom.addClass(this.element, sClassName);
7890
        this._sClassName = sClassName;
7891
    
7892
    },
7893
7894
7895
    /**
7896
    * @method _dispatchClickEvent
7897
    * @description Dispatches a DOM "click" event to the anchor element of a 
7898
	* MenuItem instance.
7899
	* @private	
7900
    */
7901
	_dispatchClickEvent: function () {
7902
7903
		var oMenuItem = this,
7904
			oAnchor,
7905
			oEvent;
7906
7907
		if (!oMenuItem.cfg.getProperty(_DISABLED)) {
7908
7909
			oAnchor = Dom.getFirstChild(oMenuItem.element);
7910
7911
			//	Dispatch a "click" event to the MenuItem's anchor so that its
7912
			//	"click" event handlers will get called in response to the user 
7913
			//	pressing the keyboard shortcut defined by the "keylistener"
7914
			//	configuration property.
7915
7916
			if (UA.ie) {
7917
				oAnchor.fireEvent(_ONCLICK);
7918
			}
7919
			else {
7920
7921
				if ((UA.gecko && UA.gecko >= 1.9) || UA.opera || UA.webkit) {
7922
7923
					oEvent = document.createEvent("HTMLEvents");
7924
					oEvent.initEvent(_CLICK, true, true);
7925
7926
				}
7927
				else {
7928
7929
					oEvent = document.createEvent("MouseEvents");
7930
					oEvent.initMouseEvent(_CLICK, true, true, window, 0, 0, 0, 
7931
						0, 0, false, false, false, false, 0, null);
7932
7933
				}
7934
7935
				oAnchor.dispatchEvent(oEvent);
7936
7937
			}
7938
7939
		}
7940
7941
	},
7942
7943
7944
    /**
7945
    * @method _createKeyListener
7946
    * @description "show" event handler for a Menu instance - responsible for 
7947
	* setting up the KeyListener instance for a MenuItem.
7948
	* @private	
7949
    * @param {String} type String representing the name of the event that 
7950
    * was fired.
7951
    * @param {Array} args Array of arguments sent when the event was fired.
7952
    * @param {Array} keyData Array of arguments sent when the event was fired.
7953
    */
7954
	_createKeyListener: function (type, args, keyData) {
7955
7956
		var oMenuItem = this,
7957
			oMenu = oMenuItem.parent;
7958
7959
		var oKeyListener = new YAHOO.util.KeyListener(
7960
										oMenu.element.ownerDocument, 
7961
										keyData, 
7962
										{
7963
											fn: oMenuItem._dispatchClickEvent, 
7964
											scope: oMenuItem, 
7965
											correctScope: true });
7966
7967
7968
		if (oMenu.cfg.getProperty(_VISIBLE)) {
7969
			oKeyListener.enable();
7970
		}
7971
7972
7973
		oMenu.subscribe(_SHOW, oKeyListener.enable, null, oKeyListener);
7974
		oMenu.subscribe(_HIDE, oKeyListener.disable, null, oKeyListener);
7975
		
7976
		oMenuItem._keyListener = oKeyListener;
7977
		
7978
		oMenu.unsubscribe(_SHOW, oMenuItem._createKeyListener, keyData);
7979
		
7980
	},
7981
7982
7983
    /**
7984
    * @method configKeyListener
7985
    * @description Event handler for when the "keylistener" configuration 
7986
    * property of a menu item changes.
7987
    * @param {String} p_sType String representing the name of the event that 
7988
    * was fired.
7989
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7990
    */
7991
    configKeyListener: function (p_sType, p_aArgs) {
7992
7993
		var oKeyData = p_aArgs[0],
7994
			oMenuItem = this,
7995
			oMenu = oMenuItem.parent;
7996
7997
		if (oMenuItem._keyData) {
7998
7999
			//	Unsubscribe from the "show" event in case the keylistener 
8000
			//	config was changed before the Menu was ever made visible.
8001
8002
			oMenu.unsubscribe(_SHOW, 
8003
					oMenuItem._createKeyListener, oMenuItem._keyData);
8004
8005
			oMenuItem._keyData = null;					
8006
					
8007
		}
8008
8009
8010
		//	Tear down for the previous value of the "keylistener" property
8011
8012
		if (oMenuItem._keyListener) {
8013
8014
			oMenu.unsubscribe(_SHOW, oMenuItem._keyListener.enable);
8015
			oMenu.unsubscribe(_HIDE, oMenuItem._keyListener.disable);
8016
8017
			oMenuItem._keyListener.disable();
8018
			oMenuItem._keyListener = null;
8019
8020
		}
8021
8022
8023
    	if (oKeyData) {
8024
	
8025
			oMenuItem._keyData = oKeyData;
8026
8027
			//	Defer the creation of the KeyListener instance until the 
8028
			//	parent Menu is visible.  This is necessary since the 
8029
			//	KeyListener instance needs to be bound to the document the 
8030
			//	Menu has been rendered into.  Deferring creation of the 
8031
			//	KeyListener instance also improves performance.
8032
8033
			oMenu.subscribe(_SHOW, oMenuItem._createKeyListener, 
8034
				oKeyData, oMenuItem);
8035
		}
8036
    
8037
    },
8038
8039
8040
    // Public methods
8041
8042
8043
	/**
8044
    * @method initDefaultConfig
8045
	* @description Initializes an item's configurable properties.
8046
	*/
8047
	initDefaultConfig : function () {
8048
8049
        var oConfig = this.cfg;
8050
8051
8052
        // Define the configuration attributes
8053
8054
        /**
8055
        * @config text
8056
        * @description String specifying the text label for the menu item.  
8057
        * When building a menu from existing HTML the value of this property
8058
        * will be interpreted from the menu's markup.
8059
        * @default ""
8060
        * @type String
8061
        */
8062
        oConfig.addProperty(
8063
            TEXT_CONFIG.key, 
8064
            { 
8065
                handler: this.configText, 
8066
                value: TEXT_CONFIG.value, 
8067
                validator: TEXT_CONFIG.validator, 
8068
                suppressEvent: TEXT_CONFIG.suppressEvent 
8069
            }
8070
        );
8071
        
8072
8073
        /**
8074
        * @config helptext
8075
        * @description String specifying additional instructional text to 
8076
        * accompany the text for the menu item.
8077
        * @deprecated Use "text" configuration property to add help text markup.  
8078
        * For example: <code>oMenuItem.cfg.setProperty("text", "Copy &#60;em 
8079
        * class=\"helptext\"&#62;Ctrl + C&#60;/em&#62;");</code>
8080
        * @default null
8081
        * @type String|<a href="http://www.w3.org/TR/
8082
        * 2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-58190037">
8083
        * HTMLElement</a>
8084
        */
8085
        oConfig.addProperty(
8086
            HELP_TEXT_CONFIG.key,
8087
            {
8088
                handler: this.configHelpText, 
8089
                supercedes: HELP_TEXT_CONFIG.supercedes,
8090
                suppressEvent: HELP_TEXT_CONFIG.suppressEvent 
8091
            }
8092
        );
8093
8094
8095
        /**
8096
        * @config url
8097
        * @description String specifying the URL for the menu item's anchor's 
8098
        * "href" attribute.  When building a menu from existing HTML the value 
8099
        * of this property will be interpreted from the menu's markup.
8100
        * @default "#"
8101
        * @type String
8102
        */        
8103
        oConfig.addProperty(
8104
            URL_CONFIG.key, 
8105
            {
8106
                handler: this.configURL, 
8107
                value: URL_CONFIG.value, 
8108
                suppressEvent: URL_CONFIG.suppressEvent
8109
            }
8110
        );
8111
8112
8113
        /**
8114
        * @config target
8115
        * @description String specifying the value for the "target" attribute 
8116
        * of the menu item's anchor element. <strong>Specifying a target will 
8117
        * require the user to click directly on the menu item's anchor node in
8118
        * order to cause the browser to navigate to the specified URL.</strong> 
8119
        * When building a menu from existing HTML the value of this property 
8120
        * will be interpreted from the menu's markup.
8121
        * @default null
8122
        * @type String
8123
        */        
8124
        oConfig.addProperty(
8125
            TARGET_CONFIG.key, 
8126
            {
8127
                handler: this.configTarget, 
8128
                suppressEvent: TARGET_CONFIG.suppressEvent
8129
            }
8130
        );
8131
8132
8133
        /**
8134
        * @config emphasis
8135
        * @description Boolean indicating if the text of the menu item will be 
8136
        * rendered with emphasis.
8137
        * @deprecated Use the "text" configuration property to add emphasis.  
8138
        * For example: <code>oMenuItem.cfg.setProperty("text", "&#60;em&#62;Some 
8139
        * Text&#60;/em&#62;");</code>
8140
        * @default false
8141
        * @type Boolean
8142
        */
8143
        oConfig.addProperty(
8144
            EMPHASIS_CONFIG.key, 
8145
            { 
8146
                handler: this.configEmphasis, 
8147
                value: EMPHASIS_CONFIG.value, 
8148
                validator: EMPHASIS_CONFIG.validator, 
8149
                suppressEvent: EMPHASIS_CONFIG.suppressEvent,
8150
                supercedes: EMPHASIS_CONFIG.supercedes
8151
            }
8152
        );
8153
8154
8155
        /**
8156
        * @config strongemphasis
8157
        * @description Boolean indicating if the text of the menu item will be 
8158
        * rendered with strong emphasis.
8159
        * @deprecated Use the "text" configuration property to add strong emphasis.  
8160
        * For example: <code>oMenuItem.cfg.setProperty("text", "&#60;strong&#62; 
8161
        * Some Text&#60;/strong&#62;");</code>
8162
        * @default false
8163
        * @type Boolean
8164
        */
8165
        oConfig.addProperty(
8166
            STRONG_EMPHASIS_CONFIG.key,
8167
            {
8168
                handler: this.configStrongEmphasis,
8169
                value: STRONG_EMPHASIS_CONFIG.value,
8170
                validator: STRONG_EMPHASIS_CONFIG.validator,
8171
                suppressEvent: STRONG_EMPHASIS_CONFIG.suppressEvent,
8172
                supercedes: STRONG_EMPHASIS_CONFIG.supercedes
8173
            }
8174
        );
8175
8176
8177
        /**
8178
        * @config checked
8179
        * @description Boolean indicating if the menu item should be rendered 
8180
        * with a checkmark.
8181
        * @default false
8182
        * @type Boolean
8183
        */
8184
        oConfig.addProperty(
8185
            CHECKED_CONFIG.key, 
8186
            {
8187
                handler: this.configChecked, 
8188
                value: CHECKED_CONFIG.value, 
8189
                validator: CHECKED_CONFIG.validator, 
8190
                suppressEvent: CHECKED_CONFIG.suppressEvent,
8191
                supercedes: CHECKED_CONFIG.supercedes
8192
            } 
8193
        );
8194
8195
8196
        /**
8197
        * @config disabled
8198
        * @description Boolean indicating if the menu item should be disabled.  
8199
        * (Disabled menu items are  dimmed and will not respond to user input 
8200
        * or fire events.)
8201
        * @default false
8202
        * @type Boolean
8203
        */
8204
        oConfig.addProperty(
8205
            DISABLED_CONFIG.key,
8206
            {
8207
                handler: this.configDisabled,
8208
                value: DISABLED_CONFIG.value,
8209
                validator: DISABLED_CONFIG.validator,
8210
                suppressEvent: DISABLED_CONFIG.suppressEvent
8211
            }
8212
        );
8213
8214
8215
        /**
8216
        * @config selected
8217
        * @description Boolean indicating if the menu item should 
8218
        * be highlighted.
8219
        * @default false
8220
        * @type Boolean
8221
        */
8222
        oConfig.addProperty(
8223
            SELECTED_CONFIG.key,
8224
            {
8225
                handler: this.configSelected,
8226
                value: SELECTED_CONFIG.value,
8227
                validator: SELECTED_CONFIG.validator,
8228
                suppressEvent: SELECTED_CONFIG.suppressEvent
8229
            }
8230
        );
8231
8232
8233
        /**
8234
        * @config submenu
8235
        * @description Object specifying the submenu to be appended to the 
8236
        * menu item.  The value can be one of the following: <ul><li>Object 
8237
        * specifying a Menu instance.</li><li>Object literal specifying the
8238
        * menu to be created.  Format: <code>{ id: [menu id], itemdata: 
8239
        * [<a href="YAHOO.widget.Menu.html#itemData">array of values for 
8240
        * items</a>] }</code>.</li><li>String specifying the id attribute 
8241
        * of the <code>&#60;div&#62;</code> element of the menu.</li><li>
8242
        * Object specifying the <code>&#60;div&#62;</code> element of the 
8243
        * menu.</li></ul>
8244
        * @default null
8245
        * @type Menu|String|Object|<a href="http://www.w3.org/TR/2000/
8246
        * WD-DOM-Level-1-20000929/level-one-html.html#ID-58190037">
8247
        * HTMLElement</a>
8248
        */
8249
        oConfig.addProperty(
8250
            SUBMENU_CONFIG.key, 
8251
            {
8252
                handler: this.configSubmenu, 
8253
                supercedes: SUBMENU_CONFIG.supercedes,
8254
                suppressEvent: SUBMENU_CONFIG.suppressEvent
8255
            }
8256
        );
8257
8258
8259
        /**
8260
        * @config onclick
8261
        * @description Object literal representing the code to be executed when 
8262
        * the item is clicked.  Format:<br> <code> {<br> 
8263
        * <strong>fn:</strong> Function,   &#47;&#47; The handler to call when 
8264
        * the event fires.<br> <strong>obj:</strong> Object, &#47;&#47; An 
8265
        * object to  pass back to the handler.<br> <strong>scope:</strong> 
8266
        * Object &#47;&#47; The object to use for the scope of the handler.
8267
        * <br> } </code>
8268
        * @type Object
8269
        * @default null
8270
        */
8271
        oConfig.addProperty(
8272
            ONCLICK_CONFIG.key, 
8273
            {
8274
                handler: this.configOnClick, 
8275
                suppressEvent: ONCLICK_CONFIG.suppressEvent 
8276
            }
8277
        );
8278
8279
8280
        /**
8281
        * @config classname
8282
        * @description CSS class to be applied to the menu item's root 
8283
        * <code>&#60;li&#62;</code> element.  The specified class(es) are 
8284
        * appended in addition to the default class as specified by the menu 
8285
        * item's CSS_CLASS_NAME constant.
8286
        * @default null
8287
        * @type String
8288
        */
8289
        oConfig.addProperty(
8290
            CLASS_NAME_CONFIG.key, 
8291
            { 
8292
                handler: this.configClassName,
8293
                value: CLASS_NAME_CONFIG.value, 
8294
                validator: CLASS_NAME_CONFIG.validator,
8295
                suppressEvent: CLASS_NAME_CONFIG.suppressEvent 
8296
            }
8297
        );
8298
8299
8300
        /**
8301
        * @config keylistener
8302
        * @description Object literal representing the key(s) that can be used 
8303
 		* to trigger the MenuItem's "click" event.  Possible attributes are 
8304
		* shift (boolean), alt (boolean), ctrl (boolean) and keys (either an int 
8305
		* or an array of ints representing keycodes).
8306
        * @default null
8307
        * @type Object
8308
        */
8309
        oConfig.addProperty(
8310
            KEY_LISTENER_CONFIG.key, 
8311
            { 
8312
                handler: this.configKeyListener,
8313
                value: KEY_LISTENER_CONFIG.value, 
8314
                suppressEvent: KEY_LISTENER_CONFIG.suppressEvent 
8315
            }
8316
        );
8317
8318
	},
8319
8320
    /**
8321
    * @method getNextSibling
8322
    * @description Finds the menu item's next sibling.
8323
    * @return YAHOO.widget.MenuItem
8324
    */
8325
	getNextSibling: function () {
8326
	
8327
		var isUL = function (el) {
8328
				return (el.nodeName.toLowerCase() === "ul");
8329
			},
8330
	
8331
			menuitemEl = this.element,
8332
			next = Dom.getNextSibling(menuitemEl),
8333
			parent,
8334
			sibling,
8335
			list;
8336
		
8337
		if (!next) {
8338
			
8339
			parent = menuitemEl.parentNode;
8340
			sibling = Dom.getNextSiblingBy(parent, isUL);
8341
			
8342
			if (sibling) {
8343
				list = sibling;
8344
			}
8345
			else {
8346
				list = Dom.getFirstChildBy(parent.parentNode, isUL);
8347
			}
8348
			
8349
			next = Dom.getFirstChild(list);
8350
			
8351
		}
8352
8353
		return YAHOO.widget.MenuManager.getMenuItem(next.id);
8354
8355
	},
8356
8357
    /**
8358
    * @method getNextEnabledSibling
8359
    * @description Finds the menu item's next enabled sibling.
8360
    * @return YAHOO.widget.MenuItem
8361
    */
8362
	getNextEnabledSibling: function () {
8363
		
8364
		var next = this.getNextSibling();
8365
		
8366
        return (next.cfg.getProperty(_DISABLED) || next.element.style.display == _NONE) ? next.getNextEnabledSibling() : next;
8367
		
8368
	},
8369
8370
8371
    /**
8372
    * @method getPreviousSibling
8373
    * @description Finds the menu item's previous sibling.
8374
    * @return {YAHOO.widget.MenuItem}
8375
    */	
8376
	getPreviousSibling: function () {
8377
8378
		var isUL = function (el) {
8379
				return (el.nodeName.toLowerCase() === "ul");
8380
			},
8381
8382
			menuitemEl = this.element,
8383
			next = Dom.getPreviousSibling(menuitemEl),
8384
			parent,
8385
			sibling,
8386
			list;
8387
		
8388
		if (!next) {
8389
			
8390
			parent = menuitemEl.parentNode;
8391
			sibling = Dom.getPreviousSiblingBy(parent, isUL);
8392
			
8393
			if (sibling) {
8394
				list = sibling;
8395
			}
8396
			else {
8397
				list = Dom.getLastChildBy(parent.parentNode, isUL);
8398
			}
8399
			
8400
			next = Dom.getLastChild(list);
8401
			
8402
		}
8403
8404
		return YAHOO.widget.MenuManager.getMenuItem(next.id);
8405
		
8406
	},
8407
8408
8409
    /**
8410
    * @method getPreviousEnabledSibling
8411
    * @description Finds the menu item's previous enabled sibling.
8412
    * @return {YAHOO.widget.MenuItem}
8413
    */
8414
	getPreviousEnabledSibling: function () {
8415
		
8416
		var next = this.getPreviousSibling();
8417
		
8418
        return (next.cfg.getProperty(_DISABLED) || next.element.style.display == _NONE) ? next.getPreviousEnabledSibling() : next;
8419
		
8420
	},
8421
8422
8423
    /**
8424
    * @method focus
8425
    * @description Causes the menu item to receive the focus and fires the 
8426
    * focus event.
8427
    */
8428
    focus: function () {
8429
8430
        var oParent = this.parent,
8431
            oAnchor = this._oAnchor,
8432
            oActiveItem = oParent.activeItem;
8433
8434
8435
        function setFocus() {
8436
8437
            try {
8438
8439
                if (!(UA.ie && !document.hasFocus())) {
8440
                
8441
					if (oActiveItem) {
8442
		
8443
						oActiveItem.blurEvent.fire();
8444
		
8445
					}
8446
	
8447
					oAnchor.focus();
8448
					
8449
					this.focusEvent.fire();
8450
                
8451
                }
8452
8453
            }
8454
            catch(e) {
8455
            
8456
            }
8457
8458
        }
8459
8460
8461
        if (!this.cfg.getProperty(_DISABLED) && oParent && oParent.cfg.getProperty(_VISIBLE) && 
8462
            this.element.style.display != _NONE) {
8463
8464
8465
            /*
8466
                Setting focus via a timer fixes a race condition in Firefox, IE 
8467
                and Opera where the browser viewport jumps as it trys to 
8468
                position and focus the menu.
8469
            */
8470
8471
            Lang.later(0, this, setFocus);
8472
8473
        }
8474
8475
    },
8476
8477
8478
    /**
8479
    * @method blur
8480
    * @description Causes the menu item to lose focus and fires the 
8481
    * blur event.
8482
    */    
8483
    blur: function () {
8484
8485
        var oParent = this.parent;
8486
8487
        if (!this.cfg.getProperty(_DISABLED) && oParent && oParent.cfg.getProperty(_VISIBLE)) {
8488
8489
            Lang.later(0, this, function () {
8490
8491
                try {
8492
    
8493
                    this._oAnchor.blur();
8494
                    this.blurEvent.fire();    
8495
8496
                } 
8497
                catch (e) {
8498
                
8499
                }
8500
                
8501
            }, 0);
8502
8503
        }
8504
8505
    },
8506
8507
8508
    /**
8509
    * @method hasFocus
8510
    * @description Returns a boolean indicating whether or not the menu item
8511
    * has focus.
8512
    * @return {Boolean}
8513
    */
8514
    hasFocus: function () {
8515
    
8516
        return (YAHOO.widget.MenuManager.getFocusedMenuItem() == this);
8517
    
8518
    },
8519
8520
8521
	/**
8522
    * @method destroy
8523
	* @description Removes the menu item's <code>&#60;li&#62;</code> element 
8524
	* from its parent <code>&#60;ul&#62;</code> element.
8525
	*/
8526
    destroy: function () {
8527
8528
        var oEl = this.element,
8529
            oSubmenu,
8530
            oParentNode,
8531
            aEventData,
8532
            i;
8533
8534
8535
        if (oEl) {
8536
8537
8538
            // If the item has a submenu, destroy it first
8539
8540
            oSubmenu = this.cfg.getProperty(_SUBMENU);
8541
8542
            if (oSubmenu) {
8543
            
8544
                oSubmenu.destroy();
8545
            
8546
            }
8547
8548
8549
            // Remove the element from the parent node
8550
8551
            oParentNode = oEl.parentNode;
8552
8553
            if (oParentNode) {
8554
8555
                oParentNode.removeChild(oEl);
8556
8557
                this.destroyEvent.fire();
8558
8559
            }
8560
8561
8562
            // Remove CustomEvent listeners
8563
8564
			i = EVENT_TYPES.length - 1;
8565
8566
			do {
8567
8568
				aEventData = EVENT_TYPES[i];
8569
				
8570
				this[aEventData[0]].unsubscribeAll();
8571
8572
			}
8573
			while (i--);
8574
            
8575
            
8576
            this.cfg.configChangedEvent.unsubscribeAll();
8577
8578
        }
8579
8580
    },
8581
8582
8583
    /**
8584
    * @method toString
8585
    * @description Returns a string representing the menu item.
8586
    * @return {String}
8587
    */
8588
    toString: function () {
8589
8590
        var sReturnVal = _MENUITEM,
8591
            sId = this.id;
8592
8593
        if (sId) {
8594
    
8595
            sReturnVal += (_SPACE + sId);
8596
        
8597
        }
8598
8599
        return sReturnVal;
8600
    
8601
    }
8602
8603
};
8604
8605
Lang.augmentProto(MenuItem, YAHOO.util.EventProvider);
8606
8607
})();
8608
(function () {
8609
8610
	var _XY = "xy",
8611
		_MOUSEDOWN = "mousedown",
8612
		_CONTEXTMENU = "ContextMenu",
8613
		_SPACE = " ";
8614
8615
/**
8616
* Creates a list of options or commands which are made visible in response to 
8617
* an HTML element's "contextmenu" event ("mousedown" for Opera).
8618
*
8619
* @param {String} p_oElement String specifying the id attribute of the 
8620
* <code>&#60;div&#62;</code> element of the context menu.
8621
* @param {String} p_oElement String specifying the id attribute of the 
8622
* <code>&#60;select&#62;</code> element to be used as the data source for the 
8623
* context menu.
8624
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8625
* html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying the 
8626
* <code>&#60;div&#62;</code> element of the context menu.
8627
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8628
* html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object specifying 
8629
* the <code>&#60;select&#62;</code> element to be used as the data source for 
8630
* the context menu.
8631
* @param {Object} p_oConfig Optional. Object literal specifying the 
8632
* configuration for the context menu. See configuration class documentation 
8633
* for more details.
8634
* @class ContextMenu
8635
* @constructor
8636
* @extends YAHOO.widget.Menu
8637
* @namespace YAHOO.widget
8638
*/
8639
YAHOO.widget.ContextMenu = function(p_oElement, p_oConfig) {
8640
8641
    YAHOO.widget.ContextMenu.superclass.constructor.call(this, p_oElement, p_oConfig);
8642
8643
};
8644
8645
8646
var Event = YAHOO.util.Event,
8647
	UA = YAHOO.env.ua,
8648
    ContextMenu = YAHOO.widget.ContextMenu,
8649
8650
8651
8652
    /**
8653
    * Constant representing the name of the ContextMenu's events
8654
    * @property EVENT_TYPES
8655
    * @private
8656
    * @final
8657
    * @type Object
8658
    */
8659
    EVENT_TYPES = {
8660
8661
        "TRIGGER_CONTEXT_MENU": "triggerContextMenu",
8662
        "CONTEXT_MENU": (UA.opera ? _MOUSEDOWN : "contextmenu"),
8663
        "CLICK": "click"
8664
8665
    },
8666
    
8667
    
8668
    /**
8669
    * Constant representing the ContextMenu's configuration properties
8670
    * @property DEFAULT_CONFIG
8671
    * @private
8672
    * @final
8673
    * @type Object
8674
    */
8675
    TRIGGER_CONFIG = { 
8676
		key: "trigger",
8677
		suppressEvent: true
8678
    };
8679
8680
8681
/**
8682
* @method position
8683
* @description "beforeShow" event handler used to position the contextmenu.
8684
* @private
8685
* @param {String} p_sType String representing the name of the event that 
8686
* was fired.
8687
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
8688
* @param {Array} p_aPos Array representing the xy position for the context menu.
8689
*/
8690
function position(p_sType, p_aArgs, p_aPos) {
8691
8692
    this.cfg.setProperty(_XY, p_aPos);
8693
    
8694
    this.beforeShowEvent.unsubscribe(position, p_aPos);
8695
8696
}
8697
8698
8699
YAHOO.lang.extend(ContextMenu, YAHOO.widget.Menu, {
8700
8701
8702
8703
// Private properties
8704
8705
8706
/**
8707
* @property _oTrigger
8708
* @description Object reference to the current value of the "trigger" 
8709
* configuration property.
8710
* @default null
8711
* @private
8712
* @type String|<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/leve
8713
* l-one-html.html#ID-58190037">HTMLElement</a>|Array
8714
*/
8715
_oTrigger: null,
8716
8717
8718
/**
8719
* @property _bCancelled
8720
* @description Boolean indicating if the display of the context menu should 
8721
* be cancelled.
8722
* @default false
8723
* @private
8724
* @type Boolean
8725
*/
8726
_bCancelled: false,
8727
8728
8729
8730
// Public properties
8731
8732
8733
/**
8734
* @property contextEventTarget
8735
* @description Object reference for the HTML element that was the target of the
8736
* "contextmenu" DOM event ("mousedown" for Opera) that triggered the display of 
8737
* the context menu.
8738
* @default null
8739
* @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8740
* html.html#ID-58190037">HTMLElement</a>
8741
*/
8742
contextEventTarget: null,
8743
8744
8745
8746
// Events
8747
8748
8749
/**
8750
* @event triggerContextMenuEvent
8751
* @description Custom Event wrapper for the "contextmenu" DOM event 
8752
* ("mousedown" for Opera) fired by the element(s) that trigger the display of 
8753
* the context menu.
8754
*/
8755
triggerContextMenuEvent: null,
8756
8757
8758
8759
/**
8760
* @method init
8761
* @description The ContextMenu class's initialization method. This method is 
8762
* automatically called by the constructor, and sets up all DOM references for 
8763
* pre-existing markup, and creates required markup if it is not already present.
8764
* @param {String} p_oElement String specifying the id attribute of the 
8765
* <code>&#60;div&#62;</code> element of the context menu.
8766
* @param {String} p_oElement String specifying the id attribute of the 
8767
* <code>&#60;select&#62;</code> element to be used as the data source for 
8768
* the context menu.
8769
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8770
* html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying the 
8771
* <code>&#60;div&#62;</code> element of the context menu.
8772
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8773
* html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object specifying 
8774
* the <code>&#60;select&#62;</code> element to be used as the data source for 
8775
* the context menu.
8776
* @param {Object} p_oConfig Optional. Object literal specifying the 
8777
* configuration for the context menu. See configuration class documentation 
8778
* for more details.
8779
*/
8780
init: function(p_oElement, p_oConfig) {
8781
8782
8783
    // Call the init of the superclass (YAHOO.widget.Menu)
8784
8785
    ContextMenu.superclass.init.call(this, p_oElement);
8786
8787
8788
    this.beforeInitEvent.fire(ContextMenu);
8789
8790
8791
    if (p_oConfig) {
8792
8793
        this.cfg.applyConfig(p_oConfig, true);
8794
8795
    }
8796
    
8797
    this.initEvent.fire(ContextMenu);
8798
    
8799
},
8800
8801
8802
/**
8803
* @method initEvents
8804
* @description Initializes the custom events for the context menu.
8805
*/
8806
initEvents: function() {
8807
8808
	ContextMenu.superclass.initEvents.call(this);
8809
8810
    // Create custom events
8811
8812
    this.triggerContextMenuEvent = this.createEvent(EVENT_TYPES.TRIGGER_CONTEXT_MENU);
8813
8814
    this.triggerContextMenuEvent.signature = YAHOO.util.CustomEvent.LIST;
8815
8816
},
8817
8818
8819
/**
8820
* @method cancel
8821
* @description Cancels the display of the context menu.
8822
*/
8823
cancel: function() {
8824
8825
    this._bCancelled = true;
8826
8827
},
8828
8829
8830
8831
// Private methods
8832
8833
8834
/**
8835
* @method _removeEventHandlers
8836
* @description Removes all of the DOM event handlers from the HTML element(s) 
8837
* whose "context menu" event ("click" for Opera) trigger the display of 
8838
* the context menu.
8839
* @private
8840
*/
8841
_removeEventHandlers: function() {
8842
8843
    var oTrigger = this._oTrigger;
8844
8845
8846
    // Remove the event handlers from the trigger(s)
8847
8848
    if (oTrigger) {
8849
8850
        Event.removeListener(oTrigger, EVENT_TYPES.CONTEXT_MENU, this._onTriggerContextMenu);    
8851
        
8852
        if (UA.opera) {
8853
        
8854
            Event.removeListener(oTrigger, EVENT_TYPES.CLICK, this._onTriggerClick);
8855
    
8856
        }
8857
8858
    }
8859
8860
},
8861
8862
8863
8864
// Private event handlers
8865
8866
8867
8868
/**
8869
* @method _onTriggerClick
8870
* @description "click" event handler for the HTML element(s) identified as the 
8871
* "trigger" for the context menu.  Used to cancel default behaviors in Opera.
8872
* @private
8873
* @param {Event} p_oEvent Object representing the DOM event object passed back 
8874
* by the event utility (YAHOO.util.Event).
8875
* @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context 
8876
* menu that is handling the event.
8877
*/
8878
_onTriggerClick: function(p_oEvent, p_oMenu) {
8879
8880
    if (p_oEvent.ctrlKey) {
8881
    
8882
        Event.stopEvent(p_oEvent);
8883
8884
    }
8885
    
8886
},
8887
8888
8889
/**
8890
* @method _onTriggerContextMenu
8891
* @description "contextmenu" event handler ("mousedown" for Opera) for the HTML 
8892
* element(s) that trigger the display of the context menu.
8893
* @private
8894
* @param {Event} p_oEvent Object representing the DOM event object passed back 
8895
* by the event utility (YAHOO.util.Event).
8896
* @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context 
8897
* menu that is handling the event.
8898
*/
8899
_onTriggerContextMenu: function(p_oEvent, p_oMenu) {
8900
8901
    var aXY;
8902
8903
    if (!(p_oEvent.type == _MOUSEDOWN && !p_oEvent.ctrlKey)) {
8904
	
8905
		this.contextEventTarget = Event.getTarget(p_oEvent);
8906
	
8907
		this.triggerContextMenuEvent.fire(p_oEvent);
8908
		
8909
	
8910
		if (!this._bCancelled) {
8911
8912
			/*
8913
				Prevent the browser's default context menu from appearing and 
8914
				stop the propagation of the "contextmenu" event so that 
8915
				other ContextMenu instances are not displayed.
8916
			*/
8917
8918
			Event.stopEvent(p_oEvent);
8919
8920
8921
			// Hide any other Menu instances that might be visible
8922
8923
			YAHOO.widget.MenuManager.hideVisible();
8924
			
8925
	
8926
8927
			// Position and display the context menu
8928
	
8929
			aXY = Event.getXY(p_oEvent);
8930
	
8931
	
8932
			if (!YAHOO.util.Dom.inDocument(this.element)) {
8933
	
8934
				this.beforeShowEvent.subscribe(position, aXY);
8935
	
8936
			}
8937
			else {
8938
	
8939
				this.cfg.setProperty(_XY, aXY);
8940
			
8941
			}
8942
	
8943
	
8944
			this.show();
8945
	
8946
		}
8947
	
8948
		this._bCancelled = false;
8949
8950
    }
8951
8952
},
8953
8954
8955
8956
// Public methods
8957
8958
8959
/**
8960
* @method toString
8961
* @description Returns a string representing the context menu.
8962
* @return {String}
8963
*/
8964
toString: function() {
8965
8966
    var sReturnVal = _CONTEXTMENU,
8967
        sId = this.id;
8968
8969
    if (sId) {
8970
8971
        sReturnVal += (_SPACE + sId);
8972
    
8973
    }
8974
8975
    return sReturnVal;
8976
8977
},
8978
8979
8980
/**
8981
* @method initDefaultConfig
8982
* @description Initializes the class's configurable properties which can be 
8983
* changed using the context menu's Config object ("cfg").
8984
*/
8985
initDefaultConfig: function() {
8986
8987
    ContextMenu.superclass.initDefaultConfig.call(this);
8988
8989
    /**
8990
    * @config trigger
8991
    * @description The HTML element(s) whose "contextmenu" event ("mousedown" 
8992
    * for Opera) trigger the display of the context menu.  Can be a string 
8993
    * representing the id attribute of the HTML element, an object reference 
8994
    * for the HTML element, or an array of strings or HTML element references.
8995
    * @default null
8996
    * @type String|<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
8997
    * level-one-html.html#ID-58190037">HTMLElement</a>|Array
8998
    */
8999
    this.cfg.addProperty(TRIGGER_CONFIG.key, 
9000
        {
9001
            handler: this.configTrigger, 
9002
            suppressEvent: TRIGGER_CONFIG.suppressEvent 
9003
        }
9004
    );
9005
9006
},
9007
9008
9009
/**
9010
* @method destroy
9011
* @description Removes the context menu's <code>&#60;div&#62;</code> element 
9012
* (and accompanying child nodes) from the document.
9013
*/
9014
destroy: function() {
9015
9016
    // Remove the DOM event handlers from the current trigger(s)
9017
9018
    this._removeEventHandlers();
9019
9020
9021
    // Continue with the superclass implementation of this method
9022
9023
    ContextMenu.superclass.destroy.call(this);
9024
9025
},
9026
9027
9028
9029
// Public event handlers for configuration properties
9030
9031
9032
/**
9033
* @method configTrigger
9034
* @description Event handler for when the value of the "trigger" configuration 
9035
* property changes. 
9036
* @param {String} p_sType String representing the name of the event that 
9037
* was fired.
9038
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
9039
* @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context 
9040
* menu that fired the event.
9041
*/
9042
configTrigger: function(p_sType, p_aArgs, p_oMenu) {
9043
    
9044
    var oTrigger = p_aArgs[0];
9045
9046
    if (oTrigger) {
9047
9048
        /*
9049
            If there is a current "trigger" - remove the event handlers 
9050
            from that element(s) before assigning new ones
9051
        */
9052
9053
        if (this._oTrigger) {
9054
        
9055
            this._removeEventHandlers();
9056
9057
        }
9058
9059
        this._oTrigger = oTrigger;
9060
9061
9062
        /*
9063
            Listen for the "mousedown" event in Opera b/c it does not 
9064
            support the "contextmenu" event
9065
        */ 
9066
  
9067
        Event.on(oTrigger, EVENT_TYPES.CONTEXT_MENU, this._onTriggerContextMenu, this, true);
9068
9069
9070
        /*
9071
            Assign a "click" event handler to the trigger element(s) for
9072
            Opera to prevent default browser behaviors.
9073
        */
9074
9075
        if (UA.opera) {
9076
        
9077
            Event.on(oTrigger, EVENT_TYPES.CLICK, this._onTriggerClick, this, true);
9078
9079
        }
9080
9081
    }
9082
    else {
9083
   
9084
        this._removeEventHandlers();
9085
    
9086
    }
9087
    
9088
}
9089
9090
}); // END YAHOO.lang.extend
9091
9092
}());
9093
9094
9095
9096
/**
9097
* Creates an item for a context menu.
9098
* 
9099
* @param {String} p_oObject String specifying the text of the context menu item.
9100
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9101
* one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the 
9102
* <code>&#60;li&#62;</code> element of the context menu item.
9103
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9104
* one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object 
9105
* specifying the <code>&#60;optgroup&#62;</code> element of the context 
9106
* menu item.
9107
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9108
* one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying 
9109
* the <code>&#60;option&#62;</code> element of the context menu item.
9110
* @param {Object} p_oConfig Optional. Object literal specifying the 
9111
* configuration for the context menu item. See configuration class 
9112
* documentation for more details.
9113
* @class ContextMenuItem
9114
* @constructor
9115
* @extends YAHOO.widget.MenuItem
9116
* @deprecated As of version 2.4.0 items for YAHOO.widget.ContextMenu instances
9117
* are of type YAHOO.widget.MenuItem.
9118
*/
9119
YAHOO.widget.ContextMenuItem = YAHOO.widget.MenuItem;
9120
(function () {
9121
9122
	var Lang = YAHOO.lang,
9123
9124
		// String constants
9125
	
9126
		_STATIC = "static",
9127
		_DYNAMIC_STATIC = "dynamic," + _STATIC,
9128
		_DISABLED = "disabled",
9129
		_SELECTED = "selected",
9130
		_AUTO_SUBMENU_DISPLAY = "autosubmenudisplay",
9131
		_SUBMENU = "submenu",
9132
		_VISIBLE = "visible",
9133
		_SPACE = " ",
9134
		_SUBMENU_TOGGLE_REGION = "submenutoggleregion",
9135
		_MENUBAR = "MenuBar";
9136
9137
/**
9138
* Horizontal collection of items, each of which can contain a submenu.
9139
* 
9140
* @param {String} p_oElement String specifying the id attribute of the 
9141
* <code>&#60;div&#62;</code> element of the menu bar.
9142
* @param {String} p_oElement String specifying the id attribute of the 
9143
* <code>&#60;select&#62;</code> element to be used as the data source for the 
9144
* menu bar.
9145
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9146
* one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying 
9147
* the <code>&#60;div&#62;</code> element of the menu bar.
9148
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9149
* one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object 
9150
* specifying the <code>&#60;select&#62;</code> element to be used as the data 
9151
* source for the menu bar.
9152
* @param {Object} p_oConfig Optional. Object literal specifying the 
9153
* configuration for the menu bar. See configuration class documentation for
9154
* more details.
9155
* @class MenuBar
9156
* @constructor
9157
* @extends YAHOO.widget.Menu
9158
* @namespace YAHOO.widget
9159
*/
9160
YAHOO.widget.MenuBar = function(p_oElement, p_oConfig) {
9161
9162
    YAHOO.widget.MenuBar.superclass.constructor.call(this, p_oElement, p_oConfig);
9163
9164
};
9165
9166
9167
/**
9168
* @method checkPosition
9169
* @description Checks to make sure that the value of the "position" property 
9170
* is one of the supported strings. Returns true if the position is supported.
9171
* @private
9172
* @param {Object} p_sPosition String specifying the position of the menu.
9173
* @return {Boolean}
9174
*/
9175
function checkPosition(p_sPosition) {
9176
9177
	var returnVal = false;
9178
9179
    if (Lang.isString(p_sPosition)) {
9180
9181
        returnVal = (_DYNAMIC_STATIC.indexOf((p_sPosition.toLowerCase())) != -1);
9182
9183
    }
9184
    
9185
    return returnVal;
9186
9187
}
9188
9189
9190
var Event = YAHOO.util.Event,
9191
    MenuBar = YAHOO.widget.MenuBar,
9192
9193
    POSITION_CONFIG =  { 
9194
		key: "position", 
9195
		value: _STATIC, 
9196
		validator: checkPosition, 
9197
		supercedes: [_VISIBLE] 
9198
	}, 
9199
9200
	SUBMENU_ALIGNMENT_CONFIG =  { 
9201
		key: "submenualignment", 
9202
		value: ["tl","bl"]
9203
	},
9204
9205
	AUTO_SUBMENU_DISPLAY_CONFIG =  { 
9206
		key: _AUTO_SUBMENU_DISPLAY, 
9207
		value: false, 
9208
		validator: Lang.isBoolean,
9209
		suppressEvent: true
9210
	},
9211
	
9212
	SUBMENU_TOGGLE_REGION_CONFIG = {
9213
		key: _SUBMENU_TOGGLE_REGION, 
9214
		value: false, 
9215
		validator: Lang.isBoolean
9216
	};
9217
9218
9219
9220
Lang.extend(MenuBar, YAHOO.widget.Menu, {
9221
9222
/**
9223
* @method init
9224
* @description The MenuBar class's initialization method. This method is 
9225
* automatically called by the constructor, and sets up all DOM references for 
9226
* pre-existing markup, and creates required markup if it is not already present.
9227
* @param {String} p_oElement String specifying the id attribute of the 
9228
* <code>&#60;div&#62;</code> element of the menu bar.
9229
* @param {String} p_oElement String specifying the id attribute of the 
9230
* <code>&#60;select&#62;</code> element to be used as the data source for the 
9231
* menu bar.
9232
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9233
* one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying 
9234
* the <code>&#60;div&#62;</code> element of the menu bar.
9235
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9236
* one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object 
9237
* specifying the <code>&#60;select&#62;</code> element to be used as the data 
9238
* source for the menu bar.
9239
* @param {Object} p_oConfig Optional. Object literal specifying the 
9240
* configuration for the menu bar. See configuration class documentation for
9241
* more details.
9242
*/
9243
init: function(p_oElement, p_oConfig) {
9244
9245
    if(!this.ITEM_TYPE) {
9246
9247
        this.ITEM_TYPE = YAHOO.widget.MenuBarItem;
9248
9249
    }
9250
9251
9252
    // Call the init of the superclass (YAHOO.widget.Menu)
9253
9254
    MenuBar.superclass.init.call(this, p_oElement);
9255
9256
9257
    this.beforeInitEvent.fire(MenuBar);
9258
9259
9260
    if(p_oConfig) {
9261
9262
        this.cfg.applyConfig(p_oConfig, true);
9263
9264
    }
9265
9266
    this.initEvent.fire(MenuBar);
9267
9268
},
9269
9270
9271
9272
// Constants
9273
9274
9275
/**
9276
* @property CSS_CLASS_NAME
9277
* @description String representing the CSS class(es) to be applied to the menu 
9278
* bar's <code>&#60;div&#62;</code> element.
9279
* @default "yuimenubar"
9280
* @final
9281
* @type String
9282
*/
9283
CSS_CLASS_NAME: "yuimenubar",
9284
9285
9286
/**
9287
* @property SUBMENU_TOGGLE_REGION_WIDTH
9288
* @description Width (in pixels) of the area of a MenuBarItem that, when pressed, will toggle the
9289
* display of the MenuBarItem's submenu.
9290
* @default 20
9291
* @final
9292
* @type Number
9293
*/
9294
SUBMENU_TOGGLE_REGION_WIDTH: 20,
9295
9296
9297
// Protected event handlers
9298
9299
9300
/**
9301
* @method _onKeyDown
9302
* @description "keydown" Custom Event handler for the menu bar.
9303
* @private
9304
* @param {String} p_sType String representing the name of the event that 
9305
* was fired.
9306
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
9307
* @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar 
9308
* that fired the event.
9309
*/
9310
_onKeyDown: function(p_sType, p_aArgs, p_oMenuBar) {
9311
9312
    var oEvent = p_aArgs[0],
9313
        oItem = p_aArgs[1],
9314
        oSubmenu,
9315
        oItemCfg,
9316
        oNextItem;
9317
9318
9319
    if(oItem && !oItem.cfg.getProperty(_DISABLED)) {
9320
9321
        oItemCfg = oItem.cfg;
9322
9323
        switch(oEvent.keyCode) {
9324
    
9325
            case 37:    // Left arrow
9326
            case 39:    // Right arrow
9327
    
9328
                if(oItem == this.activeItem && !oItemCfg.getProperty(_SELECTED)) {
9329
    
9330
                    oItemCfg.setProperty(_SELECTED, true);
9331
    
9332
                }
9333
                else {
9334
    
9335
                    oNextItem = (oEvent.keyCode == 37) ? 
9336
                        oItem.getPreviousEnabledSibling() : 
9337
                        oItem.getNextEnabledSibling();
9338
            
9339
                    if(oNextItem) {
9340
    
9341
                        this.clearActiveItem();
9342
    
9343
                        oNextItem.cfg.setProperty(_SELECTED, true);
9344
                        
9345
						oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
9346
						
9347
						if(oSubmenu) {
9348
					
9349
							oSubmenu.show();
9350
							oSubmenu.setInitialFocus();
9351
						
9352
						}
9353
						else {
9354
							oNextItem.focus();  
9355
						}
9356
    
9357
                    }
9358
    
9359
                }
9360
    
9361
                Event.preventDefault(oEvent);
9362
    
9363
            break;
9364
    
9365
            case 40:    // Down arrow
9366
    
9367
                if(this.activeItem != oItem) {
9368
    
9369
                    this.clearActiveItem();
9370
    
9371
                    oItemCfg.setProperty(_SELECTED, true);
9372
                    oItem.focus();
9373
                
9374
                }
9375
    
9376
                oSubmenu = oItemCfg.getProperty(_SUBMENU);
9377
    
9378
                if(oSubmenu) {
9379
    
9380
                    if(oSubmenu.cfg.getProperty(_VISIBLE)) {
9381
    
9382
                        oSubmenu.setInitialSelection();
9383
                        oSubmenu.setInitialFocus();
9384
                    
9385
                    }
9386
                    else {
9387
    
9388
                        oSubmenu.show();
9389
                        oSubmenu.setInitialFocus();
9390
                    
9391
                    }
9392
    
9393
                }
9394
    
9395
                Event.preventDefault(oEvent);
9396
    
9397
            break;
9398
    
9399
        }
9400
9401
    }
9402
9403
9404
    if(oEvent.keyCode == 27 && this.activeItem) { // Esc key
9405
9406
        oSubmenu = this.activeItem.cfg.getProperty(_SUBMENU);
9407
9408
        if(oSubmenu && oSubmenu.cfg.getProperty(_VISIBLE)) {
9409
        
9410
            oSubmenu.hide();
9411
            this.activeItem.focus();
9412
        
9413
        }
9414
        else {
9415
9416
            this.activeItem.cfg.setProperty(_SELECTED, false);
9417
            this.activeItem.blur();
9418
    
9419
        }
9420
9421
        Event.preventDefault(oEvent);
9422
    
9423
    }
9424
9425
},
9426
9427
9428
/**
9429
* @method _onClick
9430
* @description "click" event handler for the menu bar.
9431
* @protected
9432
* @param {String} p_sType String representing the name of the event that 
9433
* was fired.
9434
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
9435
* @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar 
9436
* that fired the event.
9437
*/
9438
_onClick: function(p_sType, p_aArgs, p_oMenuBar) {
9439
9440
    MenuBar.superclass._onClick.call(this, p_sType, p_aArgs, p_oMenuBar);
9441
9442
    var oItem = p_aArgs[1],
9443
        bReturnVal = true,
9444
    	oItemEl,
9445
        oEvent,
9446
        oTarget,
9447
        oActiveItem,
9448
        oConfig,
9449
        oSubmenu,
9450
        nMenuItemX,
9451
        nToggleRegion;
9452
9453
9454
	var toggleSubmenuDisplay = function () {
9455
9456
		if(oSubmenu.cfg.getProperty(_VISIBLE)) {
9457
		
9458
			oSubmenu.hide();
9459
		
9460
		}
9461
		else {
9462
		
9463
			oSubmenu.show();                    
9464
		
9465
		}
9466
	
9467
	};
9468
    
9469
9470
    if(oItem && !oItem.cfg.getProperty(_DISABLED)) {
9471
9472
        oEvent = p_aArgs[0];
9473
        oTarget = Event.getTarget(oEvent);
9474
        oActiveItem = this.activeItem;
9475
        oConfig = this.cfg;
9476
9477
9478
        // Hide any other submenus that might be visible
9479
    
9480
        if(oActiveItem && oActiveItem != oItem) {
9481
    
9482
            this.clearActiveItem();
9483
    
9484
        }
9485
9486
    
9487
        oItem.cfg.setProperty(_SELECTED, true);
9488
    
9489
9490
        // Show the submenu for the item
9491
    
9492
        oSubmenu = oItem.cfg.getProperty(_SUBMENU);
9493
9494
9495
        if(oSubmenu) {
9496
9497
			oItemEl = oItem.element;
9498
			nMenuItemX = YAHOO.util.Dom.getX(oItemEl);
9499
			nToggleRegion = nMenuItemX + (oItemEl.offsetWidth - this.SUBMENU_TOGGLE_REGION_WIDTH);
9500
9501
			if (oConfig.getProperty(_SUBMENU_TOGGLE_REGION)) {
9502
9503
				if (Event.getPageX(oEvent) > nToggleRegion) {
9504
9505
					toggleSubmenuDisplay();
9506
9507
					Event.preventDefault(oEvent);
9508
9509
					/*
9510
						 Return false so that other click event handlers are not called when the 
9511
						 user clicks inside the toggle region.
9512
					*/
9513
					bReturnVal = false;
9514
				
9515
				}
9516
        
9517
        	}
9518
			else {
9519
9520
				toggleSubmenuDisplay();
9521
            
9522
            }
9523
        
9524
        }
9525
    
9526
    }
9527
9528
9529
	return bReturnVal;
9530
9531
},
9532
9533
9534
9535
// Public methods
9536
9537
/**
9538
* @method configSubmenuToggle
9539
* @description Event handler for when the "submenutoggleregion" configuration property of 
9540
* a MenuBar changes.
9541
* @param {String} p_sType The name of the event that was fired.
9542
* @param {Array} p_aArgs Collection of arguments sent when the event was fired.
9543
*/
9544
configSubmenuToggle: function (p_sType, p_aArgs) {
9545
9546
	var bSubmenuToggle = p_aArgs[0];
9547
	
9548
	if (bSubmenuToggle) {
9549
	
9550
		this.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, false);
9551
	
9552
	}
9553
9554
},
9555
9556
9557
/**
9558
* @method toString
9559
* @description Returns a string representing the menu bar.
9560
* @return {String}
9561
*/
9562
toString: function() {
9563
9564
    var sReturnVal = _MENUBAR,
9565
        sId = this.id;
9566
9567
    if(sId) {
9568
9569
        sReturnVal += (_SPACE + sId);
9570
    
9571
    }
9572
9573
    return sReturnVal;
9574
9575
},
9576
9577
9578
/**
9579
* @description Initializes the class's configurable properties which can be
9580
* changed using the menu bar's Config object ("cfg").
9581
* @method initDefaultConfig
9582
*/
9583
initDefaultConfig: function() {
9584
9585
    MenuBar.superclass.initDefaultConfig.call(this);
9586
9587
    var oConfig = this.cfg;
9588
9589
	// Add configuration properties
9590
9591
9592
    /*
9593
        Set the default value for the "position" configuration property
9594
        to "static" by re-adding the property.
9595
    */
9596
9597
9598
    /**
9599
    * @config position
9600
    * @description String indicating how a menu bar should be positioned on the 
9601
    * screen.  Possible values are "static" and "dynamic."  Static menu bars 
9602
    * are visible by default and reside in the normal flow of the document 
9603
    * (CSS position: static).  Dynamic menu bars are hidden by default, reside
9604
    * out of the normal flow of the document (CSS position: absolute), and can 
9605
    * overlay other elements on the screen.
9606
    * @default static
9607
    * @type String
9608
    */
9609
    oConfig.addProperty(
9610
        POSITION_CONFIG.key, 
9611
        {
9612
            handler: this.configPosition, 
9613
            value: POSITION_CONFIG.value, 
9614
            validator: POSITION_CONFIG.validator,
9615
            supercedes: POSITION_CONFIG.supercedes
9616
        }
9617
    );
9618
9619
9620
    /*
9621
        Set the default value for the "submenualignment" configuration property
9622
        to ["tl","bl"] by re-adding the property.
9623
    */
9624
9625
    /**
9626
    * @config submenualignment
9627
    * @description Array defining how submenus should be aligned to their 
9628
    * parent menu bar item. The format is: [itemCorner, submenuCorner].
9629
    * @default ["tl","bl"]
9630
    * @type Array
9631
    */
9632
    oConfig.addProperty(
9633
        SUBMENU_ALIGNMENT_CONFIG.key, 
9634
        {
9635
            value: SUBMENU_ALIGNMENT_CONFIG.value,
9636
            suppressEvent: SUBMENU_ALIGNMENT_CONFIG.suppressEvent
9637
        }
9638
    );
9639
9640
9641
    /*
9642
        Change the default value for the "autosubmenudisplay" configuration 
9643
        property to "false" by re-adding the property.
9644
    */
9645
9646
    /**
9647
    * @config autosubmenudisplay
9648
    * @description Boolean indicating if submenus are automatically made 
9649
    * visible when the user mouses over the menu bar's items.
9650
    * @default false
9651
    * @type Boolean
9652
    */
9653
	oConfig.addProperty(
9654
	   AUTO_SUBMENU_DISPLAY_CONFIG.key, 
9655
	   {
9656
	       value: AUTO_SUBMENU_DISPLAY_CONFIG.value, 
9657
	       validator: AUTO_SUBMENU_DISPLAY_CONFIG.validator,
9658
	       suppressEvent: AUTO_SUBMENU_DISPLAY_CONFIG.suppressEvent
9659
       } 
9660
    );
9661
9662
9663
    /**
9664
    * @config submenutoggleregion
9665
    * @description Boolean indicating if only a specific region of a MenuBarItem should toggle the 
9666
    * display of a submenu.  The default width of the region is determined by the value of the
9667
    * SUBMENU_TOGGLE_REGION_WIDTH property.  If set to true, the autosubmenudisplay 
9668
    * configuration property will be set to false, and any click event listeners will not be 
9669
    * called when the user clicks inside the submenu toggle region of a MenuBarItem.  If the 
9670
    * user clicks outside of the submenu toggle region, the MenuBarItem will maintain its 
9671
    * standard behavior.
9672
    * @default false
9673
    * @type Boolean
9674
    */
9675
	oConfig.addProperty(
9676
	   SUBMENU_TOGGLE_REGION_CONFIG.key, 
9677
	   {
9678
	       value: SUBMENU_TOGGLE_REGION_CONFIG.value, 
9679
	       validator: SUBMENU_TOGGLE_REGION_CONFIG.validator,
9680
	       handler: this.configSubmenuToggle
9681
       } 
9682
    );
9683
9684
}
9685
 
9686
}); // END YAHOO.lang.extend
9687
9688
}());
9689
9690
9691
9692
/**
9693
* Creates an item for a menu bar.
9694
* 
9695
* @param {String} p_oObject String specifying the text of the menu bar item.
9696
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9697
* one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the 
9698
* <code>&#60;li&#62;</code> element of the menu bar item.
9699
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9700
* one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object 
9701
* specifying the <code>&#60;optgroup&#62;</code> element of the menu bar item.
9702
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9703
* one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying 
9704
* the <code>&#60;option&#62;</code> element of the menu bar item.
9705
* @param {Object} p_oConfig Optional. Object literal specifying the 
9706
* configuration for the menu bar item. See configuration class documentation 
9707
* for more details.
9708
* @class MenuBarItem
9709
* @constructor
9710
* @extends YAHOO.widget.MenuItem
9711
*/
9712
YAHOO.widget.MenuBarItem = function(p_oObject, p_oConfig) {
9713
9714
    YAHOO.widget.MenuBarItem.superclass.constructor.call(this, p_oObject, p_oConfig);
9715
9716
};
9717
9718
YAHOO.lang.extend(YAHOO.widget.MenuBarItem, YAHOO.widget.MenuItem, {
9719
9720
9721
9722
/**
9723
* @method init
9724
* @description The MenuBarItem class's initialization method. This method is 
9725
* automatically called by the constructor, and sets up all DOM references for 
9726
* pre-existing markup, and creates required markup if it is not already present.
9727
* @param {String} p_oObject String specifying the text of the menu bar item.
9728
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9729
* one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the 
9730
* <code>&#60;li&#62;</code> element of the menu bar item.
9731
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9732
* one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object 
9733
* specifying the <code>&#60;optgroup&#62;</code> element of the menu bar item.
9734
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9735
* one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying 
9736
* the <code>&#60;option&#62;</code> element of the menu bar item.
9737
* @param {Object} p_oConfig Optional. Object literal specifying the 
9738
* configuration for the menu bar item. See configuration class documentation 
9739
* for more details.
9740
*/
9741
init: function(p_oObject, p_oConfig) {
9742
9743
    if(!this.SUBMENU_TYPE) {
9744
9745
        this.SUBMENU_TYPE = YAHOO.widget.Menu;
9746
9747
    }
9748
9749
9750
    /* 
9751
        Call the init of the superclass (YAHOO.widget.MenuItem)
9752
        Note: We don't pass the user config in here yet 
9753
        because we only want it executed once, at the lowest 
9754
        subclass level.
9755
    */ 
9756
9757
    YAHOO.widget.MenuBarItem.superclass.init.call(this, p_oObject);  
9758
9759
9760
    var oConfig = this.cfg;
9761
9762
    if(p_oConfig) {
9763
9764
        oConfig.applyConfig(p_oConfig, true);
9765
9766
    }
9767
9768
    oConfig.fireQueue();
9769
9770
},
9771
9772
9773
9774
// Constants
9775
9776
9777
/**
9778
* @property CSS_CLASS_NAME
9779
* @description String representing the CSS class(es) to be applied to the 
9780
* <code>&#60;li&#62;</code> element of the menu bar item.
9781
* @default "yuimenubaritem"
9782
* @final
9783
* @type String
9784
*/
9785
CSS_CLASS_NAME: "yuimenubaritem",
9786
9787
9788
/**
9789
* @property CSS_LABEL_CLASS_NAME
9790
* @description String representing the CSS class(es) to be applied to the 
9791
* menu bar item's <code>&#60;a&#62;</code> element.
9792
* @default "yuimenubaritemlabel"
9793
* @final
9794
* @type String
9795
*/
9796
CSS_LABEL_CLASS_NAME: "yuimenubaritemlabel",
9797
9798
9799
9800
// Public methods
9801
9802
9803
/**
9804
* @method toString
9805
* @description Returns a string representing the menu bar item.
9806
* @return {String}
9807
*/
9808
toString: function() {
9809
9810
    var sReturnVal = "MenuBarItem";
9811
9812
    if(this.cfg && this.cfg.getProperty("text")) {
9813
9814
        sReturnVal += (": " + this.cfg.getProperty("text"));
9815
9816
    }
9817
9818
    return sReturnVal;
9819
9820
}
9821
    
9822
}); // END YAHOO.lang.extend
9823
YAHOO.register("menu", YAHOO.widget.Menu, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/plugins/bubbling-min.js (-12 lines)
Lines 1-12 Link Here
1
/*
2
=======
3
/*
4
Copyright (c) 2007, Caridy Patiño. All rights reserved.
5
Portions Copyright (c) 2007, Yahoo!, Inc. All rights reserved.
6
Code licensed under the BSD License:
7
http://www.bubbling-library.com/eng/licence
8
version: 1.4.0
9
*/
10
YAHOO.namespace("plugin","behavior");YAHOO.namespace("CMS","CMS.widget","CMS.behaviors","CMS.plugin");
11
(function(){var $Y=YAHOO.util,$E=YAHOO.util.Event,$D=YAHOO.util.Dom,$L=YAHOO.lang,$=YAHOO.util.Dom.get;YAHOO.Bubbling=function(){var obj={},ua=navigator.userAgent.toLowerCase(),isOpera=(ua.indexOf('opera')>-1);var navRelExternal=function(layer,args){var el=args[1].anchor;if(!args[1].decrepitate&&el){var r=el.getAttribute("rel"),t=el.getAttribute("target");if((!t||(t===''))&&(r=='external')){el.setAttribute("target","blank");}}};var defaultActionsControl=function(layer,args){obj.processingAction(layer,args,obj.defaultActions);};var _searchYUIButton=function(t){var el=obj.getOwnerByClassName(t,'yui-button'),bt=null,id=null;if($L.isObject(el)&&YAHOO.widget.Button){bt=YAHOO.widget.Button.getButton(el.id);}return bt;};obj.ready=false;obj.bubble={};obj.onReady=new $Y.CustomEvent('bubblingOnReady',obj,true);obj.getOwnerByClassName=function(node,className){return($D.hasClass(node,className)?node:$D.getAncestorByClassName(node,className));};obj.getOwnerByTagName=function(node,tagName){node=$D.get(node);if(!node){return null;}return(node.tagName&&node.tagName.toUpperCase()==tagName.toUpperCase()?node:$D.getAncestorByTagName(node,tagName));};obj.getAncestorByClassName=obj.getOwnerByClassName;obj.getAncestorByTagName=obj.getOwnerByTagName;obj.onKeyPressedTrigger=function(args,e,m){var b='key';e=e||$E.getEvent();m=m||{};m.action=b;m.target=args.target;m.decrepitate=false;m.event=e;m.stop=false;m.type=args.type;m.keyCode=args.keyCode;m.charCode=args.charCode;m.ctrlKey=args.ctrlKey;m.shiftKey=args.shiftKey;m.altKey=args.altKey;this.bubble.key.fire(e,m);if(m.stop){$E.stopEvent(e);}return m.stop;};obj.onEventTrigger=function(b,e,m){e=e||$E.getEvent();m=m||{};m.action=b;m.target=(e?$E.getTarget(e):null);m.decrepitate=false;m.event=e;m.stop=false;this.bubble[b].fire(e,m);if(m.stop){$E.stopEvent(e);}return m.stop;};obj.onNavigate=function(e){var conf={anchor:this.getOwnerByTagName($E.getTarget(e),'A'),button:_searchYUIButton($E.getTarget(e))};if(!conf.anchor&&!conf.button){conf.input=this.getOwnerByTagName($E.getTarget(e),'INPUT');}if(conf.button){conf.value=conf.button.get('value');}else if(conf.input){conf.value=conf.input.getAttribute('value');}if(!this.onEventTrigger('navigate',e,conf)){this.onEventTrigger('god',e,conf);}};obj.onProperty=function(e){this.onEventTrigger('property',e,{anchor:this.getOwnerByTagName($E.getTarget(e),'A'),button:_searchYUIButton($E.getTarget(e))});};obj._timeoutId=0;obj.onRepaint=function(e){clearTimeout(obj._timeoutId);obj._timeoutId=setTimeout(function(){var b='repaint',e={target:document.body},m={action:b,target:null,event:e,decrepitate:false,stop:false};obj.bubble[b].fire(e,m);if(m.stop){$E.stopEvent(e);}},150);};obj.onRollOver=function(e){this.onEventTrigger('rollover',e,{anchor:this.getOwnerByTagName($E.getTarget(e),'A')});};obj.onRollOut=function(e){this.onEventTrigger('rollout',e,{anchor:this.getOwnerByTagName($E.getTarget(e),'A')});};obj.onKeyPressed=function(args){this.onKeyPressedTrigger(args);};obj.onKeyListener=function(ev,args){this.onKeyPressedTrigger(args[1]);};obj.getActionName=function(el,depot){depot=depot||{};var b=null,r=null,f=($D.inDocument(el)?function(b){return $D.hasClass(el,b)}:function(b){return el.hasClass(b);});if(el&&($L.isObject(el)||(el=$(el)))){try{r=el.getAttribute("rel");}catch(e){};for(b in depot){if((depot.hasOwnProperty(b))&&(f(b)||(b===r))){return b;}}}return null;};obj.getFirstChildByTagName=function(el,t){if(el&&($L.isObject(el)||(el=$(el)))&&t){var l=el.getElementsByTagName(t);if(l.length>0){return l[0];}}return null;};obj.virtualTarget=function(e,el){if(el&&($L.isObject(el)||(el=$(el)))&&e){var t=$E.getRelatedTarget(e);if($L.isObject(t)){while((t.parentNode)&&$L.isObject(t.parentNode)&&(t.parentNode.tagName!=="BODY")){if(t.parentNode===el){return true;}t=t.parentNode;}}}return false;};obj.addLayer=function(layers,scope){var result=false;layers=($L.isArray(layers)?layers:[layers]);scope=scope||window;for(var i=0;i<layers.length;++i){if(layers[i]&&!this.bubble.hasOwnProperty(layers[i])){this.bubble[layers[i]]=new $Y.CustomEvent(layers[i],scope,true);result=true;}}return result;};obj.subscribe=function(layer,bh,scope){var first=this.addLayer(layer);if(layer){if($L.isObject(scope)){this.bubble[layer].subscribe(bh,scope,true);}else{this.bubble[layer].subscribe(bh);}}return first;};obj.on=obj.subscribe;obj.fire=function(layer,obj){obj=obj||{};obj.action=layer;obj.decrepitate=false;obj.stop=false;if(this.bubble.hasOwnProperty(layer)){this.bubble[layer].fire(null,obj);}return obj.stop;};obj.processingAction=function(layer,args,actions,force){var behavior=null,t;if(!args[1].decrepitate||force){t=args[1].anchor||args[1].input||args[1].button;if(t){behavior=this.getActionName(t,actions);args[1].el=t;}if(behavior&&(actions[behavior].apply(args[1],[layer,args]))){$E.stopEvent(args[0]);args[1].decrepitate=true;args[1].stop=true;}}};obj.defaultActions={};obj.addDefaultAction=function(n,f){if(n&&f&&(!this.defaultActions.hasOwnProperty(n))){this.defaultActions[n]=f;}};$E.addListener(window,"resize",obj.onRepaint,obj,true);obj.on('navigate',navRelExternal);obj.on('navigate',defaultActionsControl);obj.initMonitors=function(config){var fMonitors=function(){var oMonitors=new YAHOO.widget.Module('yui-cms-font-monitor',{monitorresize:true,visible:false});oMonitors.render(document.body);YAHOO.widget.Module.textResizeEvent.subscribe(obj.onRepaint,obj,true);YAHOO.widget.Overlay.windowScrollEvent.subscribe(obj.onRepaint,obj,true);};if($L.isFunction(YAHOO.widget.Module)){$E.onDOMReady(fMonitors,obj,true);}};obj.init=function(){if(!this.ready){var el=document.body;$E.addListener(el,"click",obj.onNavigate,obj,true);$E.addListener(el,(isOpera?"mousedown":"contextmenu"),obj.onProperty,obj,true);if(isOpera){$E.addListener(el,"click",obj.onProperty,obj,true);}$E.addListener(el,"mouseover",obj.onRollOver,obj,true);$E.addListener(el,"mouseout",obj.onRollOut,obj,true);$E.addListener(document,"keydown",obj.onKeyPressed,obj,true);$E.addListener(document,"keyup",obj.onKeyPressed,obj,true);this.ready=true;obj.onReady.fire();}};$E.onDOMReady(obj.init,obj,true);obj.addLayer(['navigate','god','property','key','repaint','rollover','rollout']);return obj;}();})();YAHOO.CMS.Bubble=YAHOO.Bubbling;
12
YAHOO.register("bubbling",YAHOO.Bubbling,{version:"1.4.0",build:"216"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/plugins/loading-min.js (-9 lines)
Lines 1-9 Link Here
1
/*
2
Copyright (c) 2007, Caridy Pati�o. All rights reserved.
3
Portions Copyright (c) 2007, Yahoo!, Inc. All rights reserved.
4
Code licensed under the BSD License:
5
http://www.bubbling-library.com/eng/licence
6
version: 1.5.0
7
*/
8
(function(){var $B=YAHOO.Bubbling,$L=YAHOO.lang,$E=YAHOO.util.Event,$D=YAHOO.util.Dom,$=YAHOO.util.Dom.get;YAHOO.widget.Loading=function(){var obj={},_handle='yui-cms-loading',_content='yui-cms-float',_visible=false,_ready=false,_timer=null,_backup={},_defStyle={zIndex:10000,left:0,top:0,margin:0,padding:0,opacity:0,overflow:'hidden',visibility:'visible',position:'absolute',display:'block'};_defConf={autodismissdelay:0,opacity:1,closeOnDOMReady:false,closeOnLoad:true,close:false,effect:false};function _onHide(){if($L.isObject(obj.element)){$D.setStyle(obj.element,'opacity',0);$D.setStyle(obj.element,'display','none');}}function _onShow(){if($L.isObject(obj.element)){$D.setStyle(obj.element,'opacity',_defConf.opacity);}}var actionControl=function(layer,args){if(_visible&&$L.isObject(obj.element)&&((obj.element===args[1].target)||$D.isAncestor(obj.element,args[1].target))){if(window.confirm('Do you want to hide the loading mask?')){obj.hide();}}};$B.on('navigate',actionControl);$B.on('property',actionControl);obj.element=null;obj.content=null;obj.anim=null;obj.backup={};obj.config=function(userConfig){c=userConfig||{};_defConf.close=($L.isBoolean(c.close)?c.close:_defConf.close);_defConf.effect=($L.isBoolean(c.effect)?c.effect:_defConf.effect);_defConf.opacity=($L.isNumber(c.opacity)?c.opacity:_defConf.opacity);_defConf.autodismissdelay=($L.isNumber(c.autodismissdelay)?c.autodismissdelay:_defConf.autodismissdelay);if(this.element&&_visible){_onShow();}};obj.backup=function(){var el=document.body;_backup.padding=$D.getStyle(el,'padding');_backup.margin=$D.getStyle(el,'margin');_backup.overflow=$D.getStyle(el,'overflow');};obj.restore=function(){var el=document.body;$D.setStyle(el,'padding',_backup.padding);$D.setStyle(el,'padding',_backup.padding);$D.setStyle(el,'overflow',_backup.overflow);};obj.init=function(){var item;this.element=$(_handle);this.content=$(_content);if(!_ready&&($L.isObject(this.element))){_ready=true;this.backup();for(item in _defStyle){if(_defStyle.hasOwnProperty(item)){$D.setStyle(this.element,item,_defStyle[item]);}}obj.show(true);}};obj.adjust=function(){var vp={top:$D.getDocumentScrollTop(),left:$D.getDocumentScrollLeft(),width:$D.getViewportWidth(),height:$D.getViewportHeight()};if(_visible){$D.setStyle(this.element,'height',vp.height+'px');$D.setStyle(this.element,'width',vp.width+'px');$D.setXY(this.element,[vp.left,vp.top]);if(this.content){var size=$D.getRegion(this.content);var oHeight=size.bottom-size.top;var oWidth=size.right-size.left;$D.setXY(this.content,[vp.left+((vp.width-oWidth)/2),vp.top+((vp.height-oHeight)/2)]);}}};obj.show=function(firstTime){if(this.element&&!_visible){_visible=true;$D.setStyle(document.body,'overflow','hidden');$D.setStyle(this.element,'display','block');if(firstTime){$B.on('repaint',obj.adjust,obj,true);}obj.adjust();if(_defConf.effect&&!firstTime){if((this.anim)&&(this.anim.isAnimated())){this.anim.stop();}this.anim=new YAHOO.util.Anim(this.element,{opacity:{to:0.9}},1.5,YAHOO.util.Easing.easeIn);this.anim.onComplete.subscribe(_onShow);this.anim.animate();}else{_onShow();}if(_defConf.closeOnDOMReady){$E.onDOMReady(obj.hide,obj,true);}if(_defConf.closeOnLoad){$E.on(window,'load',obj.hide,obj,true);}window.clearTimeout(_timer);_timer=null;if($L.isNumber(_defConf.autodismissdelay)&&(_defConf.autodismissdelay>0)){_timer=window.setTimeout(function(){obj.hide();},Math.abs(_defConf.autodismissdelay));}}};obj.hide=function(){if(this.element&&_visible){_visible=false;if(_defConf.effect){if((this.anim)&&(this.anim.isAnimated())){this.anim.stop();}this.anim=new YAHOO.util.Anim(this.element,{opacity:{to:0}},1.5,YAHOO.util.Easing.easeOut);this.anim.onComplete.subscribe(_onHide);this.anim.animate();}else{_onHide();}obj.restore();}};if($D.inDocument(_handle)){obj.init();}else{$E.onContentReady(_handle,obj.init,obj,true);}if($L.isObject(YAHOO.widget._cLoading)){obj.config(YAHOO.widget._cLoading);}return obj;}();})();
9
YAHOO.register("loading",YAHOO.widget.Loading,{version:"1.4.0",build:"214"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/utilities/utilities.js (-39 lines)
Lines 1-39 Link Here
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.8.0r4
6
*/
7
if(typeof YAHOO=="undefined"||!YAHOO){var YAHOO={};}YAHOO.namespace=function(){var A=arguments,E=null,C,B,D;for(C=0;C<A.length;C=C+1){D=(""+A[C]).split(".");E=YAHOO;for(B=(D[0]=="YAHOO")?1:0;B<D.length;B=B+1){E[D[B]]=E[D[B]]||{};E=E[D[B]];}}return E;};YAHOO.log=function(D,A,C){var B=YAHOO.widget.Logger;if(B&&B.log){return B.log(D,A,C);}else{return false;}};YAHOO.register=function(A,E,D){var I=YAHOO.env.modules,B,H,G,F,C;if(!I[A]){I[A]={versions:[],builds:[]};}B=I[A];H=D.version;G=D.build;F=YAHOO.env.listeners;B.name=A;B.version=H;B.build=G;B.versions.push(H);B.builds.push(G);B.mainClass=E;for(C=0;C<F.length;C=C+1){F[C](B);}if(E){E.VERSION=H;E.BUILD=G;}else{YAHOO.log("mainClass is undefined for module "+A,"warn");}};YAHOO.env=YAHOO.env||{modules:[],listeners:[]};YAHOO.env.getVersion=function(A){return YAHOO.env.modules[A]||null;};YAHOO.env.ua=function(){var D=function(H){var I=0;return parseFloat(H.replace(/\./g,function(){return(I++==1)?"":".";}));},G=navigator,F={ie:0,opera:0,gecko:0,webkit:0,mobile:null,air:0,caja:G.cajaVersion,secure:false,os:null},C=navigator&&navigator.userAgent,E=window&&window.location,B=E&&E.href,A;F.secure=B&&(B.toLowerCase().indexOf("https")===0);if(C){if((/windows|win32/i).test(C)){F.os="windows";}else{if((/macintosh/i).test(C)){F.os="macintosh";}}if((/KHTML/).test(C)){F.webkit=1;}A=C.match(/AppleWebKit\/([^\s]*)/);if(A&&A[1]){F.webkit=D(A[1]);if(/ Mobile\//.test(C)){F.mobile="Apple";}else{A=C.match(/NokiaN[^\/]*/);if(A){F.mobile=A[0];}}A=C.match(/AdobeAIR\/([^\s]*)/);if(A){F.air=A[0];}}if(!F.webkit){A=C.match(/Opera[\s\/]([^\s]*)/);if(A&&A[1]){F.opera=D(A[1]);A=C.match(/Opera Mini[^;]*/);if(A){F.mobile=A[0];}}else{A=C.match(/MSIE\s([^;]*)/);if(A&&A[1]){F.ie=D(A[1]);}else{A=C.match(/Gecko\/([^\s]*)/);if(A){F.gecko=1;A=C.match(/rv:([^\s\)]*)/);if(A&&A[1]){F.gecko=D(A[1]);}}}}}}return F;}();(function(){YAHOO.namespace("util","widget","example");if("undefined"!==typeof YAHOO_config){var B=YAHOO_config.listener,A=YAHOO.env.listeners,D=true,C;if(B){for(C=0;C<A.length;C++){if(A[C]==B){D=false;break;}}if(D){A.push(B);}}}})();YAHOO.lang=YAHOO.lang||{};(function(){var B=YAHOO.lang,A=Object.prototype,H="[object Array]",C="[object Function]",G="[object Object]",E=[],F=["toString","valueOf"],D={isArray:function(I){return A.toString.apply(I)===H;},isBoolean:function(I){return typeof I==="boolean";},isFunction:function(I){return(typeof I==="function")||A.toString.apply(I)===C;},isNull:function(I){return I===null;},isNumber:function(I){return typeof I==="number"&&isFinite(I);},isObject:function(I){return(I&&(typeof I==="object"||B.isFunction(I)))||false;},isString:function(I){return typeof I==="string";},isUndefined:function(I){return typeof I==="undefined";},_IEEnumFix:(YAHOO.env.ua.ie)?function(K,J){var I,M,L;for(I=0;I<F.length;I=I+1){M=F[I];L=J[M];if(B.isFunction(L)&&L!=A[M]){K[M]=L;}}}:function(){},extend:function(L,M,K){if(!M||!L){throw new Error("extend failed, please check that "+"all dependencies are included.");}var J=function(){},I;J.prototype=M.prototype;L.prototype=new J();L.prototype.constructor=L;L.superclass=M.prototype;if(M.prototype.constructor==A.constructor){M.prototype.constructor=M;}if(K){for(I in K){if(B.hasOwnProperty(K,I)){L.prototype[I]=K[I];}}B._IEEnumFix(L.prototype,K);}},augmentObject:function(M,L){if(!L||!M){throw new Error("Absorb failed, verify dependencies.");}var I=arguments,K,N,J=I[2];if(J&&J!==true){for(K=2;K<I.length;K=K+1){M[I[K]]=L[I[K]];}}else{for(N in L){if(J||!(N in M)){M[N]=L[N];}}B._IEEnumFix(M,L);}},augmentProto:function(L,K){if(!K||!L){throw new Error("Augment failed, verify dependencies.");}var I=[L.prototype,K.prototype],J;for(J=2;J<arguments.length;J=J+1){I.push(arguments[J]);}B.augmentObject.apply(this,I);},dump:function(I,N){var K,M,P=[],Q="{...}",J="f(){...}",O=", ",L=" => ";if(!B.isObject(I)){return I+"";}else{if(I instanceof Date||("nodeType" in I&&"tagName" in I)){return I;}else{if(B.isFunction(I)){return J;}}}N=(B.isNumber(N))?N:3;if(B.isArray(I)){P.push("[");for(K=0,M=I.length;K<M;K=K+1){if(B.isObject(I[K])){P.push((N>0)?B.dump(I[K],N-1):Q);}else{P.push(I[K]);}P.push(O);}if(P.length>1){P.pop();}P.push("]");}else{P.push("{");for(K in I){if(B.hasOwnProperty(I,K)){P.push(K+L);if(B.isObject(I[K])){P.push((N>0)?B.dump(I[K],N-1):Q);}else{P.push(I[K]);}P.push(O);}}if(P.length>1){P.pop();}P.push("}");}return P.join("");},substitute:function(Y,J,R){var N,M,L,U,V,X,T=[],K,O="dump",S=" ",I="{",W="}",Q,P;for(;;){N=Y.lastIndexOf(I);if(N<0){break;}M=Y.indexOf(W,N);if(N+1>=M){break;}K=Y.substring(N+1,M);U=K;X=null;L=U.indexOf(S);if(L>-1){X=U.substring(L+1);U=U.substring(0,L);}V=J[U];if(R){V=R(U,V,X);}if(B.isObject(V)){if(B.isArray(V)){V=B.dump(V,parseInt(X,10));}else{X=X||"";Q=X.indexOf(O);if(Q>-1){X=X.substring(4);}P=V.toString();if(P===G||Q>-1){V=B.dump(V,parseInt(X,10));}else{V=P;}}}else{if(!B.isString(V)&&!B.isNumber(V)){V="~-"+T.length+"-~";T[T.length]=K;}}Y=Y.substring(0,N)+V+Y.substring(M+1);}for(N=T.length-1;N>=0;N=N-1){Y=Y.replace(new RegExp("~-"+N+"-~"),"{"+T[N]+"}","g");}return Y;},trim:function(I){try{return I.replace(/^\s+|\s+$/g,"");}catch(J){return I;}},merge:function(){var L={},J=arguments,I=J.length,K;for(K=0;K<I;K=K+1){B.augmentObject(L,J[K],true);}return L;},later:function(P,J,Q,L,M){P=P||0;J=J||{};var K=Q,O=L,N,I;if(B.isString(Q)){K=J[Q];}if(!K){throw new TypeError("method undefined");}if(O&&!B.isArray(O)){O=[L];}N=function(){K.apply(J,O||E);};I=(M)?setInterval(N,P):setTimeout(N,P);return{interval:M,cancel:function(){if(this.interval){clearInterval(I);}else{clearTimeout(I);}}};},isValue:function(I){return(B.isObject(I)||B.isString(I)||B.isNumber(I)||B.isBoolean(I));}};B.hasOwnProperty=(A.hasOwnProperty)?function(I,J){return I&&I.hasOwnProperty(J);}:function(I,J){return !B.isUndefined(I[J])&&I.constructor.prototype[J]!==I[J];};D.augmentObject(B,D,true);YAHOO.util.Lang=B;B.augment=B.augmentProto;YAHOO.augment=B.augmentProto;YAHOO.extend=B.extend;})();YAHOO.register("yahoo",YAHOO,{version:"2.8.0r4",build:"2449"});
8
YAHOO.util.Get=function(){var M={},L=0,R=0,E=false,N=YAHOO.env.ua,S=YAHOO.lang;var J=function(W,T,X){var U=X||window,Y=U.document,Z=Y.createElement(W);for(var V in T){if(T[V]&&YAHOO.lang.hasOwnProperty(T,V)){Z.setAttribute(V,T[V]);}}return Z;};var I=function(U,V,T){var W={id:"yui__dyn_"+(R++),type:"text/css",rel:"stylesheet",href:U};if(T){S.augmentObject(W,T);}return J("link",W,V);};var P=function(U,V,T){var W={id:"yui__dyn_"+(R++),type:"text/javascript",src:U};if(T){S.augmentObject(W,T);}return J("script",W,V);};var A=function(T,U){return{tId:T.tId,win:T.win,data:T.data,nodes:T.nodes,msg:U,purge:function(){D(this.tId);}};};var B=function(T,W){var U=M[W],V=(S.isString(T))?U.win.document.getElementById(T):T;if(!V){Q(W,"target node not found: "+T);}return V;};var Q=function(W,V){var T=M[W];if(T.onFailure){var U=T.scope||T.win;T.onFailure.call(U,A(T,V));}};var C=function(W){var T=M[W];T.finished=true;if(T.aborted){var V="transaction "+W+" was aborted";Q(W,V);return;}if(T.onSuccess){var U=T.scope||T.win;T.onSuccess.call(U,A(T));}};var O=function(V){var T=M[V];if(T.onTimeout){var U=T.scope||T;T.onTimeout.call(U,A(T));}};var G=function(V,Z){var U=M[V];if(U.timer){U.timer.cancel();}if(U.aborted){var X="transaction "+V+" was aborted";Q(V,X);return;}if(Z){U.url.shift();if(U.varName){U.varName.shift();}}else{U.url=(S.isString(U.url))?[U.url]:U.url;if(U.varName){U.varName=(S.isString(U.varName))?[U.varName]:U.varName;}}var c=U.win,b=c.document,a=b.getElementsByTagName("head")[0],W;if(U.url.length===0){if(U.type==="script"&&N.webkit&&N.webkit<420&&!U.finalpass&&!U.varName){var Y=P(null,U.win,U.attributes);Y.innerHTML='YAHOO.util.Get._finalize("'+V+'");';U.nodes.push(Y);a.appendChild(Y);}else{C(V);}return;}var T=U.url[0];if(!T){U.url.shift();return G(V);}if(U.timeout){U.timer=S.later(U.timeout,U,O,V);}if(U.type==="script"){W=P(T,c,U.attributes);}else{W=I(T,c,U.attributes);}F(U.type,W,V,T,c,U.url.length);U.nodes.push(W);if(U.insertBefore){var e=B(U.insertBefore,V);if(e){e.parentNode.insertBefore(W,e);}}else{a.appendChild(W);}if((N.webkit||N.gecko)&&U.type==="css"){G(V,T);}};var K=function(){if(E){return;}E=true;for(var T in M){var U=M[T];if(U.autopurge&&U.finished){D(U.tId);delete M[T];}}E=false;};var D=function(Z){if(M[Z]){var T=M[Z],U=T.nodes,X=U.length,c=T.win.document,a=c.getElementsByTagName("head")[0],V,Y,W,b;if(T.insertBefore){V=B(T.insertBefore,Z);if(V){a=V.parentNode;}}for(Y=0;Y<X;Y=Y+1){W=U[Y];if(W.clearAttributes){W.clearAttributes();}else{for(b in W){delete W[b];}}a.removeChild(W);}T.nodes=[];}};var H=function(U,T,V){var X="q"+(L++);V=V||{};if(L%YAHOO.util.Get.PURGE_THRESH===0){K();}M[X]=S.merge(V,{tId:X,type:U,url:T,finished:false,aborted:false,nodes:[]});var W=M[X];W.win=W.win||window;W.scope=W.scope||W.win;W.autopurge=("autopurge" in W)?W.autopurge:(U==="script")?true:false;if(V.charset){W.attributes=W.attributes||{};W.attributes.charset=V.charset;}S.later(0,W,G,X);return{tId:X};};var F=function(c,X,W,U,Y,Z,b){var a=b||G;if(N.ie){X.onreadystatechange=function(){var d=this.readyState;if("loaded"===d||"complete"===d){X.onreadystatechange=null;a(W,U);}};}else{if(N.webkit){if(c==="script"){if(N.webkit>=420){X.addEventListener("load",function(){a(W,U);});}else{var T=M[W];if(T.varName){var V=YAHOO.util.Get.POLL_FREQ;T.maxattempts=YAHOO.util.Get.TIMEOUT/V;T.attempts=0;T._cache=T.varName[0].split(".");T.timer=S.later(V,T,function(j){var f=this._cache,e=f.length,d=this.win,g;for(g=0;g<e;g=g+1){d=d[f[g]];if(!d){this.attempts++;if(this.attempts++>this.maxattempts){var h="Over retry limit, giving up";T.timer.cancel();Q(W,h);}else{}return;}}T.timer.cancel();a(W,U);},null,true);}else{S.later(YAHOO.util.Get.POLL_FREQ,null,a,[W,U]);}}}}else{X.onload=function(){a(W,U);};}}};return{POLL_FREQ:10,PURGE_THRESH:20,TIMEOUT:2000,_finalize:function(T){S.later(0,null,C,T);},abort:function(U){var V=(S.isString(U))?U:U.tId;var T=M[V];if(T){T.aborted=true;}},script:function(T,U){return H("script",T,U);},css:function(T,U){return H("css",T,U);}};}();YAHOO.register("get",YAHOO.util.Get,{version:"2.8.0r4",build:"2449"});(function(){var Y=YAHOO,util=Y.util,lang=Y.lang,env=Y.env,PROV="_provides",SUPER="_supersedes",REQ="expanded",AFTER="_after";var YUI={dupsAllowed:{"yahoo":true,"get":true},info:{"root":"2.8.0r4/build/","base":"http://yui.yahooapis.com/2.8.0r4/build/","comboBase":"http://yui.yahooapis.com/combo?","skin":{"defaultSkin":"sam","base":"assets/skins/","path":"skin.css","after":["reset","fonts","grids","base"],"rollup":3},dupsAllowed:["yahoo","get"],"moduleInfo":{"animation":{"type":"js","path":"animation/animation-min.js","requires":["dom","event"]},"autocomplete":{"type":"js","path":"autocomplete/autocomplete-min.js","requires":["dom","event","datasource"],"optional":["connection","animation"],"skinnable":true},"base":{"type":"css","path":"base/base-min.css","after":["reset","fonts","grids"]},"button":{"type":"js","path":"button/button-min.js","requires":["element"],"optional":["menu"],"skinnable":true},"calendar":{"type":"js","path":"calendar/calendar-min.js","requires":["event","dom"],supersedes:["datemeth"],"skinnable":true},"carousel":{"type":"js","path":"carousel/carousel-min.js","requires":["element"],"optional":["animation"],"skinnable":true},"charts":{"type":"js","path":"charts/charts-min.js","requires":["element","json","datasource","swf"]},"colorpicker":{"type":"js","path":"colorpicker/colorpicker-min.js","requires":["slider","element"],"optional":["animation"],"skinnable":true},"connection":{"type":"js","path":"connection/connection-min.js","requires":["event"],"supersedes":["connectioncore"]},"connectioncore":{"type":"js","path":"connection/connection_core-min.js","requires":["event"],"pkg":"connection"},"container":{"type":"js","path":"container/container-min.js","requires":["dom","event"],"optional":["dragdrop","animation","connection"],"supersedes":["containercore"],"skinnable":true},"containercore":{"type":"js","path":"container/container_core-min.js","requires":["dom","event"],"pkg":"container"},"cookie":{"type":"js","path":"cookie/cookie-min.js","requires":["yahoo"]},"datasource":{"type":"js","path":"datasource/datasource-min.js","requires":["event"],"optional":["connection"]},"datatable":{"type":"js","path":"datatable/datatable-min.js","requires":["element","datasource"],"optional":["calendar","dragdrop","paginator"],"skinnable":true},datemath:{"type":"js","path":"datemath/datemath-min.js","requires":["yahoo"]},"dom":{"type":"js","path":"dom/dom-min.js","requires":["yahoo"]},"dragdrop":{"type":"js","path":"dragdrop/dragdrop-min.js","requires":["dom","event"]},"editor":{"type":"js","path":"editor/editor-min.js","requires":["menu","element","button"],"optional":["animation","dragdrop"],"supersedes":["simpleeditor"],"skinnable":true},"element":{"type":"js","path":"element/element-min.js","requires":["dom","event"],"optional":["event-mouseenter","event-delegate"]},"element-delegate":{"type":"js","path":"element-delegate/element-delegate-min.js","requires":["element"]},"event":{"type":"js","path":"event/event-min.js","requires":["yahoo"]},"event-simulate":{"type":"js","path":"event-simulate/event-simulate-min.js","requires":["event"]},"event-delegate":{"type":"js","path":"event-delegate/event-delegate-min.js","requires":["event"],"optional":["selector"]},"event-mouseenter":{"type":"js","path":"event-mouseenter/event-mouseenter-min.js","requires":["dom","event"]},"fonts":{"type":"css","path":"fonts/fonts-min.css"},"get":{"type":"js","path":"get/get-min.js","requires":["yahoo"]},"grids":{"type":"css","path":"grids/grids-min.css","requires":["fonts"],"optional":["reset"]},"history":{"type":"js","path":"history/history-min.js","requires":["event"]},"imagecropper":{"type":"js","path":"imagecropper/imagecropper-min.js","requires":["dragdrop","element","resize"],"skinnable":true},"imageloader":{"type":"js","path":"imageloader/imageloader-min.js","requires":["event","dom"]},"json":{"type":"js","path":"json/json-min.js","requires":["yahoo"]},"layout":{"type":"js","path":"layout/layout-min.js","requires":["element"],"optional":["animation","dragdrop","resize","selector"],"skinnable":true},"logger":{"type":"js","path":"logger/logger-min.js","requires":["event","dom"],"optional":["dragdrop"],"skinnable":true},"menu":{"type":"js","path":"menu/menu-min.js","requires":["containercore"],"skinnable":true},"paginator":{"type":"js","path":"paginator/paginator-min.js","requires":["element"],"skinnable":true},"profiler":{"type":"js","path":"profiler/profiler-min.js","requires":["yahoo"]},"profilerviewer":{"type":"js","path":"profilerviewer/profilerviewer-min.js","requires":["profiler","yuiloader","element"],"skinnable":true},"progressbar":{"type":"js","path":"progressbar/progressbar-min.js","requires":["element"],"optional":["animation"],"skinnable":true},"reset":{"type":"css","path":"reset/reset-min.css"},"reset-fonts-grids":{"type":"css","path":"reset-fonts-grids/reset-fonts-grids.css","supersedes":["reset","fonts","grids","reset-fonts"],"rollup":4},"reset-fonts":{"type":"css","path":"reset-fonts/reset-fonts.css","supersedes":["reset","fonts"],"rollup":2},"resize":{"type":"js","path":"resize/resize-min.js","requires":["dragdrop","element"],"optional":["animation"],"skinnable":true},"selector":{"type":"js","path":"selector/selector-min.js","requires":["yahoo","dom"]},"simpleeditor":{"type":"js","path":"editor/simpleeditor-min.js","requires":["element"],"optional":["containercore","menu","button","animation","dragdrop"],"skinnable":true,"pkg":"editor"},"slider":{"type":"js","path":"slider/slider-min.js","requires":["dragdrop"],"optional":["animation"],"skinnable":true},"storage":{"type":"js","path":"storage/storage-min.js","requires":["yahoo","event","cookie"],"optional":["swfstore"]},"stylesheet":{"type":"js","path":"stylesheet/stylesheet-min.js","requires":["yahoo"]},"swf":{"type":"js","path":"swf/swf-min.js","requires":["element"],"supersedes":["swfdetect"]},"swfdetect":{"type":"js","path":"swfdetect/swfdetect-min.js","requires":["yahoo"]},"swfstore":{"type":"js","path":"swfstore/swfstore-min.js","requires":["element","cookie","swf"]},"tabview":{"type":"js","path":"tabview/tabview-min.js","requires":["element"],"optional":["connection"],"skinnable":true},"treeview":{"type":"js","path":"treeview/treeview-min.js","requires":["event","dom"],"optional":["json","animation","calendar"],"skinnable":true},"uploader":{"type":"js","path":"uploader/uploader-min.js","requires":["element"]},"utilities":{"type":"js","path":"utilities/utilities.js","supersedes":["yahoo","event","dragdrop","animation","dom","connection","element","yahoo-dom-event","get","yuiloader","yuiloader-dom-event"],"rollup":8},"yahoo":{"type":"js","path":"yahoo/yahoo-min.js"},"yahoo-dom-event":{"type":"js","path":"yahoo-dom-event/yahoo-dom-event.js","supersedes":["yahoo","event","dom"],"rollup":3},"yuiloader":{"type":"js","path":"yuiloader/yuiloader-min.js","supersedes":["yahoo","get"]},"yuiloader-dom-event":{"type":"js","path":"yuiloader-dom-event/yuiloader-dom-event.js","supersedes":["yahoo","dom","event","get","yuiloader","yahoo-dom-event"],"rollup":5},"yuitest":{"type":"js","path":"yuitest/yuitest-min.js","requires":["logger"],"optional":["event-simulate"],"skinnable":true}}},ObjectUtil:{appendArray:function(o,a){if(a){for(var i=0;
9
i<a.length;i=i+1){o[a[i]]=true;}}},keys:function(o,ordered){var a=[],i;for(i in o){if(lang.hasOwnProperty(o,i)){a.push(i);}}return a;}},ArrayUtil:{appendArray:function(a1,a2){Array.prototype.push.apply(a1,a2);},indexOf:function(a,val){for(var i=0;i<a.length;i=i+1){if(a[i]===val){return i;}}return -1;},toObject:function(a){var o={};for(var i=0;i<a.length;i=i+1){o[a[i]]=true;}return o;},uniq:function(a){return YUI.ObjectUtil.keys(YUI.ArrayUtil.toObject(a));}}};YAHOO.util.YUILoader=function(o){this._internalCallback=null;this._useYahooListener=false;this.onSuccess=null;this.onFailure=Y.log;this.onProgress=null;this.onTimeout=null;this.scope=this;this.data=null;this.insertBefore=null;this.charset=null;this.varName=null;this.base=YUI.info.base;this.comboBase=YUI.info.comboBase;this.combine=false;this.root=YUI.info.root;this.timeout=0;this.ignore=null;this.force=null;this.allowRollup=true;this.filter=null;this.required={};this.moduleInfo=lang.merge(YUI.info.moduleInfo);this.rollups=null;this.loadOptional=false;this.sorted=[];this.loaded={};this.dirty=true;this.inserted={};var self=this;env.listeners.push(function(m){if(self._useYahooListener){self.loadNext(m.name);}});this.skin=lang.merge(YUI.info.skin);this._config(o);};Y.util.YUILoader.prototype={FILTERS:{RAW:{"searchExp":"-min\\.js","replaceStr":".js"},DEBUG:{"searchExp":"-min\\.js","replaceStr":"-debug.js"}},SKIN_PREFIX:"skin-",_config:function(o){if(o){for(var i in o){if(lang.hasOwnProperty(o,i)){if(i=="require"){this.require(o[i]);}else{this[i]=o[i];}}}}var f=this.filter;if(lang.isString(f)){f=f.toUpperCase();if(f==="DEBUG"){this.require("logger");}if(!Y.widget.LogWriter){Y.widget.LogWriter=function(){return Y;};}this.filter=this.FILTERS[f];}},addModule:function(o){if(!o||!o.name||!o.type||(!o.path&&!o.fullpath)){return false;}o.ext=("ext" in o)?o.ext:true;o.requires=o.requires||[];this.moduleInfo[o.name]=o;this.dirty=true;return true;},require:function(what){var a=(typeof what==="string")?arguments:what;this.dirty=true;YUI.ObjectUtil.appendArray(this.required,a);},_addSkin:function(skin,mod){var name=this.formatSkin(skin),info=this.moduleInfo,sinf=this.skin,ext=info[mod]&&info[mod].ext;if(!info[name]){this.addModule({"name":name,"type":"css","path":sinf.base+skin+"/"+sinf.path,"after":sinf.after,"rollup":sinf.rollup,"ext":ext});}if(mod){name=this.formatSkin(skin,mod);if(!info[name]){var mdef=info[mod],pkg=mdef.pkg||mod;this.addModule({"name":name,"type":"css","after":sinf.after,"path":pkg+"/"+sinf.base+skin+"/"+mod+".css","ext":ext});}}return name;},getRequires:function(mod){if(!mod){return[];}if(!this.dirty&&mod.expanded){return mod.expanded;}mod.requires=mod.requires||[];var i,d=[],r=mod.requires,o=mod.optional,info=this.moduleInfo,m;for(i=0;i<r.length;i=i+1){d.push(r[i]);m=info[r[i]];YUI.ArrayUtil.appendArray(d,this.getRequires(m));}if(o&&this.loadOptional){for(i=0;i<o.length;i=i+1){d.push(o[i]);YUI.ArrayUtil.appendArray(d,this.getRequires(info[o[i]]));}}mod.expanded=YUI.ArrayUtil.uniq(d);return mod.expanded;},getProvides:function(name,notMe){var addMe=!(notMe),ckey=(addMe)?PROV:SUPER,m=this.moduleInfo[name],o={};if(!m){return o;}if(m[ckey]){return m[ckey];}var s=m.supersedes,done={},me=this;var add=function(mm){if(!done[mm]){done[mm]=true;lang.augmentObject(o,me.getProvides(mm));}};if(s){for(var i=0;i<s.length;i=i+1){add(s[i]);}}m[SUPER]=o;m[PROV]=lang.merge(o);m[PROV][name]=true;return m[ckey];},calculate:function(o){if(o||this.dirty){this._config(o);this._setup();this._explode();if(this.allowRollup){this._rollup();}this._reduce();this._sort();this.dirty=false;}},_setup:function(){var info=this.moduleInfo,name,i,j;for(name in info){if(lang.hasOwnProperty(info,name)){var m=info[name];if(m&&m.skinnable){var o=this.skin.overrides,smod;if(o&&o[name]){for(i=0;i<o[name].length;i=i+1){smod=this._addSkin(o[name][i],name);}}else{smod=this._addSkin(this.skin.defaultSkin,name);}m.requires.push(smod);}}}var l=lang.merge(this.inserted);if(!this._sandbox){l=lang.merge(l,env.modules);}if(this.ignore){YUI.ObjectUtil.appendArray(l,this.ignore);}if(this.force){for(i=0;i<this.force.length;i=i+1){if(this.force[i] in l){delete l[this.force[i]];}}}for(j in l){if(lang.hasOwnProperty(l,j)){lang.augmentObject(l,this.getProvides(j));}}this.loaded=l;},_explode:function(){var r=this.required,i,mod;for(i in r){if(lang.hasOwnProperty(r,i)){mod=this.moduleInfo[i];if(mod){var req=this.getRequires(mod);if(req){YUI.ObjectUtil.appendArray(r,req);}}}}},_skin:function(){},formatSkin:function(skin,mod){var s=this.SKIN_PREFIX+skin;if(mod){s=s+"-"+mod;}return s;},parseSkin:function(mod){if(mod.indexOf(this.SKIN_PREFIX)===0){var a=mod.split("-");return{skin:a[1],module:a[2]};}return null;},_rollup:function(){var i,j,m,s,rollups={},r=this.required,roll,info=this.moduleInfo;if(this.dirty||!this.rollups){for(i in info){if(lang.hasOwnProperty(info,i)){m=info[i];if(m&&m.rollup){rollups[i]=m;}}}this.rollups=rollups;}for(;;){var rolled=false;for(i in rollups){if(!r[i]&&!this.loaded[i]){m=info[i];s=m.supersedes;roll=false;if(!m.rollup){continue;}var skin=(m.ext)?false:this.parseSkin(i),c=0;if(skin){for(j in r){if(lang.hasOwnProperty(r,j)){if(i!==j&&this.parseSkin(j)){c++;roll=(c>=m.rollup);if(roll){break;}}}}}else{for(j=0;j<s.length;j=j+1){if(this.loaded[s[j]]&&(!YUI.dupsAllowed[s[j]])){roll=false;break;}else{if(r[s[j]]){c++;roll=(c>=m.rollup);if(roll){break;}}}}}if(roll){r[i]=true;rolled=true;this.getRequires(m);}}}if(!rolled){break;}}},_reduce:function(){var i,j,s,m,r=this.required;for(i in r){if(i in this.loaded){delete r[i];}else{var skinDef=this.parseSkin(i);if(skinDef){if(!skinDef.module){var skin_pre=this.SKIN_PREFIX+skinDef.skin;for(j in r){if(lang.hasOwnProperty(r,j)){m=this.moduleInfo[j];var ext=m&&m.ext;if(!ext&&j!==i&&j.indexOf(skin_pre)>-1){delete r[j];}}}}}else{m=this.moduleInfo[i];s=m&&m.supersedes;if(s){for(j=0;j<s.length;j=j+1){if(s[j] in r){delete r[s[j]];}}}}}}},_onFailure:function(msg){YAHOO.log("Failure","info","loader");var f=this.onFailure;if(f){f.call(this.scope,{msg:"failure: "+msg,data:this.data,success:false});
10
}},_onTimeout:function(){YAHOO.log("Timeout","info","loader");var f=this.onTimeout;if(f){f.call(this.scope,{msg:"timeout",data:this.data,success:false});}},_sort:function(){var s=[],info=this.moduleInfo,loaded=this.loaded,checkOptional=!this.loadOptional,me=this;var requires=function(aa,bb){var mm=info[aa];if(loaded[bb]||!mm){return false;}var ii,rr=mm.expanded,after=mm.after,other=info[bb],optional=mm.optional;if(rr&&YUI.ArrayUtil.indexOf(rr,bb)>-1){return true;}if(after&&YUI.ArrayUtil.indexOf(after,bb)>-1){return true;}if(checkOptional&&optional&&YUI.ArrayUtil.indexOf(optional,bb)>-1){return true;}var ss=info[bb]&&info[bb].supersedes;if(ss){for(ii=0;ii<ss.length;ii=ii+1){if(requires(aa,ss[ii])){return true;}}}if(mm.ext&&mm.type=="css"&&!other.ext&&other.type=="css"){return true;}return false;};for(var i in this.required){if(lang.hasOwnProperty(this.required,i)){s.push(i);}}var p=0;for(;;){var l=s.length,a,b,j,k,moved=false;for(j=p;j<l;j=j+1){a=s[j];for(k=j+1;k<l;k=k+1){if(requires(a,s[k])){b=s.splice(k,1);s.splice(j,0,b[0]);moved=true;break;}}if(moved){break;}else{p=p+1;}}if(!moved){break;}}this.sorted=s;},toString:function(){var o={type:"YUILoader",base:this.base,filter:this.filter,required:this.required,loaded:this.loaded,inserted:this.inserted};lang.dump(o,1);},_combine:function(){this._combining=[];var self=this,s=this.sorted,len=s.length,js=this.comboBase,css=this.comboBase,target,startLen=js.length,i,m,type=this.loadType;YAHOO.log("type "+type);for(i=0;i<len;i=i+1){m=this.moduleInfo[s[i]];if(m&&!m.ext&&(!type||type===m.type)){target=this.root+m.path;target+="&";if(m.type=="js"){js+=target;}else{css+=target;}this._combining.push(s[i]);}}if(this._combining.length){YAHOO.log("Attempting to combine: "+this._combining,"info","loader");var callback=function(o){var c=this._combining,len=c.length,i,m;for(i=0;i<len;i=i+1){this.inserted[c[i]]=true;}this.loadNext(o.data);},loadScript=function(){if(js.length>startLen){YAHOO.util.Get.script(self._filter(js),{data:self._loading,onSuccess:callback,onFailure:self._onFailure,onTimeout:self._onTimeout,insertBefore:self.insertBefore,charset:self.charset,timeout:self.timeout,scope:self});}};if(css.length>startLen){YAHOO.util.Get.css(this._filter(css),{data:this._loading,onSuccess:loadScript,onFailure:this._onFailure,onTimeout:this._onTimeout,insertBefore:this.insertBefore,charset:this.charset,timeout:this.timeout,scope:self});}else{loadScript();}return;}else{this.loadNext(this._loading);}},insert:function(o,type){this.calculate(o);this._loading=true;this.loadType=type;if(this.combine){return this._combine();}if(!type){var self=this;this._internalCallback=function(){self._internalCallback=null;self.insert(null,"js");};this.insert(null,"css");return;}this.loadNext();},sandbox:function(o,type){this._config(o);if(!this.onSuccess){throw new Error("You must supply an onSuccess handler for your sandbox");}this._sandbox=true;var self=this;if(!type||type!=="js"){this._internalCallback=function(){self._internalCallback=null;self.sandbox(null,"js");};this.insert(null,"css");return;}if(!util.Connect){var ld=new YAHOO.util.YUILoader();ld.insert({base:this.base,filter:this.filter,require:"connection",insertBefore:this.insertBefore,charset:this.charset,onSuccess:function(){this.sandbox(null,"js");},scope:this},"js");return;}this._scriptText=[];this._loadCount=0;this._stopCount=this.sorted.length;this._xhr=[];this.calculate();var s=this.sorted,l=s.length,i,m,url;for(i=0;i<l;i=i+1){m=this.moduleInfo[s[i]];if(!m){this._onFailure("undefined module "+m);for(var j=0;j<this._xhr.length;j=j+1){this._xhr[j].abort();}return;}if(m.type!=="js"){this._loadCount++;continue;}url=m.fullpath;url=(url)?this._filter(url):this._url(m.path);var xhrData={success:function(o){var idx=o.argument[0],name=o.argument[2];this._scriptText[idx]=o.responseText;if(this.onProgress){this.onProgress.call(this.scope,{name:name,scriptText:o.responseText,xhrResponse:o,data:this.data});}this._loadCount++;if(this._loadCount>=this._stopCount){var v=this.varName||"YAHOO";var t="(function() {\n";var b="\nreturn "+v+";\n})();";var ref=eval(t+this._scriptText.join("\n")+b);this._pushEvents(ref);if(ref){this.onSuccess.call(this.scope,{reference:ref,data:this.data});}else{this._onFailure.call(this.varName+" reference failure");}}},failure:function(o){this.onFailure.call(this.scope,{msg:"XHR failure",xhrResponse:o,data:this.data});},scope:this,argument:[i,url,s[i]]};this._xhr.push(util.Connect.asyncRequest("GET",url,xhrData));}},loadNext:function(mname){if(!this._loading){return;}if(mname){if(mname!==this._loading){return;}this.inserted[mname]=true;if(this.onProgress){this.onProgress.call(this.scope,{name:mname,data:this.data});}}var s=this.sorted,len=s.length,i,m;for(i=0;i<len;i=i+1){if(s[i] in this.inserted){continue;}if(s[i]===this._loading){return;}m=this.moduleInfo[s[i]];if(!m){this.onFailure.call(this.scope,{msg:"undefined module "+m,data:this.data});return;}if(!this.loadType||this.loadType===m.type){this._loading=s[i];var fn=(m.type==="css")?util.Get.css:util.Get.script,url=m.fullpath,self=this,c=function(o){self.loadNext(o.data);};url=(url)?this._filter(url):this._url(m.path);if(env.ua.webkit&&env.ua.webkit<420&&m.type==="js"&&!m.varName){c=null;this._useYahooListener=true;}fn(url,{data:s[i],onSuccess:c,onFailure:this._onFailure,onTimeout:this._onTimeout,insertBefore:this.insertBefore,charset:this.charset,timeout:this.timeout,varName:m.varName,scope:self});return;}}this._loading=null;if(this._internalCallback){var f=this._internalCallback;this._internalCallback=null;f.call(this);}else{if(this.onSuccess){this._pushEvents();this.onSuccess.call(this.scope,{data:this.data});}}},_pushEvents:function(ref){var r=ref||YAHOO;if(r.util&&r.util.Event){r.util.Event._load();}},_filter:function(str){var f=this.filter;return(f)?str.replace(new RegExp(f.searchExp,"g"),f.replaceStr):str;},_url:function(path){return this._filter((this.base||"")+path);}};})();YAHOO.register("yuiloader",YAHOO.util.YUILoader,{version:"2.8.0r4",build:"2449"});
11
(function(){YAHOO.env._id_counter=YAHOO.env._id_counter||0;var E=YAHOO.util,L=YAHOO.lang,m=YAHOO.env.ua,A=YAHOO.lang.trim,d={},h={},N=/^t(?:able|d|h)$/i,X=/color$/i,K=window.document,W=K.documentElement,e="ownerDocument",n="defaultView",v="documentElement",t="compatMode",b="offsetLeft",P="offsetTop",u="offsetParent",Z="parentNode",l="nodeType",C="tagName",O="scrollLeft",i="scrollTop",Q="getBoundingClientRect",w="getComputedStyle",a="currentStyle",M="CSS1Compat",c="BackCompat",g="class",F="className",J="",B=" ",s="(?:^|\\s)",k="(?= |$)",U="g",p="position",f="fixed",V="relative",j="left",o="top",r="medium",q="borderLeftWidth",R="borderTopWidth",D=m.opera,I=m.webkit,H=m.gecko,T=m.ie;E.Dom={CUSTOM_ATTRIBUTES:(!W.hasAttribute)?{"for":"htmlFor","class":F}:{"htmlFor":"for","className":g},DOT_ATTRIBUTES:{},get:function(z){var AB,x,AA,y,Y,G;if(z){if(z[l]||z.item){return z;}if(typeof z==="string"){AB=z;z=K.getElementById(z);G=(z)?z.attributes:null;if(z&&G&&G.id&&G.id.value===AB){return z;}else{if(z&&K.all){z=null;x=K.all[AB];for(y=0,Y=x.length;y<Y;++y){if(x[y].id===AB){return x[y];}}}}return z;}if(YAHOO.util.Element&&z instanceof YAHOO.util.Element){z=z.get("element");}if("length" in z){AA=[];for(y=0,Y=z.length;y<Y;++y){AA[AA.length]=E.Dom.get(z[y]);}return AA;}return z;}return null;},getComputedStyle:function(G,Y){if(window[w]){return G[e][n][w](G,null)[Y];}else{if(G[a]){return E.Dom.IE_ComputedStyle.get(G,Y);}}},getStyle:function(G,Y){return E.Dom.batch(G,E.Dom._getStyle,Y);},_getStyle:function(){if(window[w]){return function(G,y){y=(y==="float")?y="cssFloat":E.Dom._toCamel(y);var x=G.style[y],Y;if(!x){Y=G[e][n][w](G,null);if(Y){x=Y[y];}}return x;};}else{if(W[a]){return function(G,y){var x;switch(y){case"opacity":x=100;try{x=G.filters["DXImageTransform.Microsoft.Alpha"].opacity;}catch(z){try{x=G.filters("alpha").opacity;}catch(Y){}}return x/100;case"float":y="styleFloat";default:y=E.Dom._toCamel(y);x=G[a]?G[a][y]:null;return(G.style[y]||x);}};}}}(),setStyle:function(G,Y,x){E.Dom.batch(G,E.Dom._setStyle,{prop:Y,val:x});},_setStyle:function(){if(T){return function(Y,G){var x=E.Dom._toCamel(G.prop),y=G.val;if(Y){switch(x){case"opacity":if(L.isString(Y.style.filter)){Y.style.filter="alpha(opacity="+y*100+")";if(!Y[a]||!Y[a].hasLayout){Y.style.zoom=1;}}break;case"float":x="styleFloat";default:Y.style[x]=y;}}else{}};}else{return function(Y,G){var x=E.Dom._toCamel(G.prop),y=G.val;if(Y){if(x=="float"){x="cssFloat";}Y.style[x]=y;}else{}};}}(),getXY:function(G){return E.Dom.batch(G,E.Dom._getXY);},_canPosition:function(G){return(E.Dom._getStyle(G,"display")!=="none"&&E.Dom._inDoc(G));},_getXY:function(){if(K[v][Q]){return function(y){var z,Y,AA,AF,AE,AD,AC,G,x,AB=Math.floor,AG=false;if(E.Dom._canPosition(y)){AA=y[Q]();AF=y[e];z=E.Dom.getDocumentScrollLeft(AF);Y=E.Dom.getDocumentScrollTop(AF);AG=[AB(AA[j]),AB(AA[o])];if(T&&m.ie<8){AE=2;AD=2;AC=AF[t];if(m.ie===6){if(AC!==c){AE=0;AD=0;}}if((AC===c)){G=S(AF[v],q);x=S(AF[v],R);if(G!==r){AE=parseInt(G,10);}if(x!==r){AD=parseInt(x,10);}}AG[0]-=AE;AG[1]-=AD;}if((Y||z)){AG[0]+=z;AG[1]+=Y;}AG[0]=AB(AG[0]);AG[1]=AB(AG[1]);}else{}return AG;};}else{return function(y){var x,Y,AA,AB,AC,z=false,G=y;if(E.Dom._canPosition(y)){z=[y[b],y[P]];x=E.Dom.getDocumentScrollLeft(y[e]);Y=E.Dom.getDocumentScrollTop(y[e]);AC=((H||m.webkit>519)?true:false);while((G=G[u])){z[0]+=G[b];z[1]+=G[P];if(AC){z=E.Dom._calcBorders(G,z);}}if(E.Dom._getStyle(y,p)!==f){G=y;while((G=G[Z])&&G[C]){AA=G[i];AB=G[O];if(H&&(E.Dom._getStyle(G,"overflow")!=="visible")){z=E.Dom._calcBorders(G,z);}if(AA||AB){z[0]-=AB;z[1]-=AA;}}z[0]+=x;z[1]+=Y;}else{if(D){z[0]-=x;z[1]-=Y;}else{if(I||H){z[0]+=x;z[1]+=Y;}}}z[0]=Math.floor(z[0]);z[1]=Math.floor(z[1]);}else{}return z;};}}(),getX:function(G){var Y=function(x){return E.Dom.getXY(x)[0];};return E.Dom.batch(G,Y,E.Dom,true);},getY:function(G){var Y=function(x){return E.Dom.getXY(x)[1];};return E.Dom.batch(G,Y,E.Dom,true);},setXY:function(G,x,Y){E.Dom.batch(G,E.Dom._setXY,{pos:x,noRetry:Y});},_setXY:function(G,z){var AA=E.Dom._getStyle(G,p),y=E.Dom.setStyle,AD=z.pos,Y=z.noRetry,AB=[parseInt(E.Dom.getComputedStyle(G,j),10),parseInt(E.Dom.getComputedStyle(G,o),10)],AC,x;if(AA=="static"){AA=V;y(G,p,AA);}AC=E.Dom._getXY(G);if(!AD||AC===false){return false;}if(isNaN(AB[0])){AB[0]=(AA==V)?0:G[b];}if(isNaN(AB[1])){AB[1]=(AA==V)?0:G[P];}if(AD[0]!==null){y(G,j,AD[0]-AC[0]+AB[0]+"px");}if(AD[1]!==null){y(G,o,AD[1]-AC[1]+AB[1]+"px");}if(!Y){x=E.Dom._getXY(G);if((AD[0]!==null&&x[0]!=AD[0])||(AD[1]!==null&&x[1]!=AD[1])){E.Dom._setXY(G,{pos:AD,noRetry:true});}}},setX:function(Y,G){E.Dom.setXY(Y,[G,null]);},setY:function(G,Y){E.Dom.setXY(G,[null,Y]);},getRegion:function(G){var Y=function(x){var y=false;if(E.Dom._canPosition(x)){y=E.Region.getRegion(x);}else{}return y;};return E.Dom.batch(G,Y,E.Dom,true);},getClientWidth:function(){return E.Dom.getViewportWidth();},getClientHeight:function(){return E.Dom.getViewportHeight();},getElementsByClassName:function(AB,AF,AC,AE,x,AD){AF=AF||"*";AC=(AC)?E.Dom.get(AC):null||K;if(!AC){return[];}var Y=[],G=AC.getElementsByTagName(AF),z=E.Dom.hasClass;for(var y=0,AA=G.length;y<AA;++y){if(z(G[y],AB)){Y[Y.length]=G[y];}}if(AE){E.Dom.batch(Y,AE,x,AD);}return Y;},hasClass:function(Y,G){return E.Dom.batch(Y,E.Dom._hasClass,G);},_hasClass:function(x,Y){var G=false,y;if(x&&Y){y=E.Dom._getAttribute(x,F)||J;if(Y.exec){G=Y.test(y);}else{G=Y&&(B+y+B).indexOf(B+Y+B)>-1;}}else{}return G;},addClass:function(Y,G){return E.Dom.batch(Y,E.Dom._addClass,G);},_addClass:function(x,Y){var G=false,y;if(x&&Y){y=E.Dom._getAttribute(x,F)||J;if(!E.Dom._hasClass(x,Y)){E.Dom.setAttribute(x,F,A(y+B+Y));G=true;}}else{}return G;},removeClass:function(Y,G){return E.Dom.batch(Y,E.Dom._removeClass,G);},_removeClass:function(y,x){var Y=false,AA,z,G;if(y&&x){AA=E.Dom._getAttribute(y,F)||J;E.Dom.setAttribute(y,F,AA.replace(E.Dom._getClassRegex(x),J));z=E.Dom._getAttribute(y,F);if(AA!==z){E.Dom.setAttribute(y,F,A(z));Y=true;if(E.Dom._getAttribute(y,F)===""){G=(y.hasAttribute&&y.hasAttribute(g))?g:F;
12
y.removeAttribute(G);}}}else{}return Y;},replaceClass:function(x,Y,G){return E.Dom.batch(x,E.Dom._replaceClass,{from:Y,to:G});},_replaceClass:function(y,x){var Y,AB,AA,G=false,z;if(y&&x){AB=x.from;AA=x.to;if(!AA){G=false;}else{if(!AB){G=E.Dom._addClass(y,x.to);}else{if(AB!==AA){z=E.Dom._getAttribute(y,F)||J;Y=(B+z.replace(E.Dom._getClassRegex(AB),B+AA)).split(E.Dom._getClassRegex(AA));Y.splice(1,0,B+AA);E.Dom.setAttribute(y,F,A(Y.join(J)));G=true;}}}}else{}return G;},generateId:function(G,x){x=x||"yui-gen";var Y=function(y){if(y&&y.id){return y.id;}var z=x+YAHOO.env._id_counter++;if(y){if(y[e]&&y[e].getElementById(z)){return E.Dom.generateId(y,z+x);}y.id=z;}return z;};return E.Dom.batch(G,Y,E.Dom,true)||Y.apply(E.Dom,arguments);},isAncestor:function(Y,x){Y=E.Dom.get(Y);x=E.Dom.get(x);var G=false;if((Y&&x)&&(Y[l]&&x[l])){if(Y.contains&&Y!==x){G=Y.contains(x);}else{if(Y.compareDocumentPosition){G=!!(Y.compareDocumentPosition(x)&16);}}}else{}return G;},inDocument:function(G,Y){return E.Dom._inDoc(E.Dom.get(G),Y);},_inDoc:function(Y,x){var G=false;if(Y&&Y[C]){x=x||Y[e];G=E.Dom.isAncestor(x[v],Y);}else{}return G;},getElementsBy:function(Y,AF,AB,AD,y,AC,AE){AF=AF||"*";AB=(AB)?E.Dom.get(AB):null||K;if(!AB){return[];}var x=[],G=AB.getElementsByTagName(AF);for(var z=0,AA=G.length;z<AA;++z){if(Y(G[z])){if(AE){x=G[z];break;}else{x[x.length]=G[z];}}}if(AD){E.Dom.batch(x,AD,y,AC);}return x;},getElementBy:function(x,G,Y){return E.Dom.getElementsBy(x,G,Y,null,null,null,true);},batch:function(x,AB,AA,z){var y=[],Y=(z)?AA:window;x=(x&&(x[C]||x.item))?x:E.Dom.get(x);if(x&&AB){if(x[C]||x.length===undefined){return AB.call(Y,x,AA);}for(var G=0;G<x.length;++G){y[y.length]=AB.call(Y,x[G],AA);}}else{return false;}return y;},getDocumentHeight:function(){var Y=(K[t]!=M||I)?K.body.scrollHeight:W.scrollHeight,G=Math.max(Y,E.Dom.getViewportHeight());return G;},getDocumentWidth:function(){var Y=(K[t]!=M||I)?K.body.scrollWidth:W.scrollWidth,G=Math.max(Y,E.Dom.getViewportWidth());return G;},getViewportHeight:function(){var G=self.innerHeight,Y=K[t];if((Y||T)&&!D){G=(Y==M)?W.clientHeight:K.body.clientHeight;}return G;},getViewportWidth:function(){var G=self.innerWidth,Y=K[t];if(Y||T){G=(Y==M)?W.clientWidth:K.body.clientWidth;}return G;},getAncestorBy:function(G,Y){while((G=G[Z])){if(E.Dom._testElement(G,Y)){return G;}}return null;},getAncestorByClassName:function(Y,G){Y=E.Dom.get(Y);if(!Y){return null;}var x=function(y){return E.Dom.hasClass(y,G);};return E.Dom.getAncestorBy(Y,x);},getAncestorByTagName:function(Y,G){Y=E.Dom.get(Y);if(!Y){return null;}var x=function(y){return y[C]&&y[C].toUpperCase()==G.toUpperCase();};return E.Dom.getAncestorBy(Y,x);},getPreviousSiblingBy:function(G,Y){while(G){G=G.previousSibling;if(E.Dom._testElement(G,Y)){return G;}}return null;},getPreviousSibling:function(G){G=E.Dom.get(G);if(!G){return null;}return E.Dom.getPreviousSiblingBy(G);},getNextSiblingBy:function(G,Y){while(G){G=G.nextSibling;if(E.Dom._testElement(G,Y)){return G;}}return null;},getNextSibling:function(G){G=E.Dom.get(G);if(!G){return null;}return E.Dom.getNextSiblingBy(G);},getFirstChildBy:function(G,x){var Y=(E.Dom._testElement(G.firstChild,x))?G.firstChild:null;return Y||E.Dom.getNextSiblingBy(G.firstChild,x);},getFirstChild:function(G,Y){G=E.Dom.get(G);if(!G){return null;}return E.Dom.getFirstChildBy(G);},getLastChildBy:function(G,x){if(!G){return null;}var Y=(E.Dom._testElement(G.lastChild,x))?G.lastChild:null;return Y||E.Dom.getPreviousSiblingBy(G.lastChild,x);},getLastChild:function(G){G=E.Dom.get(G);return E.Dom.getLastChildBy(G);},getChildrenBy:function(Y,y){var x=E.Dom.getFirstChildBy(Y,y),G=x?[x]:[];E.Dom.getNextSiblingBy(x,function(z){if(!y||y(z)){G[G.length]=z;}return false;});return G;},getChildren:function(G){G=E.Dom.get(G);if(!G){}return E.Dom.getChildrenBy(G);},getDocumentScrollLeft:function(G){G=G||K;return Math.max(G[v].scrollLeft,G.body.scrollLeft);},getDocumentScrollTop:function(G){G=G||K;return Math.max(G[v].scrollTop,G.body.scrollTop);},insertBefore:function(Y,G){Y=E.Dom.get(Y);G=E.Dom.get(G);if(!Y||!G||!G[Z]){return null;}return G[Z].insertBefore(Y,G);},insertAfter:function(Y,G){Y=E.Dom.get(Y);G=E.Dom.get(G);if(!Y||!G||!G[Z]){return null;}if(G.nextSibling){return G[Z].insertBefore(Y,G.nextSibling);}else{return G[Z].appendChild(Y);}},getClientRegion:function(){var x=E.Dom.getDocumentScrollTop(),Y=E.Dom.getDocumentScrollLeft(),y=E.Dom.getViewportWidth()+Y,G=E.Dom.getViewportHeight()+x;return new E.Region(x,y,G,Y);},setAttribute:function(Y,G,x){E.Dom.batch(Y,E.Dom._setAttribute,{attr:G,val:x});},_setAttribute:function(x,Y){var G=E.Dom._toCamel(Y.attr),y=Y.val;if(x&&x.setAttribute){if(E.Dom.DOT_ATTRIBUTES[G]){x[G]=y;}else{G=E.Dom.CUSTOM_ATTRIBUTES[G]||G;x.setAttribute(G,y);}}else{}},getAttribute:function(Y,G){return E.Dom.batch(Y,E.Dom._getAttribute,G);},_getAttribute:function(Y,G){var x;G=E.Dom.CUSTOM_ATTRIBUTES[G]||G;if(Y&&Y.getAttribute){x=Y.getAttribute(G,2);}else{}return x;},_toCamel:function(Y){var x=d;function G(y,z){return z.toUpperCase();}return x[Y]||(x[Y]=Y.indexOf("-")===-1?Y:Y.replace(/-([a-z])/gi,G));},_getClassRegex:function(Y){var G;if(Y!==undefined){if(Y.exec){G=Y;}else{G=h[Y];if(!G){Y=Y.replace(E.Dom._patterns.CLASS_RE_TOKENS,"\\$1");G=h[Y]=new RegExp(s+Y+k,U);}}}return G;},_patterns:{ROOT_TAG:/^body|html$/i,CLASS_RE_TOKENS:/([\.\(\)\^\$\*\+\?\|\[\]\{\}\\])/g},_testElement:function(G,Y){return G&&G[l]==1&&(!Y||Y(G));},_calcBorders:function(x,y){var Y=parseInt(E.Dom[w](x,R),10)||0,G=parseInt(E.Dom[w](x,q),10)||0;if(H){if(N.test(x[C])){Y=0;G=0;}}y[0]+=G;y[1]+=Y;return y;}};var S=E.Dom[w];if(m.opera){E.Dom[w]=function(Y,G){var x=S(Y,G);if(X.test(G)){x=E.Dom.Color.toRGB(x);}return x;};}if(m.webkit){E.Dom[w]=function(Y,G){var x=S(Y,G);if(x==="rgba(0, 0, 0, 0)"){x="transparent";}return x;};}if(m.ie&&m.ie>=8&&K.documentElement.hasAttribute){E.Dom.DOT_ATTRIBUTES.type=true;}})();YAHOO.util.Region=function(C,D,A,B){this.top=C;this.y=C;this[1]=C;this.right=D;this.bottom=A;this.left=B;this.x=B;this[0]=B;
13
this.width=this.right-this.left;this.height=this.bottom-this.top;};YAHOO.util.Region.prototype.contains=function(A){return(A.left>=this.left&&A.right<=this.right&&A.top>=this.top&&A.bottom<=this.bottom);};YAHOO.util.Region.prototype.getArea=function(){return((this.bottom-this.top)*(this.right-this.left));};YAHOO.util.Region.prototype.intersect=function(E){var C=Math.max(this.top,E.top),D=Math.min(this.right,E.right),A=Math.min(this.bottom,E.bottom),B=Math.max(this.left,E.left);if(A>=C&&D>=B){return new YAHOO.util.Region(C,D,A,B);}else{return null;}};YAHOO.util.Region.prototype.union=function(E){var C=Math.min(this.top,E.top),D=Math.max(this.right,E.right),A=Math.max(this.bottom,E.bottom),B=Math.min(this.left,E.left);return new YAHOO.util.Region(C,D,A,B);};YAHOO.util.Region.prototype.toString=function(){return("Region {"+"top: "+this.top+", right: "+this.right+", bottom: "+this.bottom+", left: "+this.left+", height: "+this.height+", width: "+this.width+"}");};YAHOO.util.Region.getRegion=function(D){var F=YAHOO.util.Dom.getXY(D),C=F[1],E=F[0]+D.offsetWidth,A=F[1]+D.offsetHeight,B=F[0];return new YAHOO.util.Region(C,E,A,B);};YAHOO.util.Point=function(A,B){if(YAHOO.lang.isArray(A)){B=A[1];A=A[0];}YAHOO.util.Point.superclass.constructor.call(this,B,A,B,A);};YAHOO.extend(YAHOO.util.Point,YAHOO.util.Region);(function(){var B=YAHOO.util,A="clientTop",F="clientLeft",J="parentNode",K="right",W="hasLayout",I="px",U="opacity",L="auto",D="borderLeftWidth",G="borderTopWidth",P="borderRightWidth",V="borderBottomWidth",S="visible",Q="transparent",N="height",E="width",H="style",T="currentStyle",R=/^width|height$/,O=/^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i,M={get:function(X,Z){var Y="",a=X[T][Z];if(Z===U){Y=B.Dom.getStyle(X,U);}else{if(!a||(a.indexOf&&a.indexOf(I)>-1)){Y=a;}else{if(B.Dom.IE_COMPUTED[Z]){Y=B.Dom.IE_COMPUTED[Z](X,Z);}else{if(O.test(a)){Y=B.Dom.IE.ComputedStyle.getPixel(X,Z);}else{Y=a;}}}}return Y;},getOffset:function(Z,e){var b=Z[T][e],X=e.charAt(0).toUpperCase()+e.substr(1),c="offset"+X,Y="pixel"+X,a="",d;if(b==L){d=Z[c];if(d===undefined){a=0;}a=d;if(R.test(e)){Z[H][e]=d;if(Z[c]>d){a=d-(Z[c]-d);}Z[H][e]=L;}}else{if(!Z[H][Y]&&!Z[H][e]){Z[H][e]=b;}a=Z[H][Y];}return a+I;},getBorderWidth:function(X,Z){var Y=null;if(!X[T][W]){X[H].zoom=1;}switch(Z){case G:Y=X[A];break;case V:Y=X.offsetHeight-X.clientHeight-X[A];break;case D:Y=X[F];break;case P:Y=X.offsetWidth-X.clientWidth-X[F];break;}return Y+I;},getPixel:function(Y,X){var a=null,b=Y[T][K],Z=Y[T][X];Y[H][K]=Z;a=Y[H].pixelRight;Y[H][K]=b;return a+I;},getMargin:function(Y,X){var Z;if(Y[T][X]==L){Z=0+I;}else{Z=B.Dom.IE.ComputedStyle.getPixel(Y,X);}return Z;},getVisibility:function(Y,X){var Z;while((Z=Y[T])&&Z[X]=="inherit"){Y=Y[J];}return(Z)?Z[X]:S;},getColor:function(Y,X){return B.Dom.Color.toRGB(Y[T][X])||Q;},getBorderColor:function(Y,X){var Z=Y[T],a=Z[X]||Z.color;return B.Dom.Color.toRGB(B.Dom.Color.toHex(a));}},C={};C.top=C.right=C.bottom=C.left=C[E]=C[N]=M.getOffset;C.color=M.getColor;C[G]=C[P]=C[V]=C[D]=M.getBorderWidth;C.marginTop=C.marginRight=C.marginBottom=C.marginLeft=M.getMargin;C.visibility=M.getVisibility;C.borderColor=C.borderTopColor=C.borderRightColor=C.borderBottomColor=C.borderLeftColor=M.getBorderColor;B.Dom.IE_COMPUTED=C;B.Dom.IE_ComputedStyle=M;})();(function(){var C="toString",A=parseInt,B=RegExp,D=YAHOO.util;D.Dom.Color={KEYWORDS:{black:"000",silver:"c0c0c0",gray:"808080",white:"fff",maroon:"800000",red:"f00",purple:"800080",fuchsia:"f0f",green:"008000",lime:"0f0",olive:"808000",yellow:"ff0",navy:"000080",blue:"00f",teal:"008080",aqua:"0ff"},re_RGB:/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,re_hex:/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,re_hex3:/([0-9A-F])/gi,toRGB:function(E){if(!D.Dom.Color.re_RGB.test(E)){E=D.Dom.Color.toHex(E);}if(D.Dom.Color.re_hex.exec(E)){E="rgb("+[A(B.$1,16),A(B.$2,16),A(B.$3,16)].join(", ")+")";}return E;},toHex:function(H){H=D.Dom.Color.KEYWORDS[H]||H;if(D.Dom.Color.re_RGB.exec(H)){var G=(B.$1.length===1)?"0"+B.$1:Number(B.$1),F=(B.$2.length===1)?"0"+B.$2:Number(B.$2),E=(B.$3.length===1)?"0"+B.$3:Number(B.$3);H=[G[C](16),F[C](16),E[C](16)].join("");}if(H.length<6){H=H.replace(D.Dom.Color.re_hex3,"$1$1");}if(H!=="transparent"&&H.indexOf("#")<0){H="#"+H;}return H.toLowerCase();}};}());YAHOO.register("dom",YAHOO.util.Dom,{version:"2.8.0r4",build:"2449"});YAHOO.util.CustomEvent=function(D,C,B,A,E){this.type=D;this.scope=C||window;this.silent=B;this.fireOnce=E;this.fired=false;this.firedWith=null;this.signature=A||YAHOO.util.CustomEvent.LIST;this.subscribers=[];if(!this.silent){}var F="_YUICEOnSubscribe";if(D!==F){this.subscribeEvent=new YAHOO.util.CustomEvent(F,this,true);}this.lastError=null;};YAHOO.util.CustomEvent.LIST=0;YAHOO.util.CustomEvent.FLAT=1;YAHOO.util.CustomEvent.prototype={subscribe:function(B,C,D){if(!B){throw new Error("Invalid callback for subscriber to '"+this.type+"'");}if(this.subscribeEvent){this.subscribeEvent.fire(B,C,D);}var A=new YAHOO.util.Subscriber(B,C,D);if(this.fireOnce&&this.fired){this.notify(A,this.firedWith);}else{this.subscribers.push(A);}},unsubscribe:function(D,F){if(!D){return this.unsubscribeAll();}var E=false;for(var B=0,A=this.subscribers.length;B<A;++B){var C=this.subscribers[B];if(C&&C.contains(D,F)){this._delete(B);E=true;}}return E;},fire:function(){this.lastError=null;var H=[],A=this.subscribers.length;var D=[].slice.call(arguments,0),C=true,F,B=false;if(this.fireOnce){if(this.fired){return true;}else{this.firedWith=D;}}this.fired=true;if(!A&&this.silent){return true;}if(!this.silent){}var E=this.subscribers.slice();for(F=0;F<A;++F){var G=E[F];if(!G){B=true;}else{C=this.notify(G,D);if(false===C){if(!this.silent){}break;}}}return(C!==false);},notify:function(F,C){var B,H=null,E=F.getScope(this.scope),A=YAHOO.util.Event.throwErrors;if(!this.silent){}if(this.signature==YAHOO.util.CustomEvent.FLAT){if(C.length>0){H=C[0];}try{B=F.fn.call(E,H,F.obj);}catch(G){this.lastError=G;if(A){throw G;}}}else{try{B=F.fn.call(E,this.type,C,F.obj);}catch(D){this.lastError=D;if(A){throw D;}}}return B;},unsubscribeAll:function(){var A=this.subscribers.length,B;for(B=A-1;B>-1;B--){this._delete(B);}this.subscribers=[];return A;},_delete:function(A){var B=this.subscribers[A];if(B){delete B.fn;delete B.obj;}this.subscribers.splice(A,1);},toString:function(){return"CustomEvent: "+"'"+this.type+"', "+"context: "+this.scope;}};YAHOO.util.Subscriber=function(A,B,C){this.fn=A;this.obj=YAHOO.lang.isUndefined(B)?null:B;this.overrideContext=C;};YAHOO.util.Subscriber.prototype.getScope=function(A){if(this.overrideContext){if(this.overrideContext===true){return this.obj;}else{return this.overrideContext;}}return A;};YAHOO.util.Subscriber.prototype.contains=function(A,B){if(B){return(this.fn==A&&this.obj==B);}else{return(this.fn==A);}};YAHOO.util.Subscriber.prototype.toString=function(){return"Subscriber { obj: "+this.obj+", overrideContext: "+(this.overrideContext||"no")+" }";};if(!YAHOO.util.Event){YAHOO.util.Event=function(){var G=false,H=[],J=[],A=0,E=[],B=0,C={63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9},D=YAHOO.env.ua.ie,F="focusin",I="focusout";return{POLL_RETRYS:500,POLL_INTERVAL:40,EL:0,TYPE:1,FN:2,WFN:3,UNLOAD_OBJ:3,ADJ_SCOPE:4,OBJ:5,OVERRIDE:6,CAPTURE:7,lastError:null,isSafari:YAHOO.env.ua.webkit,webkit:YAHOO.env.ua.webkit,isIE:D,_interval:null,_dri:null,_specialTypes:{focusin:(D?"focusin":"focus"),focusout:(D?"focusout":"blur")},DOMReady:false,throwErrors:false,startInterval:function(){if(!this._interval){this._interval=YAHOO.lang.later(this.POLL_INTERVAL,this,this._tryPreloadAttach,null,true);}},onAvailable:function(Q,M,O,P,N){var K=(YAHOO.lang.isString(Q))?[Q]:Q;for(var L=0;L<K.length;L=L+1){E.push({id:K[L],fn:M,obj:O,overrideContext:P,checkReady:N});}A=this.POLL_RETRYS;this.startInterval();},onContentReady:function(N,K,L,M){this.onAvailable(N,K,L,M,true);},onDOMReady:function(){this.DOMReadyEvent.subscribe.apply(this.DOMReadyEvent,arguments);},_addListener:function(M,K,V,P,T,Y){if(!V||!V.call){return false;}if(this._isValidCollection(M)){var W=true;for(var Q=0,S=M.length;Q<S;++Q){W=this.on(M[Q],K,V,P,T)&&W;}return W;}else{if(YAHOO.lang.isString(M)){var O=this.getEl(M);if(O){M=O;}else{this.onAvailable(M,function(){YAHOO.util.Event._addListener(M,K,V,P,T,Y);});return true;}}}if(!M){return false;}if("unload"==K&&P!==this){J[J.length]=[M,K,V,P,T];return true;}var L=M;if(T){if(T===true){L=P;}else{L=T;}}var N=function(Z){return V.call(L,YAHOO.util.Event.getEvent(Z,M),P);};var X=[M,K,V,N,L,P,T,Y];var R=H.length;H[R]=X;try{this._simpleAdd(M,K,N,Y);}catch(U){this.lastError=U;this.removeListener(M,K,V);return false;}return true;},_getType:function(K){return this._specialTypes[K]||K;},addListener:function(M,P,L,N,O){var K=((P==F||P==I)&&!YAHOO.env.ua.ie)?true:false;return this._addListener(M,this._getType(P),L,N,O,K);},addFocusListener:function(L,K,M,N){return this.on(L,F,K,M,N);},removeFocusListener:function(L,K){return this.removeListener(L,F,K);},addBlurListener:function(L,K,M,N){return this.on(L,I,K,M,N);},removeBlurListener:function(L,K){return this.removeListener(L,I,K);},removeListener:function(L,K,R){var M,P,U;K=this._getType(K);if(typeof L=="string"){L=this.getEl(L);}else{if(this._isValidCollection(L)){var S=true;for(M=L.length-1;M>-1;M--){S=(this.removeListener(L[M],K,R)&&S);}return S;}}if(!R||!R.call){return this.purgeElement(L,false,K);}if("unload"==K){for(M=J.length-1;M>-1;M--){U=J[M];if(U&&U[0]==L&&U[1]==K&&U[2]==R){J.splice(M,1);return true;}}return false;}var N=null;var O=arguments[3];if("undefined"===typeof O){O=this._getCacheIndex(H,L,K,R);}if(O>=0){N=H[O];}if(!L||!N){return false;}var T=N[this.CAPTURE]===true?true:false;try{this._simpleRemove(L,K,N[this.WFN],T);}catch(Q){this.lastError=Q;return false;}delete H[O][this.WFN];delete H[O][this.FN];H.splice(O,1);return true;},getTarget:function(M,L){var K=M.target||M.srcElement;return this.resolveTextNode(K);},resolveTextNode:function(L){try{if(L&&3==L.nodeType){return L.parentNode;}}catch(K){}return L;},getPageX:function(L){var K=L.pageX;if(!K&&0!==K){K=L.clientX||0;if(this.isIE){K+=this._getScrollLeft();}}return K;},getPageY:function(K){var L=K.pageY;if(!L&&0!==L){L=K.clientY||0;if(this.isIE){L+=this._getScrollTop();}}return L;},getXY:function(K){return[this.getPageX(K),this.getPageY(K)];},getRelatedTarget:function(L){var K=L.relatedTarget;if(!K){if(L.type=="mouseout"){K=L.toElement;
14
}else{if(L.type=="mouseover"){K=L.fromElement;}}}return this.resolveTextNode(K);},getTime:function(M){if(!M.time){var L=new Date().getTime();try{M.time=L;}catch(K){this.lastError=K;return L;}}return M.time;},stopEvent:function(K){this.stopPropagation(K);this.preventDefault(K);},stopPropagation:function(K){if(K.stopPropagation){K.stopPropagation();}else{K.cancelBubble=true;}},preventDefault:function(K){if(K.preventDefault){K.preventDefault();}else{K.returnValue=false;}},getEvent:function(M,K){var L=M||window.event;if(!L){var N=this.getEvent.caller;while(N){L=N.arguments[0];if(L&&Event==L.constructor){break;}N=N.caller;}}return L;},getCharCode:function(L){var K=L.keyCode||L.charCode||0;if(YAHOO.env.ua.webkit&&(K in C)){K=C[K];}return K;},_getCacheIndex:function(M,P,Q,O){for(var N=0,L=M.length;N<L;N=N+1){var K=M[N];if(K&&K[this.FN]==O&&K[this.EL]==P&&K[this.TYPE]==Q){return N;}}return -1;},generateId:function(K){var L=K.id;if(!L){L="yuievtautoid-"+B;++B;K.id=L;}return L;},_isValidCollection:function(L){try{return(L&&typeof L!=="string"&&L.length&&!L.tagName&&!L.alert&&typeof L[0]!=="undefined");}catch(K){return false;}},elCache:{},getEl:function(K){return(typeof K==="string")?document.getElementById(K):K;},clearCache:function(){},DOMReadyEvent:new YAHOO.util.CustomEvent("DOMReady",YAHOO,0,0,1),_load:function(L){if(!G){G=true;var K=YAHOO.util.Event;K._ready();K._tryPreloadAttach();}},_ready:function(L){var K=YAHOO.util.Event;if(!K.DOMReady){K.DOMReady=true;K.DOMReadyEvent.fire();K._simpleRemove(document,"DOMContentLoaded",K._ready);}},_tryPreloadAttach:function(){if(E.length===0){A=0;if(this._interval){this._interval.cancel();this._interval=null;}return;}if(this.locked){return;}if(this.isIE){if(!this.DOMReady){this.startInterval();return;}}this.locked=true;var Q=!G;if(!Q){Q=(A>0&&E.length>0);}var P=[];var R=function(T,U){var S=T;if(U.overrideContext){if(U.overrideContext===true){S=U.obj;}else{S=U.overrideContext;}}U.fn.call(S,U.obj);};var L,K,O,N,M=[];for(L=0,K=E.length;L<K;L=L+1){O=E[L];if(O){N=this.getEl(O.id);if(N){if(O.checkReady){if(G||N.nextSibling||!Q){M.push(O);E[L]=null;}}else{R(N,O);E[L]=null;}}else{P.push(O);}}}for(L=0,K=M.length;L<K;L=L+1){O=M[L];R(this.getEl(O.id),O);}A--;if(Q){for(L=E.length-1;L>-1;L--){O=E[L];if(!O||!O.id){E.splice(L,1);}}this.startInterval();}else{if(this._interval){this._interval.cancel();this._interval=null;}}this.locked=false;},purgeElement:function(O,P,R){var M=(YAHOO.lang.isString(O))?this.getEl(O):O;var Q=this.getListeners(M,R),N,K;if(Q){for(N=Q.length-1;N>-1;N--){var L=Q[N];this.removeListener(M,L.type,L.fn);}}if(P&&M&&M.childNodes){for(N=0,K=M.childNodes.length;N<K;++N){this.purgeElement(M.childNodes[N],P,R);}}},getListeners:function(M,K){var P=[],L;if(!K){L=[H,J];}else{if(K==="unload"){L=[J];}else{K=this._getType(K);L=[H];}}var R=(YAHOO.lang.isString(M))?this.getEl(M):M;for(var O=0;O<L.length;O=O+1){var T=L[O];if(T){for(var Q=0,S=T.length;Q<S;++Q){var N=T[Q];if(N&&N[this.EL]===R&&(!K||K===N[this.TYPE])){P.push({type:N[this.TYPE],fn:N[this.FN],obj:N[this.OBJ],adjust:N[this.OVERRIDE],scope:N[this.ADJ_SCOPE],index:Q});}}}}return(P.length)?P:null;},_unload:function(R){var L=YAHOO.util.Event,O,N,M,Q,P,S=J.slice(),K;for(O=0,Q=J.length;O<Q;++O){M=S[O];if(M){K=window;if(M[L.ADJ_SCOPE]){if(M[L.ADJ_SCOPE]===true){K=M[L.UNLOAD_OBJ];}else{K=M[L.ADJ_SCOPE];}}M[L.FN].call(K,L.getEvent(R,M[L.EL]),M[L.UNLOAD_OBJ]);S[O]=null;}}M=null;K=null;J=null;if(H){for(N=H.length-1;N>-1;N--){M=H[N];if(M){L.removeListener(M[L.EL],M[L.TYPE],M[L.FN],N);}}M=null;}L._simpleRemove(window,"unload",L._unload);},_getScrollLeft:function(){return this._getScroll()[1];},_getScrollTop:function(){return this._getScroll()[0];},_getScroll:function(){var K=document.documentElement,L=document.body;if(K&&(K.scrollTop||K.scrollLeft)){return[K.scrollTop,K.scrollLeft];}else{if(L){return[L.scrollTop,L.scrollLeft];}else{return[0,0];}}},regCE:function(){},_simpleAdd:function(){if(window.addEventListener){return function(M,N,L,K){M.addEventListener(N,L,(K));};}else{if(window.attachEvent){return function(M,N,L,K){M.attachEvent("on"+N,L);};}else{return function(){};}}}(),_simpleRemove:function(){if(window.removeEventListener){return function(M,N,L,K){M.removeEventListener(N,L,(K));};}else{if(window.detachEvent){return function(L,M,K){L.detachEvent("on"+M,K);};}else{return function(){};}}}()};}();(function(){var EU=YAHOO.util.Event;EU.on=EU.addListener;EU.onFocus=EU.addFocusListener;EU.onBlur=EU.addBlurListener;
15
/* DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */
16
if(EU.isIE){if(self!==self.top){document.onreadystatechange=function(){if(document.readyState=="complete"){document.onreadystatechange=null;EU._ready();}};}else{YAHOO.util.Event.onDOMReady(YAHOO.util.Event._tryPreloadAttach,YAHOO.util.Event,true);var n=document.createElement("p");EU._dri=setInterval(function(){try{n.doScroll("left");clearInterval(EU._dri);EU._dri=null;EU._ready();n=null;}catch(ex){}},EU.POLL_INTERVAL);}}else{if(EU.webkit&&EU.webkit<525){EU._dri=setInterval(function(){var rs=document.readyState;if("loaded"==rs||"complete"==rs){clearInterval(EU._dri);EU._dri=null;EU._ready();}},EU.POLL_INTERVAL);}else{EU._simpleAdd(document,"DOMContentLoaded",EU._ready);}}EU._simpleAdd(window,"load",EU._load);EU._simpleAdd(window,"unload",EU._unload);EU._tryPreloadAttach();})();}YAHOO.util.EventProvider=function(){};YAHOO.util.EventProvider.prototype={__yui_events:null,__yui_subscribers:null,subscribe:function(A,C,F,E){this.__yui_events=this.__yui_events||{};var D=this.__yui_events[A];if(D){D.subscribe(C,F,E);}else{this.__yui_subscribers=this.__yui_subscribers||{};var B=this.__yui_subscribers;if(!B[A]){B[A]=[];}B[A].push({fn:C,obj:F,overrideContext:E});}},unsubscribe:function(C,E,G){this.__yui_events=this.__yui_events||{};var A=this.__yui_events;if(C){var F=A[C];if(F){return F.unsubscribe(E,G);}}else{var B=true;for(var D in A){if(YAHOO.lang.hasOwnProperty(A,D)){B=B&&A[D].unsubscribe(E,G);}}return B;}return false;},unsubscribeAll:function(A){return this.unsubscribe(A);
17
},createEvent:function(B,G){this.__yui_events=this.__yui_events||{};var E=G||{},D=this.__yui_events,F;if(D[B]){}else{F=new YAHOO.util.CustomEvent(B,E.scope||this,E.silent,YAHOO.util.CustomEvent.FLAT,E.fireOnce);D[B]=F;if(E.onSubscribeCallback){F.subscribeEvent.subscribe(E.onSubscribeCallback);}this.__yui_subscribers=this.__yui_subscribers||{};var A=this.__yui_subscribers[B];if(A){for(var C=0;C<A.length;++C){F.subscribe(A[C].fn,A[C].obj,A[C].overrideContext);}}}return D[B];},fireEvent:function(B){this.__yui_events=this.__yui_events||{};var D=this.__yui_events[B];if(!D){return null;}var A=[];for(var C=1;C<arguments.length;++C){A.push(arguments[C]);}return D.fire.apply(D,A);},hasEvent:function(A){if(this.__yui_events){if(this.__yui_events[A]){return true;}}return false;}};(function(){var A=YAHOO.util.Event,C=YAHOO.lang;YAHOO.util.KeyListener=function(D,I,E,F){if(!D){}else{if(!I){}else{if(!E){}}}if(!F){F=YAHOO.util.KeyListener.KEYDOWN;}var G=new YAHOO.util.CustomEvent("keyPressed");this.enabledEvent=new YAHOO.util.CustomEvent("enabled");this.disabledEvent=new YAHOO.util.CustomEvent("disabled");if(C.isString(D)){D=document.getElementById(D);}if(C.isFunction(E)){G.subscribe(E);}else{G.subscribe(E.fn,E.scope,E.correctScope);}function H(O,N){if(!I.shift){I.shift=false;}if(!I.alt){I.alt=false;}if(!I.ctrl){I.ctrl=false;}if(O.shiftKey==I.shift&&O.altKey==I.alt&&O.ctrlKey==I.ctrl){var J,M=I.keys,L;if(YAHOO.lang.isArray(M)){for(var K=0;K<M.length;K++){J=M[K];L=A.getCharCode(O);if(J==L){G.fire(L,O);break;}}}else{L=A.getCharCode(O);if(M==L){G.fire(L,O);}}}}this.enable=function(){if(!this.enabled){A.on(D,F,H);this.enabledEvent.fire(I);}this.enabled=true;};this.disable=function(){if(this.enabled){A.removeListener(D,F,H);this.disabledEvent.fire(I);}this.enabled=false;};this.toString=function(){return"KeyListener ["+I.keys+"] "+D.tagName+(D.id?"["+D.id+"]":"");};};var B=YAHOO.util.KeyListener;B.KEYDOWN="keydown";B.KEYUP="keyup";B.KEY={ALT:18,BACK_SPACE:8,CAPS_LOCK:20,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,META:224,NUM_LOCK:144,PAGE_DOWN:34,PAGE_UP:33,PAUSE:19,PRINTSCREEN:44,RIGHT:39,SCROLL_LOCK:145,SHIFT:16,SPACE:32,TAB:9,UP:38};})();YAHOO.register("event",YAHOO.util.Event,{version:"2.8.0r4",build:"2449"});YAHOO.util.Connect={_msxml_progid:["Microsoft.XMLHTTP","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP"],_http_headers:{},_has_http_headers:false,_use_default_post_header:true,_default_post_header:"application/x-www-form-urlencoded; charset=UTF-8",_default_form_header:"application/x-www-form-urlencoded",_use_default_xhr_header:true,_default_xhr_header:"XMLHttpRequest",_has_default_headers:true,_default_headers:{},_poll:{},_timeOut:{},_polling_interval:50,_transaction_id:0,startEvent:new YAHOO.util.CustomEvent("start"),completeEvent:new YAHOO.util.CustomEvent("complete"),successEvent:new YAHOO.util.CustomEvent("success"),failureEvent:new YAHOO.util.CustomEvent("failure"),abortEvent:new YAHOO.util.CustomEvent("abort"),_customEvents:{onStart:["startEvent","start"],onComplete:["completeEvent","complete"],onSuccess:["successEvent","success"],onFailure:["failureEvent","failure"],onUpload:["uploadEvent","upload"],onAbort:["abortEvent","abort"]},setProgId:function(A){this._msxml_progid.unshift(A);},setDefaultPostHeader:function(A){if(typeof A=="string"){this._default_post_header=A;}else{if(typeof A=="boolean"){this._use_default_post_header=A;}}},setDefaultXhrHeader:function(A){if(typeof A=="string"){this._default_xhr_header=A;}else{this._use_default_xhr_header=A;}},setPollingInterval:function(A){if(typeof A=="number"&&isFinite(A)){this._polling_interval=A;}},createXhrObject:function(F){var D,A,B;try{A=new XMLHttpRequest();D={conn:A,tId:F,xhr:true};}catch(C){for(B=0;B<this._msxml_progid.length;++B){try{A=new ActiveXObject(this._msxml_progid[B]);D={conn:A,tId:F,xhr:true};break;}catch(E){}}}finally{return D;}},getConnectionObject:function(A){var C,D=this._transaction_id;try{if(!A){C=this.createXhrObject(D);}else{C={tId:D};if(A==="xdr"){C.conn=this._transport;C.xdr=true;}else{if(A==="upload"){C.upload=true;}}}if(C){this._transaction_id++;}}catch(B){}return C;},asyncRequest:function(G,D,F,A){var E,C,B=(F&&F.argument)?F.argument:null;if(this._isFileUpload){C="upload";}else{if(F.xdr){C="xdr";}}E=this.getConnectionObject(C);if(!E){return null;}else{if(F&&F.customevents){this.initCustomEvents(E,F);}if(this._isFormSubmit){if(this._isFileUpload){this.uploadFile(E,F,D,A);return E;}if(G.toUpperCase()=="GET"){if(this._sFormData.length!==0){D+=((D.indexOf("?")==-1)?"?":"&")+this._sFormData;}}else{if(G.toUpperCase()=="POST"){A=A?this._sFormData+"&"+A:this._sFormData;}}}if(G.toUpperCase()=="GET"&&(F&&F.cache===false)){D+=((D.indexOf("?")==-1)?"?":"&")+"rnd="+new Date().valueOf().toString();}if(this._use_default_xhr_header){if(!this._default_headers["X-Requested-With"]){this.initHeader("X-Requested-With",this._default_xhr_header,true);}}if((G.toUpperCase()==="POST"&&this._use_default_post_header)&&this._isFormSubmit===false){this.initHeader("Content-Type",this._default_post_header);}if(E.xdr){this.xdr(E,G,D,F,A);return E;}E.conn.open(G,D,true);if(this._has_default_headers||this._has_http_headers){this.setHeader(E);}this.handleReadyState(E,F);E.conn.send(A||"");if(this._isFormSubmit===true){this.resetFormState();}this.startEvent.fire(E,B);if(E.startEvent){E.startEvent.fire(E,B);}return E;}},initCustomEvents:function(A,C){var B;for(B in C.customevents){if(this._customEvents[B][0]){A[this._customEvents[B][0]]=new YAHOO.util.CustomEvent(this._customEvents[B][1],(C.scope)?C.scope:null);A[this._customEvents[B][0]].subscribe(C.customevents[B]);}}},handleReadyState:function(C,D){var B=this,A=(D&&D.argument)?D.argument:null;if(D&&D.timeout){this._timeOut[C.tId]=window.setTimeout(function(){B.abort(C,D,true);},D.timeout);}this._poll[C.tId]=window.setInterval(function(){if(C.conn&&C.conn.readyState===4){window.clearInterval(B._poll[C.tId]);delete B._poll[C.tId];if(D&&D.timeout){window.clearTimeout(B._timeOut[C.tId]);delete B._timeOut[C.tId];}B.completeEvent.fire(C,A);if(C.completeEvent){C.completeEvent.fire(C,A);}B.handleTransactionResponse(C,D);}},this._polling_interval);},handleTransactionResponse:function(B,I,D){var E,A,G=(I&&I.argument)?I.argument:null,C=(B.r&&B.r.statusText==="xdr:success")?true:false,H=(B.r&&B.r.statusText==="xdr:failure")?true:false,J=D;try{if((B.conn.status!==undefined&&B.conn.status!==0)||C){E=B.conn.status;}else{if(H&&!J){E=0;}else{E=13030;}}}catch(F){E=13030;}if((E>=200&&E<300)||E===1223||C){A=B.xdr?B.r:this.createResponseObject(B,G);if(I&&I.success){if(!I.scope){I.success(A);}else{I.success.apply(I.scope,[A]);}}this.successEvent.fire(A);if(B.successEvent){B.successEvent.fire(A);}}else{switch(E){case 12002:case 12029:case 12030:case 12031:case 12152:case 13030:A=this.createExceptionObject(B.tId,G,(D?D:false));if(I&&I.failure){if(!I.scope){I.failure(A);}else{I.failure.apply(I.scope,[A]);}}break;default:A=(B.xdr)?B.response:this.createResponseObject(B,G);if(I&&I.failure){if(!I.scope){I.failure(A);}else{I.failure.apply(I.scope,[A]);}}}this.failureEvent.fire(A);if(B.failureEvent){B.failureEvent.fire(A);}}this.releaseObject(B);A=null;},createResponseObject:function(A,G){var D={},I={},E,C,F,B;try{C=A.conn.getAllResponseHeaders();F=C.split("\n");for(E=0;E<F.length;E++){B=F[E].indexOf(":");if(B!=-1){I[F[E].substring(0,B)]=YAHOO.lang.trim(F[E].substring(B+2));}}}catch(H){}D.tId=A.tId;D.status=(A.conn.status==1223)?204:A.conn.status;D.statusText=(A.conn.status==1223)?"No Content":A.conn.statusText;D.getResponseHeader=I;D.getAllResponseHeaders=C;D.responseText=A.conn.responseText;D.responseXML=A.conn.responseXML;if(G){D.argument=G;}return D;},createExceptionObject:function(H,D,A){var F=0,G="communication failure",C=-1,B="transaction aborted",E={};E.tId=H;if(A){E.status=C;E.statusText=B;}else{E.status=F;E.statusText=G;}if(D){E.argument=D;}return E;},initHeader:function(A,D,C){var B=(C)?this._default_headers:this._http_headers;B[A]=D;if(C){this._has_default_headers=true;}else{this._has_http_headers=true;}},setHeader:function(A){var B;if(this._has_default_headers){for(B in this._default_headers){if(YAHOO.lang.hasOwnProperty(this._default_headers,B)){A.conn.setRequestHeader(B,this._default_headers[B]);}}}if(this._has_http_headers){for(B in this._http_headers){if(YAHOO.lang.hasOwnProperty(this._http_headers,B)){A.conn.setRequestHeader(B,this._http_headers[B]);
18
}}this._http_headers={};this._has_http_headers=false;}},resetDefaultHeaders:function(){this._default_headers={};this._has_default_headers=false;},abort:function(E,G,A){var D,B=(G&&G.argument)?G.argument:null;E=E||{};if(E.conn){if(E.xhr){if(this.isCallInProgress(E)){E.conn.abort();window.clearInterval(this._poll[E.tId]);delete this._poll[E.tId];if(A){window.clearTimeout(this._timeOut[E.tId]);delete this._timeOut[E.tId];}D=true;}}else{if(E.xdr){E.conn.abort(E.tId);D=true;}}}else{if(E.upload){var C="yuiIO"+E.tId;var F=document.getElementById(C);if(F){YAHOO.util.Event.removeListener(F,"load");document.body.removeChild(F);if(A){window.clearTimeout(this._timeOut[E.tId]);delete this._timeOut[E.tId];}D=true;}}else{D=false;}}if(D===true){this.abortEvent.fire(E,B);if(E.abortEvent){E.abortEvent.fire(E,B);}this.handleTransactionResponse(E,G,true);}return D;},isCallInProgress:function(A){A=A||{};if(A.xhr&&A.conn){return A.conn.readyState!==4&&A.conn.readyState!==0;}else{if(A.xdr&&A.conn){return A.conn.isCallInProgress(A.tId);}else{if(A.upload===true){return document.getElementById("yuiIO"+A.tId)?true:false;}else{return false;}}}},releaseObject:function(A){if(A&&A.conn){A.conn=null;A=null;}}};(function(){var G=YAHOO.util.Connect,H={};function D(I){var J='<object id="YUIConnectionSwf" type="application/x-shockwave-flash" data="'+I+'" width="0" height="0">'+'<param name="movie" value="'+I+'">'+'<param name="allowScriptAccess" value="always">'+"</object>",K=document.createElement("div");document.body.appendChild(K);K.innerHTML=J;}function B(L,I,J,M,K){H[parseInt(L.tId)]={"o":L,"c":M};if(K){M.method=I;M.data=K;}L.conn.send(J,M,L.tId);}function E(I){D(I);G._transport=document.getElementById("YUIConnectionSwf");}function C(){G.xdrReadyEvent.fire();}function A(J,I){if(J){G.startEvent.fire(J,I.argument);if(J.startEvent){J.startEvent.fire(J,I.argument);}}}function F(J){var K=H[J.tId].o,I=H[J.tId].c;if(J.statusText==="xdr:start"){A(K,I);return;}J.responseText=decodeURI(J.responseText);K.r=J;if(I.argument){K.r.argument=I.argument;}this.handleTransactionResponse(K,I,J.statusText==="xdr:abort"?true:false);delete H[J.tId];}G.xdr=B;G.swf=D;G.transport=E;G.xdrReadyEvent=new YAHOO.util.CustomEvent("xdrReady");G.xdrReady=C;G.handleXdrResponse=F;})();(function(){var D=YAHOO.util.Connect,F=YAHOO.util.Event;D._isFormSubmit=false;D._isFileUpload=false;D._formNode=null;D._sFormData=null;D._submitElementValue=null;D.uploadEvent=new YAHOO.util.CustomEvent("upload"),D._hasSubmitListener=function(){if(F){F.addListener(document,"click",function(J){var I=F.getTarget(J),H=I.nodeName.toLowerCase();if((H==="input"||H==="button")&&(I.type&&I.type.toLowerCase()=="submit")){D._submitElementValue=encodeURIComponent(I.name)+"="+encodeURIComponent(I.value);}});return true;}return false;}();function G(T,O,J){var S,I,R,P,W,Q=false,M=[],V=0,L,N,K,U,H;this.resetFormState();if(typeof T=="string"){S=(document.getElementById(T)||document.forms[T]);}else{if(typeof T=="object"){S=T;}else{return;}}if(O){this.createFrame(J?J:null);this._isFormSubmit=true;this._isFileUpload=true;this._formNode=S;return;}for(L=0,N=S.elements.length;L<N;++L){I=S.elements[L];W=I.disabled;R=I.name;if(!W&&R){R=encodeURIComponent(R)+"=";P=encodeURIComponent(I.value);switch(I.type){case"select-one":if(I.selectedIndex>-1){H=I.options[I.selectedIndex];M[V++]=R+encodeURIComponent((H.attributes.value&&H.attributes.value.specified)?H.value:H.text);}break;case"select-multiple":if(I.selectedIndex>-1){for(K=I.selectedIndex,U=I.options.length;K<U;++K){H=I.options[K];if(H.selected){M[V++]=R+encodeURIComponent((H.attributes.value&&H.attributes.value.specified)?H.value:H.text);}}}break;case"radio":case"checkbox":if(I.checked){M[V++]=R+P;}break;case"file":case undefined:case"reset":case"button":break;case"submit":if(Q===false){if(this._hasSubmitListener&&this._submitElementValue){M[V++]=this._submitElementValue;}Q=true;}break;default:M[V++]=R+P;}}}this._isFormSubmit=true;this._sFormData=M.join("&");this.initHeader("Content-Type",this._default_form_header);return this._sFormData;}function C(){this._isFormSubmit=false;this._isFileUpload=false;this._formNode=null;this._sFormData="";}function B(H){var I="yuiIO"+this._transaction_id,J;if(YAHOO.env.ua.ie){J=document.createElement('<iframe id="'+I+'" name="'+I+'" />');if(typeof H=="boolean"){J.src="javascript:false";}}else{J=document.createElement("iframe");J.id=I;J.name=I;}J.style.position="absolute";J.style.top="-1000px";J.style.left="-1000px";document.body.appendChild(J);}function E(H){var K=[],I=H.split("&"),J,L;for(J=0;J<I.length;J++){L=I[J].indexOf("=");if(L!=-1){K[J]=document.createElement("input");K[J].type="hidden";K[J].name=decodeURIComponent(I[J].substring(0,L));K[J].value=decodeURIComponent(I[J].substring(L+1));this._formNode.appendChild(K[J]);}}return K;}function A(K,V,L,J){var Q="yuiIO"+K.tId,R="multipart/form-data",T=document.getElementById(Q),M=(document.documentMode&&document.documentMode===8)?true:false,W=this,S=(V&&V.argument)?V.argument:null,U,P,I,O,H,N;H={action:this._formNode.getAttribute("action"),method:this._formNode.getAttribute("method"),target:this._formNode.getAttribute("target")};this._formNode.setAttribute("action",L);this._formNode.setAttribute("method","POST");this._formNode.setAttribute("target",Q);if(YAHOO.env.ua.ie&&!M){this._formNode.setAttribute("encoding",R);}else{this._formNode.setAttribute("enctype",R);}if(J){U=this.appendPostData(J);}this._formNode.submit();this.startEvent.fire(K,S);if(K.startEvent){K.startEvent.fire(K,S);}if(V&&V.timeout){this._timeOut[K.tId]=window.setTimeout(function(){W.abort(K,V,true);},V.timeout);}if(U&&U.length>0){for(P=0;P<U.length;P++){this._formNode.removeChild(U[P]);}}for(I in H){if(YAHOO.lang.hasOwnProperty(H,I)){if(H[I]){this._formNode.setAttribute(I,H[I]);}else{this._formNode.removeAttribute(I);}}}this.resetFormState();N=function(){if(V&&V.timeout){window.clearTimeout(W._timeOut[K.tId]);delete W._timeOut[K.tId];}W.completeEvent.fire(K,S);if(K.completeEvent){K.completeEvent.fire(K,S);
19
}O={tId:K.tId,argument:V.argument};try{O.responseText=T.contentWindow.document.body?T.contentWindow.document.body.innerHTML:T.contentWindow.document.documentElement.textContent;O.responseXML=T.contentWindow.document.XMLDocument?T.contentWindow.document.XMLDocument:T.contentWindow.document;}catch(X){}if(V&&V.upload){if(!V.scope){V.upload(O);}else{V.upload.apply(V.scope,[O]);}}W.uploadEvent.fire(O);if(K.uploadEvent){K.uploadEvent.fire(O);}F.removeListener(T,"load",N);setTimeout(function(){document.body.removeChild(T);W.releaseObject(K);},100);};F.addListener(T,"load",N);}D.setForm=G;D.resetFormState=C;D.createFrame=B;D.appendPostData=E;D.uploadFile=A;})();YAHOO.register("connection",YAHOO.util.Connect,{version:"2.8.0r4",build:"2449"});(function(){var B=YAHOO.util;var A=function(D,C,E,F){if(!D){}this.init(D,C,E,F);};A.NAME="Anim";A.prototype={toString:function(){var C=this.getEl()||{};var D=C.id||C.tagName;return(this.constructor.NAME+": "+D);},patterns:{noNegatives:/width|height|opacity|padding/i,offsetAttribute:/^((width|height)|(top|left))$/,defaultUnit:/width|height|top$|bottom$|left$|right$/i,offsetUnit:/\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i},doMethod:function(C,E,D){return this.method(this.currentFrame,E,D-E,this.totalFrames);},setAttribute:function(C,F,E){var D=this.getEl();if(this.patterns.noNegatives.test(C)){F=(F>0)?F:0;}if(C in D&&!("style" in D&&C in D.style)){D[C]=F;}else{B.Dom.setStyle(D,C,F+E);}},getAttribute:function(C){var E=this.getEl();var G=B.Dom.getStyle(E,C);if(G!=="auto"&&!this.patterns.offsetUnit.test(G)){return parseFloat(G);}var D=this.patterns.offsetAttribute.exec(C)||[];var H=!!(D[3]);var F=!!(D[2]);if("style" in E){if(F||(B.Dom.getStyle(E,"position")=="absolute"&&H)){G=E["offset"+D[0].charAt(0).toUpperCase()+D[0].substr(1)];}else{G=0;}}else{if(C in E){G=E[C];}}return G;},getDefaultUnit:function(C){if(this.patterns.defaultUnit.test(C)){return"px";}return"";},setRuntimeAttribute:function(D){var I;var E;var F=this.attributes;this.runtimeAttributes[D]={};var H=function(J){return(typeof J!=="undefined");};if(!H(F[D]["to"])&&!H(F[D]["by"])){return false;}I=(H(F[D]["from"]))?F[D]["from"]:this.getAttribute(D);if(H(F[D]["to"])){E=F[D]["to"];}else{if(H(F[D]["by"])){if(I.constructor==Array){E=[];for(var G=0,C=I.length;G<C;++G){E[G]=I[G]+F[D]["by"][G]*1;}}else{E=I+F[D]["by"]*1;}}}this.runtimeAttributes[D].start=I;this.runtimeAttributes[D].end=E;this.runtimeAttributes[D].unit=(H(F[D].unit))?F[D]["unit"]:this.getDefaultUnit(D);return true;},init:function(E,J,I,C){var D=false;var F=null;var H=0;E=B.Dom.get(E);this.attributes=J||{};this.duration=!YAHOO.lang.isUndefined(I)?I:1;this.method=C||B.Easing.easeNone;this.useSeconds=true;this.currentFrame=0;this.totalFrames=B.AnimMgr.fps;this.setEl=function(M){E=B.Dom.get(M);};this.getEl=function(){return E;};this.isAnimated=function(){return D;};this.getStartTime=function(){return F;};this.runtimeAttributes={};this.animate=function(){if(this.isAnimated()){return false;}this.currentFrame=0;this.totalFrames=(this.useSeconds)?Math.ceil(B.AnimMgr.fps*this.duration):this.duration;if(this.duration===0&&this.useSeconds){this.totalFrames=1;}B.AnimMgr.registerElement(this);return true;};this.stop=function(M){if(!this.isAnimated()){return false;}if(M){this.currentFrame=this.totalFrames;this._onTween.fire();}B.AnimMgr.stop(this);};var L=function(){this.onStart.fire();this.runtimeAttributes={};for(var M in this.attributes){this.setRuntimeAttribute(M);}D=true;H=0;F=new Date();};var K=function(){var O={duration:new Date()-this.getStartTime(),currentFrame:this.currentFrame};O.toString=function(){return("duration: "+O.duration+", currentFrame: "+O.currentFrame);};this.onTween.fire(O);var N=this.runtimeAttributes;for(var M in N){this.setAttribute(M,this.doMethod(M,N[M].start,N[M].end),N[M].unit);}H+=1;};var G=function(){var M=(new Date()-F)/1000;var N={duration:M,frames:H,fps:H/M};N.toString=function(){return("duration: "+N.duration+", frames: "+N.frames+", fps: "+N.fps);};D=false;H=0;this.onComplete.fire(N);};this._onStart=new B.CustomEvent("_start",this,true);this.onStart=new B.CustomEvent("start",this);this.onTween=new B.CustomEvent("tween",this);this._onTween=new B.CustomEvent("_tween",this,true);this.onComplete=new B.CustomEvent("complete",this);this._onComplete=new B.CustomEvent("_complete",this,true);this._onStart.subscribe(L);this._onTween.subscribe(K);this._onComplete.subscribe(G);}};B.Anim=A;})();YAHOO.util.AnimMgr=new function(){var C=null;var B=[];var A=0;this.fps=1000;this.delay=1;this.registerElement=function(F){B[B.length]=F;A+=1;F._onStart.fire();this.start();};this.unRegister=function(G,F){F=F||E(G);if(!G.isAnimated()||F===-1){return false;}G._onComplete.fire();B.splice(F,1);A-=1;if(A<=0){this.stop();}return true;};this.start=function(){if(C===null){C=setInterval(this.run,this.delay);}};this.stop=function(H){if(!H){clearInterval(C);for(var G=0,F=B.length;G<F;++G){this.unRegister(B[0],0);}B=[];C=null;A=0;}else{this.unRegister(H);}};this.run=function(){for(var H=0,F=B.length;H<F;++H){var G=B[H];if(!G||!G.isAnimated()){continue;}if(G.currentFrame<G.totalFrames||G.totalFrames===null){G.currentFrame+=1;if(G.useSeconds){D(G);}G._onTween.fire();}else{YAHOO.util.AnimMgr.stop(G,H);}}};var E=function(H){for(var G=0,F=B.length;G<F;++G){if(B[G]===H){return G;}}return -1;};var D=function(G){var J=G.totalFrames;var I=G.currentFrame;var H=(G.currentFrame*G.duration*1000/G.totalFrames);var F=(new Date()-G.getStartTime());var K=0;if(F<G.duration*1000){K=Math.round((F/H-1)*G.currentFrame);}else{K=J-(I+1);}if(K>0&&isFinite(K)){if(G.currentFrame+K>=J){K=J-(I+1);}G.currentFrame+=K;}};this._queue=B;this._getIndex=E;};YAHOO.util.Bezier=new function(){this.getPosition=function(E,D){var F=E.length;var C=[];for(var B=0;B<F;++B){C[B]=[E[B][0],E[B][1]];}for(var A=1;A<F;++A){for(B=0;B<F-A;++B){C[B][0]=(1-D)*C[B][0]+D*C[parseInt(B+1,10)][0];C[B][1]=(1-D)*C[B][1]+D*C[parseInt(B+1,10)][1];}}return[C[0][0],C[0][1]];};};(function(){var A=function(F,E,G,H){A.superclass.constructor.call(this,F,E,G,H);};A.NAME="ColorAnim";A.DEFAULT_BGCOLOR="#fff";var C=YAHOO.util;YAHOO.extend(A,C.Anim);var D=A.superclass;var B=A.prototype;B.patterns.color=/color$/i;B.patterns.rgb=/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;B.patterns.hex=/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;B.patterns.hex3=/^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;B.patterns.transparent=/^transparent|rgba\(0, 0, 0, 0\)$/;B.parseColor=function(E){if(E.length==3){return E;}var F=this.patterns.hex.exec(E);if(F&&F.length==4){return[parseInt(F[1],16),parseInt(F[2],16),parseInt(F[3],16)];}F=this.patterns.rgb.exec(E);if(F&&F.length==4){return[parseInt(F[1],10),parseInt(F[2],10),parseInt(F[3],10)];}F=this.patterns.hex3.exec(E);if(F&&F.length==4){return[parseInt(F[1]+F[1],16),parseInt(F[2]+F[2],16),parseInt(F[3]+F[3],16)];
20
}return null;};B.getAttribute=function(E){var G=this.getEl();if(this.patterns.color.test(E)){var I=YAHOO.util.Dom.getStyle(G,E);var H=this;if(this.patterns.transparent.test(I)){var F=YAHOO.util.Dom.getAncestorBy(G,function(J){return !H.patterns.transparent.test(I);});if(F){I=C.Dom.getStyle(F,E);}else{I=A.DEFAULT_BGCOLOR;}}}else{I=D.getAttribute.call(this,E);}return I;};B.doMethod=function(F,J,G){var I;if(this.patterns.color.test(F)){I=[];for(var H=0,E=J.length;H<E;++H){I[H]=D.doMethod.call(this,F,J[H],G[H]);}I="rgb("+Math.floor(I[0])+","+Math.floor(I[1])+","+Math.floor(I[2])+")";}else{I=D.doMethod.call(this,F,J,G);}return I;};B.setRuntimeAttribute=function(F){D.setRuntimeAttribute.call(this,F);if(this.patterns.color.test(F)){var H=this.attributes;var J=this.parseColor(this.runtimeAttributes[F].start);var G=this.parseColor(this.runtimeAttributes[F].end);if(typeof H[F]["to"]==="undefined"&&typeof H[F]["by"]!=="undefined"){G=this.parseColor(H[F].by);for(var I=0,E=J.length;I<E;++I){G[I]=J[I]+G[I];}}this.runtimeAttributes[F].start=J;this.runtimeAttributes[F].end=G;}};C.ColorAnim=A;})();
21
/*
22
TERMS OF USE - EASING EQUATIONS
23
Open source under the BSD License.
24
Copyright 2001 Robert Penner All rights reserved.
25
26
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
27
28
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
29
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
30
 * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
31
32
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
*/
34
YAHOO.util.Easing={easeNone:function(B,A,D,C){return D*B/C+A;},easeIn:function(B,A,D,C){return D*(B/=C)*B+A;},easeOut:function(B,A,D,C){return -D*(B/=C)*(B-2)+A;},easeBoth:function(B,A,D,C){if((B/=C/2)<1){return D/2*B*B+A;}return -D/2*((--B)*(B-2)-1)+A;},easeInStrong:function(B,A,D,C){return D*(B/=C)*B*B*B+A;},easeOutStrong:function(B,A,D,C){return -D*((B=B/C-1)*B*B*B-1)+A;},easeBothStrong:function(B,A,D,C){if((B/=C/2)<1){return D/2*B*B*B*B+A;}return -D/2*((B-=2)*B*B*B-2)+A;},elasticIn:function(C,A,G,F,B,E){if(C==0){return A;}if((C/=F)==1){return A+G;}if(!E){E=F*0.3;}if(!B||B<Math.abs(G)){B=G;var D=E/4;}else{var D=E/(2*Math.PI)*Math.asin(G/B);}return -(B*Math.pow(2,10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E))+A;},elasticOut:function(C,A,G,F,B,E){if(C==0){return A;}if((C/=F)==1){return A+G;}if(!E){E=F*0.3;}if(!B||B<Math.abs(G)){B=G;var D=E/4;}else{var D=E/(2*Math.PI)*Math.asin(G/B);}return B*Math.pow(2,-10*C)*Math.sin((C*F-D)*(2*Math.PI)/E)+G+A;},elasticBoth:function(C,A,G,F,B,E){if(C==0){return A;}if((C/=F/2)==2){return A+G;}if(!E){E=F*(0.3*1.5);}if(!B||B<Math.abs(G)){B=G;var D=E/4;}else{var D=E/(2*Math.PI)*Math.asin(G/B);}if(C<1){return -0.5*(B*Math.pow(2,10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E))+A;}return B*Math.pow(2,-10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E)*0.5+G+A;},backIn:function(B,A,E,D,C){if(typeof C=="undefined"){C=1.70158;}return E*(B/=D)*B*((C+1)*B-C)+A;},backOut:function(B,A,E,D,C){if(typeof C=="undefined"){C=1.70158;}return E*((B=B/D-1)*B*((C+1)*B+C)+1)+A;},backBoth:function(B,A,E,D,C){if(typeof C=="undefined"){C=1.70158;}if((B/=D/2)<1){return E/2*(B*B*(((C*=(1.525))+1)*B-C))+A;}return E/2*((B-=2)*B*(((C*=(1.525))+1)*B+C)+2)+A;},bounceIn:function(B,A,D,C){return D-YAHOO.util.Easing.bounceOut(C-B,0,D,C)+A;},bounceOut:function(B,A,D,C){if((B/=C)<(1/2.75)){return D*(7.5625*B*B)+A;}else{if(B<(2/2.75)){return D*(7.5625*(B-=(1.5/2.75))*B+0.75)+A;}else{if(B<(2.5/2.75)){return D*(7.5625*(B-=(2.25/2.75))*B+0.9375)+A;}}}return D*(7.5625*(B-=(2.625/2.75))*B+0.984375)+A;},bounceBoth:function(B,A,D,C){if(B<C/2){return YAHOO.util.Easing.bounceIn(B*2,0,D,C)*0.5+A;}return YAHOO.util.Easing.bounceOut(B*2-C,0,D,C)*0.5+D*0.5+A;}};(function(){var A=function(H,G,I,J){if(H){A.superclass.constructor.call(this,H,G,I,J);}};A.NAME="Motion";var E=YAHOO.util;YAHOO.extend(A,E.ColorAnim);var F=A.superclass;var C=A.prototype;C.patterns.points=/^points$/i;C.setAttribute=function(G,I,H){if(this.patterns.points.test(G)){H=H||"px";F.setAttribute.call(this,"left",I[0],H);F.setAttribute.call(this,"top",I[1],H);}else{F.setAttribute.call(this,G,I,H);}};C.getAttribute=function(G){if(this.patterns.points.test(G)){var H=[F.getAttribute.call(this,"left"),F.getAttribute.call(this,"top")];}else{H=F.getAttribute.call(this,G);}return H;};C.doMethod=function(G,K,H){var J=null;if(this.patterns.points.test(G)){var I=this.method(this.currentFrame,0,100,this.totalFrames)/100;J=E.Bezier.getPosition(this.runtimeAttributes[G],I);}else{J=F.doMethod.call(this,G,K,H);}return J;};C.setRuntimeAttribute=function(P){if(this.patterns.points.test(P)){var H=this.getEl();var J=this.attributes;var G;var L=J["points"]["control"]||[];var I;var M,O;if(L.length>0&&!(L[0] instanceof Array)){L=[L];}else{var K=[];for(M=0,O=L.length;M<O;++M){K[M]=L[M];}L=K;}if(E.Dom.getStyle(H,"position")=="static"){E.Dom.setStyle(H,"position","relative");}if(D(J["points"]["from"])){E.Dom.setXY(H,J["points"]["from"]);
35
}else{E.Dom.setXY(H,E.Dom.getXY(H));}G=this.getAttribute("points");if(D(J["points"]["to"])){I=B.call(this,J["points"]["to"],G);var N=E.Dom.getXY(this.getEl());for(M=0,O=L.length;M<O;++M){L[M]=B.call(this,L[M],G);}}else{if(D(J["points"]["by"])){I=[G[0]+J["points"]["by"][0],G[1]+J["points"]["by"][1]];for(M=0,O=L.length;M<O;++M){L[M]=[G[0]+L[M][0],G[1]+L[M][1]];}}}this.runtimeAttributes[P]=[G];if(L.length>0){this.runtimeAttributes[P]=this.runtimeAttributes[P].concat(L);}this.runtimeAttributes[P][this.runtimeAttributes[P].length]=I;}else{F.setRuntimeAttribute.call(this,P);}};var B=function(G,I){var H=E.Dom.getXY(this.getEl());G=[G[0]-H[0]+I[0],G[1]-H[1]+I[1]];return G;};var D=function(G){return(typeof G!=="undefined");};E.Motion=A;})();(function(){var D=function(F,E,G,H){if(F){D.superclass.constructor.call(this,F,E,G,H);}};D.NAME="Scroll";var B=YAHOO.util;YAHOO.extend(D,B.ColorAnim);var C=D.superclass;var A=D.prototype;A.doMethod=function(E,H,F){var G=null;if(E=="scroll"){G=[this.method(this.currentFrame,H[0],F[0]-H[0],this.totalFrames),this.method(this.currentFrame,H[1],F[1]-H[1],this.totalFrames)];}else{G=C.doMethod.call(this,E,H,F);}return G;};A.getAttribute=function(E){var G=null;var F=this.getEl();if(E=="scroll"){G=[F.scrollLeft,F.scrollTop];}else{G=C.getAttribute.call(this,E);}return G;};A.setAttribute=function(E,H,G){var F=this.getEl();if(E=="scroll"){F.scrollLeft=H[0];F.scrollTop=H[1];}else{C.setAttribute.call(this,E,H,G);}};B.Scroll=D;})();YAHOO.register("animation",YAHOO.util.Anim,{version:"2.8.0r4",build:"2449"});if(!YAHOO.util.DragDropMgr){YAHOO.util.DragDropMgr=function(){var A=YAHOO.util.Event,B=YAHOO.util.Dom;return{useShim:false,_shimActive:false,_shimState:false,_debugShim:false,_createShim:function(){var C=document.createElement("div");C.id="yui-ddm-shim";if(document.body.firstChild){document.body.insertBefore(C,document.body.firstChild);}else{document.body.appendChild(C);}C.style.display="none";C.style.backgroundColor="red";C.style.position="absolute";C.style.zIndex="99999";B.setStyle(C,"opacity","0");this._shim=C;A.on(C,"mouseup",this.handleMouseUp,this,true);A.on(C,"mousemove",this.handleMouseMove,this,true);A.on(window,"scroll",this._sizeShim,this,true);},_sizeShim:function(){if(this._shimActive){var C=this._shim;C.style.height=B.getDocumentHeight()+"px";C.style.width=B.getDocumentWidth()+"px";C.style.top="0";C.style.left="0";}},_activateShim:function(){if(this.useShim){if(!this._shim){this._createShim();}this._shimActive=true;var C=this._shim,D="0";if(this._debugShim){D=".5";}B.setStyle(C,"opacity",D);this._sizeShim();C.style.display="block";}},_deactivateShim:function(){this._shim.style.display="none";this._shimActive=false;},_shim:null,ids:{},handleIds:{},dragCurrent:null,dragOvers:{},deltaX:0,deltaY:0,preventDefault:true,stopPropagation:true,initialized:false,locked:false,interactionInfo:null,init:function(){this.initialized=true;},POINT:0,INTERSECT:1,STRICT_INTERSECT:2,mode:0,_execOnAll:function(E,D){for(var F in this.ids){for(var C in this.ids[F]){var G=this.ids[F][C];if(!this.isTypeOfDD(G)){continue;}G[E].apply(G,D);}}},_onLoad:function(){this.init();A.on(document,"mouseup",this.handleMouseUp,this,true);A.on(document,"mousemove",this.handleMouseMove,this,true);A.on(window,"unload",this._onUnload,this,true);A.on(window,"resize",this._onResize,this,true);},_onResize:function(C){this._execOnAll("resetConstraints",[]);},lock:function(){this.locked=true;},unlock:function(){this.locked=false;},isLocked:function(){return this.locked;},locationCache:{},useCache:true,clickPixelThresh:3,clickTimeThresh:1000,dragThreshMet:false,clickTimeout:null,startX:0,startY:0,fromTimeout:false,regDragDrop:function(D,C){if(!this.initialized){this.init();}if(!this.ids[C]){this.ids[C]={};}this.ids[C][D.id]=D;},removeDDFromGroup:function(E,C){if(!this.ids[C]){this.ids[C]={};}var D=this.ids[C];if(D&&D[E.id]){delete D[E.id];}},_remove:function(E){for(var D in E.groups){if(D){var C=this.ids[D];if(C&&C[E.id]){delete C[E.id];}}}delete this.handleIds[E.id];},regHandle:function(D,C){if(!this.handleIds[D]){this.handleIds[D]={};}this.handleIds[D][C]=C;},isDragDrop:function(C){return(this.getDDById(C))?true:false;},getRelated:function(H,D){var G=[];for(var F in H.groups){for(var E in this.ids[F]){var C=this.ids[F][E];if(!this.isTypeOfDD(C)){continue;}if(!D||C.isTarget){G[G.length]=C;}}}return G;},isLegalTarget:function(G,F){var D=this.getRelated(G,true);for(var E=0,C=D.length;E<C;++E){if(D[E].id==F.id){return true;}}return false;},isTypeOfDD:function(C){return(C&&C.__ygDragDrop);},isHandle:function(D,C){return(this.handleIds[D]&&this.handleIds[D][C]);},getDDById:function(D){for(var C in this.ids){if(this.ids[C][D]){return this.ids[C][D];}}return null;},handleMouseDown:function(E,D){this.currentTarget=YAHOO.util.Event.getTarget(E);this.dragCurrent=D;var C=D.getEl();this.startX=YAHOO.util.Event.getPageX(E);this.startY=YAHOO.util.Event.getPageY(E);this.deltaX=this.startX-C.offsetLeft;this.deltaY=this.startY-C.offsetTop;this.dragThreshMet=false;this.clickTimeout=setTimeout(function(){var F=YAHOO.util.DDM;F.startDrag(F.startX,F.startY);F.fromTimeout=true;},this.clickTimeThresh);},startDrag:function(C,E){if(this.dragCurrent&&this.dragCurrent.useShim){this._shimState=this.useShim;this.useShim=true;}this._activateShim();clearTimeout(this.clickTimeout);var D=this.dragCurrent;if(D&&D.events.b4StartDrag){D.b4StartDrag(C,E);D.fireEvent("b4StartDragEvent",{x:C,y:E});}if(D&&D.events.startDrag){D.startDrag(C,E);D.fireEvent("startDragEvent",{x:C,y:E});}this.dragThreshMet=true;},handleMouseUp:function(C){if(this.dragCurrent){clearTimeout(this.clickTimeout);if(this.dragThreshMet){if(this.fromTimeout){this.fromTimeout=false;this.handleMouseMove(C);}this.fromTimeout=false;this.fireEvents(C,true);}else{}this.stopDrag(C);this.stopEvent(C);}},stopEvent:function(C){if(this.stopPropagation){YAHOO.util.Event.stopPropagation(C);}if(this.preventDefault){YAHOO.util.Event.preventDefault(C);}},stopDrag:function(E,D){var C=this.dragCurrent;if(C&&!D){if(this.dragThreshMet){if(C.events.b4EndDrag){C.b4EndDrag(E);C.fireEvent("b4EndDragEvent",{e:E});}if(C.events.endDrag){C.endDrag(E);C.fireEvent("endDragEvent",{e:E});}}if(C.events.mouseUp){C.onMouseUp(E);C.fireEvent("mouseUpEvent",{e:E});}}if(this._shimActive){this._deactivateShim();if(this.dragCurrent&&this.dragCurrent.useShim){this.useShim=this._shimState;this._shimState=false;}}this.dragCurrent=null;this.dragOvers={};},handleMouseMove:function(F){var C=this.dragCurrent;if(C){if(YAHOO.util.Event.isIE&&!F.button){this.stopEvent(F);return this.handleMouseUp(F);}else{if(F.clientX<0||F.clientY<0){}}if(!this.dragThreshMet){var E=Math.abs(this.startX-YAHOO.util.Event.getPageX(F));var D=Math.abs(this.startY-YAHOO.util.Event.getPageY(F));if(E>this.clickPixelThresh||D>this.clickPixelThresh){this.startDrag(this.startX,this.startY);}}if(this.dragThreshMet){if(C&&C.events.b4Drag){C.b4Drag(F);C.fireEvent("b4DragEvent",{e:F});}if(C&&C.events.drag){C.onDrag(F);C.fireEvent("dragEvent",{e:F});}if(C){this.fireEvents(F,false);}}this.stopEvent(F);}},fireEvents:function(V,L){var a=this.dragCurrent;if(!a||a.isLocked()||a.dragOnly){return;}var N=YAHOO.util.Event.getPageX(V),M=YAHOO.util.Event.getPageY(V),P=new YAHOO.util.Point(N,M),K=a.getTargetCoord(P.x,P.y),F=a.getDragEl(),E=["out","over","drop","enter"],U=new YAHOO.util.Region(K.y,K.x+F.offsetWidth,K.y+F.offsetHeight,K.x),I=[],D={},Q=[],c={outEvts:[],overEvts:[],dropEvts:[],enterEvts:[]};for(var S in this.dragOvers){var d=this.dragOvers[S];if(!this.isTypeOfDD(d)){continue;
36
}if(!this.isOverTarget(P,d,this.mode,U)){c.outEvts.push(d);}I[S]=true;delete this.dragOvers[S];}for(var R in a.groups){if("string"!=typeof R){continue;}for(S in this.ids[R]){var G=this.ids[R][S];if(!this.isTypeOfDD(G)){continue;}if(G.isTarget&&!G.isLocked()&&G!=a){if(this.isOverTarget(P,G,this.mode,U)){D[R]=true;if(L){c.dropEvts.push(G);}else{if(!I[G.id]){c.enterEvts.push(G);}else{c.overEvts.push(G);}this.dragOvers[G.id]=G;}}}}}this.interactionInfo={out:c.outEvts,enter:c.enterEvts,over:c.overEvts,drop:c.dropEvts,point:P,draggedRegion:U,sourceRegion:this.locationCache[a.id],validDrop:L};for(var C in D){Q.push(C);}if(L&&!c.dropEvts.length){this.interactionInfo.validDrop=false;if(a.events.invalidDrop){a.onInvalidDrop(V);a.fireEvent("invalidDropEvent",{e:V});}}for(S=0;S<E.length;S++){var Y=null;if(c[E[S]+"Evts"]){Y=c[E[S]+"Evts"];}if(Y&&Y.length){var H=E[S].charAt(0).toUpperCase()+E[S].substr(1),X="onDrag"+H,J="b4Drag"+H,O="drag"+H+"Event",W="drag"+H;if(this.mode){if(a.events[J]){a[J](V,Y,Q);a.fireEvent(J+"Event",{event:V,info:Y,group:Q});}if(a.events[W]){a[X](V,Y,Q);a.fireEvent(O,{event:V,info:Y,group:Q});}}else{for(var Z=0,T=Y.length;Z<T;++Z){if(a.events[J]){a[J](V,Y[Z].id,Q[0]);a.fireEvent(J+"Event",{event:V,info:Y[Z].id,group:Q[0]});}if(a.events[W]){a[X](V,Y[Z].id,Q[0]);a.fireEvent(O,{event:V,info:Y[Z].id,group:Q[0]});}}}}}},getBestMatch:function(E){var G=null;var D=E.length;if(D==1){G=E[0];}else{for(var F=0;F<D;++F){var C=E[F];if(this.mode==this.INTERSECT&&C.cursorIsOver){G=C;break;}else{if(!G||!G.overlap||(C.overlap&&G.overlap.getArea()<C.overlap.getArea())){G=C;}}}}return G;},refreshCache:function(D){var F=D||this.ids;for(var C in F){if("string"!=typeof C){continue;}for(var E in this.ids[C]){var G=this.ids[C][E];if(this.isTypeOfDD(G)){var H=this.getLocation(G);if(H){this.locationCache[G.id]=H;}else{delete this.locationCache[G.id];}}}}},verifyEl:function(D){try{if(D){var C=D.offsetParent;if(C){return true;}}}catch(E){}return false;},getLocation:function(H){if(!this.isTypeOfDD(H)){return null;}var F=H.getEl(),K,E,D,M,L,N,C,J,G;try{K=YAHOO.util.Dom.getXY(F);}catch(I){}if(!K){return null;}E=K[0];D=E+F.offsetWidth;M=K[1];L=M+F.offsetHeight;N=M-H.padding[0];C=D+H.padding[1];J=L+H.padding[2];G=E-H.padding[3];return new YAHOO.util.Region(N,C,J,G);},isOverTarget:function(K,C,E,F){var G=this.locationCache[C.id];if(!G||!this.useCache){G=this.getLocation(C);this.locationCache[C.id]=G;}if(!G){return false;}C.cursorIsOver=G.contains(K);var J=this.dragCurrent;if(!J||(!E&&!J.constrainX&&!J.constrainY)){return C.cursorIsOver;}C.overlap=null;if(!F){var H=J.getTargetCoord(K.x,K.y);var D=J.getDragEl();F=new YAHOO.util.Region(H.y,H.x+D.offsetWidth,H.y+D.offsetHeight,H.x);}var I=F.intersect(G);if(I){C.overlap=I;return(E)?true:C.cursorIsOver;}else{return false;}},_onUnload:function(D,C){this.unregAll();},unregAll:function(){if(this.dragCurrent){this.stopDrag();this.dragCurrent=null;}this._execOnAll("unreg",[]);this.ids={};},elementCache:{},getElWrapper:function(D){var C=this.elementCache[D];if(!C||!C.el){C=this.elementCache[D]=new this.ElementWrapper(YAHOO.util.Dom.get(D));}return C;},getElement:function(C){return YAHOO.util.Dom.get(C);},getCss:function(D){var C=YAHOO.util.Dom.get(D);return(C)?C.style:null;},ElementWrapper:function(C){this.el=C||null;this.id=this.el&&C.id;this.css=this.el&&C.style;},getPosX:function(C){return YAHOO.util.Dom.getX(C);},getPosY:function(C){return YAHOO.util.Dom.getY(C);},swapNode:function(E,C){if(E.swapNode){E.swapNode(C);}else{var F=C.parentNode;var D=C.nextSibling;if(D==E){F.insertBefore(E,C);}else{if(C==E.nextSibling){F.insertBefore(C,E);}else{E.parentNode.replaceChild(C,E);F.insertBefore(E,D);}}}},getScroll:function(){var E,C,F=document.documentElement,D=document.body;if(F&&(F.scrollTop||F.scrollLeft)){E=F.scrollTop;C=F.scrollLeft;}else{if(D){E=D.scrollTop;C=D.scrollLeft;}else{}}return{top:E,left:C};},getStyle:function(D,C){return YAHOO.util.Dom.getStyle(D,C);},getScrollTop:function(){return this.getScroll().top;},getScrollLeft:function(){return this.getScroll().left;},moveToEl:function(C,E){var D=YAHOO.util.Dom.getXY(E);YAHOO.util.Dom.setXY(C,D);},getClientHeight:function(){return YAHOO.util.Dom.getViewportHeight();},getClientWidth:function(){return YAHOO.util.Dom.getViewportWidth();},numericSort:function(D,C){return(D-C);},_timeoutCount:0,_addListeners:function(){var C=YAHOO.util.DDM;if(YAHOO.util.Event&&document){C._onLoad();}else{if(C._timeoutCount>2000){}else{setTimeout(C._addListeners,10);if(document&&document.body){C._timeoutCount+=1;}}}},handleWasClicked:function(C,E){if(this.isHandle(E,C.id)){return true;}else{var D=C.parentNode;while(D){if(this.isHandle(E,D.id)){return true;}else{D=D.parentNode;}}}return false;}};}();YAHOO.util.DDM=YAHOO.util.DragDropMgr;YAHOO.util.DDM._addListeners();}(function(){var A=YAHOO.util.Event;var B=YAHOO.util.Dom;YAHOO.util.DragDrop=function(E,C,D){if(E){this.init(E,C,D);}};YAHOO.util.DragDrop.prototype={events:null,on:function(){this.subscribe.apply(this,arguments);},id:null,config:null,dragElId:null,handleElId:null,invalidHandleTypes:null,invalidHandleIds:null,invalidHandleClasses:null,startPageX:0,startPageY:0,groups:null,locked:false,lock:function(){this.locked=true;},unlock:function(){this.locked=false;},isTarget:true,padding:null,dragOnly:false,useShim:false,_domRef:null,__ygDragDrop:true,constrainX:false,constrainY:false,minX:0,maxX:0,minY:0,maxY:0,deltaX:0,deltaY:0,maintainOffset:false,xTicks:null,yTicks:null,primaryButtonOnly:true,available:false,hasOuterHandles:false,cursorIsOver:false,overlap:null,b4StartDrag:function(C,D){},startDrag:function(C,D){},b4Drag:function(C){},onDrag:function(C){},onDragEnter:function(C,D){},b4DragOver:function(C){},onDragOver:function(C,D){},b4DragOut:function(C){},onDragOut:function(C,D){},b4DragDrop:function(C){},onDragDrop:function(C,D){},onInvalidDrop:function(C){},b4EndDrag:function(C){},endDrag:function(C){},b4MouseDown:function(C){},onMouseDown:function(C){},onMouseUp:function(C){},onAvailable:function(){},getEl:function(){if(!this._domRef){this._domRef=B.get(this.id);
37
}return this._domRef;},getDragEl:function(){return B.get(this.dragElId);},init:function(F,C,D){this.initTarget(F,C,D);A.on(this._domRef||this.id,"mousedown",this.handleMouseDown,this,true);for(var E in this.events){this.createEvent(E+"Event");}},initTarget:function(E,C,D){this.config=D||{};this.events={};this.DDM=YAHOO.util.DDM;this.groups={};if(typeof E!=="string"){this._domRef=E;E=B.generateId(E);}this.id=E;this.addToGroup((C)?C:"default");this.handleElId=E;A.onAvailable(E,this.handleOnAvailable,this,true);this.setDragElId(E);this.invalidHandleTypes={A:"A"};this.invalidHandleIds={};this.invalidHandleClasses=[];this.applyConfig();},applyConfig:function(){this.events={mouseDown:true,b4MouseDown:true,mouseUp:true,b4StartDrag:true,startDrag:true,b4EndDrag:true,endDrag:true,drag:true,b4Drag:true,invalidDrop:true,b4DragOut:true,dragOut:true,dragEnter:true,b4DragOver:true,dragOver:true,b4DragDrop:true,dragDrop:true};if(this.config.events){for(var C in this.config.events){if(this.config.events[C]===false){this.events[C]=false;}}}this.padding=this.config.padding||[0,0,0,0];this.isTarget=(this.config.isTarget!==false);this.maintainOffset=(this.config.maintainOffset);this.primaryButtonOnly=(this.config.primaryButtonOnly!==false);this.dragOnly=((this.config.dragOnly===true)?true:false);this.useShim=((this.config.useShim===true)?true:false);},handleOnAvailable:function(){this.available=true;this.resetConstraints();this.onAvailable();},setPadding:function(E,C,F,D){if(!C&&0!==C){this.padding=[E,E,E,E];}else{if(!F&&0!==F){this.padding=[E,C,E,C];}else{this.padding=[E,C,F,D];}}},setInitPosition:function(F,E){var G=this.getEl();if(!this.DDM.verifyEl(G)){if(G&&G.style&&(G.style.display=="none")){}else{}return;}var D=F||0;var C=E||0;var H=B.getXY(G);this.initPageX=H[0]-D;this.initPageY=H[1]-C;this.lastPageX=H[0];this.lastPageY=H[1];this.setStartPosition(H);},setStartPosition:function(D){var C=D||B.getXY(this.getEl());this.deltaSetXY=null;this.startPageX=C[0];this.startPageY=C[1];},addToGroup:function(C){this.groups[C]=true;this.DDM.regDragDrop(this,C);},removeFromGroup:function(C){if(this.groups[C]){delete this.groups[C];}this.DDM.removeDDFromGroup(this,C);},setDragElId:function(C){this.dragElId=C;},setHandleElId:function(C){if(typeof C!=="string"){C=B.generateId(C);}this.handleElId=C;this.DDM.regHandle(this.id,C);},setOuterHandleElId:function(C){if(typeof C!=="string"){C=B.generateId(C);}A.on(C,"mousedown",this.handleMouseDown,this,true);this.setHandleElId(C);this.hasOuterHandles=true;},unreg:function(){A.removeListener(this.id,"mousedown",this.handleMouseDown);this._domRef=null;this.DDM._remove(this);},isLocked:function(){return(this.DDM.isLocked()||this.locked);},handleMouseDown:function(J,I){var D=J.which||J.button;if(this.primaryButtonOnly&&D>1){return;}if(this.isLocked()){return;}var C=this.b4MouseDown(J),F=true;if(this.events.b4MouseDown){F=this.fireEvent("b4MouseDownEvent",J);}var E=this.onMouseDown(J),H=true;if(this.events.mouseDown){H=this.fireEvent("mouseDownEvent",J);}if((C===false)||(E===false)||(F===false)||(H===false)){return;}this.DDM.refreshCache(this.groups);var G=new YAHOO.util.Point(A.getPageX(J),A.getPageY(J));if(!this.hasOuterHandles&&!this.DDM.isOverTarget(G,this)){}else{if(this.clickValidator(J)){this.setStartPosition();this.DDM.handleMouseDown(J,this);this.DDM.stopEvent(J);}else{}}},clickValidator:function(D){var C=YAHOO.util.Event.getTarget(D);return(this.isValidHandleChild(C)&&(this.id==this.handleElId||this.DDM.handleWasClicked(C,this.id)));},getTargetCoord:function(E,D){var C=E-this.deltaX;var F=D-this.deltaY;if(this.constrainX){if(C<this.minX){C=this.minX;}if(C>this.maxX){C=this.maxX;}}if(this.constrainY){if(F<this.minY){F=this.minY;}if(F>this.maxY){F=this.maxY;}}C=this.getTick(C,this.xTicks);F=this.getTick(F,this.yTicks);return{x:C,y:F};},addInvalidHandleType:function(C){var D=C.toUpperCase();this.invalidHandleTypes[D]=D;},addInvalidHandleId:function(C){if(typeof C!=="string"){C=B.generateId(C);}this.invalidHandleIds[C]=C;},addInvalidHandleClass:function(C){this.invalidHandleClasses.push(C);},removeInvalidHandleType:function(C){var D=C.toUpperCase();delete this.invalidHandleTypes[D];},removeInvalidHandleId:function(C){if(typeof C!=="string"){C=B.generateId(C);}delete this.invalidHandleIds[C];},removeInvalidHandleClass:function(D){for(var E=0,C=this.invalidHandleClasses.length;E<C;++E){if(this.invalidHandleClasses[E]==D){delete this.invalidHandleClasses[E];}}},isValidHandleChild:function(F){var E=true;var H;try{H=F.nodeName.toUpperCase();}catch(G){H=F.nodeName;}E=E&&!this.invalidHandleTypes[H];E=E&&!this.invalidHandleIds[F.id];for(var D=0,C=this.invalidHandleClasses.length;E&&D<C;++D){E=!B.hasClass(F,this.invalidHandleClasses[D]);}return E;},setXTicks:function(F,C){this.xTicks=[];this.xTickSize=C;var E={};for(var D=this.initPageX;D>=this.minX;D=D-C){if(!E[D]){this.xTicks[this.xTicks.length]=D;E[D]=true;}}for(D=this.initPageX;D<=this.maxX;D=D+C){if(!E[D]){this.xTicks[this.xTicks.length]=D;E[D]=true;}}this.xTicks.sort(this.DDM.numericSort);},setYTicks:function(F,C){this.yTicks=[];this.yTickSize=C;var E={};for(var D=this.initPageY;D>=this.minY;D=D-C){if(!E[D]){this.yTicks[this.yTicks.length]=D;E[D]=true;}}for(D=this.initPageY;D<=this.maxY;D=D+C){if(!E[D]){this.yTicks[this.yTicks.length]=D;E[D]=true;}}this.yTicks.sort(this.DDM.numericSort);},setXConstraint:function(E,D,C){this.leftConstraint=parseInt(E,10);this.rightConstraint=parseInt(D,10);this.minX=this.initPageX-this.leftConstraint;this.maxX=this.initPageX+this.rightConstraint;if(C){this.setXTicks(this.initPageX,C);}this.constrainX=true;},clearConstraints:function(){this.constrainX=false;this.constrainY=false;this.clearTicks();},clearTicks:function(){this.xTicks=null;this.yTicks=null;this.xTickSize=0;this.yTickSize=0;},setYConstraint:function(C,E,D){this.topConstraint=parseInt(C,10);this.bottomConstraint=parseInt(E,10);this.minY=this.initPageY-this.topConstraint;this.maxY=this.initPageY+this.bottomConstraint;if(D){this.setYTicks(this.initPageY,D);
38
}this.constrainY=true;},resetConstraints:function(){if(this.initPageX||this.initPageX===0){var D=(this.maintainOffset)?this.lastPageX-this.initPageX:0;var C=(this.maintainOffset)?this.lastPageY-this.initPageY:0;this.setInitPosition(D,C);}else{this.setInitPosition();}if(this.constrainX){this.setXConstraint(this.leftConstraint,this.rightConstraint,this.xTickSize);}if(this.constrainY){this.setYConstraint(this.topConstraint,this.bottomConstraint,this.yTickSize);}},getTick:function(I,F){if(!F){return I;}else{if(F[0]>=I){return F[0];}else{for(var D=0,C=F.length;D<C;++D){var E=D+1;if(F[E]&&F[E]>=I){var H=I-F[D];var G=F[E]-I;return(G>H)?F[D]:F[E];}}return F[F.length-1];}}},toString:function(){return("DragDrop "+this.id);}};YAHOO.augment(YAHOO.util.DragDrop,YAHOO.util.EventProvider);})();YAHOO.util.DD=function(C,A,B){if(C){this.init(C,A,B);}};YAHOO.extend(YAHOO.util.DD,YAHOO.util.DragDrop,{scroll:true,autoOffset:function(C,B){var A=C-this.startPageX;var D=B-this.startPageY;this.setDelta(A,D);},setDelta:function(B,A){this.deltaX=B;this.deltaY=A;},setDragElPos:function(C,B){var A=this.getDragEl();this.alignElWithMouse(A,C,B);},alignElWithMouse:function(C,G,F){var E=this.getTargetCoord(G,F);if(!this.deltaSetXY){var H=[E.x,E.y];YAHOO.util.Dom.setXY(C,H);var D=parseInt(YAHOO.util.Dom.getStyle(C,"left"),10);var B=parseInt(YAHOO.util.Dom.getStyle(C,"top"),10);this.deltaSetXY=[D-E.x,B-E.y];}else{YAHOO.util.Dom.setStyle(C,"left",(E.x+this.deltaSetXY[0])+"px");YAHOO.util.Dom.setStyle(C,"top",(E.y+this.deltaSetXY[1])+"px");}this.cachePosition(E.x,E.y);var A=this;setTimeout(function(){A.autoScroll.call(A,E.x,E.y,C.offsetHeight,C.offsetWidth);},0);},cachePosition:function(B,A){if(B){this.lastPageX=B;this.lastPageY=A;}else{var C=YAHOO.util.Dom.getXY(this.getEl());this.lastPageX=C[0];this.lastPageY=C[1];}},autoScroll:function(J,I,E,K){if(this.scroll){var L=this.DDM.getClientHeight();var B=this.DDM.getClientWidth();var N=this.DDM.getScrollTop();var D=this.DDM.getScrollLeft();var H=E+I;var M=K+J;var G=(L+N-I-this.deltaY);var F=(B+D-J-this.deltaX);var C=40;var A=(document.all)?80:30;if(H>L&&G<C){window.scrollTo(D,N+A);}if(I<N&&N>0&&I-N<C){window.scrollTo(D,N-A);}if(M>B&&F<C){window.scrollTo(D+A,N);}if(J<D&&D>0&&J-D<C){window.scrollTo(D-A,N);}}},applyConfig:function(){YAHOO.util.DD.superclass.applyConfig.call(this);this.scroll=(this.config.scroll!==false);},b4MouseDown:function(A){this.setStartPosition();this.autoOffset(YAHOO.util.Event.getPageX(A),YAHOO.util.Event.getPageY(A));},b4Drag:function(A){this.setDragElPos(YAHOO.util.Event.getPageX(A),YAHOO.util.Event.getPageY(A));},toString:function(){return("DD "+this.id);}});YAHOO.util.DDProxy=function(C,A,B){if(C){this.init(C,A,B);this.initFrame();}};YAHOO.util.DDProxy.dragElId="ygddfdiv";YAHOO.extend(YAHOO.util.DDProxy,YAHOO.util.DD,{resizeFrame:true,centerFrame:false,createFrame:function(){var B=this,A=document.body;if(!A||!A.firstChild){setTimeout(function(){B.createFrame();},50);return;}var F=this.getDragEl(),E=YAHOO.util.Dom;if(!F){F=document.createElement("div");F.id=this.dragElId;var D=F.style;D.position="absolute";D.visibility="hidden";D.cursor="move";D.border="2px solid #aaa";D.zIndex=999;D.height="25px";D.width="25px";var C=document.createElement("div");E.setStyle(C,"height","100%");E.setStyle(C,"width","100%");E.setStyle(C,"background-color","#ccc");E.setStyle(C,"opacity","0");F.appendChild(C);A.insertBefore(F,A.firstChild);}},initFrame:function(){this.createFrame();},applyConfig:function(){YAHOO.util.DDProxy.superclass.applyConfig.call(this);this.resizeFrame=(this.config.resizeFrame!==false);this.centerFrame=(this.config.centerFrame);this.setDragElId(this.config.dragElId||YAHOO.util.DDProxy.dragElId);},showFrame:function(E,D){var C=this.getEl();var A=this.getDragEl();var B=A.style;this._resizeProxy();if(this.centerFrame){this.setDelta(Math.round(parseInt(B.width,10)/2),Math.round(parseInt(B.height,10)/2));}this.setDragElPos(E,D);YAHOO.util.Dom.setStyle(A,"visibility","visible");},_resizeProxy:function(){if(this.resizeFrame){var H=YAHOO.util.Dom;var B=this.getEl();var C=this.getDragEl();var G=parseInt(H.getStyle(C,"borderTopWidth"),10);var I=parseInt(H.getStyle(C,"borderRightWidth"),10);var F=parseInt(H.getStyle(C,"borderBottomWidth"),10);var D=parseInt(H.getStyle(C,"borderLeftWidth"),10);if(isNaN(G)){G=0;}if(isNaN(I)){I=0;}if(isNaN(F)){F=0;}if(isNaN(D)){D=0;}var E=Math.max(0,B.offsetWidth-I-D);var A=Math.max(0,B.offsetHeight-G-F);H.setStyle(C,"width",E+"px");H.setStyle(C,"height",A+"px");}},b4MouseDown:function(B){this.setStartPosition();var A=YAHOO.util.Event.getPageX(B);var C=YAHOO.util.Event.getPageY(B);this.autoOffset(A,C);},b4StartDrag:function(A,B){this.showFrame(A,B);},b4EndDrag:function(A){YAHOO.util.Dom.setStyle(this.getDragEl(),"visibility","hidden");},endDrag:function(D){var C=YAHOO.util.Dom;var B=this.getEl();var A=this.getDragEl();C.setStyle(A,"visibility","");C.setStyle(B,"visibility","hidden");YAHOO.util.DDM.moveToEl(B,A);C.setStyle(A,"visibility","hidden");C.setStyle(B,"visibility","");},toString:function(){return("DDProxy "+this.id);}});YAHOO.util.DDTarget=function(C,A,B){if(C){this.initTarget(C,A,B);}};YAHOO.extend(YAHOO.util.DDTarget,YAHOO.util.DragDrop,{toString:function(){return("DDTarget "+this.id);}});YAHOO.register("dragdrop",YAHOO.util.DragDropMgr,{version:"2.8.0r4",build:"2449"});YAHOO.util.Attribute=function(B,A){if(A){this.owner=A;this.configure(B,true);}};YAHOO.util.Attribute.prototype={name:undefined,value:null,owner:null,readOnly:false,writeOnce:false,_initialConfig:null,_written:false,method:null,setter:null,getter:null,validator:null,getValue:function(){var A=this.value;if(this.getter){A=this.getter.call(this.owner,this.name,A);}return A;},setValue:function(F,B){var E,A=this.owner,C=this.name;var D={type:C,prevValue:this.getValue(),newValue:F};if(this.readOnly||(this.writeOnce&&this._written)){return false;}if(this.validator&&!this.validator.call(A,F)){return false;}if(!B){E=A.fireBeforeChangeEvent(D);if(E===false){return false;}}if(this.setter){F=this.setter.call(A,F,this.name);if(F===undefined){}}if(this.method){this.method.call(A,F,this.name);}this.value=F;this._written=true;D.type=C;if(!B){this.owner.fireChangeEvent(D);}return true;},configure:function(B,C){B=B||{};if(C){this._written=false;}this._initialConfig=this._initialConfig||{};for(var A in B){if(B.hasOwnProperty(A)){this[A]=B[A];if(C){this._initialConfig[A]=B[A];}}}},resetValue:function(){return this.setValue(this._initialConfig.value);},resetConfig:function(){this.configure(this._initialConfig,true);},refresh:function(A){this.setValue(this.value,A);}};(function(){var A=YAHOO.util.Lang;YAHOO.util.AttributeProvider=function(){};YAHOO.util.AttributeProvider.prototype={_configs:null,get:function(C){this._configs=this._configs||{};var B=this._configs[C];if(!B||!this._configs.hasOwnProperty(C)){return null;}return B.getValue();},set:function(D,E,B){this._configs=this._configs||{};var C=this._configs[D];if(!C){return false;}return C.setValue(E,B);},getAttributeKeys:function(){this._configs=this._configs;var C=[],B;for(B in this._configs){if(A.hasOwnProperty(this._configs,B)&&!A.isUndefined(this._configs[B])){C[C.length]=B;}}return C;},setAttributes:function(D,B){for(var C in D){if(A.hasOwnProperty(D,C)){this.set(C,D[C],B);}}},resetValue:function(C,B){this._configs=this._configs||{};if(this._configs[C]){this.set(C,this._configs[C]._initialConfig.value,B);return true;}return false;},refresh:function(E,C){this._configs=this._configs||{};var F=this._configs;E=((A.isString(E))?[E]:E)||this.getAttributeKeys();for(var D=0,B=E.length;D<B;++D){if(F.hasOwnProperty(E[D])){this._configs[E[D]].refresh(C);}}},register:function(B,C){this.setAttributeConfig(B,C);},getAttributeConfig:function(C){this._configs=this._configs||{};var B=this._configs[C]||{};var D={};for(C in B){if(A.hasOwnProperty(B,C)){D[C]=B[C];}}return D;},setAttributeConfig:function(B,C,D){this._configs=this._configs||{};C=C||{};if(!this._configs[B]){C.name=B;this._configs[B]=this.createAttribute(C);}else{this._configs[B].configure(C,D);}},configureAttribute:function(B,C,D){this.setAttributeConfig(B,C,D);},resetAttributeConfig:function(B){this._configs=this._configs||{};this._configs[B].resetConfig();},subscribe:function(B,C){this._events=this._events||{};if(!(B in this._events)){this._events[B]=this.createEvent(B);}YAHOO.util.EventProvider.prototype.subscribe.apply(this,arguments);},on:function(){this.subscribe.apply(this,arguments);},addListener:function(){this.subscribe.apply(this,arguments);},fireBeforeChangeEvent:function(C){var B="before";B+=C.type.charAt(0).toUpperCase()+C.type.substr(1)+"Change";C.type=B;return this.fireEvent(C.type,C);},fireChangeEvent:function(B){B.type+="Change";return this.fireEvent(B.type,B);},createAttribute:function(B){return new YAHOO.util.Attribute(B,this);}};YAHOO.augment(YAHOO.util.AttributeProvider,YAHOO.util.EventProvider);})();(function(){var B=YAHOO.util.Dom,D=YAHOO.util.AttributeProvider,C={mouseenter:true,mouseleave:true};var A=function(E,F){this.init.apply(this,arguments);};A.DOM_EVENTS={"click":true,"dblclick":true,"keydown":true,"keypress":true,"keyup":true,"mousedown":true,"mousemove":true,"mouseout":true,"mouseover":true,"mouseup":true,"mouseenter":true,"mouseleave":true,"focus":true,"blur":true,"submit":true,"change":true};A.prototype={DOM_EVENTS:null,DEFAULT_HTML_SETTER:function(G,E){var F=this.get("element");if(F){F[E]=G;}return G;},DEFAULT_HTML_GETTER:function(E){var F=this.get("element"),G;if(F){G=F[E];}return G;},appendChild:function(E){E=E.get?E.get("element"):E;return this.get("element").appendChild(E);},getElementsByTagName:function(E){return this.get("element").getElementsByTagName(E);},hasChildNodes:function(){return this.get("element").hasChildNodes();},insertBefore:function(E,F){E=E.get?E.get("element"):E;F=(F&&F.get)?F.get("element"):F;return this.get("element").insertBefore(E,F);},removeChild:function(E){E=E.get?E.get("element"):E;return this.get("element").removeChild(E);},replaceChild:function(E,F){E=E.get?E.get("element"):E;F=F.get?F.get("element"):F;return this.get("element").replaceChild(E,F);},initAttributes:function(E){},addListener:function(J,I,K,H){H=H||this;var E=YAHOO.util.Event,G=this.get("element")||this.get("id"),F=this;if(C[J]&&!E._createMouseDelegate){return false;}if(!this._events[J]){if(G&&this.DOM_EVENTS[J]){E.on(G,J,function(M,L){if(M.srcElement&&!M.target){M.target=M.srcElement;}if((M.toElement&&!M.relatedTarget)||(M.fromElement&&!M.relatedTarget)){M.relatedTarget=E.getRelatedTarget(M);}if(!M.currentTarget){M.currentTarget=G;}F.fireEvent(J,M,L);},K,H);}this.createEvent(J,{scope:this});}return YAHOO.util.EventProvider.prototype.subscribe.apply(this,arguments);},on:function(){return this.addListener.apply(this,arguments);},subscribe:function(){return this.addListener.apply(this,arguments);},removeListener:function(F,E){return this.unsubscribe.apply(this,arguments);},addClass:function(E){B.addClass(this.get("element"),E);},getElementsByClassName:function(F,E){return B.getElementsByClassName(F,E,this.get("element"));},hasClass:function(E){return B.hasClass(this.get("element"),E);},removeClass:function(E){return B.removeClass(this.get("element"),E);},replaceClass:function(F,E){return B.replaceClass(this.get("element"),F,E);},setStyle:function(F,E){return B.setStyle(this.get("element"),F,E);
39
},getStyle:function(E){return B.getStyle(this.get("element"),E);},fireQueue:function(){var F=this._queue;for(var G=0,E=F.length;G<E;++G){this[F[G][0]].apply(this,F[G][1]);}},appendTo:function(F,G){F=(F.get)?F.get("element"):B.get(F);this.fireEvent("beforeAppendTo",{type:"beforeAppendTo",target:F});G=(G&&G.get)?G.get("element"):B.get(G);var E=this.get("element");if(!E){return false;}if(!F){return false;}if(E.parent!=F){if(G){F.insertBefore(E,G);}else{F.appendChild(E);}}this.fireEvent("appendTo",{type:"appendTo",target:F});return E;},get:function(E){var G=this._configs||{},F=G.element;if(F&&!G[E]&&!YAHOO.lang.isUndefined(F.value[E])){this._setHTMLAttrConfig(E);}return D.prototype.get.call(this,E);},setAttributes:function(K,H){var F={},I=this._configOrder;for(var J=0,E=I.length;J<E;++J){if(K[I[J]]!==undefined){F[I[J]]=true;this.set(I[J],K[I[J]],H);}}for(var G in K){if(K.hasOwnProperty(G)&&!F[G]){this.set(G,K[G],H);}}},set:function(F,H,E){var G=this.get("element");if(!G){this._queue[this._queue.length]=["set",arguments];if(this._configs[F]){this._configs[F].value=H;}return;}if(!this._configs[F]&&!YAHOO.lang.isUndefined(G[F])){this._setHTMLAttrConfig(F);}return D.prototype.set.apply(this,arguments);},setAttributeConfig:function(E,F,G){this._configOrder.push(E);D.prototype.setAttributeConfig.apply(this,arguments);},createEvent:function(F,E){this._events[F]=true;return D.prototype.createEvent.apply(this,arguments);},init:function(F,E){this._initElement(F,E);},destroy:function(){var E=this.get("element");YAHOO.util.Event.purgeElement(E,true);this.unsubscribeAll();if(E&&E.parentNode){E.parentNode.removeChild(E);}this._queue=[];this._events={};this._configs={};this._configOrder=[];},_initElement:function(G,F){this._queue=this._queue||[];this._events=this._events||{};this._configs=this._configs||{};this._configOrder=[];F=F||{};F.element=F.element||G||null;var I=false;var E=A.DOM_EVENTS;this.DOM_EVENTS=this.DOM_EVENTS||{};for(var H in E){if(E.hasOwnProperty(H)){this.DOM_EVENTS[H]=E[H];}}if(typeof F.element==="string"){this._setHTMLAttrConfig("id",{value:F.element});}if(B.get(F.element)){I=true;this._initHTMLElement(F);this._initContent(F);}YAHOO.util.Event.onAvailable(F.element,function(){if(!I){this._initHTMLElement(F);}this.fireEvent("available",{type:"available",target:B.get(F.element)});},this,true);YAHOO.util.Event.onContentReady(F.element,function(){if(!I){this._initContent(F);}this.fireEvent("contentReady",{type:"contentReady",target:B.get(F.element)});},this,true);},_initHTMLElement:function(E){this.setAttributeConfig("element",{value:B.get(E.element),readOnly:true});},_initContent:function(E){this.initAttributes(E);this.setAttributes(E,true);this.fireQueue();},_setHTMLAttrConfig:function(E,G){var F=this.get("element");G=G||{};G.name=E;G.setter=G.setter||this.DEFAULT_HTML_SETTER;G.getter=G.getter||this.DEFAULT_HTML_GETTER;G.value=G.value||F[E];this._configs[E]=new YAHOO.util.Attribute(G,this);}};YAHOO.augment(A,D);YAHOO.util.Element=A;})();YAHOO.register("element",YAHOO.util.Element,{version:"2.8.0r4",build:"2449"});YAHOO.register("utilities", YAHOO, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/lib/yui/yahoo-dom-event/yahoo-dom-event.js (-14 lines)
Lines 1-14 Link Here
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.8.0r4
6
*/
7
if(typeof YAHOO=="undefined"||!YAHOO){var YAHOO={};}YAHOO.namespace=function(){var A=arguments,E=null,C,B,D;for(C=0;C<A.length;C=C+1){D=(""+A[C]).split(".");E=YAHOO;for(B=(D[0]=="YAHOO")?1:0;B<D.length;B=B+1){E[D[B]]=E[D[B]]||{};E=E[D[B]];}}return E;};YAHOO.log=function(D,A,C){var B=YAHOO.widget.Logger;if(B&&B.log){return B.log(D,A,C);}else{return false;}};YAHOO.register=function(A,E,D){var I=YAHOO.env.modules,B,H,G,F,C;if(!I[A]){I[A]={versions:[],builds:[]};}B=I[A];H=D.version;G=D.build;F=YAHOO.env.listeners;B.name=A;B.version=H;B.build=G;B.versions.push(H);B.builds.push(G);B.mainClass=E;for(C=0;C<F.length;C=C+1){F[C](B);}if(E){E.VERSION=H;E.BUILD=G;}else{YAHOO.log("mainClass is undefined for module "+A,"warn");}};YAHOO.env=YAHOO.env||{modules:[],listeners:[]};YAHOO.env.getVersion=function(A){return YAHOO.env.modules[A]||null;};YAHOO.env.ua=function(){var D=function(H){var I=0;return parseFloat(H.replace(/\./g,function(){return(I++==1)?"":".";}));},G=navigator,F={ie:0,opera:0,gecko:0,webkit:0,mobile:null,air:0,caja:G.cajaVersion,secure:false,os:null},C=navigator&&navigator.userAgent,E=window&&window.location,B=E&&E.href,A;F.secure=B&&(B.toLowerCase().indexOf("https")===0);if(C){if((/windows|win32/i).test(C)){F.os="windows";}else{if((/macintosh/i).test(C)){F.os="macintosh";}}if((/KHTML/).test(C)){F.webkit=1;}A=C.match(/AppleWebKit\/([^\s]*)/);if(A&&A[1]){F.webkit=D(A[1]);if(/ Mobile\//.test(C)){F.mobile="Apple";}else{A=C.match(/NokiaN[^\/]*/);if(A){F.mobile=A[0];}}A=C.match(/AdobeAIR\/([^\s]*)/);if(A){F.air=A[0];}}if(!F.webkit){A=C.match(/Opera[\s\/]([^\s]*)/);if(A&&A[1]){F.opera=D(A[1]);A=C.match(/Opera Mini[^;]*/);if(A){F.mobile=A[0];}}else{A=C.match(/MSIE\s([^;]*)/);if(A&&A[1]){F.ie=D(A[1]);}else{A=C.match(/Gecko\/([^\s]*)/);if(A){F.gecko=1;A=C.match(/rv:([^\s\)]*)/);if(A&&A[1]){F.gecko=D(A[1]);}}}}}}return F;}();(function(){YAHOO.namespace("util","widget","example");if("undefined"!==typeof YAHOO_config){var B=YAHOO_config.listener,A=YAHOO.env.listeners,D=true,C;if(B){for(C=0;C<A.length;C++){if(A[C]==B){D=false;break;}}if(D){A.push(B);}}}})();YAHOO.lang=YAHOO.lang||{};(function(){var B=YAHOO.lang,A=Object.prototype,H="[object Array]",C="[object Function]",G="[object Object]",E=[],F=["toString","valueOf"],D={isArray:function(I){return A.toString.apply(I)===H;},isBoolean:function(I){return typeof I==="boolean";},isFunction:function(I){return(typeof I==="function")||A.toString.apply(I)===C;},isNull:function(I){return I===null;},isNumber:function(I){return typeof I==="number"&&isFinite(I);},isObject:function(I){return(I&&(typeof I==="object"||B.isFunction(I)))||false;},isString:function(I){return typeof I==="string";},isUndefined:function(I){return typeof I==="undefined";},_IEEnumFix:(YAHOO.env.ua.ie)?function(K,J){var I,M,L;for(I=0;I<F.length;I=I+1){M=F[I];L=J[M];if(B.isFunction(L)&&L!=A[M]){K[M]=L;}}}:function(){},extend:function(L,M,K){if(!M||!L){throw new Error("extend failed, please check that "+"all dependencies are included.");}var J=function(){},I;J.prototype=M.prototype;L.prototype=new J();L.prototype.constructor=L;L.superclass=M.prototype;if(M.prototype.constructor==A.constructor){M.prototype.constructor=M;}if(K){for(I in K){if(B.hasOwnProperty(K,I)){L.prototype[I]=K[I];}}B._IEEnumFix(L.prototype,K);}},augmentObject:function(M,L){if(!L||!M){throw new Error("Absorb failed, verify dependencies.");}var I=arguments,K,N,J=I[2];if(J&&J!==true){for(K=2;K<I.length;K=K+1){M[I[K]]=L[I[K]];}}else{for(N in L){if(J||!(N in M)){M[N]=L[N];}}B._IEEnumFix(M,L);}},augmentProto:function(L,K){if(!K||!L){throw new Error("Augment failed, verify dependencies.");}var I=[L.prototype,K.prototype],J;for(J=2;J<arguments.length;J=J+1){I.push(arguments[J]);}B.augmentObject.apply(this,I);},dump:function(I,N){var K,M,P=[],Q="{...}",J="f(){...}",O=", ",L=" => ";if(!B.isObject(I)){return I+"";}else{if(I instanceof Date||("nodeType" in I&&"tagName" in I)){return I;}else{if(B.isFunction(I)){return J;}}}N=(B.isNumber(N))?N:3;if(B.isArray(I)){P.push("[");for(K=0,M=I.length;K<M;K=K+1){if(B.isObject(I[K])){P.push((N>0)?B.dump(I[K],N-1):Q);}else{P.push(I[K]);}P.push(O);}if(P.length>1){P.pop();}P.push("]");}else{P.push("{");for(K in I){if(B.hasOwnProperty(I,K)){P.push(K+L);if(B.isObject(I[K])){P.push((N>0)?B.dump(I[K],N-1):Q);}else{P.push(I[K]);}P.push(O);}}if(P.length>1){P.pop();}P.push("}");}return P.join("");},substitute:function(Y,J,R){var N,M,L,U,V,X,T=[],K,O="dump",S=" ",I="{",W="}",Q,P;for(;;){N=Y.lastIndexOf(I);if(N<0){break;}M=Y.indexOf(W,N);if(N+1>=M){break;}K=Y.substring(N+1,M);U=K;X=null;L=U.indexOf(S);if(L>-1){X=U.substring(L+1);U=U.substring(0,L);}V=J[U];if(R){V=R(U,V,X);}if(B.isObject(V)){if(B.isArray(V)){V=B.dump(V,parseInt(X,10));}else{X=X||"";Q=X.indexOf(O);if(Q>-1){X=X.substring(4);}P=V.toString();if(P===G||Q>-1){V=B.dump(V,parseInt(X,10));}else{V=P;}}}else{if(!B.isString(V)&&!B.isNumber(V)){V="~-"+T.length+"-~";T[T.length]=K;}}Y=Y.substring(0,N)+V+Y.substring(M+1);}for(N=T.length-1;N>=0;N=N-1){Y=Y.replace(new RegExp("~-"+N+"-~"),"{"+T[N]+"}","g");}return Y;},trim:function(I){try{return I.replace(/^\s+|\s+$/g,"");}catch(J){return I;}},merge:function(){var L={},J=arguments,I=J.length,K;for(K=0;K<I;K=K+1){B.augmentObject(L,J[K],true);}return L;},later:function(P,J,Q,L,M){P=P||0;J=J||{};var K=Q,O=L,N,I;if(B.isString(Q)){K=J[Q];}if(!K){throw new TypeError("method undefined");}if(O&&!B.isArray(O)){O=[L];}N=function(){K.apply(J,O||E);};I=(M)?setInterval(N,P):setTimeout(N,P);return{interval:M,cancel:function(){if(this.interval){clearInterval(I);}else{clearTimeout(I);}}};},isValue:function(I){return(B.isObject(I)||B.isString(I)||B.isNumber(I)||B.isBoolean(I));}};B.hasOwnProperty=(A.hasOwnProperty)?function(I,J){return I&&I.hasOwnProperty(J);}:function(I,J){return !B.isUndefined(I[J])&&I.constructor.prototype[J]!==I[J];};D.augmentObject(B,D,true);YAHOO.util.Lang=B;B.augment=B.augmentProto;YAHOO.augment=B.augmentProto;YAHOO.extend=B.extend;})();YAHOO.register("yahoo",YAHOO,{version:"2.8.0r4",build:"2449"});
8
(function(){YAHOO.env._id_counter=YAHOO.env._id_counter||0;var E=YAHOO.util,L=YAHOO.lang,m=YAHOO.env.ua,A=YAHOO.lang.trim,d={},h={},N=/^t(?:able|d|h)$/i,X=/color$/i,K=window.document,W=K.documentElement,e="ownerDocument",n="defaultView",v="documentElement",t="compatMode",b="offsetLeft",P="offsetTop",u="offsetParent",Z="parentNode",l="nodeType",C="tagName",O="scrollLeft",i="scrollTop",Q="getBoundingClientRect",w="getComputedStyle",a="currentStyle",M="CSS1Compat",c="BackCompat",g="class",F="className",J="",B=" ",s="(?:^|\\s)",k="(?= |$)",U="g",p="position",f="fixed",V="relative",j="left",o="top",r="medium",q="borderLeftWidth",R="borderTopWidth",D=m.opera,I=m.webkit,H=m.gecko,T=m.ie;E.Dom={CUSTOM_ATTRIBUTES:(!W.hasAttribute)?{"for":"htmlFor","class":F}:{"htmlFor":"for","className":g},DOT_ATTRIBUTES:{},get:function(z){var AB,x,AA,y,Y,G;if(z){if(z[l]||z.item){return z;}if(typeof z==="string"){AB=z;z=K.getElementById(z);G=(z)?z.attributes:null;if(z&&G&&G.id&&G.id.value===AB){return z;}else{if(z&&K.all){z=null;x=K.all[AB];for(y=0,Y=x.length;y<Y;++y){if(x[y].id===AB){return x[y];}}}}return z;}if(YAHOO.util.Element&&z instanceof YAHOO.util.Element){z=z.get("element");}if("length" in z){AA=[];for(y=0,Y=z.length;y<Y;++y){AA[AA.length]=E.Dom.get(z[y]);}return AA;}return z;}return null;},getComputedStyle:function(G,Y){if(window[w]){return G[e][n][w](G,null)[Y];}else{if(G[a]){return E.Dom.IE_ComputedStyle.get(G,Y);}}},getStyle:function(G,Y){return E.Dom.batch(G,E.Dom._getStyle,Y);},_getStyle:function(){if(window[w]){return function(G,y){y=(y==="float")?y="cssFloat":E.Dom._toCamel(y);var x=G.style[y],Y;if(!x){Y=G[e][n][w](G,null);if(Y){x=Y[y];}}return x;};}else{if(W[a]){return function(G,y){var x;switch(y){case"opacity":x=100;try{x=G.filters["DXImageTransform.Microsoft.Alpha"].opacity;}catch(z){try{x=G.filters("alpha").opacity;}catch(Y){}}return x/100;case"float":y="styleFloat";default:y=E.Dom._toCamel(y);x=G[a]?G[a][y]:null;return(G.style[y]||x);}};}}}(),setStyle:function(G,Y,x){E.Dom.batch(G,E.Dom._setStyle,{prop:Y,val:x});},_setStyle:function(){if(T){return function(Y,G){var x=E.Dom._toCamel(G.prop),y=G.val;if(Y){switch(x){case"opacity":if(L.isString(Y.style.filter)){Y.style.filter="alpha(opacity="+y*100+")";if(!Y[a]||!Y[a].hasLayout){Y.style.zoom=1;}}break;case"float":x="styleFloat";default:Y.style[x]=y;}}else{}};}else{return function(Y,G){var x=E.Dom._toCamel(G.prop),y=G.val;if(Y){if(x=="float"){x="cssFloat";}Y.style[x]=y;}else{}};}}(),getXY:function(G){return E.Dom.batch(G,E.Dom._getXY);},_canPosition:function(G){return(E.Dom._getStyle(G,"display")!=="none"&&E.Dom._inDoc(G));},_getXY:function(){if(K[v][Q]){return function(y){var z,Y,AA,AF,AE,AD,AC,G,x,AB=Math.floor,AG=false;if(E.Dom._canPosition(y)){AA=y[Q]();AF=y[e];z=E.Dom.getDocumentScrollLeft(AF);Y=E.Dom.getDocumentScrollTop(AF);AG=[AB(AA[j]),AB(AA[o])];if(T&&m.ie<8){AE=2;AD=2;AC=AF[t];if(m.ie===6){if(AC!==c){AE=0;AD=0;}}if((AC===c)){G=S(AF[v],q);x=S(AF[v],R);if(G!==r){AE=parseInt(G,10);}if(x!==r){AD=parseInt(x,10);}}AG[0]-=AE;AG[1]-=AD;}if((Y||z)){AG[0]+=z;AG[1]+=Y;}AG[0]=AB(AG[0]);AG[1]=AB(AG[1]);}else{}return AG;};}else{return function(y){var x,Y,AA,AB,AC,z=false,G=y;if(E.Dom._canPosition(y)){z=[y[b],y[P]];x=E.Dom.getDocumentScrollLeft(y[e]);Y=E.Dom.getDocumentScrollTop(y[e]);AC=((H||m.webkit>519)?true:false);while((G=G[u])){z[0]+=G[b];z[1]+=G[P];if(AC){z=E.Dom._calcBorders(G,z);}}if(E.Dom._getStyle(y,p)!==f){G=y;while((G=G[Z])&&G[C]){AA=G[i];AB=G[O];if(H&&(E.Dom._getStyle(G,"overflow")!=="visible")){z=E.Dom._calcBorders(G,z);}if(AA||AB){z[0]-=AB;z[1]-=AA;}}z[0]+=x;z[1]+=Y;}else{if(D){z[0]-=x;z[1]-=Y;}else{if(I||H){z[0]+=x;z[1]+=Y;}}}z[0]=Math.floor(z[0]);z[1]=Math.floor(z[1]);}else{}return z;};}}(),getX:function(G){var Y=function(x){return E.Dom.getXY(x)[0];};return E.Dom.batch(G,Y,E.Dom,true);},getY:function(G){var Y=function(x){return E.Dom.getXY(x)[1];};return E.Dom.batch(G,Y,E.Dom,true);},setXY:function(G,x,Y){E.Dom.batch(G,E.Dom._setXY,{pos:x,noRetry:Y});},_setXY:function(G,z){var AA=E.Dom._getStyle(G,p),y=E.Dom.setStyle,AD=z.pos,Y=z.noRetry,AB=[parseInt(E.Dom.getComputedStyle(G,j),10),parseInt(E.Dom.getComputedStyle(G,o),10)],AC,x;if(AA=="static"){AA=V;y(G,p,AA);}AC=E.Dom._getXY(G);if(!AD||AC===false){return false;}if(isNaN(AB[0])){AB[0]=(AA==V)?0:G[b];}if(isNaN(AB[1])){AB[1]=(AA==V)?0:G[P];}if(AD[0]!==null){y(G,j,AD[0]-AC[0]+AB[0]+"px");}if(AD[1]!==null){y(G,o,AD[1]-AC[1]+AB[1]+"px");}if(!Y){x=E.Dom._getXY(G);if((AD[0]!==null&&x[0]!=AD[0])||(AD[1]!==null&&x[1]!=AD[1])){E.Dom._setXY(G,{pos:AD,noRetry:true});}}},setX:function(Y,G){E.Dom.setXY(Y,[G,null]);},setY:function(G,Y){E.Dom.setXY(G,[null,Y]);},getRegion:function(G){var Y=function(x){var y=false;if(E.Dom._canPosition(x)){y=E.Region.getRegion(x);}else{}return y;};return E.Dom.batch(G,Y,E.Dom,true);},getClientWidth:function(){return E.Dom.getViewportWidth();},getClientHeight:function(){return E.Dom.getViewportHeight();},getElementsByClassName:function(AB,AF,AC,AE,x,AD){AF=AF||"*";AC=(AC)?E.Dom.get(AC):null||K;if(!AC){return[];}var Y=[],G=AC.getElementsByTagName(AF),z=E.Dom.hasClass;for(var y=0,AA=G.length;y<AA;++y){if(z(G[y],AB)){Y[Y.length]=G[y];}}if(AE){E.Dom.batch(Y,AE,x,AD);}return Y;},hasClass:function(Y,G){return E.Dom.batch(Y,E.Dom._hasClass,G);},_hasClass:function(x,Y){var G=false,y;if(x&&Y){y=E.Dom._getAttribute(x,F)||J;if(Y.exec){G=Y.test(y);}else{G=Y&&(B+y+B).indexOf(B+Y+B)>-1;}}else{}return G;},addClass:function(Y,G){return E.Dom.batch(Y,E.Dom._addClass,G);},_addClass:function(x,Y){var G=false,y;if(x&&Y){y=E.Dom._getAttribute(x,F)||J;if(!E.Dom._hasClass(x,Y)){E.Dom.setAttribute(x,F,A(y+B+Y));G=true;}}else{}return G;},removeClass:function(Y,G){return E.Dom.batch(Y,E.Dom._removeClass,G);},_removeClass:function(y,x){var Y=false,AA,z,G;if(y&&x){AA=E.Dom._getAttribute(y,F)||J;E.Dom.setAttribute(y,F,AA.replace(E.Dom._getClassRegex(x),J));z=E.Dom._getAttribute(y,F);if(AA!==z){E.Dom.setAttribute(y,F,A(z));Y=true;if(E.Dom._getAttribute(y,F)===""){G=(y.hasAttribute&&y.hasAttribute(g))?g:F;
9
y.removeAttribute(G);}}}else{}return Y;},replaceClass:function(x,Y,G){return E.Dom.batch(x,E.Dom._replaceClass,{from:Y,to:G});},_replaceClass:function(y,x){var Y,AB,AA,G=false,z;if(y&&x){AB=x.from;AA=x.to;if(!AA){G=false;}else{if(!AB){G=E.Dom._addClass(y,x.to);}else{if(AB!==AA){z=E.Dom._getAttribute(y,F)||J;Y=(B+z.replace(E.Dom._getClassRegex(AB),B+AA)).split(E.Dom._getClassRegex(AA));Y.splice(1,0,B+AA);E.Dom.setAttribute(y,F,A(Y.join(J)));G=true;}}}}else{}return G;},generateId:function(G,x){x=x||"yui-gen";var Y=function(y){if(y&&y.id){return y.id;}var z=x+YAHOO.env._id_counter++;if(y){if(y[e]&&y[e].getElementById(z)){return E.Dom.generateId(y,z+x);}y.id=z;}return z;};return E.Dom.batch(G,Y,E.Dom,true)||Y.apply(E.Dom,arguments);},isAncestor:function(Y,x){Y=E.Dom.get(Y);x=E.Dom.get(x);var G=false;if((Y&&x)&&(Y[l]&&x[l])){if(Y.contains&&Y!==x){G=Y.contains(x);}else{if(Y.compareDocumentPosition){G=!!(Y.compareDocumentPosition(x)&16);}}}else{}return G;},inDocument:function(G,Y){return E.Dom._inDoc(E.Dom.get(G),Y);},_inDoc:function(Y,x){var G=false;if(Y&&Y[C]){x=x||Y[e];G=E.Dom.isAncestor(x[v],Y);}else{}return G;},getElementsBy:function(Y,AF,AB,AD,y,AC,AE){AF=AF||"*";AB=(AB)?E.Dom.get(AB):null||K;if(!AB){return[];}var x=[],G=AB.getElementsByTagName(AF);for(var z=0,AA=G.length;z<AA;++z){if(Y(G[z])){if(AE){x=G[z];break;}else{x[x.length]=G[z];}}}if(AD){E.Dom.batch(x,AD,y,AC);}return x;},getElementBy:function(x,G,Y){return E.Dom.getElementsBy(x,G,Y,null,null,null,true);},batch:function(x,AB,AA,z){var y=[],Y=(z)?AA:window;x=(x&&(x[C]||x.item))?x:E.Dom.get(x);if(x&&AB){if(x[C]||x.length===undefined){return AB.call(Y,x,AA);}for(var G=0;G<x.length;++G){y[y.length]=AB.call(Y,x[G],AA);}}else{return false;}return y;},getDocumentHeight:function(){var Y=(K[t]!=M||I)?K.body.scrollHeight:W.scrollHeight,G=Math.max(Y,E.Dom.getViewportHeight());return G;},getDocumentWidth:function(){var Y=(K[t]!=M||I)?K.body.scrollWidth:W.scrollWidth,G=Math.max(Y,E.Dom.getViewportWidth());return G;},getViewportHeight:function(){var G=self.innerHeight,Y=K[t];if((Y||T)&&!D){G=(Y==M)?W.clientHeight:K.body.clientHeight;}return G;},getViewportWidth:function(){var G=self.innerWidth,Y=K[t];if(Y||T){G=(Y==M)?W.clientWidth:K.body.clientWidth;}return G;},getAncestorBy:function(G,Y){while((G=G[Z])){if(E.Dom._testElement(G,Y)){return G;}}return null;},getAncestorByClassName:function(Y,G){Y=E.Dom.get(Y);if(!Y){return null;}var x=function(y){return E.Dom.hasClass(y,G);};return E.Dom.getAncestorBy(Y,x);},getAncestorByTagName:function(Y,G){Y=E.Dom.get(Y);if(!Y){return null;}var x=function(y){return y[C]&&y[C].toUpperCase()==G.toUpperCase();};return E.Dom.getAncestorBy(Y,x);},getPreviousSiblingBy:function(G,Y){while(G){G=G.previousSibling;if(E.Dom._testElement(G,Y)){return G;}}return null;},getPreviousSibling:function(G){G=E.Dom.get(G);if(!G){return null;}return E.Dom.getPreviousSiblingBy(G);},getNextSiblingBy:function(G,Y){while(G){G=G.nextSibling;if(E.Dom._testElement(G,Y)){return G;}}return null;},getNextSibling:function(G){G=E.Dom.get(G);if(!G){return null;}return E.Dom.getNextSiblingBy(G);},getFirstChildBy:function(G,x){var Y=(E.Dom._testElement(G.firstChild,x))?G.firstChild:null;return Y||E.Dom.getNextSiblingBy(G.firstChild,x);},getFirstChild:function(G,Y){G=E.Dom.get(G);if(!G){return null;}return E.Dom.getFirstChildBy(G);},getLastChildBy:function(G,x){if(!G){return null;}var Y=(E.Dom._testElement(G.lastChild,x))?G.lastChild:null;return Y||E.Dom.getPreviousSiblingBy(G.lastChild,x);},getLastChild:function(G){G=E.Dom.get(G);return E.Dom.getLastChildBy(G);},getChildrenBy:function(Y,y){var x=E.Dom.getFirstChildBy(Y,y),G=x?[x]:[];E.Dom.getNextSiblingBy(x,function(z){if(!y||y(z)){G[G.length]=z;}return false;});return G;},getChildren:function(G){G=E.Dom.get(G);if(!G){}return E.Dom.getChildrenBy(G);},getDocumentScrollLeft:function(G){G=G||K;return Math.max(G[v].scrollLeft,G.body.scrollLeft);},getDocumentScrollTop:function(G){G=G||K;return Math.max(G[v].scrollTop,G.body.scrollTop);},insertBefore:function(Y,G){Y=E.Dom.get(Y);G=E.Dom.get(G);if(!Y||!G||!G[Z]){return null;}return G[Z].insertBefore(Y,G);},insertAfter:function(Y,G){Y=E.Dom.get(Y);G=E.Dom.get(G);if(!Y||!G||!G[Z]){return null;}if(G.nextSibling){return G[Z].insertBefore(Y,G.nextSibling);}else{return G[Z].appendChild(Y);}},getClientRegion:function(){var x=E.Dom.getDocumentScrollTop(),Y=E.Dom.getDocumentScrollLeft(),y=E.Dom.getViewportWidth()+Y,G=E.Dom.getViewportHeight()+x;return new E.Region(x,y,G,Y);},setAttribute:function(Y,G,x){E.Dom.batch(Y,E.Dom._setAttribute,{attr:G,val:x});},_setAttribute:function(x,Y){var G=E.Dom._toCamel(Y.attr),y=Y.val;if(x&&x.setAttribute){if(E.Dom.DOT_ATTRIBUTES[G]){x[G]=y;}else{G=E.Dom.CUSTOM_ATTRIBUTES[G]||G;x.setAttribute(G,y);}}else{}},getAttribute:function(Y,G){return E.Dom.batch(Y,E.Dom._getAttribute,G);},_getAttribute:function(Y,G){var x;G=E.Dom.CUSTOM_ATTRIBUTES[G]||G;if(Y&&Y.getAttribute){x=Y.getAttribute(G,2);}else{}return x;},_toCamel:function(Y){var x=d;function G(y,z){return z.toUpperCase();}return x[Y]||(x[Y]=Y.indexOf("-")===-1?Y:Y.replace(/-([a-z])/gi,G));},_getClassRegex:function(Y){var G;if(Y!==undefined){if(Y.exec){G=Y;}else{G=h[Y];if(!G){Y=Y.replace(E.Dom._patterns.CLASS_RE_TOKENS,"\\$1");G=h[Y]=new RegExp(s+Y+k,U);}}}return G;},_patterns:{ROOT_TAG:/^body|html$/i,CLASS_RE_TOKENS:/([\.\(\)\^\$\*\+\?\|\[\]\{\}\\])/g},_testElement:function(G,Y){return G&&G[l]==1&&(!Y||Y(G));},_calcBorders:function(x,y){var Y=parseInt(E.Dom[w](x,R),10)||0,G=parseInt(E.Dom[w](x,q),10)||0;if(H){if(N.test(x[C])){Y=0;G=0;}}y[0]+=G;y[1]+=Y;return y;}};var S=E.Dom[w];if(m.opera){E.Dom[w]=function(Y,G){var x=S(Y,G);if(X.test(G)){x=E.Dom.Color.toRGB(x);}return x;};}if(m.webkit){E.Dom[w]=function(Y,G){var x=S(Y,G);if(x==="rgba(0, 0, 0, 0)"){x="transparent";}return x;};}if(m.ie&&m.ie>=8&&K.documentElement.hasAttribute){E.Dom.DOT_ATTRIBUTES.type=true;}})();YAHOO.util.Region=function(C,D,A,B){this.top=C;this.y=C;this[1]=C;this.right=D;this.bottom=A;this.left=B;this.x=B;this[0]=B;
10
this.width=this.right-this.left;this.height=this.bottom-this.top;};YAHOO.util.Region.prototype.contains=function(A){return(A.left>=this.left&&A.right<=this.right&&A.top>=this.top&&A.bottom<=this.bottom);};YAHOO.util.Region.prototype.getArea=function(){return((this.bottom-this.top)*(this.right-this.left));};YAHOO.util.Region.prototype.intersect=function(E){var C=Math.max(this.top,E.top),D=Math.min(this.right,E.right),A=Math.min(this.bottom,E.bottom),B=Math.max(this.left,E.left);if(A>=C&&D>=B){return new YAHOO.util.Region(C,D,A,B);}else{return null;}};YAHOO.util.Region.prototype.union=function(E){var C=Math.min(this.top,E.top),D=Math.max(this.right,E.right),A=Math.max(this.bottom,E.bottom),B=Math.min(this.left,E.left);return new YAHOO.util.Region(C,D,A,B);};YAHOO.util.Region.prototype.toString=function(){return("Region {"+"top: "+this.top+", right: "+this.right+", bottom: "+this.bottom+", left: "+this.left+", height: "+this.height+", width: "+this.width+"}");};YAHOO.util.Region.getRegion=function(D){var F=YAHOO.util.Dom.getXY(D),C=F[1],E=F[0]+D.offsetWidth,A=F[1]+D.offsetHeight,B=F[0];return new YAHOO.util.Region(C,E,A,B);};YAHOO.util.Point=function(A,B){if(YAHOO.lang.isArray(A)){B=A[1];A=A[0];}YAHOO.util.Point.superclass.constructor.call(this,B,A,B,A);};YAHOO.extend(YAHOO.util.Point,YAHOO.util.Region);(function(){var B=YAHOO.util,A="clientTop",F="clientLeft",J="parentNode",K="right",W="hasLayout",I="px",U="opacity",L="auto",D="borderLeftWidth",G="borderTopWidth",P="borderRightWidth",V="borderBottomWidth",S="visible",Q="transparent",N="height",E="width",H="style",T="currentStyle",R=/^width|height$/,O=/^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i,M={get:function(X,Z){var Y="",a=X[T][Z];if(Z===U){Y=B.Dom.getStyle(X,U);}else{if(!a||(a.indexOf&&a.indexOf(I)>-1)){Y=a;}else{if(B.Dom.IE_COMPUTED[Z]){Y=B.Dom.IE_COMPUTED[Z](X,Z);}else{if(O.test(a)){Y=B.Dom.IE.ComputedStyle.getPixel(X,Z);}else{Y=a;}}}}return Y;},getOffset:function(Z,e){var b=Z[T][e],X=e.charAt(0).toUpperCase()+e.substr(1),c="offset"+X,Y="pixel"+X,a="",d;if(b==L){d=Z[c];if(d===undefined){a=0;}a=d;if(R.test(e)){Z[H][e]=d;if(Z[c]>d){a=d-(Z[c]-d);}Z[H][e]=L;}}else{if(!Z[H][Y]&&!Z[H][e]){Z[H][e]=b;}a=Z[H][Y];}return a+I;},getBorderWidth:function(X,Z){var Y=null;if(!X[T][W]){X[H].zoom=1;}switch(Z){case G:Y=X[A];break;case V:Y=X.offsetHeight-X.clientHeight-X[A];break;case D:Y=X[F];break;case P:Y=X.offsetWidth-X.clientWidth-X[F];break;}return Y+I;},getPixel:function(Y,X){var a=null,b=Y[T][K],Z=Y[T][X];Y[H][K]=Z;a=Y[H].pixelRight;Y[H][K]=b;return a+I;},getMargin:function(Y,X){var Z;if(Y[T][X]==L){Z=0+I;}else{Z=B.Dom.IE.ComputedStyle.getPixel(Y,X);}return Z;},getVisibility:function(Y,X){var Z;while((Z=Y[T])&&Z[X]=="inherit"){Y=Y[J];}return(Z)?Z[X]:S;},getColor:function(Y,X){return B.Dom.Color.toRGB(Y[T][X])||Q;},getBorderColor:function(Y,X){var Z=Y[T],a=Z[X]||Z.color;return B.Dom.Color.toRGB(B.Dom.Color.toHex(a));}},C={};C.top=C.right=C.bottom=C.left=C[E]=C[N]=M.getOffset;C.color=M.getColor;C[G]=C[P]=C[V]=C[D]=M.getBorderWidth;C.marginTop=C.marginRight=C.marginBottom=C.marginLeft=M.getMargin;C.visibility=M.getVisibility;C.borderColor=C.borderTopColor=C.borderRightColor=C.borderBottomColor=C.borderLeftColor=M.getBorderColor;B.Dom.IE_COMPUTED=C;B.Dom.IE_ComputedStyle=M;})();(function(){var C="toString",A=parseInt,B=RegExp,D=YAHOO.util;D.Dom.Color={KEYWORDS:{black:"000",silver:"c0c0c0",gray:"808080",white:"fff",maroon:"800000",red:"f00",purple:"800080",fuchsia:"f0f",green:"008000",lime:"0f0",olive:"808000",yellow:"ff0",navy:"000080",blue:"00f",teal:"008080",aqua:"0ff"},re_RGB:/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,re_hex:/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,re_hex3:/([0-9A-F])/gi,toRGB:function(E){if(!D.Dom.Color.re_RGB.test(E)){E=D.Dom.Color.toHex(E);}if(D.Dom.Color.re_hex.exec(E)){E="rgb("+[A(B.$1,16),A(B.$2,16),A(B.$3,16)].join(", ")+")";}return E;},toHex:function(H){H=D.Dom.Color.KEYWORDS[H]||H;if(D.Dom.Color.re_RGB.exec(H)){var G=(B.$1.length===1)?"0"+B.$1:Number(B.$1),F=(B.$2.length===1)?"0"+B.$2:Number(B.$2),E=(B.$3.length===1)?"0"+B.$3:Number(B.$3);H=[G[C](16),F[C](16),E[C](16)].join("");}if(H.length<6){H=H.replace(D.Dom.Color.re_hex3,"$1$1");}if(H!=="transparent"&&H.indexOf("#")<0){H="#"+H;}return H.toLowerCase();}};}());YAHOO.register("dom",YAHOO.util.Dom,{version:"2.8.0r4",build:"2449"});YAHOO.util.CustomEvent=function(D,C,B,A,E){this.type=D;this.scope=C||window;this.silent=B;this.fireOnce=E;this.fired=false;this.firedWith=null;this.signature=A||YAHOO.util.CustomEvent.LIST;this.subscribers=[];if(!this.silent){}var F="_YUICEOnSubscribe";if(D!==F){this.subscribeEvent=new YAHOO.util.CustomEvent(F,this,true);}this.lastError=null;};YAHOO.util.CustomEvent.LIST=0;YAHOO.util.CustomEvent.FLAT=1;YAHOO.util.CustomEvent.prototype={subscribe:function(B,C,D){if(!B){throw new Error("Invalid callback for subscriber to '"+this.type+"'");}if(this.subscribeEvent){this.subscribeEvent.fire(B,C,D);}var A=new YAHOO.util.Subscriber(B,C,D);if(this.fireOnce&&this.fired){this.notify(A,this.firedWith);}else{this.subscribers.push(A);}},unsubscribe:function(D,F){if(!D){return this.unsubscribeAll();}var E=false;for(var B=0,A=this.subscribers.length;B<A;++B){var C=this.subscribers[B];if(C&&C.contains(D,F)){this._delete(B);E=true;}}return E;},fire:function(){this.lastError=null;var H=[],A=this.subscribers.length;var D=[].slice.call(arguments,0),C=true,F,B=false;if(this.fireOnce){if(this.fired){return true;}else{this.firedWith=D;}}this.fired=true;if(!A&&this.silent){return true;}if(!this.silent){}var E=this.subscribers.slice();for(F=0;F<A;++F){var G=E[F];if(!G){B=true;}else{C=this.notify(G,D);if(false===C){if(!this.silent){}break;}}}return(C!==false);},notify:function(F,C){var B,H=null,E=F.getScope(this.scope),A=YAHOO.util.Event.throwErrors;if(!this.silent){}if(this.signature==YAHOO.util.CustomEvent.FLAT){if(C.length>0){H=C[0];}try{B=F.fn.call(E,H,F.obj);}catch(G){this.lastError=G;if(A){throw G;}}}else{try{B=F.fn.call(E,this.type,C,F.obj);}catch(D){this.lastError=D;if(A){throw D;}}}return B;},unsubscribeAll:function(){var A=this.subscribers.length,B;for(B=A-1;B>-1;B--){this._delete(B);}this.subscribers=[];return A;},_delete:function(A){var B=this.subscribers[A];if(B){delete B.fn;delete B.obj;}this.subscribers.splice(A,1);},toString:function(){return"CustomEvent: "+"'"+this.type+"', "+"context: "+this.scope;}};YAHOO.util.Subscriber=function(A,B,C){this.fn=A;this.obj=YAHOO.lang.isUndefined(B)?null:B;this.overrideContext=C;};YAHOO.util.Subscriber.prototype.getScope=function(A){if(this.overrideContext){if(this.overrideContext===true){return this.obj;}else{return this.overrideContext;}}return A;};YAHOO.util.Subscriber.prototype.contains=function(A,B){if(B){return(this.fn==A&&this.obj==B);}else{return(this.fn==A);}};YAHOO.util.Subscriber.prototype.toString=function(){return"Subscriber { obj: "+this.obj+", overrideContext: "+(this.overrideContext||"no")+" }";};if(!YAHOO.util.Event){YAHOO.util.Event=function(){var G=false,H=[],J=[],A=0,E=[],B=0,C={63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9},D=YAHOO.env.ua.ie,F="focusin",I="focusout";return{POLL_RETRYS:500,POLL_INTERVAL:40,EL:0,TYPE:1,FN:2,WFN:3,UNLOAD_OBJ:3,ADJ_SCOPE:4,OBJ:5,OVERRIDE:6,CAPTURE:7,lastError:null,isSafari:YAHOO.env.ua.webkit,webkit:YAHOO.env.ua.webkit,isIE:D,_interval:null,_dri:null,_specialTypes:{focusin:(D?"focusin":"focus"),focusout:(D?"focusout":"blur")},DOMReady:false,throwErrors:false,startInterval:function(){if(!this._interval){this._interval=YAHOO.lang.later(this.POLL_INTERVAL,this,this._tryPreloadAttach,null,true);}},onAvailable:function(Q,M,O,P,N){var K=(YAHOO.lang.isString(Q))?[Q]:Q;for(var L=0;L<K.length;L=L+1){E.push({id:K[L],fn:M,obj:O,overrideContext:P,checkReady:N});}A=this.POLL_RETRYS;this.startInterval();},onContentReady:function(N,K,L,M){this.onAvailable(N,K,L,M,true);},onDOMReady:function(){this.DOMReadyEvent.subscribe.apply(this.DOMReadyEvent,arguments);},_addListener:function(M,K,V,P,T,Y){if(!V||!V.call){return false;}if(this._isValidCollection(M)){var W=true;for(var Q=0,S=M.length;Q<S;++Q){W=this.on(M[Q],K,V,P,T)&&W;}return W;}else{if(YAHOO.lang.isString(M)){var O=this.getEl(M);if(O){M=O;}else{this.onAvailable(M,function(){YAHOO.util.Event._addListener(M,K,V,P,T,Y);});return true;}}}if(!M){return false;}if("unload"==K&&P!==this){J[J.length]=[M,K,V,P,T];return true;}var L=M;if(T){if(T===true){L=P;}else{L=T;}}var N=function(Z){return V.call(L,YAHOO.util.Event.getEvent(Z,M),P);};var X=[M,K,V,N,L,P,T,Y];var R=H.length;H[R]=X;try{this._simpleAdd(M,K,N,Y);}catch(U){this.lastError=U;this.removeListener(M,K,V);return false;}return true;},_getType:function(K){return this._specialTypes[K]||K;},addListener:function(M,P,L,N,O){var K=((P==F||P==I)&&!YAHOO.env.ua.ie)?true:false;return this._addListener(M,this._getType(P),L,N,O,K);},addFocusListener:function(L,K,M,N){return this.on(L,F,K,M,N);},removeFocusListener:function(L,K){return this.removeListener(L,F,K);},addBlurListener:function(L,K,M,N){return this.on(L,I,K,M,N);},removeBlurListener:function(L,K){return this.removeListener(L,I,K);},removeListener:function(L,K,R){var M,P,U;K=this._getType(K);if(typeof L=="string"){L=this.getEl(L);}else{if(this._isValidCollection(L)){var S=true;for(M=L.length-1;M>-1;M--){S=(this.removeListener(L[M],K,R)&&S);}return S;}}if(!R||!R.call){return this.purgeElement(L,false,K);}if("unload"==K){for(M=J.length-1;M>-1;M--){U=J[M];if(U&&U[0]==L&&U[1]==K&&U[2]==R){J.splice(M,1);return true;}}return false;}var N=null;var O=arguments[3];if("undefined"===typeof O){O=this._getCacheIndex(H,L,K,R);}if(O>=0){N=H[O];}if(!L||!N){return false;}var T=N[this.CAPTURE]===true?true:false;try{this._simpleRemove(L,K,N[this.WFN],T);}catch(Q){this.lastError=Q;return false;}delete H[O][this.WFN];delete H[O][this.FN];H.splice(O,1);return true;},getTarget:function(M,L){var K=M.target||M.srcElement;return this.resolveTextNode(K);},resolveTextNode:function(L){try{if(L&&3==L.nodeType){return L.parentNode;}}catch(K){}return L;},getPageX:function(L){var K=L.pageX;if(!K&&0!==K){K=L.clientX||0;if(this.isIE){K+=this._getScrollLeft();}}return K;},getPageY:function(K){var L=K.pageY;if(!L&&0!==L){L=K.clientY||0;if(this.isIE){L+=this._getScrollTop();}}return L;},getXY:function(K){return[this.getPageX(K),this.getPageY(K)];},getRelatedTarget:function(L){var K=L.relatedTarget;if(!K){if(L.type=="mouseout"){K=L.toElement;
11
}else{if(L.type=="mouseover"){K=L.fromElement;}}}return this.resolveTextNode(K);},getTime:function(M){if(!M.time){var L=new Date().getTime();try{M.time=L;}catch(K){this.lastError=K;return L;}}return M.time;},stopEvent:function(K){this.stopPropagation(K);this.preventDefault(K);},stopPropagation:function(K){if(K.stopPropagation){K.stopPropagation();}else{K.cancelBubble=true;}},preventDefault:function(K){if(K.preventDefault){K.preventDefault();}else{K.returnValue=false;}},getEvent:function(M,K){var L=M||window.event;if(!L){var N=this.getEvent.caller;while(N){L=N.arguments[0];if(L&&Event==L.constructor){break;}N=N.caller;}}return L;},getCharCode:function(L){var K=L.keyCode||L.charCode||0;if(YAHOO.env.ua.webkit&&(K in C)){K=C[K];}return K;},_getCacheIndex:function(M,P,Q,O){for(var N=0,L=M.length;N<L;N=N+1){var K=M[N];if(K&&K[this.FN]==O&&K[this.EL]==P&&K[this.TYPE]==Q){return N;}}return -1;},generateId:function(K){var L=K.id;if(!L){L="yuievtautoid-"+B;++B;K.id=L;}return L;},_isValidCollection:function(L){try{return(L&&typeof L!=="string"&&L.length&&!L.tagName&&!L.alert&&typeof L[0]!=="undefined");}catch(K){return false;}},elCache:{},getEl:function(K){return(typeof K==="string")?document.getElementById(K):K;},clearCache:function(){},DOMReadyEvent:new YAHOO.util.CustomEvent("DOMReady",YAHOO,0,0,1),_load:function(L){if(!G){G=true;var K=YAHOO.util.Event;K._ready();K._tryPreloadAttach();}},_ready:function(L){var K=YAHOO.util.Event;if(!K.DOMReady){K.DOMReady=true;K.DOMReadyEvent.fire();K._simpleRemove(document,"DOMContentLoaded",K._ready);}},_tryPreloadAttach:function(){if(E.length===0){A=0;if(this._interval){this._interval.cancel();this._interval=null;}return;}if(this.locked){return;}if(this.isIE){if(!this.DOMReady){this.startInterval();return;}}this.locked=true;var Q=!G;if(!Q){Q=(A>0&&E.length>0);}var P=[];var R=function(T,U){var S=T;if(U.overrideContext){if(U.overrideContext===true){S=U.obj;}else{S=U.overrideContext;}}U.fn.call(S,U.obj);};var L,K,O,N,M=[];for(L=0,K=E.length;L<K;L=L+1){O=E[L];if(O){N=this.getEl(O.id);if(N){if(O.checkReady){if(G||N.nextSibling||!Q){M.push(O);E[L]=null;}}else{R(N,O);E[L]=null;}}else{P.push(O);}}}for(L=0,K=M.length;L<K;L=L+1){O=M[L];R(this.getEl(O.id),O);}A--;if(Q){for(L=E.length-1;L>-1;L--){O=E[L];if(!O||!O.id){E.splice(L,1);}}this.startInterval();}else{if(this._interval){this._interval.cancel();this._interval=null;}}this.locked=false;},purgeElement:function(O,P,R){var M=(YAHOO.lang.isString(O))?this.getEl(O):O;var Q=this.getListeners(M,R),N,K;if(Q){for(N=Q.length-1;N>-1;N--){var L=Q[N];this.removeListener(M,L.type,L.fn);}}if(P&&M&&M.childNodes){for(N=0,K=M.childNodes.length;N<K;++N){this.purgeElement(M.childNodes[N],P,R);}}},getListeners:function(M,K){var P=[],L;if(!K){L=[H,J];}else{if(K==="unload"){L=[J];}else{K=this._getType(K);L=[H];}}var R=(YAHOO.lang.isString(M))?this.getEl(M):M;for(var O=0;O<L.length;O=O+1){var T=L[O];if(T){for(var Q=0,S=T.length;Q<S;++Q){var N=T[Q];if(N&&N[this.EL]===R&&(!K||K===N[this.TYPE])){P.push({type:N[this.TYPE],fn:N[this.FN],obj:N[this.OBJ],adjust:N[this.OVERRIDE],scope:N[this.ADJ_SCOPE],index:Q});}}}}return(P.length)?P:null;},_unload:function(R){var L=YAHOO.util.Event,O,N,M,Q,P,S=J.slice(),K;for(O=0,Q=J.length;O<Q;++O){M=S[O];if(M){K=window;if(M[L.ADJ_SCOPE]){if(M[L.ADJ_SCOPE]===true){K=M[L.UNLOAD_OBJ];}else{K=M[L.ADJ_SCOPE];}}M[L.FN].call(K,L.getEvent(R,M[L.EL]),M[L.UNLOAD_OBJ]);S[O]=null;}}M=null;K=null;J=null;if(H){for(N=H.length-1;N>-1;N--){M=H[N];if(M){L.removeListener(M[L.EL],M[L.TYPE],M[L.FN],N);}}M=null;}L._simpleRemove(window,"unload",L._unload);},_getScrollLeft:function(){return this._getScroll()[1];},_getScrollTop:function(){return this._getScroll()[0];},_getScroll:function(){var K=document.documentElement,L=document.body;if(K&&(K.scrollTop||K.scrollLeft)){return[K.scrollTop,K.scrollLeft];}else{if(L){return[L.scrollTop,L.scrollLeft];}else{return[0,0];}}},regCE:function(){},_simpleAdd:function(){if(window.addEventListener){return function(M,N,L,K){M.addEventListener(N,L,(K));};}else{if(window.attachEvent){return function(M,N,L,K){M.attachEvent("on"+N,L);};}else{return function(){};}}}(),_simpleRemove:function(){if(window.removeEventListener){return function(M,N,L,K){M.removeEventListener(N,L,(K));};}else{if(window.detachEvent){return function(L,M,K){L.detachEvent("on"+M,K);};}else{return function(){};}}}()};}();(function(){var EU=YAHOO.util.Event;EU.on=EU.addListener;EU.onFocus=EU.addFocusListener;EU.onBlur=EU.addBlurListener;
12
/* DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */
13
if(EU.isIE){if(self!==self.top){document.onreadystatechange=function(){if(document.readyState=="complete"){document.onreadystatechange=null;EU._ready();}};}else{YAHOO.util.Event.onDOMReady(YAHOO.util.Event._tryPreloadAttach,YAHOO.util.Event,true);var n=document.createElement("p");EU._dri=setInterval(function(){try{n.doScroll("left");clearInterval(EU._dri);EU._dri=null;EU._ready();n=null;}catch(ex){}},EU.POLL_INTERVAL);}}else{if(EU.webkit&&EU.webkit<525){EU._dri=setInterval(function(){var rs=document.readyState;if("loaded"==rs||"complete"==rs){clearInterval(EU._dri);EU._dri=null;EU._ready();}},EU.POLL_INTERVAL);}else{EU._simpleAdd(document,"DOMContentLoaded",EU._ready);}}EU._simpleAdd(window,"load",EU._load);EU._simpleAdd(window,"unload",EU._unload);EU._tryPreloadAttach();})();}YAHOO.util.EventProvider=function(){};YAHOO.util.EventProvider.prototype={__yui_events:null,__yui_subscribers:null,subscribe:function(A,C,F,E){this.__yui_events=this.__yui_events||{};var D=this.__yui_events[A];if(D){D.subscribe(C,F,E);}else{this.__yui_subscribers=this.__yui_subscribers||{};var B=this.__yui_subscribers;if(!B[A]){B[A]=[];}B[A].push({fn:C,obj:F,overrideContext:E});}},unsubscribe:function(C,E,G){this.__yui_events=this.__yui_events||{};var A=this.__yui_events;if(C){var F=A[C];if(F){return F.unsubscribe(E,G);}}else{var B=true;for(var D in A){if(YAHOO.lang.hasOwnProperty(A,D)){B=B&&A[D].unsubscribe(E,G);}}return B;}return false;},unsubscribeAll:function(A){return this.unsubscribe(A);
14
},createEvent:function(B,G){this.__yui_events=this.__yui_events||{};var E=G||{},D=this.__yui_events,F;if(D[B]){}else{F=new YAHOO.util.CustomEvent(B,E.scope||this,E.silent,YAHOO.util.CustomEvent.FLAT,E.fireOnce);D[B]=F;if(E.onSubscribeCallback){F.subscribeEvent.subscribe(E.onSubscribeCallback);}this.__yui_subscribers=this.__yui_subscribers||{};var A=this.__yui_subscribers[B];if(A){for(var C=0;C<A.length;++C){F.subscribe(A[C].fn,A[C].obj,A[C].overrideContext);}}}return D[B];},fireEvent:function(B){this.__yui_events=this.__yui_events||{};var D=this.__yui_events[B];if(!D){return null;}var A=[];for(var C=1;C<arguments.length;++C){A.push(arguments[C]);}return D.fire.apply(D,A);},hasEvent:function(A){if(this.__yui_events){if(this.__yui_events[A]){return true;}}return false;}};(function(){var A=YAHOO.util.Event,C=YAHOO.lang;YAHOO.util.KeyListener=function(D,I,E,F){if(!D){}else{if(!I){}else{if(!E){}}}if(!F){F=YAHOO.util.KeyListener.KEYDOWN;}var G=new YAHOO.util.CustomEvent("keyPressed");this.enabledEvent=new YAHOO.util.CustomEvent("enabled");this.disabledEvent=new YAHOO.util.CustomEvent("disabled");if(C.isString(D)){D=document.getElementById(D);}if(C.isFunction(E)){G.subscribe(E);}else{G.subscribe(E.fn,E.scope,E.correctScope);}function H(O,N){if(!I.shift){I.shift=false;}if(!I.alt){I.alt=false;}if(!I.ctrl){I.ctrl=false;}if(O.shiftKey==I.shift&&O.altKey==I.alt&&O.ctrlKey==I.ctrl){var J,M=I.keys,L;if(YAHOO.lang.isArray(M)){for(var K=0;K<M.length;K++){J=M[K];L=A.getCharCode(O);if(J==L){G.fire(L,O);break;}}}else{L=A.getCharCode(O);if(M==L){G.fire(L,O);}}}}this.enable=function(){if(!this.enabled){A.on(D,F,H);this.enabledEvent.fire(I);}this.enabled=true;};this.disable=function(){if(this.enabled){A.removeListener(D,F,H);this.disabledEvent.fire(I);}this.enabled=false;};this.toString=function(){return"KeyListener ["+I.keys+"] "+D.tagName+(D.id?"["+D.id+"]":"");};};var B=YAHOO.util.KeyListener;B.KEYDOWN="keydown";B.KEYUP="keyup";B.KEY={ALT:18,BACK_SPACE:8,CAPS_LOCK:20,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,META:224,NUM_LOCK:144,PAGE_DOWN:34,PAGE_UP:33,PAUSE:19,PRINTSCREEN:44,RIGHT:39,SCROLL_LOCK:145,SHIFT:16,SPACE:32,TAB:9,UP:38};})();YAHOO.register("event",YAHOO.util.Event,{version:"2.8.0r4",build:"2449"});YAHOO.register("yahoo-dom-event", YAHOO, {version: "2.8.0r4", build: "2449"});
(-)a/koha-tmpl/intranet-tmpl/prog/css/preferences.css (-3 lines)
Lines 96-104 h3.collapsed i.fa.fa-caret-down::before { Link Here
96
	font-weight: normal;
96
	font-weight: normal;
97
}
97
}
98
98
99
#yui-main {
100
	margin-bottom:2em;
101
}
102
#toolbar.floating {
99
#toolbar.floating {
103
    box-shadow: 0 3px 2px 0 rgba(0, 0, 0, 0.5);
100
    box-shadow: 0 3px 2px 0 rgba(0, 0, 0, 0.5);
104
    border-radius: 0;
101
    border-radius: 0;
(-)a/koha-tmpl/intranet-tmpl/prog/css/print.css (-7 lines)
Lines 299-305 td.debit { Link Here
299
#batchModify,
299
#batchModify,
300
#navmenu,
300
#navmenu,
301
.gradient,
301
.gradient,
302
div.yui-b,
303
.noprint,
302
.noprint,
304
form#sortbyform,
303
form#sortbyform,
305
#cartDetails,
304
#cartDetails,
Lines 313-329 button.dt-button { Link Here
313
    display: none;
312
    display: none;
314
}
313
}
315
314
316
div#yui-main div.yui-b,
317
.ui-tabs .ui-tabs-panel,
315
.ui-tabs .ui-tabs-panel,
318
.ui-tabs .ui-tabs-hide {
316
.ui-tabs .ui-tabs-hide {
319
    display : block !important;
317
    display : block !important;
320
}
318
}
321
319
322
.yui-t1 #yui-main div.yui-b,
323
.yui-t2 #yui-main div.yui-b,
324
.yui-t7 #yui-main div.yui-b {
325
	margin-left : 0;
326
}
327
fieldset {
320
fieldset {
328
	border : 0;
321
	border : 0;
329
}
322
}
(-)a/koha-tmpl/intranet-tmpl/prog/css/printreceiptinvoice.css (-10 lines)
Lines 326-332 div#header_search, Link Here
326
div#toolbar,
326
div#toolbar,
327
div#changelanguage,
327
div#changelanguage,
328
div#menu,
328
div#menu,
329
div.yui-b,
330
.noprint,
329
.noprint,
331
form#sortbyform,
330
form#sortbyform,
332
#cartDetails,
331
#cartDetails,
Lines 336-350 fieldset.action, Link Here
336
    display: none;
335
    display: none;
337
}
336
}
338
337
339
div#yui-main div.yui-b {
340
	display : block;
341
}
342
343
.yui-t1 #yui-main div.yui-b,
344
.yui-t2 #yui-main div.yui-b,
345
.yui-t7 #yui-main div.yui-b {
346
	margin-left : 0;
347
}
348
fieldset {
338
fieldset {
349
	border : 0;
339
	border : 0;
350
}
340
}
(-)a/koha-tmpl/intranet-tmpl/prog/css/right-to-left.css (-142 / +5 lines)
Lines 1-6 Link Here
1
fieldset.rows ol.radio label, fieldset.rows li.radio label { float: right; margin: 0 1em 0 0.3em; }
1
fieldset.rows ol.radio label, fieldset.rows li.radio label { float: right; margin: 0 1em 0 0.3em; }
2
2
3
4
/* Adjust text directions */
3
/* Adjust text directions */
5
4
6
body,
5
body,
Lines 18-47 h5, Link Here
18
h6,
17
h6,
19
legend,
18
legend,
20
th,
19
th,
21
odoc,
22
p,
20
p,
23
ul li,
21
ul li,
24
ul.toolbar,
22
ul.toolbar,
25
#doc2,
26
#doc3,
27
#doc4,
28
.autocomplete .sample-result,
23
.autocomplete .sample-result,
29
.ui-tabs-panel,
24
.ui-tabs-panel,
30
.yui-t1,
31
.yui-t2,
32
.yui-t3,
33
.yui-t4
34
.yui-t5,
35
.yui-t6,
36
.yui-t7
37
{
25
{
38
   text-align: right;
26
   text-align: right;
39
}
27
}
40
28
41
#doc, #doc2, #doc3, #doc4, .yui-t1, .yui-t2, .yui-t3, .yui-t4, .yui-t5, .yui-t6, .yui-t7 {
42
    text-align: right;
43
}
44
45
#issuest th,
29
#issuest th,
46
.column-tool
30
.column-tool
47
{
31
{
Lines 72-87 span.important, Link Here
72
#marcDocsSelect,
56
#marcDocsSelect,
73
#toplevelnav,
57
#toplevelnav,
74
.ui-tabs-nav li,
58
.ui-tabs-nav li,
75
.yui-g div.first,
76
.yui-gb div.first,
77
.yui-gc div.first,
78
.yui-gc div.first div.first,
79
.yui-gd div.first,
80
.yui-ge div.first,
81
.yui-gf div.first,
82
.yui-t1 .yui-b,
83
.yui-t2 .yui-b,
84
.yui-t3 .yui-b
85
{
59
{
86
   float: right;
60
   float: right;
87
}
61
}
Lines 98-132 input, Link Here
98
   float: none;
72
   float: none;
99
}
73
}
100
74
101
div.sysprefs div.hint,
75
div.sysprefs div.hint {
102
.yui-g .yui-u,
103
.yui-t1 #yui-main,
104
.yui-t2 #yui-main,
105
.yui-t3 #yui-main,
106
107
{
108
   float: right ;
76
   float: right ;
109
}
77
}
110
.yui-t1 {
111
float:right
112
}
113
78
114
/* Adjust margins, padding, alignment and table-element widths */
79
/* Adjust margins, padding, alignment and table-element widths */
115
80
116
.yui-t1 #yui-main,
117
.yui-t2 #yui-main,
118
.yui-t3 #yui-main
119
{
120
   margin-left: 0;
121
}
122
123
.yui-t1 #yui-main .yui-b,
124
.yui-t2 #yui-main .yui-b
125
{
126
   margin-left: 0;
127
   /* karam margin-right: 13em; */
128
}
129
130
div#menu li a
81
div#menu li a
131
{
82
{
132
   margin-left: -1px;
83
   margin-left: -1px;
Lines 135-143 div#menu li a Link Here
135
div#menu,
86
div#menu,
136
div.patroninfo ul,
87
div.patroninfo ul,
137
div.patroninfo h5,
88
div.patroninfo h5,
138
#guarantorsearch,
89
#guarantorsearch {
139
.yui-g input
140
{
141
   margin-left: 0.5em;
90
   margin-left: 0.5em;
142
}
91
}
143
fieldset.rows img,
92
fieldset.rows img,
Lines 158-184 div#header_search Link Here
158
   margin-right:200px;
107
   margin-right:200px;
159
}
108
}
160
109
161
.yui-g .yui-u
162
{
163
   padding-right: 0;
164
}
165
166
.yui-u
167
{
168
   padding-right: 0.5em;
169
}
170
171
ul
110
ul
172
{
111
{
173
   padding-left: 0;
112
   padding-left: 0;
174
   padding-right: 1.1em;
113
   padding-right: 1.1em;
175
}
114
}
176
115
177
.yui-b
178
{
179
   padding-bottom: 5em;
180
}
181
182
#login
116
#login
183
{
117
{
184
   left: 0.5em;
118
   left: 0.5em;
Lines 195-216 ul Link Here
195
   right:auto;
129
   right:auto;
196
}
130
}
197
131
198
div.listgroup,
132
div.listgroup {
199
.yui-g p
200
{
201
   clear:right;
133
   clear:right;
202
}
134
}
203
135
204
.yui-t2 #yui-main
205
{
206
   width: 75%;
207
}
208
209
.yui-t3 #yui-main
210
{
211
   width: 70%;
212
}
213
214
.holdcount
136
.holdcount
215
{
137
{
216
   line-height: 150%;
138
   line-height: 150%;
Lines 237-245 div.patroninfo h5 Link Here
237
159
238
h1#logo,
160
h1#logo,
239
#koha_url,
161
#koha_url,
240
#login,
162
#login {
241
.yui-t1 .yui-b
242
{
243
   position: absolute;
163
   position: absolute;
244
}
164
}
245
165
Lines 283-302 div.subfield_line label { Link Here
283
    text-align: right;
203
    text-align: right;
284
    clear: right;
204
    clear: right;
285
}
205
}
286
.yui-t3 #yui-main .yui-b {
287
    margin-left: -0.0759em;
288
}
289
290
#doc3 {
291
    background-position: right top;
292
}
293
294
.yui-gb{
295
    /* use this will break the tools page "" width: 30%;""*/
296
    float: right;
297
}
298
299
300
206
301
ul#toplevelmenu {
207
ul#toplevelmenu {
302
    padding: 0px;
208
    padding: 0px;
Lines 314-336 ul#toplevelmenu { Link Here
314
    padding-right: 25px;
220
    padding-right: 25px;
315
}
221
}
316
222
317
318
319
.yui-g .yui-u, .yui-g .yui-g, .yui-g .yui-gb, .yui-g .yui-gc, .yui-g .yui-gd, .yui-g .yui-ge, .yui-g .yui-gf, .yui-gc .yui-u, .yui-gd .yui-g, .yui-g .yui-gc .yui-u, .yui-ge .yui-u, .yui-ge .yui-g, .yui-gf .yui-g, .yui-gf .yui-u {
320
    display: inline;
321
322
}
323
324
325
326
fieldset.action {
223
fieldset.action {
327
    float: right;
224
    float: right;
328
225
329
}
226
}
330
#yui-main .yui-b {
331
332
    width: auto;
333
}
334
227
335
/***********************************************************/
228
/***********************************************************/
336
229
Lines 339-359 fieldset.action { Link Here
339
    float: right;
232
    float: right;
340
}
233
}
341
234
342
/*for the tools main page */
343
.yui-gb .yui-u {
344
    float: left;
345
    margin-right: 2%;
346
    margin-left: 0%;
347
    width: 25%;
348
}
349
350
/*NEWS*/
351
div.yui-b {
352
    position: absolute;
353
}
354
div#yui-main{
355
float:left;
356
}
357
/*floating taps for marceditor and other taps plases */
235
/*floating taps for marceditor and other taps plases */
358
.ui-tabs .ui-tabs-nav li {
236
.ui-tabs .ui-tabs-nav li {
359
    float: right;
237
    float: right;
Lines 395-415 p label, { Link Here
395
    background-clip: padding-box;
273
    background-clip: padding-box;
396
}
274
}
397
275
398
399
/* */
400
401
div#yui-main {
402
403
    margin-right: 22em;
404
}
405
406
/* */
407
408
div#yui-main.sysprefs {
409
    margin-right: 0em;
410
    float: right;
411
}
412
413
#user-menu {
276
#user-menu {
414
    left: 5px;
277
    left: 5px;
415
    right: unset;
278
    right: unset;
Lines 465-468 div.dt-buttons { Link Here
465
        float: none;
328
        float: none;
466
    }
329
    }
467
330
468
}
331
}
(-)a/koha-tmpl/intranet-tmpl/prog/css/src/_tables.scss (-4 lines)
Lines 124-133 table { Link Here
124
        tbody {
124
        tbody {
125
            td {
125
            td {
126
                padding: .5em;
126
                padding: .5em;
127
128
                &.dataTables_empty {
129
                    display: none;
130
                }
131
            }
127
            }
132
        }
128
        }
133
129
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/about.tt (-4 lines)
Lines 700-709 Link Here
700
            <h2>Bootstrap Icons</h2>
700
            <h2>Bootstrap Icons</h2>
701
            <p><a href="https://icons.getbootstrap.com/">Bootstrap Icons</a> licensed under the <a href="https://github.com/twbs/icons/blob/main/LICENSE.md">MIT license</a>.</p>
701
            <p><a href="https://icons.getbootstrap.com/">Bootstrap Icons</a> licensed under the <a href="https://github.com/twbs/icons/blob/main/LICENSE.md">MIT license</a>.</p>
702
702
703
            <h2>YUI</h2>
704
            <p>
705
            <a href="http://yuilibrary.com/license/">BSD License</a>
706
            </p>
707
            <h2>Famfamfam iconset</h2>
703
            <h2>Famfamfam iconset</h2>
708
              <ul>
704
              <ul>
709
                <li><a href="http://www.famfamfam.com/lab/icons/silk/">FamFamFam Site</a></li>
705
                <li><a href="http://www.famfamfam.com/lab/icons/silk/">FamFamFam Site</a></li>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basketgroup.tt (-134 / +131 lines)
Lines 6-93 Link Here
6
<title>Basket grouping for [% booksellername | html %] &rsaquo; Koha</title>
6
<title>Basket grouping for [% booksellername | html %] &rsaquo; Koha</title>
7
[% INCLUDE 'doc-head-close.inc' %]
7
[% INCLUDE 'doc-head-close.inc' %]
8
[% INCLUDE 'datatables.inc' %]
8
[% INCLUDE 'datatables.inc' %]
9
[% Asset.js("lib/yui/utilities/utilities.js") | $raw %]
10
[% Asset.js("lib/yui/button/button-min.js") | $raw %]
11
[% Asset.js("lib/yui/container/container_core-min.js") | $raw %]
12
[% Asset.js("lib/yui/menu/menu-min.js") | $raw %]
13
[% Asset.js("js/basketgroup.js") | $raw %]
14
[% IF ( grouping ) %]
15
[% Asset.js("lib/yui/yahoo-dom-event/yahoo-dom-event.js") | $raw %]
16
[% Asset.js("lib/yui/animation/animation-min.js") | $raw %]
17
[% Asset.js("lib/yui/dragdrop/dragdrop-min.js") | $raw %]
18
[% Asset.js("lib/yui/element/element-min.js") | $raw %]
19
<style>
20
/*margin and padding on body element
21
  can introduce errors in determining
22
  element position and are not recommended;
23
  we turn them off as a foundation for YUI
24
  CSS treatments. */
25
26
#ungrouped {
27
	overflow: auto;
28
	height: 400px;
29
}
30
31
.draglist{
32
	width: 200px;
33
	height: 300px;
34
	overflow: auto;
35
}
36
37
div.workarea_alt { padding: 5px; float:left; width: 95%;}
38
div.closed { background-color: pink; padding:10px; float:left; width: 45%;}
39
40
ul.draglist {
41
    position: relative;
42
    background: #EEE;
43
    padding-bottom:10;
44
    border: 1px inset gray;
45
    list-style: none;
46
    margin:0;
47
    padding: 5px;
48
}
49
50
ul.draglist li {
51
    margin: 1px;
52
    cursor: move;
53
    list-style: none;
54
}
55
56
ul.draglist_alt {
57
    position: relative;
58
    border: 1px solid gray;
59
    list-style: none;
60
    margin: 0;
61
    background: #f7f7f7;
62
    padding: 5px;
63
    cursor: move;
64
}
65
66
ul.draglist_alt li {
67
    margin: 1px;
68
    list-style: none;
69
}
70
71
li.grouped {
72
    background-color: #D1E6EC;
73
    border:1px solid #7EA6B2;
74
    list-style: none;
75
}
76
77
li.ungrouped {
78
    background-color: #D8D4E2;
79
    border:1px solid #6B4C86;
80
}
81
82
fieldset.various li {
83
    list-style: none;
84
    clear: none;
85
}
86
87
</style>
88
 [% END %]
89
<script>
9
<script>
90
    YAHOO.util.Event.onDOMReady(DDApp.init, DDApp, true);
91
10
92
    var MSG_CONFIRM_CLOSE_BASKETGROUP = _("Are you sure you want to close this basketgroup?");
11
    var MSG_CONFIRM_CLOSE_BASKETGROUP = _("Are you sure you want to close this basketgroup?");
93
    var MSG_CLOSE_EMPTY_BASKET = _("Why close an empty basket?");
12
    var MSG_CLOSE_EMPTY_BASKET = _("Why close an empty basket?");
Lines 111-123 fieldset.various li { Link Here
111
        [% ELSE %]
30
        [% ELSE %]
112
            $("#basket_groups a[href='#opened']").tab("show");
31
            $("#basket_groups a[href='#opened']").tab("show");
113
        [% END %]
32
        [% END %]
114
        $("table").dataTable($.extend(true, {}, dataTablesDefaults, {
33
        [% UNLESS ( grouping ) %]
115
            "aoColumnDefs": [
34
            $("table").dataTable($.extend(true, {}, dataTablesDefaults, {
116
                { "aTargets": [ -1 ], "bSortable": false, "bSearchable": false },
35
                "aoColumnDefs": [
117
            ],
36
                    { "aTargets": [ -1 ], "bSortable": false, "bSearchable": false },
118
            "bAutoWidth": false,
37
                ],
119
            "sPaginationType": "full"
38
                "bAutoWidth": false,
120
        } ));
39
                "sPaginationType": "full"
40
            } ));
41
        [% ELSE %]
42
            grouped = $("#grouped").DataTable($.extend(true, {}, dataTablesDefaults, {
43
                "dom": 't',
44
                "columnDefs": [
45
                    { 'sortable': false, 'targets': [ 'NoSort' ] }
46
                ],
47
                'autoWidth': false,
48
                "language": {
49
                    "emptyTable": _("There are no baskets in this group")
50
                }
51
            } ));
52
            ungrouped = $("#ungrouped").DataTable($.extend(true, {}, dataTablesDefaults, {
53
                "dom": 't',
54
                "columnDefs": [
55
                    { 'sortable': false, 'targets': [ 'NoSort' ] }
56
                ],
57
                'autoWidth': false,
58
                "language": {
59
                    "emptyTable": _("There are no ungrouped baskets")
60
                }
61
            } ));
62
        [% END %]
63
64
        $("#basketgroupcolumns").on("click", ".addtogroup", function(){
65
            const row = $("#" + $(this).data("basketid") );
66
            if( row ){
67
                $(this).removeClass("addtogroup").addClass("removefromgroup").html("<i class=\"fa fa-trash\" aria-hidden=\"true\"></i> " + _("Remove") );
68
                row.removeClass("ungrouped").addClass("grouped");
69
                ungrouped.row( row ).remove().draw();
70
                grouped.row.add( row ).draw();
71
            }
72
        });
73
74
        $("#basketgroupcolumns").on("click", ".removefromgroup", function(){
75
            const row = $("#" + $(this).data("basketid") );
76
            if( row ){
77
                $(this).removeClass("removefromgroup").addClass("addtogroup").html("<i class=\"fa fa-plus\" aria-hidden=\"true\"></i> " + _("Add to group") );
78
                $(this).removeClass("").addClass("");
79
                row.removeClass("grouped").addClass("ungrouped");
80
                grouped.row( row ).remove().draw();
81
                ungrouped.row.add( row ).draw();
82
            }
83
        });
121
    });
84
    });
122
</script>
85
</script>
123
86
Lines 190-221 fieldset.various li { Link Here
190
                    <div id="basketgroupcolumns" class="row">
153
                    <div id="basketgroupcolumns" class="row">
191
                        [% UNLESS (closedbg) %]
154
                        [% UNLESS (closedbg) %]
192
                            <div class="col-xs-6 col-xs-push-6">
155
                            <div class="col-xs-6 col-xs-push-6">
193
                                <form action="[% scriptname | html %]" method="post" name="basketgroups" id="basketgroups">
156
194
                                    <div id="groups">
157
                                    <div id="groups">
195
                                        <fieldset class="brief">
158
                                        <div class="workarea_alt" >
196
                                            <div class="workarea_alt" >
159
                                            <h3>Ungrouped baskets</h3>
197
                                                <h3>Ungrouped baskets</h3>
160
                                                <table id="ungrouped" class="basketgroup_baskets">
198
                                                <ul id="ungrouped" class="draglist_alt">
161
                                                    <thead>
199
                                                    [% IF ( baskets ) %]
162
                                                        <tr>
200
                                                        [% FOREACH basket IN baskets %]
163
                                                            <th>Basket</th>
201
                                                            <li class="ungrouped" id="b-[% basket.basketno | html %]" >
164
                                                            <th>Total</th>
202
                                                                <a href="basket.pl?basketno=[% basket.basketno | uri %]">
165
                                                            <th class="NoSort"></th>
203
                                                                    [% IF ( basket.basketname ) %]
166
                                                        </tr>
204
                                                                        [% basket.basketname | html %]
167
                                                    </thead>
205
                                                                    [% ELSE %]
168
                                                    <tbody>
206
                                                                        <span>No name, basketnumber: [% basket.basketno | html %]</span>
169
                                                        [% IF ( baskets ) %]
207
                                                                    [% END %]
170
                                                            [% FOREACH basket IN baskets %]
208
                                                                </a>, <br />
171
                                                                <tr class="ungrouped" id="b-[% basket.basketno | html %]">
209
                                                                Total: [% basket.total | $Price %]
172
                                                                    <td>
210
                                                                <input type="hidden" class="basket" name="basket" value="[% basket.basketno | html %]" />
173
                                                                        <a href="basket.pl?basketno=[% basket.basketno | uri %]">
211
                                                            </li>
174
                                                                            [% IF ( basket.basketname ) %]
175
                                                                                [% basket.basketname | html %]
176
                                                                            [% ELSE %]
177
                                                                                <span>No name, basketnumber: [% basket.basketno | html %]</span>
178
                                                                            [% END %]
179
                                                                        </a>
180
                                                                    </td>
181
                                                                    <td data-sort="[% basket.total | html %]">
182
                                                                        [% basket.total | $Price %]
183
                                                                        <input type="hidden" class="basket" name="basket" value="[% basket.basketno | html %]" />
184
                                                                    </td>
185
                                                                    <td>
186
                                                                        <a class="addtogroup btn btn-default btn-xs" data-basketid="b-[% basket.basketno | html %]">
187
                                                                            <i class="fa fa-plus" aria-hidden="true"></i> Add to group
188
                                                                        </a>
189
                                                                    </td>
190
                                                                </tr>
191
                                                            [% END %]
212
                                                        [% END %]
192
                                                        [% END %]
213
                                                    [% END %]
193
                                                    </tbody>
214
                                                </ul>
194
                                                </table>
215
                                            </div>
195
                                        </div>
216
                                        </fieldset>
217
                                    </div>
196
                                    </div>
218
                                </form>
197
219
                            </div>
198
                            </div>
220
                        [% END %]
199
                        [% END %]
221
                        [% IF ( closedbg ) %]
200
                        [% IF ( closedbg ) %]
Lines 223-229 fieldset.various li { Link Here
223
                        [% ELSE %]
202
                        [% ELSE %]
224
                            <div class="col-xs-6 col-xs-pull-6">
203
                            <div class="col-xs-6 col-xs-pull-6">
225
                        [% END %]
204
                        [% END %]
226
                            <form action="" method="post" id="groupingform" onsubmit="return submitForm(this)">
205
                            <form action="/cgi-bin/koha/acqui/basketgroup.pl" method="post" id="groupingform" onsubmit="return submitForm(this)">
227
                                <fieldset id="various" class="brief">
206
                                <fieldset id="various" class="brief">
228
                                    <ol>
207
                                    <ol>
229
                                        [% UNLESS (closedbg) %]
208
                                        [% UNLESS (closedbg) %]
Lines 281-314 fieldset.various li { Link Here
281
                                                [% END %]
260
                                                [% END %]
282
                                            </li>
261
                                            </li>
283
                                            <li>
262
                                            <li>
284
                                                <span class="label">Baskets in this group:</span>
263
                                                <h3>Baskets in this group:</h3>
285
                                                [% UNLESS (closedbg) %]
264
                                                <table id="grouped" class="basketgroup_baskets">
286
                                                    <ul class="draglist" id="bg">
265
                                                    <thead>
287
                                                [% ELSE %]
266
                                                        <tr>
288
                                                    <ul>
267
                                                            <th>Basket</th>
289
                                                [% END %]
268
                                                            <th>Total</th>
290
                                                [% FOREACH selectedbasket IN selectedbaskets %]
269
                                                            <th class="NoSort"></th>
291
                                                    <li class="grouped" id="b-[% selectedbasket.basketno | html %]" >
270
                                                        </tr>
292
                                                        <a href="basket.pl?basketno=[% selectedbasket.basketno | uri %]">
271
                                                    </thead>
293
                                                            [% IF ( selectedbasket.basketname ) %]
272
                                                    <tbody>
294
                                                                [% selectedbasket.basketname | html %]
273
                                                        [% FOREACH selectedbasket IN selectedbaskets %]
295
                                                            [% ELSE %]
274
                                                            <tr id="b-[% selectedbasket.basketno | html %]">
296
                                                                No name, basketnumber: [% selectedbasket.basketno | html %]
275
                                                                <td>
297
                                                            [% END %]
276
                                                                    <a href="basket.pl?basketno=[% selectedbasket.basketno | uri %]">
298
                                                        </a>, <br />
277
                                                                        [% IF ( selectedbasket.basketname ) %]
299
                                                        Total: [% selectedbasket.total | $Price %]
278
                                                                            [% selectedbasket.basketname | html %]
300
                                                        <input type="hidden" class="basket" name="basket" value="[% selectedbasket.basketno | html %]" />
279
                                                                        [% ELSE %]
301
                                                    </li>
280
                                                                            No name, basketnumber: [% selectedbasket.basketno | html %]
302
                                                [% END %]
281
                                                                        [% END %]
303
                                            </ul>
282
                                                                    </a>
304
                                        </li>
283
                                                                </td>
284
                                                                <td data-sort="[% selectedbasket.total | html %]">
285
                                                                    [% selectedbasket.total | $Price %]
286
                                                                    <input type="hidden" class="basket" name="basket" value="[% selectedbasket.basketno | html %]" />
287
                                                                </td>
288
                                                                <td>
289
                                                                    [% IF ( closedbg ) %]
290
                                                                    [% ELSE %]
291
                                                                        <a class="removefromgroup btn btn-default btn-xs" data-basketid="b-[% selectedbasket.basketno | html %]" id="addtogroup[% selectedbasket.basketno | html %]">
292
                                                                            <i class="fa fa-trash" aria-hidden="true"></i> Remove
293
                                                                        </a>
294
                                                                    [% END %]
295
                                                                </td>
296
                                                            </tr>
297
                                                        [% END %]
298
                                                    </tbody>
299
                                                </table>
300
                                            </li>
305
                                            [% UNLESS (closedbg) %]
301
                                            [% UNLESS (closedbg) %]
306
                                                <li><label><input type="checkbox" id="closedbg" name="closedbg" />Close basket group</label></li>
302
                                                <li><label><input type="checkbox" id="closedbg" name="closedbg" /> Close basket group</label></li>
307
                                            [% ELSE %]
303
                                            [% ELSE %]
308
                                                <input type="hidden" id="closedbg" name="closedbg" value ="1"/>
304
                                                <input type="hidden" id="closedbg" name="closedbg" value ="1"/>
309
                                            [% END %]
305
                                            [% END %]
310
                                    </ol>
306
                                    </ol>
311
                                </fieldset>
307
                                </fieldset>
308
312
                                [% UNLESS (closedbg) %]
309
                                [% UNLESS (closedbg) %]
313
                                    <fieldset class="action"><input type="hidden" name="booksellerid" value="[% booksellerid | html %]" />
310
                                    <fieldset class="action"><input type="hidden" name="booksellerid" value="[% booksellerid | html %]" />
314
                                        [% IF ( basketgroupid ) %]
311
                                        [% IF ( basketgroupid ) %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/offline-mf.tt (-1 lines)
Lines 20-26 CACHE: Link Here
20
[% interface | html %]/[% theme | html %]/js/basket.js
20
[% interface | html %]/[% theme | html %]/js/basket.js
21
[% interface | html %]/[% theme | html %]/js/offlinecirc.js
21
[% interface | html %]/[% theme | html %]/js/offlinecirc.js
22
[% interface | html %]/[% theme | html %]/js/staff-global.js
22
[% interface | html %]/[% theme | html %]/js/staff-global.js
23
[% themelang | html %]/lib/yui/reset-fonts-grids.css
24
[% interface | html %]/prog/img/koha-logo-medium.png
23
[% interface | html %]/prog/img/koha-logo-medium.png
25
[% interface | html %]/prog/img/loading.gif
24
[% interface | html %]/prog/img/loading.gif
26
[% interface | html %]/prog/sound/beep.ogg
25
[% interface | html %]/prog/sound/beep.ogg
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/search.tt (-1 / +1 lines)
Lines 14-20 Link Here
14
</head>
14
</head>
15
15
16
<body id="common_patron_search" class="common">
16
<body id="common_patron_search" class="common">
17
<div id="patron_search" class="yui-t7">
17
<div id="patron_search">
18
    <div class="container-fluid">
18
    <div class="container-fluid">
19
19
20
        [% PROCESS patron_search_filters categories => categories, libraries => libraries, filters => ['branch', 'category'], search_filter => searchmember %]
20
        [% PROCESS patron_search_filters categories => categories, libraries => libraries, filters => ['branch', 'category'], search_filter => searchmember %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/import_borrowers.tt (-2 lines)
Lines 11-17 Link Here
11
</title>
11
</title>
12
[% INCLUDE 'doc-head-close.inc' %]
12
[% INCLUDE 'doc-head-close.inc' %]
13
<style>
13
<style>
14
    .yui-u fieldset.rows .widelabel { width: 12em; }
15
    label.description { width: 20em; }
14
    label.description { width: 20em; }
16
    .line_error { width: 100%; }
15
    .line_error { width: 100%; }
17
    code { background-color: yellow; }
16
    code { background-color: yellow; }
18
- 

Return to bug 13614