Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('yui2-menu', function(Y) {
2
    var YAHOO    = Y.YUI2;
3
    /*
4
Copyright (c) 2011, Yahoo! Inc. All rights reserved.
5
Code licensed under the BSD License:
6
http://developer.yahoo.com/yui/license.html
7
version: 2.9.0
8
*/
9
 
10
 
11
/**
12
* @module menu
13
* @description <p>The Menu family of components features a collection of
14
* controls that make it easy to add menus to your website or web application.
15
* With the Menu Controls you can create website fly-out menus, customized
16
* context menus, or application-style menu bars with just a small amount of
17
* scripting.</p><p>The Menu family of controls features:</p>
18
* <ul>
19
*    <li>Keyboard and mouse navigation.</li>
20
*    <li>A rich event model that provides access to all of a menu's
21
*    interesting moments.</li>
22
*    <li>Support for
23
*    <a href="http://en.wikipedia.org/wiki/Progressive_Enhancement">Progressive
24
*    Enhancement</a>; Menus can be created from simple,
25
*    semantic markup on the page or purely through JavaScript.</li>
26
* </ul>
27
* @title Menu
28
* @namespace YAHOO.widget
29
* @requires Event, Dom, Container
30
*/
31
(function () {
32
 
33
    var UA = YAHOO.env.ua,
34
        Dom = YAHOO.util.Dom,
35
        Event = YAHOO.util.Event,
36
        Lang = YAHOO.lang,
37
 
38
        _DIV = "DIV",
39
        _HD = "hd",
40
        _BD = "bd",
41
        _FT = "ft",
42
        _LI = "LI",
43
        _DISABLED = "disabled",
44
        _MOUSEOVER = "mouseover",
45
        _MOUSEOUT = "mouseout",
46
        _MOUSEDOWN = "mousedown",
47
        _MOUSEUP = "mouseup",
48
        _CLICK = "click",
49
        _KEYDOWN = "keydown",
50
        _KEYUP = "keyup",
51
        _KEYPRESS = "keypress",
52
        _CLICK_TO_HIDE = "clicktohide",
53
        _POSITION = "position",
54
        _DYNAMIC = "dynamic",
55
        _SHOW_DELAY = "showdelay",
56
        _SELECTED = "selected",
57
        _VISIBLE = "visible",
58
        _UL = "UL",
59
        _MENUMANAGER = "MenuManager";
60
 
61
 
62
    /**
63
    * Singleton that manages a collection of all menus and menu items.  Listens
64
    * for DOM events at the document level and dispatches the events to the
65
    * corresponding menu or menu item.
66
    *
67
    * @namespace YAHOO.widget
68
    * @class MenuManager
69
    * @static
70
    */
71
    YAHOO.widget.MenuManager = function () {
72
 
73
        // Private member variables
74
 
75
 
76
        // Flag indicating if the DOM event handlers have been attached
77
 
78
        var m_bInitializedEventHandlers = false,
79
 
80
 
81
        // Collection of menus
82
 
83
        m_oMenus = {},
84
 
85
 
86
        // Collection of visible menus
87
 
88
        m_oVisibleMenus = {},
89
 
90
 
91
        //  Collection of menu items
92
 
93
        m_oItems = {},
94
 
95
 
96
        // Map of DOM event types to their equivalent CustomEvent types
97
 
98
        m_oEventTypes = {
99
            "click": "clickEvent",
100
            "mousedown": "mouseDownEvent",
101
            "mouseup": "mouseUpEvent",
102
            "mouseover": "mouseOverEvent",
103
            "mouseout": "mouseOutEvent",
104
            "keydown": "keyDownEvent",
105
            "keyup": "keyUpEvent",
106
            "keypress": "keyPressEvent",
107
            "focus": "focusEvent",
108
            "focusin": "focusEvent",
109
            "blur": "blurEvent",
110
            "focusout": "blurEvent"
111
        },
112
 
113
 
114
        m_oFocusedMenuItem = null;
115
 
116
 
117
 
118
        // Private methods
119
 
120
 
121
        /**
122
        * @method getMenuRootElement
123
        * @description Finds the root DIV node of a menu or the root LI node of
124
        * a menu item.
125
        * @private
126
        * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
127
        * level-one-html.html#ID-58190037">HTMLElement</a>} p_oElement Object
128
        * specifying an HTML element.
129
        */
130
        function getMenuRootElement(p_oElement) {
131
 
132
            var oParentNode,
133
                returnVal;
134
 
135
            if (p_oElement && p_oElement.tagName) {
136
 
137
                switch (p_oElement.tagName.toUpperCase()) {
138
 
139
                case _DIV:
140
 
141
                    oParentNode = p_oElement.parentNode;
142
 
143
                    // Check if the DIV is the inner "body" node of a menu
144
 
145
                    if ((
146
                            Dom.hasClass(p_oElement, _HD) ||
147
                            Dom.hasClass(p_oElement, _BD) ||
148
                            Dom.hasClass(p_oElement, _FT)
149
                        ) &&
150
                        oParentNode &&
151
                        oParentNode.tagName &&
152
                        oParentNode.tagName.toUpperCase() == _DIV) {
153
 
154
                        returnVal = oParentNode;
155
 
156
                    }
157
                    else {
158
 
159
                        returnVal = p_oElement;
160
 
161
                    }
162
 
163
                    break;
164
 
165
                case _LI:
166
 
167
                    returnVal = p_oElement;
168
 
169
                    break;
170
 
171
                default:
172
 
173
                    oParentNode = p_oElement.parentNode;
174
 
175
                    if (oParentNode) {
176
 
177
                        returnVal = getMenuRootElement(oParentNode);
178
 
179
                    }
180
 
181
                    break;
182
 
183
                }
184
 
185
            }
186
 
187
            return returnVal;
188
 
189
        }
190
 
191
 
192
 
193
        // Private event handlers
194
 
195
 
196
        /**
197
        * @method onDOMEvent
198
        * @description Generic, global event handler for all of a menu's
199
        * DOM-based events.  This listens for events against the document
200
        * object.  If the target of a given event is a member of a menu or
201
        * menu item's DOM, the instance's corresponding Custom Event is fired.
202
        * @private
203
        * @param {Event} p_oEvent Object representing the DOM event object
204
        * passed back by the event utility (YAHOO.util.Event).
205
        */
206
        function onDOMEvent(p_oEvent) {
207
 
208
            // Get the target node of the DOM event
209
 
210
            var oTarget = Event.getTarget(p_oEvent),
211
 
212
            // See if the target of the event was a menu, or a menu item
213
 
214
            oElement = getMenuRootElement(oTarget),
215
            bFireEvent = true,
216
            sEventType = p_oEvent.type,
217
            sCustomEventType,
218
            sTagName,
219
            sId,
220
            oMenuItem,
221
            oMenu;
222
 
223
 
224
            if (oElement) {
225
 
226
                sTagName = oElement.tagName.toUpperCase();
227
 
228
                if (sTagName == _LI) {
229
 
230
                    sId = oElement.id;
231
 
232
                    if (sId && m_oItems[sId]) {
233
 
234
                        oMenuItem = m_oItems[sId];
235
                        oMenu = oMenuItem.parent;
236
 
237
                    }
238
 
239
                }
240
                else if (sTagName == _DIV) {
241
 
242
                    if (oElement.id) {
243
 
244
                        oMenu = m_oMenus[oElement.id];
245
 
246
                    }
247
 
248
                }
249
 
250
            }
251
 
252
 
253
            if (oMenu) {
254
 
255
                sCustomEventType = m_oEventTypes[sEventType];
256
 
257
                /*
258
                    There is an inconsistency between Firefox for Mac OS X and
259
                    Firefox Windows & Linux regarding the triggering of the
260
                    display of the browser's context menu and the subsequent
261
                    firing of the "click" event. In Firefox for Windows & Linux,
262
                    when the user triggers the display of the browser's context
263
                    menu the "click" event also fires for the document object,
264
                    even though the "click" event did not fire for the element
265
                    that was the original target of the "contextmenu" event.
266
                    This is unique to Firefox on Windows & Linux.  For all
267
                    other A-Grade browsers, including Firefox for Mac OS X, the
268
                    "click" event doesn't fire for the document object.
269
 
270
                    This bug in Firefox for Windows affects Menu, as Menu
271
                    instances listen for events at the document level and
272
                    dispatches Custom Events of the same name.  Therefore users
273
                    of Menu will get an unwanted firing of the "click"
274
                    custom event.  The following line fixes this bug.
275
                */
276
 
277
 
278
 
279
                if (sEventType == "click" &&
280
                    (UA.gecko && oMenu.platform != "mac") &&
281
                    p_oEvent.button > 0) {
282
 
283
                    bFireEvent = false;
284
 
285
                }
286
 
287
                // Fire the Custom Event that corresponds the current DOM event
288
 
289
                if (bFireEvent && oMenuItem && !oMenuItem.cfg.getProperty(_DISABLED)) {
290
                    oMenuItem[sCustomEventType].fire(p_oEvent);
291
                }
292
 
293
                if (bFireEvent) {
294
                    oMenu[sCustomEventType].fire(p_oEvent, oMenuItem);
295
                }
296
 
297
            }
298
            else if (sEventType == _MOUSEDOWN) {
299
 
300
                /*
301
                    If the target of the event wasn't a menu, hide all
302
                    dynamically positioned menus
303
                */
304
 
305
                for (var i in m_oVisibleMenus) {
306
 
307
                    if (Lang.hasOwnProperty(m_oVisibleMenus, i)) {
308
 
309
                        oMenu = m_oVisibleMenus[i];
310
 
311
                        if (oMenu.cfg.getProperty(_CLICK_TO_HIDE) &&
312
                            !(oMenu instanceof YAHOO.widget.MenuBar) &&
313
                            oMenu.cfg.getProperty(_POSITION) == _DYNAMIC) {
314
 
315
                            oMenu.hide();
316
 
317
                            //	In IE when the user mouses down on a focusable
318
                            //	element that element will be focused and become
319
                            //	the "activeElement".
320
                            //	(http://msdn.microsoft.com/en-us/library/ms533065(VS.85).aspx)
321
                            //	However, there is a bug in IE where if there is
322
                            //	a positioned element with a focused descendant
323
                            //	that is hidden in response to the mousedown
324
                            //	event, the target of the mousedown event will
325
                            //	appear to have focus, but will not be set as
326
                            //	the activeElement.  This will result in the
327
                            //	element not firing key events, even though it
328
                            //	appears to have focus.  The following call to
329
                            //	"setActive" fixes this bug.
330
 
331
                            if (UA.ie && oTarget.focus && (UA.ie < 9)) {
332
                                oTarget.setActive();
333
                            }
334
 
335
                        }
336
                        else {
337
 
338
                            if (oMenu.cfg.getProperty(_SHOW_DELAY) > 0) {
339
 
340
                                oMenu._cancelShowDelay();
341
 
342
                            }
343
 
344
 
345
                            if (oMenu.activeItem) {
346
 
347
                                oMenu.activeItem.blur();
348
                                oMenu.activeItem.cfg.setProperty(_SELECTED, false);
349
 
350
                                oMenu.activeItem = null;
351
 
352
                            }
353
 
354
                        }
355
 
356
                    }
357
 
358
                }
359
 
360
            }
361
 
362
        }
363
 
364
 
365
        /**
366
        * @method onMenuDestroy
367
        * @description "destroy" event handler for a menu.
368
        * @private
369
        * @param {String} p_sType String representing the name of the event
370
        * that was fired.
371
        * @param {Array} p_aArgs Array of arguments sent when the event
372
        * was fired.
373
        * @param {YAHOO.widget.Menu} p_oMenu The menu that fired the event.
374
        */
375
        function onMenuDestroy(p_sType, p_aArgs, p_oMenu) {
376
 
377
            if (m_oMenus[p_oMenu.id]) {
378
 
379
                this.removeMenu(p_oMenu);
380
 
381
            }
382
 
383
        }
384
 
385
 
386
        /**
387
        * @method onMenuFocus
388
        * @description "focus" event handler for a MenuItem instance.
389
        * @private
390
        * @param {String} p_sType String representing the name of the event
391
        * that was fired.
392
        * @param {Array} p_aArgs Array of arguments sent when the event
393
        * was fired.
394
        */
395
        function onMenuFocus(p_sType, p_aArgs) {
396
 
397
            var oItem = p_aArgs[1];
398
 
399
            if (oItem) {
400
 
401
                m_oFocusedMenuItem = oItem;
402
 
403
            }
404
 
405
        }
406
 
407
 
408
        /**
409
        * @method onMenuBlur
410
        * @description "blur" event handler for a MenuItem instance.
411
        * @private
412
        * @param {String} p_sType String representing the name of the event
413
        * that was fired.
414
        * @param {Array} p_aArgs Array of arguments sent when the event
415
        * was fired.
416
        */
417
        function onMenuBlur(p_sType, p_aArgs) {
418
 
419
            m_oFocusedMenuItem = null;
420
 
421
        }
422
 
423
 
424
        /**
425
        * @method onMenuVisibleConfigChange
426
        * @description Event handler for when the "visible" configuration
427
        * property of a Menu instance changes.
428
        * @private
429
        * @param {String} p_sType String representing the name of the event
430
        * that was fired.
431
        * @param {Array} p_aArgs Array of arguments sent when the event
432
        * was fired.
433
        */
434
        function onMenuVisibleConfigChange(p_sType, p_aArgs) {
435
 
436
            var bVisible = p_aArgs[0],
437
                sId = this.id;
438
 
439
            if (bVisible) {
440
 
441
                m_oVisibleMenus[sId] = this;
442
 
443
                YAHOO.log(this + " added to the collection of visible menus.",
444
                    "info", _MENUMANAGER);
445
 
446
            }
447
            else if (m_oVisibleMenus[sId]) {
448
 
449
                delete m_oVisibleMenus[sId];
450
 
451
                YAHOO.log(this + " removed from the collection of visible menus.",
452
                    "info", _MENUMANAGER);
453
 
454
            }
455
 
456
        }
457
 
458
 
459
        /**
460
        * @method onItemDestroy
461
        * @description "destroy" event handler for a MenuItem instance.
462
        * @private
463
        * @param {String} p_sType String representing the name of the event
464
        * that was fired.
465
        * @param {Array} p_aArgs Array of arguments sent when the event
466
        * was fired.
467
        */
468
        function onItemDestroy(p_sType, p_aArgs) {
469
 
470
            removeItem(this);
471
 
472
        }
473
 
474
 
475
        /**
476
        * @method removeItem
477
        * @description Removes a MenuItem instance from the MenuManager's collection of MenuItems.
478
        * @private
479
        * @param {MenuItem} p_oMenuItem The MenuItem instance to be removed.
480
        */
481
        function removeItem(p_oMenuItem) {
482
 
483
            var sId = p_oMenuItem.id;
484
 
485
            if (sId && m_oItems[sId]) {
486
 
487
                if (m_oFocusedMenuItem == p_oMenuItem) {
488
 
489
                    m_oFocusedMenuItem = null;
490
 
491
                }
492
 
493
                delete m_oItems[sId];
494
 
495
                p_oMenuItem.destroyEvent.unsubscribe(onItemDestroy);
496
 
497
                YAHOO.log(p_oMenuItem + " successfully unregistered.", "info", _MENUMANAGER);
498
 
499
            }
500
 
501
        }
502
 
503
 
504
        /**
505
        * @method onItemAdded
506
        * @description "itemadded" event handler for a Menu instance.
507
        * @private
508
        * @param {String} p_sType String representing the name of the event
509
        * that was fired.
510
        * @param {Array} p_aArgs Array of arguments sent when the event
511
        * was fired.
512
        */
513
        function onItemAdded(p_sType, p_aArgs) {
514
 
515
            var oItem = p_aArgs[0],
516
                sId;
517
 
518
            if (oItem instanceof YAHOO.widget.MenuItem) {
519
 
520
                sId = oItem.id;
521
 
522
                if (!m_oItems[sId]) {
523
 
524
                    m_oItems[sId] = oItem;
525
 
526
                    oItem.destroyEvent.subscribe(onItemDestroy);
527
 
528
                    YAHOO.log(oItem + " successfully registered.", "info", _MENUMANAGER);
529
 
530
                }
531
 
532
            }
533
 
534
        }
535
 
536
 
537
        return {
538
 
539
            // Privileged methods
540
 
541
 
542
            /**
543
            * @method addMenu
544
            * @description Adds a menu to the collection of known menus.
545
            * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu
546
            * instance to be added.
547
            */
548
            addMenu: function (p_oMenu) {
549
 
550
                var oDoc;
551
 
552
                if (p_oMenu instanceof YAHOO.widget.Menu && p_oMenu.id &&
553
                    !m_oMenus[p_oMenu.id]) {
554
 
555
                    m_oMenus[p_oMenu.id] = p_oMenu;
556
 
557
 
558
                    if (!m_bInitializedEventHandlers) {
559
 
560
                        oDoc = document;
561
 
562
                        Event.on(oDoc, _MOUSEOVER, onDOMEvent, this, true);
563
                        Event.on(oDoc, _MOUSEOUT, onDOMEvent, this, true);
564
                        Event.on(oDoc, _MOUSEDOWN, onDOMEvent, this, true);
565
                        Event.on(oDoc, _MOUSEUP, onDOMEvent, this, true);
566
                        Event.on(oDoc, _CLICK, onDOMEvent, this, true);
567
                        Event.on(oDoc, _KEYDOWN, onDOMEvent, this, true);
568
                        Event.on(oDoc, _KEYUP, onDOMEvent, this, true);
569
                        Event.on(oDoc, _KEYPRESS, onDOMEvent, this, true);
570
 
571
                        Event.onFocus(oDoc, onDOMEvent, this, true);
572
                        Event.onBlur(oDoc, onDOMEvent, this, true);
573
 
574
                        m_bInitializedEventHandlers = true;
575
 
576
                        YAHOO.log("DOM event handlers initialized.", "info", _MENUMANAGER);
577
 
578
                    }
579
 
580
                    p_oMenu.cfg.subscribeToConfigEvent(_VISIBLE, onMenuVisibleConfigChange);
581
                    p_oMenu.destroyEvent.subscribe(onMenuDestroy, p_oMenu, this);
582
                    p_oMenu.itemAddedEvent.subscribe(onItemAdded);
583
                    p_oMenu.focusEvent.subscribe(onMenuFocus);
584
                    p_oMenu.blurEvent.subscribe(onMenuBlur);
585
 
586
                    YAHOO.log(p_oMenu + " successfully registered.", "info", _MENUMANAGER);
587
 
588
                }
589
 
590
            },
591
 
592
 
593
            /**
594
            * @method removeMenu
595
            * @description Removes a menu from the collection of known menus.
596
            * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu
597
            * instance to be removed.
598
            */
599
            removeMenu: function (p_oMenu) {
600
 
601
                var sId,
602
                    aItems,
603
                    i;
604
 
605
                if (p_oMenu) {
606
 
607
                    sId = p_oMenu.id;
608
 
609
                    if ((sId in m_oMenus) && (m_oMenus[sId] == p_oMenu)) {
610
 
611
                        // Unregister each menu item
612
 
613
                        aItems = p_oMenu.getItems();
614
 
615
                        if (aItems && aItems.length > 0) {
616
 
617
                            i = aItems.length - 1;
618
 
619
                            do {
620
 
621
                                removeItem(aItems[i]);
622
 
623
                            }
624
                            while (i--);
625
 
626
                        }
627
 
628
 
629
                        // Unregister the menu
630
 
631
                        delete m_oMenus[sId];
632
 
633
                        YAHOO.log(p_oMenu + " successfully unregistered.", "info", _MENUMANAGER);
634
 
635
 
636
                        /*
637
                             Unregister the menu from the collection of
638
                             visible menus
639
                        */
640
 
641
                        if ((sId in m_oVisibleMenus) && (m_oVisibleMenus[sId] == p_oMenu)) {
642
 
643
                            delete m_oVisibleMenus[sId];
644
 
645
                            YAHOO.log(p_oMenu + " unregistered from the" +
646
                                        " collection of visible menus.", "info", _MENUMANAGER);
647
 
648
                        }
649
 
650
 
651
                        // Unsubscribe event listeners
652
 
653
                        if (p_oMenu.cfg) {
654
 
655
                            p_oMenu.cfg.unsubscribeFromConfigEvent(_VISIBLE,
656
                                onMenuVisibleConfigChange);
657
 
658
                        }
659
 
660
                        p_oMenu.destroyEvent.unsubscribe(onMenuDestroy,
661
                            p_oMenu);
662
 
663
                        p_oMenu.itemAddedEvent.unsubscribe(onItemAdded);
664
                        p_oMenu.focusEvent.unsubscribe(onMenuFocus);
665
                        p_oMenu.blurEvent.unsubscribe(onMenuBlur);
666
 
667
                    }
668
 
669
                }
670
 
671
            },
672
 
673
 
674
            /**
675
            * @method hideVisible
676
            * @description Hides all visible, dynamically positioned menus
677
            * (excluding instances of YAHOO.widget.MenuBar).
678
            */
679
            hideVisible: function () {
680
 
681
                var oMenu;
682
 
683
                for (var i in m_oVisibleMenus) {
684
 
685
                    if (Lang.hasOwnProperty(m_oVisibleMenus, i)) {
686
 
687
                        oMenu = m_oVisibleMenus[i];
688
 
689
                        if (!(oMenu instanceof YAHOO.widget.MenuBar) &&
690
                            oMenu.cfg.getProperty(_POSITION) == _DYNAMIC) {
691
 
692
                            oMenu.hide();
693
 
694
                        }
695
 
696
                    }
697
 
698
                }
699
 
700
            },
701
 
702
 
703
            /**
704
            * @method getVisible
705
            * @description Returns a collection of all visible menus registered
706
            * with the menu manger.
707
            * @return {Object}
708
            */
709
            getVisible: function () {
710
 
711
                return m_oVisibleMenus;
712
 
713
            },
714
 
715
 
716
            /**
717
            * @method getMenus
718
            * @description Returns a collection of all menus registered with the
719
            * menu manger.
720
            * @return {Object}
721
            */
722
            getMenus: function () {
723
 
724
                return m_oMenus;
725
 
726
            },
727
 
728
 
729
            /**
730
            * @method getMenu
731
            * @description Returns a menu with the specified id.
732
            * @param {String} p_sId String specifying the id of the
733
            * <code>&#60;div&#62;</code> element representing the menu to
734
            * be retrieved.
735
            * @return {YAHOO.widget.Menu}
736
            */
737
            getMenu: function (p_sId) {
738
 
739
                var returnVal;
740
 
741
                if (p_sId in m_oMenus) {
742
 
743
                    returnVal = m_oMenus[p_sId];
744
 
745
                }
746
 
747
                return returnVal;
748
 
749
            },
750
 
751
 
752
            /**
753
            * @method getMenuItem
754
            * @description Returns a menu item with the specified id.
755
            * @param {String} p_sId String specifying the id of the
756
            * <code>&#60;li&#62;</code> element representing the menu item to
757
            * be retrieved.
758
            * @return {YAHOO.widget.MenuItem}
759
            */
760
            getMenuItem: function (p_sId) {
761
 
762
                var returnVal;
763
 
764
                if (p_sId in m_oItems) {
765
 
766
                    returnVal = m_oItems[p_sId];
767
 
768
                }
769
 
770
                return returnVal;
771
 
772
            },
773
 
774
 
775
            /**
776
            * @method getMenuItemGroup
777
            * @description Returns an array of menu item instances whose
778
            * corresponding <code>&#60;li&#62;</code> elements are child
779
            * nodes of the <code>&#60;ul&#62;</code> element with the
780
            * specified id.
781
            * @param {String} p_sId String specifying the id of the
782
            * <code>&#60;ul&#62;</code> element representing the group of
783
            * menu items to be retrieved.
784
            * @return {Array}
785
            */
786
            getMenuItemGroup: function (p_sId) {
787
 
788
                var oUL = Dom.get(p_sId),
789
                    aItems,
790
                    oNode,
791
                    oItem,
792
                    sId,
793
                    returnVal;
794
 
795
 
796
                if (oUL && oUL.tagName && oUL.tagName.toUpperCase() == _UL) {
797
 
798
                    oNode = oUL.firstChild;
799
 
800
                    if (oNode) {
801
 
802
                        aItems = [];
803
 
804
                        do {
805
 
806
                            sId = oNode.id;
807
 
808
                            if (sId) {
809
 
810
                                oItem = this.getMenuItem(sId);
811
 
812
                                if (oItem) {
813
 
814
                                    aItems[aItems.length] = oItem;
815
 
816
                                }
817
 
818
                            }
819
 
820
                        }
821
                        while ((oNode = oNode.nextSibling));
822
 
823
 
824
                        if (aItems.length > 0) {
825
 
826
                            returnVal = aItems;
827
 
828
                        }
829
 
830
                    }
831
 
832
                }
833
 
834
                return returnVal;
835
 
836
            },
837
 
838
 
839
            /**
840
            * @method getFocusedMenuItem
841
            * @description Returns a reference to the menu item that currently
842
            * has focus.
843
            * @return {YAHOO.widget.MenuItem}
844
            */
845
            getFocusedMenuItem: function () {
846
 
847
                return m_oFocusedMenuItem;
848
 
849
            },
850
 
851
 
852
            /**
853
            * @method getFocusedMenu
854
            * @description Returns a reference to the menu that currently
855
            * has focus.
856
            * @return {YAHOO.widget.Menu}
857
            */
858
            getFocusedMenu: function () {
859
 
860
                var returnVal;
861
 
862
                if (m_oFocusedMenuItem) {
863
 
864
                    returnVal = m_oFocusedMenuItem.parent.getRoot();
865
 
866
                }
867
 
868
                return returnVal;
869
 
870
            },
871
 
872
 
873
            /**
874
            * @method toString
875
            * @description Returns a string representing the menu manager.
876
            * @return {String}
877
            */
878
            toString: function () {
879
 
880
                return _MENUMANAGER;
881
 
882
            }
883
 
884
        };
885
 
886
    }();
887
 
888
})();
889
 
890
 
891
 
892
(function () {
893
 
894
    var Lang = YAHOO.lang,
895
 
896
    // String constants
897
 
898
        _MENU = "Menu",
899
        _DIV_UPPERCASE = "DIV",
900
        _DIV_LOWERCASE = "div",
901
        _ID = "id",
902
        _SELECT = "SELECT",
903
        _XY = "xy",
904
        _Y = "y",
905
        _UL_UPPERCASE = "UL",
906
        _UL_LOWERCASE = "ul",
907
        _FIRST_OF_TYPE = "first-of-type",
908
        _LI = "LI",
909
        _OPTGROUP = "OPTGROUP",
910
        _OPTION = "OPTION",
911
        _DISABLED = "disabled",
912
        _NONE = "none",
913
        _SELECTED = "selected",
914
        _GROUP_INDEX = "groupindex",
915
        _INDEX = "index",
916
        _SUBMENU = "submenu",
917
        _VISIBLE = "visible",
918
        _HIDE_DELAY = "hidedelay",
919
        _POSITION = "position",
920
        _DYNAMIC = "dynamic",
921
        _STATIC = "static",
922
        _DYNAMIC_STATIC = _DYNAMIC + "," + _STATIC,
923
        _URL = "url",
924
        _HASH = "#",
925
        _TARGET = "target",
926
        _MAX_HEIGHT = "maxheight",
927
        _TOP_SCROLLBAR = "topscrollbar",
928
        _BOTTOM_SCROLLBAR = "bottomscrollbar",
929
        _UNDERSCORE = "_",
930
        _TOP_SCROLLBAR_DISABLED = _TOP_SCROLLBAR + _UNDERSCORE + _DISABLED,
931
        _BOTTOM_SCROLLBAR_DISABLED = _BOTTOM_SCROLLBAR + _UNDERSCORE + _DISABLED,
932
        _MOUSEMOVE = "mousemove",
933
        _SHOW_DELAY = "showdelay",
934
        _SUBMENU_HIDE_DELAY = "submenuhidedelay",
935
        _IFRAME = "iframe",
936
        _CONSTRAIN_TO_VIEWPORT = "constraintoviewport",
937
        _PREVENT_CONTEXT_OVERLAP = "preventcontextoverlap",
938
        _SUBMENU_ALIGNMENT = "submenualignment",
939
        _AUTO_SUBMENU_DISPLAY = "autosubmenudisplay",
940
        _CLICK_TO_HIDE = "clicktohide",
941
        _CONTAINER = "container",
942
        _SCROLL_INCREMENT = "scrollincrement",
943
        _MIN_SCROLL_HEIGHT = "minscrollheight",
944
        _CLASSNAME = "classname",
945
        _SHADOW = "shadow",
946
        _KEEP_OPEN = "keepopen",
947
        _HD = "hd",
948
        _HAS_TITLE = "hastitle",
949
        _CONTEXT = "context",
950
        _EMPTY_STRING = "",
951
        _MOUSEDOWN = "mousedown",
952
        _KEYDOWN = "keydown",
953
        _HEIGHT = "height",
954
        _WIDTH = "width",
955
        _PX = "px",
956
        _EFFECT = "effect",
957
        _MONITOR_RESIZE = "monitorresize",
958
        _DISPLAY = "display",
959
        _BLOCK = "block",
960
        _VISIBILITY = "visibility",
961
        _ABSOLUTE = "absolute",
962
        _ZINDEX = "zindex",
963
        _YUI_MENU_BODY_SCROLLED = "yui-menu-body-scrolled",
964
        _NON_BREAKING_SPACE = "&#32;",
965
        _SPACE = " ",
966
        _MOUSEOVER = "mouseover",
967
        _MOUSEOUT = "mouseout",
968
        _ITEM_ADDED = "itemAdded",
969
        _ITEM_REMOVED = "itemRemoved",
970
        _HIDDEN = "hidden",
971
        _YUI_MENU_SHADOW = "yui-menu-shadow",
972
        _YUI_MENU_SHADOW_VISIBLE = _YUI_MENU_SHADOW + "-visible",
973
        _YUI_MENU_SHADOW_YUI_MENU_SHADOW_VISIBLE = _YUI_MENU_SHADOW + _SPACE + _YUI_MENU_SHADOW_VISIBLE;
974
 
975
 
976
/**
977
* The Menu class creates a container that holds a vertical list representing
978
* a set of options or commands.  Menu is the base class for all
979
* menu containers.
980
* @param {String} p_oElement String specifying the id attribute of the
981
* <code>&#60;div&#62;</code> element of the menu.
982
* @param {String} p_oElement String specifying the id attribute of the
983
* <code>&#60;select&#62;</code> element to be used as the data source
984
* for the menu.
985
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
986
* level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
987
* specifying the <code>&#60;div&#62;</code> element of the menu.
988
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
989
* level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement
990
* Object specifying the <code>&#60;select&#62;</code> element to be used as
991
* the data source for the menu.
992
* @param {Object} p_oConfig Optional. Object literal specifying the
993
* configuration for the menu. See configuration class documentation for
994
* more details.
995
* @namespace YAHOO.widget
996
* @class Menu
997
* @constructor
998
* @extends YAHOO.widget.Overlay
999
*/
1000
YAHOO.widget.Menu = function (p_oElement, p_oConfig) {
1001
 
1002
    if (p_oConfig) {
1003
        this.parent = p_oConfig.parent;
1004
        this.lazyLoad = p_oConfig.lazyLoad || p_oConfig.lazyload;
1005
        this.itemData = p_oConfig.itemData || p_oConfig.itemdata;
1006
    }
1007
 
1008
    YAHOO.widget.Menu.superclass.constructor.call(this, p_oElement, p_oConfig);
1009
};
1010
 
1011
 
1012
 
1013
/**
1014
* @method checkPosition
1015
* @description Checks to make sure that the value of the "position" property
1016
* is one of the supported strings. Returns true if the position is supported.
1017
* @private
1018
* @param {Object} p_sPosition String specifying the position of the menu.
1019
* @return {Boolean}
1020
*/
1021
function checkPosition(p_sPosition) {
1022
 
1023
    var returnVal = false;
1024
 
1025
    if (Lang.isString(p_sPosition)) {
1026
 
1027
        returnVal = (_DYNAMIC_STATIC.indexOf((p_sPosition.toLowerCase())) != -1);
1028
 
1029
    }
1030
 
1031
    return returnVal;
1032
 
1033
}
1034
 
1035
 
1036
var Dom = YAHOO.util.Dom,
1037
    Event = YAHOO.util.Event,
1038
    Module = YAHOO.widget.Module,
1039
    Overlay = YAHOO.widget.Overlay,
1040
    Menu = YAHOO.widget.Menu,
1041
    MenuManager = YAHOO.widget.MenuManager,
1042
    CustomEvent = YAHOO.util.CustomEvent,
1043
    UA = YAHOO.env.ua,
1044
 
1045
    m_oShadowTemplate,
1046
 
1047
    bFocusListenerInitialized = false,
1048
 
1049
    oFocusedElement,
1050
 
1051
    EVENT_TYPES = [
1052
 
1053
        ["mouseOverEvent", _MOUSEOVER],
1054
        ["mouseOutEvent", _MOUSEOUT],
1055
        ["mouseDownEvent", _MOUSEDOWN],
1056
        ["mouseUpEvent", "mouseup"],
1057
        ["clickEvent", "click"],
1058
        ["keyPressEvent", "keypress"],
1059
        ["keyDownEvent", _KEYDOWN],
1060
        ["keyUpEvent", "keyup"],
1061
        ["focusEvent", "focus"],
1062
        ["blurEvent", "blur"],
1063
        ["itemAddedEvent", _ITEM_ADDED],
1064
        ["itemRemovedEvent", _ITEM_REMOVED]
1065
 
1066
    ],
1067
 
1068
    VISIBLE_CONFIG =  {
1069
        key: _VISIBLE,
1070
        value: false,
1071
        validator: Lang.isBoolean
1072
    },
1073
 
1074
    CONSTRAIN_TO_VIEWPORT_CONFIG =  {
1075
        key: _CONSTRAIN_TO_VIEWPORT,
1076
        value: true,
1077
        validator: Lang.isBoolean,
1078
        supercedes: [_IFRAME,"x",_Y,_XY]
1079
    },
1080
 
1081
    PREVENT_CONTEXT_OVERLAP_CONFIG =  {
1082
        key: _PREVENT_CONTEXT_OVERLAP,
1083
        value: true,
1084
        validator: Lang.isBoolean,
1085
        supercedes: [_CONSTRAIN_TO_VIEWPORT]
1086
    },
1087
 
1088
    POSITION_CONFIG =  {
1089
        key: _POSITION,
1090
        value: _DYNAMIC,
1091
        validator: checkPosition,
1092
        supercedes: [_VISIBLE, _IFRAME]
1093
    },
1094
 
1095
    SUBMENU_ALIGNMENT_CONFIG =  {
1096
        key: _SUBMENU_ALIGNMENT,
1097
        value: ["tl","tr"]
1098
    },
1099
 
1100
    AUTO_SUBMENU_DISPLAY_CONFIG =  {
1101
        key: _AUTO_SUBMENU_DISPLAY,
1102
        value: true,
1103
        validator: Lang.isBoolean,
1104
        suppressEvent: true
1105
    },
1106
 
1107
    SHOW_DELAY_CONFIG =  {
1108
        key: _SHOW_DELAY,
1109
        value: 250,
1110
        validator: Lang.isNumber,
1111
        suppressEvent: true
1112
    },
1113
 
1114
    HIDE_DELAY_CONFIG =  {
1115
        key: _HIDE_DELAY,
1116
        value: 0,
1117
        validator: Lang.isNumber,
1118
        suppressEvent: true
1119
    },
1120
 
1121
    SUBMENU_HIDE_DELAY_CONFIG =  {
1122
        key: _SUBMENU_HIDE_DELAY,
1123
        value: 250,
1124
        validator: Lang.isNumber,
1125
        suppressEvent: true
1126
    },
1127
 
1128
    CLICK_TO_HIDE_CONFIG =  {
1129
        key: _CLICK_TO_HIDE,
1130
        value: true,
1131
        validator: Lang.isBoolean,
1132
        suppressEvent: true
1133
    },
1134
 
1135
    CONTAINER_CONFIG =  {
1136
        key: _CONTAINER,
1137
        suppressEvent: true
1138
    },
1139
 
1140
    SCROLL_INCREMENT_CONFIG =  {
1141
        key: _SCROLL_INCREMENT,
1142
        value: 1,
1143
        validator: Lang.isNumber,
1144
        supercedes: [_MAX_HEIGHT],
1145
        suppressEvent: true
1146
    },
1147
 
1148
    MIN_SCROLL_HEIGHT_CONFIG =  {
1149
        key: _MIN_SCROLL_HEIGHT,
1150
        value: 90,
1151
        validator: Lang.isNumber,
1152
        supercedes: [_MAX_HEIGHT],
1153
        suppressEvent: true
1154
    },
1155
 
1156
    MAX_HEIGHT_CONFIG =  {
1157
        key: _MAX_HEIGHT,
1158
        value: 0,
1159
        validator: Lang.isNumber,
1160
        supercedes: [_IFRAME],
1161
        suppressEvent: true
1162
    },
1163
 
1164
    CLASS_NAME_CONFIG =  {
1165
        key: _CLASSNAME,
1166
        value: null,
1167
        validator: Lang.isString,
1168
        suppressEvent: true
1169
    },
1170
 
1171
    DISABLED_CONFIG =  {
1172
        key: _DISABLED,
1173
        value: false,
1174
        validator: Lang.isBoolean,
1175
        suppressEvent: true
1176
    },
1177
 
1178
    SHADOW_CONFIG =  {
1179
        key: _SHADOW,
1180
        value: true,
1181
        validator: Lang.isBoolean,
1182
        suppressEvent: true,
1183
        supercedes: [_VISIBLE]
1184
    },
1185
 
1186
    KEEP_OPEN_CONFIG = {
1187
        key: _KEEP_OPEN,
1188
        value: false,
1189
        validator: Lang.isBoolean
1190
    };
1191
 
1192
 
1193
function onDocFocus(event) {
1194
 
1195
    oFocusedElement = Event.getTarget(event);
1196
 
1197
}
1198
 
1199
 
1200
 
1201
YAHOO.lang.extend(Menu, Overlay, {
1202
 
1203
 
1204
// Constants
1205
 
1206
 
1207
/**
1208
* @property CSS_CLASS_NAME
1209
* @description String representing the CSS class(es) to be applied to the
1210
* menu's <code>&#60;div&#62;</code> element.
1211
* @default "yuimenu"
1212
* @final
1213
* @type String
1214
*/
1215
CSS_CLASS_NAME: "yuimenu",
1216
 
1217
 
1218
/**
1219
* @property ITEM_TYPE
1220
* @description Object representing the type of menu item to instantiate and
1221
* add when parsing the child nodes (either <code>&#60;li&#62;</code> element,
1222
* <code>&#60;optgroup&#62;</code> element or <code>&#60;option&#62;</code>)
1223
* of the menu's source HTML element.
1224
* @default YAHOO.widget.MenuItem
1225
* @final
1226
* @type YAHOO.widget.MenuItem
1227
*/
1228
ITEM_TYPE: null,
1229
 
1230
 
1231
/**
1232
* @property GROUP_TITLE_TAG_NAME
1233
* @description String representing the tagname of the HTML element used to
1234
* title the menu's item groups.
1235
* @default H6
1236
* @final
1237
* @type String
1238
*/
1239
GROUP_TITLE_TAG_NAME: "h6",
1240
 
1241
 
1242
/**
1243
* @property OFF_SCREEN_POSITION
1244
* @description Array representing the default x and y position that a menu
1245
* should have when it is positioned outside the viewport by the
1246
* "poistionOffScreen" method.
1247
* @default "-999em"
1248
* @final
1249
* @type String
1250
*/
1251
OFF_SCREEN_POSITION: "-999em",
1252
 
1253
 
1254
// Private properties
1255
 
1256
 
1257
/**
1258
* @property _useHideDelay
1259
* @description Boolean indicating if the "mouseover" and "mouseout" event
1260
* handlers used for hiding the menu via a call to "YAHOO.lang.later" have
1261
* already been assigned.
1262
* @default false
1263
* @private
1264
* @type Boolean
1265
*/
1266
_useHideDelay: false,
1267
 
1268
 
1269
/**
1270
* @property _bHandledMouseOverEvent
1271
* @description Boolean indicating the current state of the menu's
1272
* "mouseover" event.
1273
* @default false
1274
* @private
1275
* @type Boolean
1276
*/
1277
_bHandledMouseOverEvent: false,
1278
 
1279
 
1280
/**
1281
* @property _bHandledMouseOutEvent
1282
* @description Boolean indicating the current state of the menu's
1283
* "mouseout" event.
1284
* @default false
1285
* @private
1286
* @type Boolean
1287
*/
1288
_bHandledMouseOutEvent: false,
1289
 
1290
 
1291
/**
1292
* @property _aGroupTitleElements
1293
* @description Array of HTML element used to title groups of menu items.
1294
* @default []
1295
* @private
1296
* @type Array
1297
*/
1298
_aGroupTitleElements: null,
1299
 
1300
 
1301
/**
1302
* @property _aItemGroups
1303
* @description Multi-dimensional Array representing the menu items as they
1304
* are grouped in the menu.
1305
* @default []
1306
* @private
1307
* @type Array
1308
*/
1309
_aItemGroups: null,
1310
 
1311
 
1312
/**
1313
* @property _aListElements
1314
* @description Array of <code>&#60;ul&#62;</code> elements, each of which is
1315
* the parent node for each item's <code>&#60;li&#62;</code> element.
1316
* @default []
1317
* @private
1318
* @type Array
1319
*/
1320
_aListElements: null,
1321
 
1322
 
1323
/**
1324
* @property _nCurrentMouseX
1325
* @description The current x coordinate of the mouse inside the area of
1326
* the menu.
1327
* @default 0
1328
* @private
1329
* @type Number
1330
*/
1331
_nCurrentMouseX: 0,
1332
 
1333
 
1334
/**
1335
* @property _bStopMouseEventHandlers
1336
* @description Stops "mouseover," "mouseout," and "mousemove" event handlers
1337
* from executing.
1338
* @default false
1339
* @private
1340
* @type Boolean
1341
*/
1342
_bStopMouseEventHandlers: false,
1343
 
1344
 
1345
/**
1346
* @property _sClassName
1347
* @description The current value of the "classname" configuration attribute.
1348
* @default null
1349
* @private
1350
* @type String
1351
*/
1352
_sClassName: null,
1353
 
1354
 
1355
 
1356
// Public properties
1357
 
1358
 
1359
/**
1360
* @property lazyLoad
1361
* @description Boolean indicating if the menu's "lazy load" feature is
1362
* enabled.  If set to "true," initialization and rendering of the menu's
1363
* items will be deferred until the first time it is made visible.  This
1364
* property should be set via the constructor using the configuration
1365
* object literal.
1366
* @default false
1367
* @type Boolean
1368
*/
1369
lazyLoad: false,
1370
 
1371
 
1372
/**
1373
* @property itemData
1374
* @description Array of items to be added to the menu.  The array can contain
1375
* strings representing the text for each item to be created, object literals
1376
* representing the menu item configuration properties, or MenuItem instances.
1377
* This property should be set via the constructor using the configuration
1378
* object literal.
1379
* @default null
1380
* @type Array
1381
*/
1382
itemData: null,
1383
 
1384
 
1385
/**
1386
* @property activeItem
1387
* @description Object reference to the item in the menu that has is selected.
1388
* @default null
1389
* @type YAHOO.widget.MenuItem
1390
*/
1391
activeItem: null,
1392
 
1393
 
1394
/**
1395
* @property parent
1396
* @description Object reference to the menu's parent menu or menu item.
1397
* This property can be set via the constructor using the configuration
1398
* object literal.
1399
* @default null
1400
* @type YAHOO.widget.MenuItem
1401
*/
1402
parent: null,
1403
 
1404
 
1405
/**
1406
* @property srcElement
1407
* @description Object reference to the HTML element (either
1408
* <code>&#60;select&#62;</code> or <code>&#60;div&#62;</code>) used to
1409
* create the menu.
1410
* @default null
1411
* @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1412
* level-one-html.html#ID-94282980">HTMLSelectElement</a>|<a
1413
* href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.
1414
* html#ID-22445964">HTMLDivElement</a>
1415
*/
1416
srcElement: null,
1417
 
1418
 
1419
 
1420
// Events
1421
 
1422
 
1423
/**
1424
* @event mouseOverEvent
1425
* @description Fires when the mouse has entered the menu.  Passes back
1426
* the DOM Event object as an argument.
1427
*/
1428
 
1429
 
1430
/**
1431
* @event mouseOutEvent
1432
* @description Fires when the mouse has left the menu.  Passes back the DOM
1433
* Event object as an argument.
1434
* @type YAHOO.util.CustomEvent
1435
*/
1436
 
1437
 
1438
/**
1439
* @event mouseDownEvent
1440
* @description Fires when the user mouses down on the menu.  Passes back the
1441
* DOM Event object as an argument.
1442
* @type YAHOO.util.CustomEvent
1443
*/
1444
 
1445
 
1446
/**
1447
* @event mouseUpEvent
1448
* @description Fires when the user releases a mouse button while the mouse is
1449
* over the menu.  Passes back the DOM Event object as an argument.
1450
* @type YAHOO.util.CustomEvent
1451
*/
1452
 
1453
 
1454
/**
1455
* @event clickEvent
1456
* @description Fires when the user clicks the on the menu.  Passes back the
1457
* DOM Event object as an argument.
1458
* @type YAHOO.util.CustomEvent
1459
*/
1460
 
1461
 
1462
/**
1463
* @event keyPressEvent
1464
* @description Fires when the user presses an alphanumeric key when one of the
1465
* menu's items has focus.  Passes back the DOM Event object as an argument.
1466
* @type YAHOO.util.CustomEvent
1467
*/
1468
 
1469
 
1470
/**
1471
* @event keyDownEvent
1472
* @description Fires when the user presses a key when one of the menu's items
1473
* has focus.  Passes back the DOM Event object as an argument.
1474
* @type YAHOO.util.CustomEvent
1475
*/
1476
 
1477
 
1478
/**
1479
* @event keyUpEvent
1480
* @description Fires when the user releases a key when one of the menu's items
1481
* has focus.  Passes back the DOM Event object as an argument.
1482
* @type YAHOO.util.CustomEvent
1483
*/
1484
 
1485
 
1486
/**
1487
* @event itemAddedEvent
1488
* @description Fires when an item is added to the menu.
1489
* @type YAHOO.util.CustomEvent
1490
*/
1491
 
1492
 
1493
/**
1494
* @event itemRemovedEvent
1495
* @description Fires when an item is removed to the menu.
1496
* @type YAHOO.util.CustomEvent
1497
*/
1498
 
1499
 
1500
/**
1501
* @method init
1502
* @description The Menu class's initialization method. This method is
1503
* automatically called by the constructor, and sets up all DOM references
1504
* for pre-existing markup, and creates required markup if it is not
1505
* already present.
1506
* @param {String} p_oElement String specifying the id attribute of the
1507
* <code>&#60;div&#62;</code> element of the menu.
1508
* @param {String} p_oElement String specifying the id attribute of the
1509
* <code>&#60;select&#62;</code> element to be used as the data source
1510
* for the menu.
1511
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1512
* level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
1513
* specifying the <code>&#60;div&#62;</code> element of the menu.
1514
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1515
* level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement
1516
* Object specifying the <code>&#60;select&#62;</code> element to be used as
1517
* the data source for the menu.
1518
* @param {Object} p_oConfig Optional. Object literal specifying the
1519
* configuration for the menu. See configuration class documentation for
1520
* more details.
1521
*/
1522
init: function (p_oElement, p_oConfig) {
1523
 
1524
    this._aItemGroups = [];
1525
    this._aListElements = [];
1526
    this._aGroupTitleElements = [];
1527
 
1528
    if (!this.ITEM_TYPE) {
1529
 
1530
        this.ITEM_TYPE = YAHOO.widget.MenuItem;
1531
 
1532
    }
1533
 
1534
 
1535
    var oElement;
1536
 
1537
    if (Lang.isString(p_oElement)) {
1538
 
1539
        oElement = Dom.get(p_oElement);
1540
 
1541
    }
1542
    else if (p_oElement.tagName) {
1543
 
1544
        oElement = p_oElement;
1545
 
1546
    }
1547
 
1548
 
1549
    if (oElement && oElement.tagName) {
1550
 
1551
        switch(oElement.tagName.toUpperCase()) {
1552
 
1553
            case _DIV_UPPERCASE:
1554
 
1555
                this.srcElement = oElement;
1556
 
1557
                if (!oElement.id) {
1558
 
1559
                    oElement.setAttribute(_ID, Dom.generateId());
1560
 
1561
                }
1562
 
1563
 
1564
                /*
1565
                    Note: we don't pass the user config in here yet
1566
                    because we only want it executed once, at the lowest
1567
                    subclass level.
1568
                */
1569
 
1570
                Menu.superclass.init.call(this, oElement);
1571
 
1572
                this.beforeInitEvent.fire(Menu);
1573
 
1574
                YAHOO.log("Source element: " + this.srcElement.tagName, "info", this.toString());
1575
 
1576
            break;
1577
 
1578
            case _SELECT:
1579
 
1580
                this.srcElement = oElement;
1581
 
1582
 
1583
                /*
1584
                    The source element is not something that we can use
1585
                    outright, so we need to create a new Overlay
1586
 
1587
                    Note: we don't pass the user config in here yet
1588
                    because we only want it executed once, at the lowest
1589
                    subclass level.
1590
                */
1591
 
1592
                Menu.superclass.init.call(this, Dom.generateId());
1593
 
1594
                this.beforeInitEvent.fire(Menu);
1595
 
1596
                YAHOO.log("Source element: " + this.srcElement.tagName, "info", this.toString());
1597
 
1598
            break;
1599
 
1600
        }
1601
 
1602
    }
1603
    else {
1604
 
1605
        /*
1606
            Note: we don't pass the user config in here yet
1607
            because we only want it executed once, at the lowest
1608
            subclass level.
1609
        */
1610
 
1611
        Menu.superclass.init.call(this, p_oElement);
1612
 
1613
        this.beforeInitEvent.fire(Menu);
1614
 
1615
        YAHOO.log("No source element found.  Created element with id: " + this.id, "info", this.toString());
1616
 
1617
    }
1618
 
1619
 
1620
    if (this.element) {
1621
        Dom.addClass(this.element, this.CSS_CLASS_NAME);
1622
 
1623
        // Subscribe to Custom Events
1624
        this.initEvent.subscribe(this._onInit);
1625
        this.beforeRenderEvent.subscribe(this._onBeforeRender);
1626
        this.renderEvent.subscribe(this._onRender);
1627
        this.beforeShowEvent.subscribe(this._onBeforeShow);
1628
        this.hideEvent.subscribe(this._onHide);
1629
        this.showEvent.subscribe(this._onShow);
1630
        this.beforeHideEvent.subscribe(this._onBeforeHide);
1631
        this.mouseOverEvent.subscribe(this._onMouseOver);
1632
        this.mouseOutEvent.subscribe(this._onMouseOut);
1633
        this.clickEvent.subscribe(this._onClick);
1634
        this.keyDownEvent.subscribe(this._onKeyDown);
1635
        this.keyPressEvent.subscribe(this._onKeyPress);
1636
        this.blurEvent.subscribe(this._onBlur);
1637
 
1638
        if (!bFocusListenerInitialized) {
1639
            Event.onFocus(document, onDocFocus);
1640
            bFocusListenerInitialized = true;
1641
        }
1642
 
1643
        //	Fixes an issue in Firefox 2 and Webkit where Dom's "getX" and "getY"
1644
        //	methods return values that don't take scrollTop into consideration
1645
 
1646
        if ((UA.gecko && UA.gecko < 1.9) || (UA.webkit && UA.webkit < 523)) {
1647
            this.cfg.subscribeToConfigEvent(_Y, this._onYChange);
1648
        }
1649
 
1650
 
1651
        if (p_oConfig) {
1652
            this.cfg.applyConfig(p_oConfig, true);
1653
        }
1654
 
1655
        // Register the Menu instance with the MenuManager
1656
        MenuManager.addMenu(this);
1657
 
1658
        this.initEvent.fire(Menu);
1659
    }
1660
},
1661
 
1662
 
1663
 
1664
// Private methods
1665
 
1666
 
1667
/**
1668
* @method _initSubTree
1669
* @description Iterates the childNodes of the source element to find nodes
1670
* used to instantiate menu and menu items.
1671
* @private
1672
*/
1673
_initSubTree: function () {
1674
 
1675
    var oSrcElement = this.srcElement,
1676
        sSrcElementTagName,
1677
        nGroup,
1678
        sGroupTitleTagName,
1679
        oNode,
1680
        aListElements,
1681
        nListElements,
1682
        i;
1683
 
1684
 
1685
    if (oSrcElement) {
1686
 
1687
        sSrcElementTagName =
1688
            (oSrcElement.tagName && oSrcElement.tagName.toUpperCase());
1689
 
1690
 
1691
        if (sSrcElementTagName == _DIV_UPPERCASE) {
1692
 
1693
            //  Populate the collection of item groups and item group titles
1694
 
1695
            oNode = this.body.firstChild;
1696
 
1697
 
1698
            if (oNode) {
1699
 
1700
                nGroup = 0;
1701
                sGroupTitleTagName = this.GROUP_TITLE_TAG_NAME.toUpperCase();
1702
 
1703
                do {
1704
 
1705
 
1706
                    if (oNode && oNode.tagName) {
1707
 
1708
                        switch (oNode.tagName.toUpperCase()) {
1709
 
1710
                            case sGroupTitleTagName:
1711
 
1712
                                this._aGroupTitleElements[nGroup] = oNode;
1713
 
1714
                            break;
1715
 
1716
                            case _UL_UPPERCASE:
1717
 
1718
                                this._aListElements[nGroup] = oNode;
1719
                                this._aItemGroups[nGroup] = [];
1720
                                nGroup++;
1721
 
1722
                            break;
1723
 
1724
                        }
1725
 
1726
                    }
1727
 
1728
                }
1729
                while ((oNode = oNode.nextSibling));
1730
 
1731
 
1732
                /*
1733
                    Apply the "first-of-type" class to the first UL to mimic
1734
                    the ":first-of-type" CSS3 psuedo class.
1735
                */
1736
 
1737
                if (this._aListElements[0]) {
1738
 
1739
                    Dom.addClass(this._aListElements[0], _FIRST_OF_TYPE);
1740
 
1741
                }
1742
 
1743
            }
1744
 
1745
        }
1746
 
1747
 
1748
        oNode = null;
1749
 
1750
        YAHOO.log("Searching DOM for items to initialize.", "info", this.toString());
1751
 
1752
 
1753
        if (sSrcElementTagName) {
1754
 
1755
            switch (sSrcElementTagName) {
1756
 
1757
                case _DIV_UPPERCASE:
1758
 
1759
                    aListElements = this._aListElements;
1760
                    nListElements = aListElements.length;
1761
 
1762
                    if (nListElements > 0) {
1763
 
1764
                        YAHOO.log("Found " + nListElements + " item groups to initialize.",
1765
                                    "info", this.toString());
1766
 
1767
                        i = nListElements - 1;
1768
 
1769
                        do {
1770
 
1771
                            oNode = aListElements[i].firstChild;
1772
 
1773
                            if (oNode) {
1774
 
1775
                                YAHOO.log("Scanning " +
1776
                                    aListElements[i].childNodes.length +
1777
                                    " child nodes for items to initialize.", "info", this.toString());
1778
 
1779
                                do {
1780
 
1781
                                    if (oNode && oNode.tagName &&
1782
                                        oNode.tagName.toUpperCase() == _LI) {
1783
 
1784
                                        YAHOO.log("Initializing " +
1785
                                            oNode.tagName + " node.", "info", this.toString());
1786
 
1787
                                        this.addItem(new this.ITEM_TYPE(oNode,
1788
                                                    { parent: this }), i);
1789
 
1790
                                    }
1791
 
1792
                                }
1793
                                while ((oNode = oNode.nextSibling));
1794
 
1795
                            }
1796
 
1797
                        }
1798
                        while (i--);
1799
 
1800
                    }
1801
 
1802
                break;
1803
 
1804
                case _SELECT:
1805
 
1806
                    YAHOO.log("Scanning " +
1807
                        oSrcElement.childNodes.length +
1808
                        " child nodes for items to initialize.", "info", this.toString());
1809
 
1810
                    oNode = oSrcElement.firstChild;
1811
 
1812
                    do {
1813
 
1814
                        if (oNode && oNode.tagName) {
1815
 
1816
                            switch (oNode.tagName.toUpperCase()) {
1817
 
1818
                                case _OPTGROUP:
1819
                                case _OPTION:
1820
 
1821
                                    YAHOO.log("Initializing " +
1822
                                        oNode.tagName + " node.", "info", this.toString());
1823
 
1824
                                    this.addItem(
1825
                                            new this.ITEM_TYPE(
1826
                                                    oNode,
1827
                                                    { parent: this }
1828
                                                )
1829
                                            );
1830
 
1831
                                break;
1832
 
1833
                            }
1834
 
1835
                        }
1836
 
1837
                    }
1838
                    while ((oNode = oNode.nextSibling));
1839
 
1840
                break;
1841
 
1842
            }
1843
 
1844
        }
1845
 
1846
    }
1847
 
1848
},
1849
 
1850
 
1851
/**
1852
* @method _getFirstEnabledItem
1853
* @description Returns the first enabled item in the menu.
1854
* @return {YAHOO.widget.MenuItem}
1855
* @private
1856
*/
1857
_getFirstEnabledItem: function () {
1858
 
1859
    var aItems = this.getItems(),
1860
        nItems = aItems.length,
1861
        oItem,
1862
        returnVal;
1863
 
1864
 
1865
    for(var i=0; i<nItems; i++) {
1866
 
1867
        oItem = aItems[i];
1868
 
1869
        if (oItem && !oItem.cfg.getProperty(_DISABLED) && oItem.element.style.display != _NONE) {
1870
 
1871
            returnVal = oItem;
1872
            break;
1873
 
1874
        }
1875
 
1876
    }
1877
 
1878
    return returnVal;
1879
 
1880
},
1881
 
1882
 
1883
/**
1884
* @method _addItemToGroup
1885
* @description Adds a menu item to a group.
1886
* @private
1887
* @param {Number} p_nGroupIndex Number indicating the group to which the
1888
* item belongs.
1889
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
1890
* instance to be added to the menu.
1891
* @param {HTML} p_oItem String or markup specifying the content of the item to be added
1892
* to the menu. The item is inserted into the DOM as HTML, and should be escaped by the implementor if coming from an external source.
1893
* @param {Object} p_oItem Object literal containing a set of menu item
1894
* configuration properties.
1895
* @param {Number} p_nItemIndex Optional. Number indicating the index at
1896
* which the menu item should be added.
1897
* @return {YAHOO.widget.MenuItem}
1898
*/
1899
_addItemToGroup: function (p_nGroupIndex, p_oItem, p_nItemIndex) {
1900
 
1901
    var oItem,
1902
        nGroupIndex,
1903
        aGroup,
1904
        oGroupItem,
1905
        bAppend,
1906
        oNextItemSibling,
1907
        nItemIndex,
1908
        returnVal;
1909
 
1910
 
1911
    function getNextItemSibling(p_aArray, p_nStartIndex) {
1912
 
1913
        return (p_aArray[p_nStartIndex] || getNextItemSibling(p_aArray, (p_nStartIndex+1)));
1914
 
1915
    }
1916
 
1917
 
1918
    if (p_oItem instanceof this.ITEM_TYPE) {
1919
 
1920
        oItem = p_oItem;
1921
        oItem.parent = this;
1922
 
1923
    }
1924
    else if (Lang.isString(p_oItem)) {
1925
 
1926
        oItem = new this.ITEM_TYPE(p_oItem, { parent: this });
1927
 
1928
    }
1929
    else if (Lang.isObject(p_oItem)) {
1930
 
1931
        p_oItem.parent = this;
1932
 
1933
        oItem = new this.ITEM_TYPE(p_oItem.text, p_oItem);
1934
 
1935
    }
1936
 
1937
 
1938
    if (oItem) {
1939
 
1940
        if (oItem.cfg.getProperty(_SELECTED)) {
1941
 
1942
            this.activeItem = oItem;
1943
 
1944
        }
1945
 
1946
 
1947
        nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0;
1948
        aGroup = this._getItemGroup(nGroupIndex);
1949
 
1950
 
1951
 
1952
        if (!aGroup) {
1953
 
1954
            aGroup = this._createItemGroup(nGroupIndex);
1955
 
1956
        }
1957
 
1958
 
1959
        if (Lang.isNumber(p_nItemIndex)) {
1960
 
1961
            bAppend = (p_nItemIndex >= aGroup.length);
1962
 
1963
 
1964
            if (aGroup[p_nItemIndex]) {
1965
 
1966
                aGroup.splice(p_nItemIndex, 0, oItem);
1967
 
1968
            }
1969
            else {
1970
 
1971
                aGroup[p_nItemIndex] = oItem;
1972
 
1973
            }
1974
 
1975
 
1976
            oGroupItem = aGroup[p_nItemIndex];
1977
 
1978
            if (oGroupItem) {
1979
 
1980
                if (bAppend && (!oGroupItem.element.parentNode ||
1981
                        oGroupItem.element.parentNode.nodeType == 11)) {
1982
 
1983
                    this._aListElements[nGroupIndex].appendChild(oGroupItem.element);
1984
 
1985
                }
1986
                else {
1987
 
1988
                    oNextItemSibling = getNextItemSibling(aGroup, (p_nItemIndex+1));
1989
 
1990
                    if (oNextItemSibling && (!oGroupItem.element.parentNode ||
1991
                            oGroupItem.element.parentNode.nodeType == 11)) {
1992
 
1993
                        this._aListElements[nGroupIndex].insertBefore(
1994
                                oGroupItem.element, oNextItemSibling.element);
1995
 
1996
                    }
1997
 
1998
                }
1999
 
2000
 
2001
                oGroupItem.parent = this;
2002
 
2003
                this._subscribeToItemEvents(oGroupItem);
2004
 
2005
                this._configureSubmenu(oGroupItem);
2006
 
2007
                this._updateItemProperties(nGroupIndex);
2008
 
2009
                YAHOO.log("Item inserted." +
2010
                    " Text: " + oGroupItem.cfg.getProperty("text") + ", " +
2011
                    " Index: " + oGroupItem.index + ", " +
2012
                    " Group Index: " + oGroupItem.groupIndex, "info", this.toString());
2013
 
2014
                this.itemAddedEvent.fire(oGroupItem);
2015
                this.changeContentEvent.fire();
2016
 
2017
                returnVal = oGroupItem;
2018
 
2019
            }
2020
 
2021
        }
2022
        else {
2023
 
2024
            nItemIndex = aGroup.length;
2025
 
2026
            aGroup[nItemIndex] = oItem;
2027
 
2028
            oGroupItem = aGroup[nItemIndex];
2029
 
2030
 
2031
            if (oGroupItem) {
2032
 
2033
                if (!Dom.isAncestor(this._aListElements[nGroupIndex], oGroupItem.element)) {
2034
 
2035
                    this._aListElements[nGroupIndex].appendChild(oGroupItem.element);
2036
 
2037
                }
2038
 
2039
                oGroupItem.element.setAttribute(_GROUP_INDEX, nGroupIndex);
2040
                oGroupItem.element.setAttribute(_INDEX, nItemIndex);
2041
 
2042
                oGroupItem.parent = this;
2043
 
2044
                oGroupItem.index = nItemIndex;
2045
                oGroupItem.groupIndex = nGroupIndex;
2046
 
2047
                this._subscribeToItemEvents(oGroupItem);
2048
 
2049
                this._configureSubmenu(oGroupItem);
2050
 
2051
                if (nItemIndex === 0) {
2052
 
2053
                    Dom.addClass(oGroupItem.element, _FIRST_OF_TYPE);
2054
 
2055
                }
2056
 
2057
                YAHOO.log("Item added." +
2058
                    " Text: " + oGroupItem.cfg.getProperty("text") + ", " +
2059
                    " Index: " + oGroupItem.index + ", " +
2060
                    " Group Index: " + oGroupItem.groupIndex, "info", this.toString());
2061
 
2062
 
2063
                this.itemAddedEvent.fire(oGroupItem);
2064
                this.changeContentEvent.fire();
2065
 
2066
                returnVal = oGroupItem;
2067
 
2068
            }
2069
 
2070
        }
2071
 
2072
    }
2073
 
2074
    return returnVal;
2075
 
2076
},
2077
 
2078
 
2079
/**
2080
* @method _removeItemFromGroupByIndex
2081
* @description Removes a menu item from a group by index.  Returns the menu
2082
* item that was removed.
2083
* @private
2084
* @param {Number} p_nGroupIndex Number indicating the group to which the menu
2085
* item belongs.
2086
* @param {Number} p_nItemIndex Number indicating the index of the menu item
2087
* to be removed.
2088
* @return {YAHOO.widget.MenuItem}
2089
*/
2090
_removeItemFromGroupByIndex: function (p_nGroupIndex, p_nItemIndex) {
2091
 
2092
    var nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0,
2093
        aGroup = this._getItemGroup(nGroupIndex),
2094
        aArray,
2095
        oItem,
2096
        oUL;
2097
 
2098
    if (aGroup) {
2099
 
2100
        aArray = aGroup.splice(p_nItemIndex, 1);
2101
        oItem = aArray[0];
2102
 
2103
        if (oItem) {
2104
 
2105
            // Update the index and className properties of each member
2106
 
2107
            this._updateItemProperties(nGroupIndex);
2108
 
2109
            if (aGroup.length === 0) {
2110
 
2111
                // Remove the UL
2112
 
2113
                oUL = this._aListElements[nGroupIndex];
2114
 
2115
                if (oUL && oUL.parentNode) {
2116
                    oUL.parentNode.removeChild(oUL);
2117
                }
2118
 
2119
                // Remove the group from the array of items
2120
 
2121
                this._aItemGroups.splice(nGroupIndex, 1);
2122
 
2123
 
2124
                // Remove the UL from the array of ULs
2125
 
2126
                this._aListElements.splice(nGroupIndex, 1);
2127
 
2128
 
2129
                /*
2130
                     Assign the "first-of-type" class to the new first UL
2131
                     in the collection
2132
                */
2133
 
2134
                oUL = this._aListElements[0];
2135
 
2136
                if (oUL) {
2137
 
2138
                    Dom.addClass(oUL, _FIRST_OF_TYPE);
2139
 
2140
                }
2141
 
2142
            }
2143
 
2144
 
2145
            this.itemRemovedEvent.fire(oItem);
2146
            this.changeContentEvent.fire();
2147
 
2148
        }
2149
 
2150
    }
2151
 
2152
    // Return a reference to the item that was removed
2153
 
2154
    return oItem;
2155
 
2156
},
2157
 
2158
 
2159
/**
2160
* @method _removeItemFromGroupByValue
2161
* @description Removes a menu item from a group by reference.  Returns the
2162
* menu item that was removed.
2163
* @private
2164
* @param {Number} p_nGroupIndex Number indicating the group to which the
2165
* menu item belongs.
2166
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
2167
* instance to be removed.
2168
* @return {YAHOO.widget.MenuItem}
2169
*/
2170
_removeItemFromGroupByValue: function (p_nGroupIndex, p_oItem) {
2171
 
2172
    var aGroup = this._getItemGroup(p_nGroupIndex),
2173
        nItems,
2174
        nItemIndex,
2175
        returnVal,
2176
        i;
2177
 
2178
    if (aGroup) {
2179
 
2180
        nItems = aGroup.length;
2181
        nItemIndex = -1;
2182
 
2183
        if (nItems > 0) {
2184
 
2185
            i = nItems-1;
2186
 
2187
            do {
2188
 
2189
                if (aGroup[i] == p_oItem) {
2190
 
2191
                    nItemIndex = i;
2192
                    break;
2193
 
2194
                }
2195
 
2196
            }
2197
            while (i--);
2198
 
2199
            if (nItemIndex > -1) {
2200
 
2201
                returnVal = this._removeItemFromGroupByIndex(p_nGroupIndex, nItemIndex);
2202
 
2203
            }
2204
 
2205
        }
2206
 
2207
    }
2208
 
2209
    return returnVal;
2210
 
2211
},
2212
 
2213
 
2214
/**
2215
* @method _updateItemProperties
2216
* @description Updates the "index," "groupindex," and "className" properties
2217
* of the menu items in the specified group.
2218
* @private
2219
* @param {Number} p_nGroupIndex Number indicating the group of items to update.
2220
*/
2221
_updateItemProperties: function (p_nGroupIndex) {
2222
 
2223
    var aGroup = this._getItemGroup(p_nGroupIndex),
2224
        nItems = aGroup.length,
2225
        oItem,
2226
        oLI,
2227
        i;
2228
 
2229
 
2230
    if (nItems > 0) {
2231
 
2232
        i = nItems - 1;
2233
 
2234
        // Update the index and className properties of each member
2235
 
2236
        do {
2237
 
2238
            oItem = aGroup[i];
2239
 
2240
            if (oItem) {
2241
 
2242
                oLI = oItem.element;
2243
 
2244
                oItem.index = i;
2245
                oItem.groupIndex = p_nGroupIndex;
2246
 
2247
                oLI.setAttribute(_GROUP_INDEX, p_nGroupIndex);
2248
                oLI.setAttribute(_INDEX, i);
2249
 
2250
                Dom.removeClass(oLI, _FIRST_OF_TYPE);
2251
 
2252
            }
2253
 
2254
        }
2255
        while (i--);
2256
 
2257
 
2258
        if (oLI) {
2259
 
2260
            Dom.addClass(oLI, _FIRST_OF_TYPE);
2261
 
2262
        }
2263
 
2264
    }
2265
 
2266
},
2267
 
2268
 
2269
/**
2270
* @method _createItemGroup
2271
* @description Creates a new menu item group (array) and its associated
2272
* <code>&#60;ul&#62;</code> element. Returns an aray of menu item groups.
2273
* @private
2274
* @param {Number} p_nIndex Number indicating the group to create.
2275
* @return {Array}
2276
*/
2277
_createItemGroup: function (p_nIndex) {
2278
 
2279
    var oUL,
2280
        returnVal;
2281
 
2282
    if (!this._aItemGroups[p_nIndex]) {
2283
 
2284
        this._aItemGroups[p_nIndex] = [];
2285
 
2286
        oUL = document.createElement(_UL_LOWERCASE);
2287
 
2288
        this._aListElements[p_nIndex] = oUL;
2289
 
2290
        returnVal = this._aItemGroups[p_nIndex];
2291
 
2292
    }
2293
 
2294
    return returnVal;
2295
 
2296
},
2297
 
2298
 
2299
/**
2300
* @method _getItemGroup
2301
* @description Returns the menu item group at the specified index.
2302
* @private
2303
* @param {Number} p_nIndex Number indicating the index of the menu item group
2304
* to be retrieved.
2305
* @return {Array}
2306
*/
2307
_getItemGroup: function (p_nIndex) {
2308
 
2309
    var nIndex = Lang.isNumber(p_nIndex) ? p_nIndex : 0,
2310
        aGroups = this._aItemGroups,
2311
        returnVal;
2312
 
2313
    if (nIndex in aGroups) {
2314
 
2315
        returnVal = aGroups[nIndex];
2316
 
2317
    }
2318
 
2319
    return returnVal;
2320
 
2321
},
2322
 
2323
 
2324
/**
2325
* @method _configureSubmenu
2326
* @description Subscribes the menu item's submenu to its parent menu's events.
2327
* @private
2328
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
2329
* instance with the submenu to be configured.
2330
*/
2331
_configureSubmenu: function (p_oItem) {
2332
 
2333
    var oSubmenu = p_oItem.cfg.getProperty(_SUBMENU);
2334
 
2335
    if (oSubmenu) {
2336
 
2337
        /*
2338
            Listen for configuration changes to the parent menu
2339
            so they they can be applied to the submenu.
2340
        */
2341
 
2342
        this.cfg.configChangedEvent.subscribe(this._onParentMenuConfigChange, oSubmenu, true);
2343
 
2344
        this.renderEvent.subscribe(this._onParentMenuRender, oSubmenu, true);
2345
 
2346
    }
2347
 
2348
},
2349
 
2350
 
2351
 
2352
 
2353
/**
2354
* @method _subscribeToItemEvents
2355
* @description Subscribes a menu to a menu item's event.
2356
* @private
2357
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
2358
* instance whose events should be subscribed to.
2359
*/
2360
_subscribeToItemEvents: function (p_oItem) {
2361
 
2362
    p_oItem.destroyEvent.subscribe(this._onMenuItemDestroy, p_oItem, this);
2363
    p_oItem.cfg.configChangedEvent.subscribe(this._onMenuItemConfigChange, p_oItem, this);
2364
 
2365
},
2366
 
2367
 
2368
/**
2369
* @method _onVisibleChange
2370
* @description Change event handler for the the menu's "visible" configuration
2371
* property.
2372
* @private
2373
* @param {String} p_sType String representing the name of the event that
2374
* was fired.
2375
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
2376
*/
2377
_onVisibleChange: function (p_sType, p_aArgs) {
2378
 
2379
    var bVisible = p_aArgs[0];
2380
 
2381
    if (bVisible) {
2382
 
2383
        Dom.addClass(this.element, _VISIBLE);
2384
 
2385
    }
2386
    else {
2387
 
2388
        Dom.removeClass(this.element, _VISIBLE);
2389
 
2390
    }
2391
 
2392
},
2393
 
2394
 
2395
/**
2396
* @method _cancelHideDelay
2397
* @description Cancels the call to "hideMenu."
2398
* @private
2399
*/
2400
_cancelHideDelay: function () {
2401
 
2402
    var oTimer = this.getRoot()._hideDelayTimer;
2403
 
2404
    if (oTimer) {
2405
 
2406
        oTimer.cancel();
2407
 
2408
    }
2409
 
2410
},
2411
 
2412
 
2413
/**
2414
* @method _execHideDelay
2415
* @description Hides the menu after the number of milliseconds specified by
2416
* the "hidedelay" configuration property.
2417
* @private
2418
*/
2419
_execHideDelay: function () {
2420
 
2421
    this._cancelHideDelay();
2422
 
2423
    var oRoot = this.getRoot();
2424
 
2425
    oRoot._hideDelayTimer = Lang.later(oRoot.cfg.getProperty(_HIDE_DELAY), this, function () {
2426
 
2427
        if (oRoot.activeItem) {
2428
            if (oRoot.hasFocus()) {
2429
                oRoot.activeItem.focus();
2430
            }
2431
            oRoot.clearActiveItem();
2432
        }
2433
 
2434
        if (oRoot == this && !(this instanceof YAHOO.widget.MenuBar) &&
2435
            this.cfg.getProperty(_POSITION) == _DYNAMIC) {
2436
            this.hide();
2437
        }
2438
    });
2439
 
2440
},
2441
 
2442
 
2443
/**
2444
* @method _cancelShowDelay
2445
* @description Cancels the call to the "showMenu."
2446
* @private
2447
*/
2448
_cancelShowDelay: function () {
2449
    var oTimer = this.getRoot()._showDelayTimer;
2450
    if (oTimer) {
2451
        oTimer.cancel();
2452
    }
2453
},
2454
 
2455
 
2456
/**
2457
* @method _execSubmenuHideDelay
2458
* @description Hides a submenu after the number of milliseconds specified by
2459
* the "submenuhidedelay" configuration property have elapsed.
2460
* @private
2461
* @param {YAHOO.widget.Menu} p_oSubmenu Object specifying the submenu that
2462
* should be hidden.
2463
* @param {Number} p_nMouseX The x coordinate of the mouse when it left
2464
* the specified submenu's parent menu item.
2465
* @param {Number} p_nHideDelay The number of milliseconds that should ellapse
2466
* before the submenu is hidden.
2467
*/
2468
_execSubmenuHideDelay: function (p_oSubmenu, p_nMouseX, p_nHideDelay) {
2469
 
2470
    p_oSubmenu._submenuHideDelayTimer = Lang.later(50, this, function () {
2471
 
2472
        if (this._nCurrentMouseX > (p_nMouseX + 10)) {
2473
 
2474
            p_oSubmenu._submenuHideDelayTimer = Lang.later(p_nHideDelay, p_oSubmenu, function () {
2475
 
2476
                this.hide();
2477
 
2478
            });
2479
 
2480
        }
2481
        else {
2482
 
2483
            p_oSubmenu.hide();
2484
 
2485
        }
2486
 
2487
    });
2488
 
2489
},
2490
 
2491
 
2492
 
2493
// Protected methods
2494
 
2495
 
2496
/**
2497
* @method _disableScrollHeader
2498
* @description Disables the header used for scrolling the body of the menu.
2499
* @protected
2500
*/
2501
_disableScrollHeader: function () {
2502
 
2503
    if (!this._bHeaderDisabled) {
2504
 
2505
        Dom.addClass(this.header, _TOP_SCROLLBAR_DISABLED);
2506
        this._bHeaderDisabled = true;
2507
 
2508
    }
2509
 
2510
},
2511
 
2512
 
2513
/**
2514
* @method _disableScrollFooter
2515
* @description Disables the footer used for scrolling the body of the menu.
2516
* @protected
2517
*/
2518
_disableScrollFooter: function () {
2519
 
2520
    if (!this._bFooterDisabled) {
2521
 
2522
        Dom.addClass(this.footer, _BOTTOM_SCROLLBAR_DISABLED);
2523
        this._bFooterDisabled = true;
2524
 
2525
    }
2526
 
2527
},
2528
 
2529
 
2530
/**
2531
* @method _enableScrollHeader
2532
* @description Enables the header used for scrolling the body of the menu.
2533
* @protected
2534
*/
2535
_enableScrollHeader: function () {
2536
 
2537
    if (this._bHeaderDisabled) {
2538
 
2539
        Dom.removeClass(this.header, _TOP_SCROLLBAR_DISABLED);
2540
        this._bHeaderDisabled = false;
2541
 
2542
    }
2543
 
2544
},
2545
 
2546
 
2547
/**
2548
* @method _enableScrollFooter
2549
* @description Enables the footer used for scrolling the body of the menu.
2550
* @protected
2551
*/
2552
_enableScrollFooter: function () {
2553
 
2554
    if (this._bFooterDisabled) {
2555
 
2556
        Dom.removeClass(this.footer, _BOTTOM_SCROLLBAR_DISABLED);
2557
        this._bFooterDisabled = false;
2558
 
2559
    }
2560
 
2561
},
2562
 
2563
 
2564
/**
2565
* @method _onMouseOver
2566
* @description "mouseover" event handler for the menu.
2567
* @protected
2568
* @param {String} p_sType String representing the name of the event that
2569
* was fired.
2570
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
2571
*/
2572
_onMouseOver: function (p_sType, p_aArgs) {
2573
 
2574
    var oEvent = p_aArgs[0],
2575
        oItem = p_aArgs[1],
2576
        oTarget = Event.getTarget(oEvent),
2577
        oRoot = this.getRoot(),
2578
        oSubmenuHideDelayTimer = this._submenuHideDelayTimer,
2579
        oParentMenu,
2580
        nShowDelay,
2581
        bShowDelay,
2582
        oActiveItem,
2583
        oItemCfg,
2584
        oSubmenu;
2585
 
2586
 
2587
    var showSubmenu = function () {
2588
 
2589
        if (this.parent.cfg.getProperty(_SELECTED)) {
2590
 
2591
            this.show();
2592
 
2593
        }
2594
 
2595
    };
2596
 
2597
 
2598
    if (!this._bStopMouseEventHandlers) {
2599
 
2600
        if (!this._bHandledMouseOverEvent && (oTarget == this.element ||
2601
                Dom.isAncestor(this.element, oTarget))) {
2602
 
2603
            // Menu mouseover logic
2604
 
2605
            if (this._useHideDelay) {
2606
                this._cancelHideDelay();
2607
            }
2608
 
2609
            this._nCurrentMouseX = 0;
2610
 
2611
            Event.on(this.element, _MOUSEMOVE, this._onMouseMove, this, true);
2612
 
2613
 
2614
            /*
2615
                If the mouse is moving from the submenu back to its corresponding menu item,
2616
                don't hide the submenu or clear the active MenuItem.
2617
            */
2618
 
2619
            if (!(oItem && Dom.isAncestor(oItem.element, Event.getRelatedTarget(oEvent)))) {
2620
 
2621
                this.clearActiveItem();
2622
 
2623
            }
2624
 
2625
 
2626
            if (this.parent && oSubmenuHideDelayTimer) {
2627
 
2628
                oSubmenuHideDelayTimer.cancel();
2629
 
2630
                this.parent.cfg.setProperty(_SELECTED, true);
2631
 
2632
                oParentMenu = this.parent.parent;
2633
 
2634
                oParentMenu._bHandledMouseOutEvent = true;
2635
                oParentMenu._bHandledMouseOverEvent = false;
2636
 
2637
            }
2638
 
2639
 
2640
            this._bHandledMouseOverEvent = true;
2641
            this._bHandledMouseOutEvent = false;
2642
 
2643
        }
2644
 
2645
 
2646
        if (oItem && !oItem.handledMouseOverEvent && !oItem.cfg.getProperty(_DISABLED) &&
2647
            (oTarget == oItem.element || Dom.isAncestor(oItem.element, oTarget))) {
2648
 
2649
            // Menu Item mouseover logic
2650
 
2651
            nShowDelay = this.cfg.getProperty(_SHOW_DELAY);
2652
            bShowDelay = (nShowDelay > 0);
2653
 
2654
 
2655
            if (bShowDelay) {
2656
 
2657
                this._cancelShowDelay();
2658
 
2659
            }
2660
 
2661
 
2662
            oActiveItem = this.activeItem;
2663
 
2664
            if (oActiveItem) {
2665
 
2666
                oActiveItem.cfg.setProperty(_SELECTED, false);
2667
 
2668
            }
2669
 
2670
 
2671
            oItemCfg = oItem.cfg;
2672
 
2673
            // Select and focus the current menu item
2674
 
2675
            oItemCfg.setProperty(_SELECTED, true);
2676
 
2677
 
2678
            if (this.hasFocus() || oRoot._hasFocus) {
2679
 
2680
                oItem.focus();
2681
 
2682
                oRoot._hasFocus = false;
2683
 
2684
            }
2685
 
2686
 
2687
            if (this.cfg.getProperty(_AUTO_SUBMENU_DISPLAY)) {
2688
 
2689
                // Show the submenu this menu item
2690
 
2691
                oSubmenu = oItemCfg.getProperty(_SUBMENU);
2692
 
2693
                if (oSubmenu) {
2694
 
2695
                    if (bShowDelay) {
2696
 
2697
                        oRoot._showDelayTimer =
2698
                            Lang.later(oRoot.cfg.getProperty(_SHOW_DELAY), oSubmenu, showSubmenu);
2699
 
2700
                    }
2701
                    else {
2702
 
2703
                        oSubmenu.show();
2704
 
2705
                    }
2706
 
2707
                }
2708
 
2709
            }
2710
 
2711
            oItem.handledMouseOverEvent = true;
2712
            oItem.handledMouseOutEvent = false;
2713
 
2714
        }
2715
 
2716
    }
2717
 
2718
},
2719
 
2720
 
2721
/**
2722
* @method _onMouseOut
2723
* @description "mouseout" event handler for the menu.
2724
* @protected
2725
* @param {String} p_sType String representing the name of the event that
2726
* was fired.
2727
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
2728
*/
2729
_onMouseOut: function (p_sType, p_aArgs) {
2730
 
2731
    var oEvent = p_aArgs[0],
2732
        oItem = p_aArgs[1],
2733
        oRelatedTarget = Event.getRelatedTarget(oEvent),
2734
        bMovingToSubmenu = false,
2735
        oItemCfg,
2736
        oSubmenu,
2737
        nSubmenuHideDelay,
2738
        nShowDelay;
2739
 
2740
 
2741
    YAHOO.log("onMouseout: this == " + this);
2742
 
2743
    if (!this._bStopMouseEventHandlers) {
2744
 
2745
        if (oItem && !oItem.cfg.getProperty(_DISABLED)) {
2746
 
2747
            oItemCfg = oItem.cfg;
2748
            oSubmenu = oItemCfg.getProperty(_SUBMENU);
2749
 
2750
 
2751
            if (oSubmenu && (oRelatedTarget == oSubmenu.element || Dom.isAncestor(oSubmenu.element, oRelatedTarget))) {
2752
                bMovingToSubmenu = true;
2753
            }
2754
 
2755
            if (!oItem.handledMouseOutEvent && ((oRelatedTarget != oItem.element && !Dom.isAncestor(oItem.element, oRelatedTarget)) || bMovingToSubmenu)) {
2756
                if (!bMovingToSubmenu) {
2757
                    oItem.cfg.setProperty(_SELECTED, false);
2758
                    if (oSubmenu) {
2759
 
2760
                        nSubmenuHideDelay = this.cfg.getProperty(_SUBMENU_HIDE_DELAY);
2761
                        nShowDelay = this.cfg.getProperty(_SHOW_DELAY);
2762
                        if (!(this instanceof YAHOO.widget.MenuBar) && nSubmenuHideDelay > 0 && nSubmenuHideDelay >= nShowDelay) {
2763
                            this._execSubmenuHideDelay(oSubmenu, Event.getPageX(oEvent), nSubmenuHideDelay);
2764
                        } else {
2765
                            oSubmenu.hide();
2766
                        }
2767
                    }
2768
                }
2769
 
2770
                oItem.handledMouseOutEvent = true;
2771
                oItem.handledMouseOverEvent = false;
2772
            }
2773
        }
2774
 
2775
        YAHOO.log("onMouseout: oRelatedTarget = " + oRelatedTarget.className);
2776
        YAHOO.log("onMouseout: this.element = " + this.element.id);
2777
        YAHOO.log("onMouseout: Ancestorthis.element = " + Dom.isAncestor(this.element, oRelatedTarget));
2778
        YAHOO.log("onMouseout: canHide = " + this._didMouseLeave(oRelatedTarget));
2779
 
2780
        if (!this._bHandledMouseOutEvent) {
2781
            if (this._didMouseLeave(oRelatedTarget) || bMovingToSubmenu) {
2782
                // Menu mouseout logic
2783
                if (this._useHideDelay) {
2784
                    this._execHideDelay();
2785
                }
2786
 
2787
                Event.removeListener(this.element, _MOUSEMOVE, this._onMouseMove);
2788
 
2789
                this._nCurrentMouseX = Event.getPageX(oEvent);
2790
 
2791
                this._bHandledMouseOutEvent = true;
2792
                this._bHandledMouseOverEvent = false;
2793
            }
2794
        }
2795
    }
2796
 
2797
},
2798
 
2799
/**
2800
 * Utilility method to determine if we really moused out of the menu based on the related target
2801
 * @method _didMouseLeave
2802
 * @protected
2803
 * @param {HTMLElement} oRelatedTarget The related target based on which we're making the decision
2804
 * @return {boolean} true if it's OK to hide based on the related target.
2805
 */
2806
_didMouseLeave : function(oRelatedTarget) {
2807
    // Hide if we're not moving back to the element from somewhere inside the element, or we're moving to an element inside the menu.
2808
    // The shadow is treated as an edge case, inside inside the menu, but we get no further mouseouts, because it overflows the element,
2809
    // so we need to close when moving to the menu.
2810
    return (oRelatedTarget === this._shadow || (oRelatedTarget != this.element && !Dom.isAncestor(this.element, oRelatedTarget)));
2811
},
2812
 
2813
/**
2814
* @method _onMouseMove
2815
* @description "click" event handler for the menu.
2816
* @protected
2817
* @param {Event} p_oEvent Object representing the DOM event object passed
2818
* back by the event utility (YAHOO.util.Event).
2819
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
2820
* fired the event.
2821
*/
2822
_onMouseMove: function (p_oEvent, p_oMenu) {
2823
 
2824
    if (!this._bStopMouseEventHandlers) {
2825
 
2826
        this._nCurrentMouseX = Event.getPageX(p_oEvent);
2827
 
2828
    }
2829
 
2830
},
2831
 
2832
 
2833
/**
2834
* @method _onClick
2835
* @description "click" event handler for the menu.
2836
* @protected
2837
* @param {String} p_sType String representing the name of the event that
2838
* was fired.
2839
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
2840
*/
2841
_onClick: function (p_sType, p_aArgs) {
2842
 
2843
    var oEvent = p_aArgs[0],
2844
        oItem = p_aArgs[1],
2845
        bInMenuAnchor = false,
2846
        oSubmenu,
2847
        oMenu,
2848
        oRoot,
2849
        sId,
2850
        sURL,
2851
        nHashPos,
2852
        nLen;
2853
 
2854
 
2855
    var hide = function () {
2856
 
2857
        oRoot = this.getRoot();
2858
 
2859
        if (oRoot instanceof YAHOO.widget.MenuBar ||
2860
            oRoot.cfg.getProperty(_POSITION) == _STATIC) {
2861
 
2862
            oRoot.clearActiveItem();
2863
 
2864
        }
2865
        else {
2866
 
2867
            oRoot.hide();
2868
 
2869
        }
2870
 
2871
    };
2872
 
2873
 
2874
    if (oItem) {
2875
 
2876
        if (oItem.cfg.getProperty(_DISABLED)) {
2877
 
2878
            Event.preventDefault(oEvent);
2879
 
2880
            hide.call(this);
2881
 
2882
        }
2883
        else {
2884
 
2885
            oSubmenu = oItem.cfg.getProperty(_SUBMENU);
2886
 
2887
 
2888
            /*
2889
                 Check if the URL of the anchor is pointing to an element that is
2890
                 a child of the menu.
2891
            */
2892
 
2893
            sURL = oItem.cfg.getProperty(_URL);
2894
 
2895
 
2896
            if (sURL) {
2897
 
2898
                nHashPos = sURL.indexOf(_HASH);
2899
 
2900
                nLen = sURL.length;
2901
 
2902
 
2903
                if (nHashPos != -1) {
2904
 
2905
                    sURL = sURL.substr(nHashPos, nLen);
2906
 
2907
                    nLen = sURL.length;
2908
 
2909
 
2910
                    if (nLen > 1) {
2911
 
2912
                        sId = sURL.substr(1, nLen);
2913
 
2914
                        oMenu = YAHOO.widget.MenuManager.getMenu(sId);
2915
 
2916
                        if (oMenu) {
2917
 
2918
                            bInMenuAnchor =
2919
                                (this.getRoot() === oMenu.getRoot());
2920
 
2921
                        }
2922
 
2923
                    }
2924
                    else if (nLen === 1) {
2925
 
2926
                        bInMenuAnchor = true;
2927
 
2928
                    }
2929
 
2930
                }
2931
 
2932
            }
2933
 
2934
 
2935
            if (bInMenuAnchor && !oItem.cfg.getProperty(_TARGET)) {
2936
 
2937
                Event.preventDefault(oEvent);
2938
 
2939
 
2940
                if (UA.webkit) {
2941
 
2942
                    oItem.focus();
2943
 
2944
                }
2945
                else {
2946
 
2947
                    oItem.focusEvent.fire();
2948
 
2949
                }
2950
 
2951
            }
2952
 
2953
 
2954
            if (!oSubmenu && !this.cfg.getProperty(_KEEP_OPEN)) {
2955
 
2956
                hide.call(this);
2957
 
2958
            }
2959
 
2960
        }
2961
 
2962
    }
2963
 
2964
},
2965
 
2966
/*
2967
    This function is called to prevent a bug in Firefox.  In Firefox,
2968
    moving a DOM element into a stationary mouse pointer will cause the
2969
    browser to fire mouse events.  This can result in the menu mouse
2970
    event handlers being called uncessarily, especially when menus are
2971
    moved into a stationary mouse pointer as a result of a
2972
    key event handler.
2973
*/
2974
/**
2975
 * Utility method to stop mouseevents from being fired if the DOM
2976
 * changes under a stationary mouse pointer (as opposed to the mouse moving
2977
 * over a DOM element).
2978
 *
2979
 * @method _stopMouseEventHandlers
2980
 * @private
2981
 */
2982
_stopMouseEventHandlers: function() {
2983
    this._bStopMouseEventHandlers = true;
2984
 
2985
    Lang.later(10, this, function () {
2986
        this._bStopMouseEventHandlers = false;
2987
    });
2988
},
2989
 
2990
/**
2991
* @method _onKeyDown
2992
* @description "keydown" event handler for the menu.
2993
* @protected
2994
* @param {String} p_sType String representing the name of the event that
2995
* was fired.
2996
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
2997
*/
2998
_onKeyDown: function (p_sType, p_aArgs) {
2999
 
3000
    var oEvent = p_aArgs[0],
3001
        oItem = p_aArgs[1],
3002
        oSubmenu,
3003
        oItemCfg,
3004
        oParentItem,
3005
        oRoot,
3006
        oNextItem,
3007
        oBody,
3008
        nBodyScrollTop,
3009
        nBodyOffsetHeight,
3010
        aItems,
3011
        nItems,
3012
        nNextItemOffsetTop,
3013
        nScrollTarget,
3014
        oParentMenu,
3015
        oFocusedEl;
3016
 
3017
 
3018
    if (this._useHideDelay) {
3019
        this._cancelHideDelay();
3020
    }
3021
 
3022
    if (oItem && !oItem.cfg.getProperty(_DISABLED)) {
3023
 
3024
        oItemCfg = oItem.cfg;
3025
        oParentItem = this.parent;
3026
 
3027
        switch(oEvent.keyCode) {
3028
 
3029
            case 38:    // Up arrow
3030
            case 40:    // Down arrow
3031
 
3032
                oNextItem = (oEvent.keyCode == 38) ?
3033
                    oItem.getPreviousEnabledSibling() :
3034
                    oItem.getNextEnabledSibling();
3035
 
3036
                if (oNextItem) {
3037
 
3038
                    this.clearActiveItem();
3039
 
3040
                    oNextItem.cfg.setProperty(_SELECTED, true);
3041
                    oNextItem.focus();
3042
 
3043
                    if (this.cfg.getProperty(_MAX_HEIGHT) > 0 || Dom.hasClass(this.body, _YUI_MENU_BODY_SCROLLED)) {
3044
 
3045
                        oBody = this.body;
3046
                        nBodyScrollTop = oBody.scrollTop;
3047
                        nBodyOffsetHeight = oBody.offsetHeight;
3048
                        aItems = this.getItems();
3049
                        nItems = aItems.length - 1;
3050
                        nNextItemOffsetTop = oNextItem.element.offsetTop;
3051
 
3052
 
3053
                        if (oEvent.keyCode == 40 ) {    // Down
3054
 
3055
                            if (nNextItemOffsetTop >= (nBodyOffsetHeight + nBodyScrollTop)) {
3056
 
3057
                                oBody.scrollTop = nNextItemOffsetTop - nBodyOffsetHeight;
3058
 
3059
                            }
3060
                            else if (nNextItemOffsetTop <= nBodyScrollTop) {
3061
 
3062
                                oBody.scrollTop = 0;
3063
 
3064
                            }
3065
 
3066
 
3067
                            if (oNextItem == aItems[nItems]) {
3068
 
3069
                                oBody.scrollTop = oNextItem.element.offsetTop;
3070
 
3071
                            }
3072
 
3073
                        }
3074
                        else {  // Up
3075
 
3076
                            if (nNextItemOffsetTop <= nBodyScrollTop) {
3077
 
3078
                                oBody.scrollTop = nNextItemOffsetTop - oNextItem.element.offsetHeight;
3079
 
3080
                            }
3081
                            else if (nNextItemOffsetTop >= (nBodyScrollTop + nBodyOffsetHeight)) {
3082
 
3083
                                oBody.scrollTop = nNextItemOffsetTop;
3084
 
3085
                            }
3086
 
3087
 
3088
                            if (oNextItem == aItems[0]) {
3089
 
3090
                                oBody.scrollTop = 0;
3091
 
3092
                            }
3093
 
3094
                        }
3095
 
3096
 
3097
                        nBodyScrollTop = oBody.scrollTop;
3098
                        nScrollTarget = oBody.scrollHeight - oBody.offsetHeight;
3099
 
3100
                        if (nBodyScrollTop === 0) {
3101
 
3102
                            this._disableScrollHeader();
3103
                            this._enableScrollFooter();
3104
 
3105
                        }
3106
                        else if (nBodyScrollTop == nScrollTarget) {
3107
 
3108
                             this._enableScrollHeader();
3109
                             this._disableScrollFooter();
3110
 
3111
                        }
3112
                        else {
3113
 
3114
                            this._enableScrollHeader();
3115
                            this._enableScrollFooter();
3116
 
3117
                        }
3118
 
3119
                    }
3120
 
3121
                }
3122
 
3123
 
3124
                Event.preventDefault(oEvent);
3125
 
3126
                this._stopMouseEventHandlers();
3127
 
3128
            break;
3129
 
3130
 
3131
            case 39:    // Right arrow
3132
 
3133
                oSubmenu = oItemCfg.getProperty(_SUBMENU);
3134
 
3135
                if (oSubmenu) {
3136
 
3137
                    if (!oItemCfg.getProperty(_SELECTED)) {
3138
 
3139
                        oItemCfg.setProperty(_SELECTED, true);
3140
 
3141
                    }
3142
 
3143
                    oSubmenu.show();
3144
                    oSubmenu.setInitialFocus();
3145
                    oSubmenu.setInitialSelection();
3146
 
3147
                }
3148
                else {
3149
 
3150
                    oRoot = this.getRoot();
3151
 
3152
                    if (oRoot instanceof YAHOO.widget.MenuBar) {
3153
 
3154
                        oNextItem = oRoot.activeItem.getNextEnabledSibling();
3155
 
3156
                        if (oNextItem) {
3157
 
3158
                            oRoot.clearActiveItem();
3159
 
3160
                            oNextItem.cfg.setProperty(_SELECTED, true);
3161
 
3162
                            oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
3163
 
3164
                            if (oSubmenu) {
3165
 
3166
                                oSubmenu.show();
3167
                                oSubmenu.setInitialFocus();
3168
 
3169
                            }
3170
                            else {
3171
 
3172
                                oNextItem.focus();
3173
 
3174
                            }
3175
 
3176
                        }
3177
 
3178
                    }
3179
 
3180
                }
3181
 
3182
 
3183
                Event.preventDefault(oEvent);
3184
 
3185
                this._stopMouseEventHandlers();
3186
 
3187
            break;
3188
 
3189
 
3190
            case 37:    // Left arrow
3191
 
3192
                if (oParentItem) {
3193
 
3194
                    oParentMenu = oParentItem.parent;
3195
 
3196
                    if (oParentMenu instanceof YAHOO.widget.MenuBar) {
3197
 
3198
                        oNextItem =
3199
                            oParentMenu.activeItem.getPreviousEnabledSibling();
3200
 
3201
                        if (oNextItem) {
3202
 
3203
                            oParentMenu.clearActiveItem();
3204
 
3205
                            oNextItem.cfg.setProperty(_SELECTED, true);
3206
 
3207
                            oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
3208
 
3209
                            if (oSubmenu) {
3210
 
3211
                                oSubmenu.show();
3212
                                oSubmenu.setInitialFocus();
3213
 
3214
                            }
3215
                            else {
3216
 
3217
                                oNextItem.focus();
3218
 
3219
                            }
3220
 
3221
                        }
3222
 
3223
                    }
3224
                    else {
3225
 
3226
                        this.hide();
3227
 
3228
                        oParentItem.focus();
3229
 
3230
                    }
3231
 
3232
                }
3233
 
3234
                Event.preventDefault(oEvent);
3235
 
3236
                this._stopMouseEventHandlers();
3237
 
3238
            break;
3239
 
3240
        }
3241
 
3242
 
3243
    }
3244
 
3245
 
3246
    if (oEvent.keyCode == 27) { // Esc key
3247
 
3248
        if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3249
 
3250
            this.hide();
3251
 
3252
            if (this.parent) {
3253
 
3254
                this.parent.focus();
3255
 
3256
            }
3257
            else {
3258
                // Focus the element that previously had focus
3259
 
3260
                oFocusedEl = this._focusedElement;
3261
 
3262
                if (oFocusedEl && oFocusedEl.focus) {
3263
 
3264
                    try {
3265
                        oFocusedEl.focus();
3266
                    }
3267
                    catch(ex) {
3268
                    }
3269
 
3270
                }
3271
 
3272
            }
3273
 
3274
        }
3275
        else if (this.activeItem) {
3276
 
3277
            oSubmenu = this.activeItem.cfg.getProperty(_SUBMENU);
3278
 
3279
            if (oSubmenu && oSubmenu.cfg.getProperty(_VISIBLE)) {
3280
 
3281
                oSubmenu.hide();
3282
                this.activeItem.focus();
3283
 
3284
            }
3285
            else {
3286
 
3287
                this.activeItem.blur();
3288
                this.activeItem.cfg.setProperty(_SELECTED, false);
3289
 
3290
            }
3291
 
3292
        }
3293
 
3294
 
3295
        Event.preventDefault(oEvent);
3296
 
3297
    }
3298
 
3299
},
3300
 
3301
 
3302
/**
3303
* @method _onKeyPress
3304
* @description "keypress" event handler for a Menu instance.
3305
* @protected
3306
* @param {String} p_sType The name of the event that was fired.
3307
* @param {Array} p_aArgs Collection of arguments sent when the event
3308
* was fired.
3309
*/
3310
_onKeyPress: function (p_sType, p_aArgs) {
3311
 
3312
    var oEvent = p_aArgs[0];
3313
 
3314
 
3315
    if (oEvent.keyCode == 40 || oEvent.keyCode == 38) {
3316
 
3317
        Event.preventDefault(oEvent);
3318
 
3319
    }
3320
 
3321
},
3322
 
3323
 
3324
/**
3325
* @method _onBlur
3326
* @description "blur" event handler for a Menu instance.
3327
* @protected
3328
* @param {String} p_sType The name of the event that was fired.
3329
* @param {Array} p_aArgs Collection of arguments sent when the event
3330
* was fired.
3331
*/
3332
_onBlur: function (p_sType, p_aArgs) {
3333
 
3334
    if (this._hasFocus) {
3335
        this._hasFocus = false;
3336
    }
3337
 
3338
},
3339
 
3340
/**
3341
* @method _onYChange
3342
* @description "y" event handler for a Menu instance.
3343
* @protected
3344
* @param {String} p_sType The name of the event that was fired.
3345
* @param {Array} p_aArgs Collection of arguments sent when the event
3346
* was fired.
3347
*/
3348
_onYChange: function (p_sType, p_aArgs) {
3349
 
3350
    var oParent = this.parent,
3351
        nScrollTop,
3352
        oIFrame,
3353
        nY;
3354
 
3355
 
3356
    if (oParent) {
3357
 
3358
        nScrollTop = oParent.parent.body.scrollTop;
3359
 
3360
 
3361
        if (nScrollTop > 0) {
3362
 
3363
            nY = (this.cfg.getProperty(_Y) - nScrollTop);
3364
 
3365
            Dom.setY(this.element, nY);
3366
 
3367
            oIFrame = this.iframe;
3368
 
3369
 
3370
            if (oIFrame) {
3371
 
3372
                Dom.setY(oIFrame, nY);
3373
 
3374
            }
3375
 
3376
            this.cfg.setProperty(_Y, nY, true);
3377
 
3378
        }
3379
 
3380
    }
3381
 
3382
},
3383
 
3384
 
3385
/**
3386
* @method _onScrollTargetMouseOver
3387
* @description "mouseover" event handler for the menu's "header" and "footer"
3388
* elements.  Used to scroll the body of the menu up and down when the
3389
* menu's "maxheight" configuration property is set to a value greater than 0.
3390
* @protected
3391
* @param {Event} p_oEvent Object representing the DOM event object passed
3392
* back by the event utility (YAHOO.util.Event).
3393
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
3394
* fired the event.
3395
*/
3396
_onScrollTargetMouseOver: function (p_oEvent, p_oMenu) {
3397
 
3398
    var oBodyScrollTimer = this._bodyScrollTimer;
3399
 
3400
 
3401
    if (oBodyScrollTimer) {
3402
 
3403
        oBodyScrollTimer.cancel();
3404
 
3405
    }
3406
 
3407
 
3408
    this._cancelHideDelay();
3409
 
3410
 
3411
    var oTarget = Event.getTarget(p_oEvent),
3412
        oBody = this.body,
3413
        nScrollIncrement = this.cfg.getProperty(_SCROLL_INCREMENT),
3414
        nScrollTarget,
3415
        fnScrollFunction;
3416
 
3417
 
3418
    function scrollBodyDown() {
3419
 
3420
        var nScrollTop = oBody.scrollTop;
3421
 
3422
 
3423
        if (nScrollTop < nScrollTarget) {
3424
 
3425
            oBody.scrollTop = (nScrollTop + nScrollIncrement);
3426
 
3427
            this._enableScrollHeader();
3428
 
3429
        }
3430
        else {
3431
 
3432
            oBody.scrollTop = nScrollTarget;
3433
 
3434
            this._bodyScrollTimer.cancel();
3435
 
3436
            this._disableScrollFooter();
3437
 
3438
        }
3439
 
3440
    }
3441
 
3442
 
3443
    function scrollBodyUp() {
3444
 
3445
        var nScrollTop = oBody.scrollTop;
3446
 
3447
 
3448
        if (nScrollTop > 0) {
3449
 
3450
            oBody.scrollTop = (nScrollTop - nScrollIncrement);
3451
 
3452
            this._enableScrollFooter();
3453
 
3454
        }
3455
        else {
3456
 
3457
            oBody.scrollTop = 0;
3458
 
3459
            this._bodyScrollTimer.cancel();
3460
 
3461
            this._disableScrollHeader();
3462
 
3463
        }
3464
 
3465
    }
3466
 
3467
 
3468
    if (Dom.hasClass(oTarget, _HD)) {
3469
 
3470
        fnScrollFunction = scrollBodyUp;
3471
 
3472
    }
3473
    else {
3474
 
3475
        nScrollTarget = oBody.scrollHeight - oBody.offsetHeight;
3476
 
3477
        fnScrollFunction = scrollBodyDown;
3478
 
3479
    }
3480
 
3481
 
3482
    this._bodyScrollTimer = Lang.later(10, this, fnScrollFunction, null, true);
3483
 
3484
},
3485
 
3486
 
3487
/**
3488
* @method _onScrollTargetMouseOut
3489
* @description "mouseout" event handler for the menu's "header" and "footer"
3490
* elements.  Used to stop scrolling the body of the menu up and down when the
3491
* menu's "maxheight" configuration property is set to a value greater than 0.
3492
* @protected
3493
* @param {Event} p_oEvent Object representing the DOM event object passed
3494
* back by the event utility (YAHOO.util.Event).
3495
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
3496
* fired the event.
3497
*/
3498
_onScrollTargetMouseOut: function (p_oEvent, p_oMenu) {
3499
 
3500
    var oBodyScrollTimer = this._bodyScrollTimer;
3501
 
3502
    if (oBodyScrollTimer) {
3503
 
3504
        oBodyScrollTimer.cancel();
3505
 
3506
    }
3507
 
3508
    this._cancelHideDelay();
3509
 
3510
},
3511
 
3512
 
3513
 
3514
// Private methods
3515
 
3516
 
3517
/**
3518
* @method _onInit
3519
* @description "init" event handler for the menu.
3520
* @private
3521
* @param {String} p_sType String representing the name of the event that
3522
* was fired.
3523
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
3524
*/
3525
_onInit: function (p_sType, p_aArgs) {
3526
 
3527
    this.cfg.subscribeToConfigEvent(_VISIBLE, this._onVisibleChange);
3528
 
3529
    var bRootMenu = !this.parent,
3530
        bLazyLoad = this.lazyLoad;
3531
 
3532
 
3533
    /*
3534
        Automatically initialize a menu's subtree if:
3535
 
3536
        1) This is the root menu and lazyload is off
3537
 
3538
        2) This is the root menu, lazyload is on, but the menu is
3539
           already visible
3540
 
3541
        3) This menu is a submenu and lazyload is off
3542
    */
3543
 
3544
 
3545
 
3546
    if (((bRootMenu && !bLazyLoad) ||
3547
        (bRootMenu && (this.cfg.getProperty(_VISIBLE) ||
3548
        this.cfg.getProperty(_POSITION) == _STATIC)) ||
3549
        (!bRootMenu && !bLazyLoad)) && this.getItemGroups().length === 0) {
3550
 
3551
        if (this.srcElement) {
3552
 
3553
            this._initSubTree();
3554
 
3555
        }
3556
 
3557
 
3558
        if (this.itemData) {
3559
 
3560
            this.addItems(this.itemData);
3561
 
3562
        }
3563
 
3564
    }
3565
    else if (bLazyLoad) {
3566
 
3567
        this.cfg.fireQueue();
3568
 
3569
    }
3570
 
3571
},
3572
 
3573
 
3574
/**
3575
* @method _onBeforeRender
3576
* @description "beforerender" event handler for the menu.  Appends all of the
3577
* <code>&#60;ul&#62;</code>, <code>&#60;li&#62;</code> and their accompanying
3578
* title elements to the body element of the menu.
3579
* @private
3580
* @param {String} p_sType String representing the name of the event that
3581
* was fired.
3582
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
3583
*/
3584
_onBeforeRender: function (p_sType, p_aArgs) {
3585
 
3586
    var oEl = this.element,
3587
        nListElements = this._aListElements.length,
3588
        bFirstList = true,
3589
        i = 0,
3590
        oUL,
3591
        oGroupTitle;
3592
 
3593
    if (nListElements > 0) {
3594
 
3595
        do {
3596
 
3597
            oUL = this._aListElements[i];
3598
 
3599
            if (oUL) {
3600
 
3601
                if (bFirstList) {
3602
 
3603
                    Dom.addClass(oUL, _FIRST_OF_TYPE);
3604
                    bFirstList = false;
3605
 
3606
                }
3607
 
3608
 
3609
                if (!Dom.isAncestor(oEl, oUL)) {
3610
 
3611
                    this.appendToBody(oUL);
3612
 
3613
                }
3614
 
3615
 
3616
                oGroupTitle = this._aGroupTitleElements[i];
3617
 
3618
                if (oGroupTitle) {
3619
 
3620
                    if (!Dom.isAncestor(oEl, oGroupTitle)) {
3621
 
3622
                        oUL.parentNode.insertBefore(oGroupTitle, oUL);
3623
 
3624
                    }
3625
 
3626
 
3627
                    Dom.addClass(oUL, _HAS_TITLE);
3628
 
3629
                }
3630
 
3631
            }
3632
 
3633
            i++;
3634
 
3635
        }
3636
        while (i < nListElements);
3637
 
3638
    }
3639
 
3640
},
3641
 
3642
 
3643
/**
3644
* @method _onRender
3645
* @description "render" event handler for the menu.
3646
* @private
3647
* @param {String} p_sType String representing the name of the event that
3648
* was fired.
3649
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
3650
*/
3651
_onRender: function (p_sType, p_aArgs) {
3652
 
3653
    if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3654
 
3655
        if (!this.cfg.getProperty(_VISIBLE)) {
3656
 
3657
            this.positionOffScreen();
3658
 
3659
        }
3660
 
3661
    }
3662
 
3663
},
3664
 
3665
 
3666
 
3667
 
3668
 
3669
/**
3670
* @method _onBeforeShow
3671
* @description "beforeshow" event handler for the menu.
3672
* @private
3673
* @param {String} p_sType String representing the name of the event that
3674
* was fired.
3675
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
3676
*/
3677
_onBeforeShow: function (p_sType, p_aArgs) {
3678
 
3679
    var nOptions,
3680
        n,
3681
        oSrcElement,
3682
        oContainer = this.cfg.getProperty(_CONTAINER);
3683
 
3684
 
3685
    if (this.lazyLoad && this.getItemGroups().length === 0) {
3686
 
3687
        if (this.srcElement) {
3688
 
3689
            this._initSubTree();
3690
 
3691
        }
3692
 
3693
 
3694
        if (this.itemData) {
3695
 
3696
            if (this.parent && this.parent.parent &&
3697
                this.parent.parent.srcElement &&
3698
                this.parent.parent.srcElement.tagName.toUpperCase() ==
3699
                _SELECT) {
3700
 
3701
                nOptions = this.itemData.length;
3702
 
3703
                for(n=0; n<nOptions; n++) {
3704
 
3705
                    if (this.itemData[n].tagName) {
3706
 
3707
                        this.addItem((new this.ITEM_TYPE(this.itemData[n])));
3708
 
3709
                    }
3710
 
3711
                }
3712
 
3713
            }
3714
            else {
3715
 
3716
                this.addItems(this.itemData);
3717
 
3718
            }
3719
 
3720
        }
3721
 
3722
 
3723
        oSrcElement = this.srcElement;
3724
 
3725
        if (oSrcElement) {
3726
 
3727
            if (oSrcElement.tagName.toUpperCase() == _SELECT) {
3728
 
3729
                if (Dom.inDocument(oSrcElement)) {
3730
 
3731
                    this.render(oSrcElement.parentNode);
3732
 
3733
                }
3734
                else {
3735
 
3736
                    this.render(oContainer);
3737
 
3738
                }
3739
 
3740
            }
3741
            else {
3742
 
3743
                this.render();
3744
 
3745
            }
3746
 
3747
        }
3748
        else {
3749
 
3750
            if (this.parent) {
3751
 
3752
                this.render(this.parent.element);
3753
 
3754
            }
3755
            else {
3756
 
3757
                this.render(oContainer);
3758
 
3759
            }
3760
 
3761
        }
3762
 
3763
    }
3764
 
3765
 
3766
 
3767
    var oParent = this.parent,
3768
        aAlignment;
3769
 
3770
 
3771
    if (!oParent && this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3772
 
3773
        this.cfg.refireEvent(_XY);
3774
 
3775
    }
3776
 
3777
 
3778
    if (oParent) {
3779
 
3780
        aAlignment = oParent.parent.cfg.getProperty(_SUBMENU_ALIGNMENT);
3781
 
3782
        this.cfg.setProperty(_CONTEXT, [oParent.element, aAlignment[0], aAlignment[1]]);
3783
        this.align();
3784
 
3785
    }
3786
 
3787
},
3788
 
3789
 
3790
getConstrainedY: function (y) {
3791
 
3792
    var oMenu = this,
3793
 
3794
        aContext = oMenu.cfg.getProperty(_CONTEXT),
3795
        nInitialMaxHeight = oMenu.cfg.getProperty(_MAX_HEIGHT),
3796
 
3797
        nMaxHeight,
3798
 
3799
        oOverlapPositions = {
3800
 
3801
            "trbr": true,
3802
            "tlbl": true,
3803
            "bltl": true,
3804
            "brtr": true
3805
 
3806
        },
3807
 
3808
        bPotentialContextOverlap = (aContext && oOverlapPositions[aContext[1] + aContext[2]]),
3809
 
3810
        oMenuEl = oMenu.element,
3811
        nMenuOffsetHeight = oMenuEl.offsetHeight,
3812
 
3813
        nViewportOffset = Overlay.VIEWPORT_OFFSET,
3814
        viewPortHeight = Dom.getViewportHeight(),
3815
        scrollY = Dom.getDocumentScrollTop(),
3816
 
3817
        bCanConstrain =
3818
            (oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT) + nViewportOffset < viewPortHeight),
3819
 
3820
        nAvailableHeight,
3821
 
3822
        oContextEl,
3823
        nContextElY,
3824
        nContextElHeight,
3825
 
3826
        bFlipped = false,
3827
 
3828
        nTopRegionHeight,
3829
        nBottomRegionHeight,
3830
 
3831
        topConstraint = scrollY + nViewportOffset,
3832
        bottomConstraint = scrollY + viewPortHeight - nMenuOffsetHeight - nViewportOffset,
3833
 
3834
        yNew = y;
3835
 
3836
 
3837
    var flipVertical = function () {
3838
 
3839
        var nNewY;
3840
 
3841
        // The Menu is below the context element, flip it above
3842
        if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
3843
            nNewY = (nContextElY - nMenuOffsetHeight);
3844
        }
3845
        else {	// The Menu is above the context element, flip it below
3846
            nNewY = (nContextElY + nContextElHeight);
3847
        }
3848
 
3849
        oMenu.cfg.setProperty(_Y, (nNewY + scrollY), true);
3850
 
3851
        return nNewY;
3852
 
3853
    };
3854
 
3855
 
3856
    /*
3857
         Uses the context element's position to calculate the availble height
3858
         above and below it to display its corresponding Menu.
3859
    */
3860
 
3861
    var getDisplayRegionHeight = function () {
3862
 
3863
        // The Menu is below the context element
3864
        if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
3865
            return (nBottomRegionHeight - nViewportOffset);
3866
        }
3867
        else {	// The Menu is above the context element
3868
            return (nTopRegionHeight - nViewportOffset);
3869
        }
3870
 
3871
    };
3872
 
3873
 
3874
    /*
3875
        Sets the Menu's "y" configuration property to the correct value based on its
3876
        current orientation.
3877
    */
3878
 
3879
    var alignY = function () {
3880
 
3881
        var nNewY;
3882
 
3883
        if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
3884
            nNewY = (nContextElY + nContextElHeight);
3885
        }
3886
        else {
3887
            nNewY = (nContextElY - oMenuEl.offsetHeight);
3888
        }
3889
 
3890
        oMenu.cfg.setProperty(_Y, (nNewY + scrollY), true);
3891
 
3892
    };
3893
 
3894
 
3895
    //	Resets the maxheight of the Menu to the value set by the user
3896
 
3897
    var resetMaxHeight = function () {
3898
 
3899
        oMenu._setScrollHeight(this.cfg.getProperty(_MAX_HEIGHT));
3900
 
3901
        oMenu.hideEvent.unsubscribe(resetMaxHeight);
3902
 
3903
    };
3904
 
3905
 
3906
    /*
3907
        Trys to place the Menu in the best possible position (either above or
3908
        below its corresponding context element).
3909
    */
3910
 
3911
    var setVerticalPosition = function () {
3912
 
3913
        var nDisplayRegionHeight = getDisplayRegionHeight(),
3914
            bMenuHasItems = (oMenu.getItems().length > 0),
3915
            nMenuMinScrollHeight,
3916
            fnReturnVal;
3917
 
3918
 
3919
        if (nMenuOffsetHeight > nDisplayRegionHeight) {
3920
 
3921
            nMenuMinScrollHeight =
3922
                bMenuHasItems ? oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT) : nMenuOffsetHeight;
3923
 
3924
 
3925
            if ((nDisplayRegionHeight > nMenuMinScrollHeight) && bMenuHasItems) {
3926
                nMaxHeight = nDisplayRegionHeight;
3927
            }
3928
            else {
3929
                nMaxHeight = nInitialMaxHeight;
3930
            }
3931
 
3932
 
3933
            oMenu._setScrollHeight(nMaxHeight);
3934
            oMenu.hideEvent.subscribe(resetMaxHeight);
3935
 
3936
 
3937
            // Re-align the Menu since its height has just changed
3938
            // as a result of the setting of the maxheight property.
3939
 
3940
            alignY();
3941
 
3942
 
3943
            if (nDisplayRegionHeight < nMenuMinScrollHeight) {
3944
 
3945
                if (bFlipped) {
3946
 
3947
                    /*
3948
                         All possible positions and values for the "maxheight"
3949
                         configuration property have been tried, but none were
3950
                         successful, so fall back to the original size and position.
3951
                    */
3952
 
3953
                    flipVertical();
3954
 
3955
                }
3956
                else {
3957
 
3958
                    flipVertical();
3959
 
3960
                    bFlipped = true;
3961
 
3962
                    fnReturnVal = setVerticalPosition();
3963
 
3964
                }
3965
 
3966
            }
3967
 
3968
        }
3969
        else if (nMaxHeight && (nMaxHeight !== nInitialMaxHeight)) {
3970
 
3971
            oMenu._setScrollHeight(nInitialMaxHeight);
3972
            oMenu.hideEvent.subscribe(resetMaxHeight);
3973
 
3974
            // Re-align the Menu since its height has just changed
3975
            // as a result of the setting of the maxheight property.
3976
 
3977
            alignY();
3978
 
3979
        }
3980
 
3981
        return fnReturnVal;
3982
 
3983
    };
3984
 
3985
 
3986
    // Determine if the current value for the Menu's "y" configuration property will
3987
    // result in the Menu being positioned outside the boundaries of the viewport
3988
 
3989
    if (y < topConstraint || y  > bottomConstraint) {
3990
 
3991
        // 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 (bCanConstrain) {
3995
 
3996
            if (oMenu.cfg.getProperty(_PREVENT_CONTEXT_OVERLAP) && bPotentialContextOverlap) {
3997
 
3998
                //	SOLUTION #1:
3999
                //	If the "preventcontextoverlap" configuration property is set to "true",
4000
                //	try to flip and/or scroll the Menu to both keep it inside the boundaries of the
4001
                //	viewport AND from overlaping its context element (MenuItem or MenuBarItem).
4002
 
4003
                oContextEl = aContext[0];
4004
                nContextElHeight = oContextEl.offsetHeight;
4005
                nContextElY = (Dom.getY(oContextEl) - scrollY);
4006
 
4007
                nTopRegionHeight = nContextElY;
4008
                nBottomRegionHeight = (viewPortHeight - (nContextElY + nContextElHeight));
4009
 
4010
                setVerticalPosition();
4011
 
4012
                yNew = oMenu.cfg.getProperty(_Y);
4013
 
4014
            }
4015
            else if (!(oMenu instanceof YAHOO.widget.MenuBar) &&
4016
                nMenuOffsetHeight >= viewPortHeight) {
4017
 
4018
                //	SOLUTION #2:
4019
                //	If the Menu exceeds the height of the viewport, introduce scroll bars
4020
                //	to keep the Menu inside the boundaries of the viewport
4021
 
4022
                nAvailableHeight = (viewPortHeight - (nViewportOffset * 2));
4023
 
4024
                if (nAvailableHeight > oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT)) {
4025
 
4026
                    oMenu._setScrollHeight(nAvailableHeight);
4027
                    oMenu.hideEvent.subscribe(resetMaxHeight);
4028
 
4029
                    alignY();
4030
 
4031
                    yNew = oMenu.cfg.getProperty(_Y);
4032
 
4033
                }
4034
 
4035
            }
4036
            else {
4037
 
4038
                //	SOLUTION #3:
4039
 
4040
                if (y < topConstraint) {
4041
                    yNew  = topConstraint;
4042
                } else if (y  > bottomConstraint) {
4043
                    yNew  = bottomConstraint;
4044
                }
4045
 
4046
            }
4047
 
4048
        }
4049
        else {
4050
            //	The "y" configuration property cannot be set to a value that will keep
4051
            //	entire Menu inside the boundary of the viewport.  Therefore, set
4052
            //	the "y" configuration property to scrollY to keep as much of the
4053
            //	Menu inside the viewport as possible.
4054
            yNew = nViewportOffset + scrollY;
4055
        }
4056
 
4057
    }
4058
 
4059
    return yNew;
4060
 
4061
},
4062
 
4063
 
4064
/**
4065
* @method _onHide
4066
* @description "hide" event handler for the menu.
4067
* @private
4068
* @param {String} p_sType String representing the name of the event that
4069
* was fired.
4070
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4071
*/
4072
_onHide: function (p_sType, p_aArgs) {
4073
 
4074
    if (this.cfg.getProperty(_POSITION) === _DYNAMIC) {
4075
 
4076
        this.positionOffScreen();
4077
 
4078
    }
4079
 
4080
},
4081
 
4082
 
4083
/**
4084
* @method _onShow
4085
* @description "show" event handler for the menu.
4086
* @private
4087
* @param {String} p_sType String representing the name of the event that
4088
* was fired.
4089
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4090
*/
4091
_onShow: function (p_sType, p_aArgs) {
4092
 
4093
    var oParent = this.parent,
4094
        oParentMenu,
4095
        oElement,
4096
        nOffsetWidth,
4097
        sWidth;
4098
 
4099
 
4100
    function disableAutoSubmenuDisplay(p_oEvent) {
4101
 
4102
        var oTarget;
4103
 
4104
        if (p_oEvent.type == _MOUSEDOWN || (p_oEvent.type == _KEYDOWN && p_oEvent.keyCode == 27)) {
4105
 
4106
            /*
4107
                Set the "autosubmenudisplay" to "false" if the user
4108
                clicks outside the menu bar.
4109
            */
4110
 
4111
            oTarget = Event.getTarget(p_oEvent);
4112
 
4113
            if (oTarget != oParentMenu.element || !Dom.isAncestor(oParentMenu.element, oTarget)) {
4114
 
4115
                oParentMenu.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, false);
4116
 
4117
                Event.removeListener(document, _MOUSEDOWN, disableAutoSubmenuDisplay);
4118
                Event.removeListener(document, _KEYDOWN, disableAutoSubmenuDisplay);
4119
 
4120
            }
4121
 
4122
        }
4123
 
4124
    }
4125
 
4126
 
4127
    function onSubmenuHide(p_sType, p_aArgs, p_sWidth) {
4128
 
4129
        this.cfg.setProperty(_WIDTH, _EMPTY_STRING);
4130
        this.hideEvent.unsubscribe(onSubmenuHide, p_sWidth);
4131
 
4132
    }
4133
 
4134
 
4135
    if (oParent) {
4136
 
4137
        oParentMenu = oParent.parent;
4138
 
4139
 
4140
        if (!oParentMenu.cfg.getProperty(_AUTO_SUBMENU_DISPLAY) &&
4141
            (oParentMenu instanceof YAHOO.widget.MenuBar ||
4142
            oParentMenu.cfg.getProperty(_POSITION) == _STATIC)) {
4143
 
4144
            oParentMenu.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, true);
4145
 
4146
            Event.on(document, _MOUSEDOWN, disableAutoSubmenuDisplay);
4147
            Event.on(document, _KEYDOWN, disableAutoSubmenuDisplay);
4148
 
4149
        }
4150
 
4151
 
4152
        //	The following fixes an issue with the selected state of a MenuItem
4153
        //	not rendering correctly when a submenu is aligned to the left of
4154
        //	its parent Menu instance.
4155
 
4156
        if ((this.cfg.getProperty("x") < oParentMenu.cfg.getProperty("x")) &&
4157
            (UA.gecko && UA.gecko < 1.9) && !this.cfg.getProperty(_WIDTH)) {
4158
 
4159
            oElement = this.element;
4160
            nOffsetWidth = oElement.offsetWidth;
4161
 
4162
            /*
4163
                Measuring the difference of the offsetWidth before and after
4164
                setting the "width" style attribute allows us to compute the
4165
                about of padding and borders applied to the element, which in
4166
                turn allows us to set the "width" property correctly.
4167
            */
4168
 
4169
            oElement.style.width = nOffsetWidth + _PX;
4170
 
4171
            sWidth = (nOffsetWidth - (oElement.offsetWidth - nOffsetWidth)) + _PX;
4172
 
4173
            this.cfg.setProperty(_WIDTH, sWidth);
4174
 
4175
            this.hideEvent.subscribe(onSubmenuHide, sWidth);
4176
 
4177
        }
4178
 
4179
    }
4180
 
4181
 
4182
    /*
4183
        Dynamically positioned, root Menus focus themselves when visible, and
4184
        will then, when hidden, restore focus to the UI control that had focus
4185
        before the Menu was made visible.
4186
    */
4187
 
4188
    if (this === this.getRoot() && this.cfg.getProperty(_POSITION) === _DYNAMIC) {
4189
 
4190
        this._focusedElement = oFocusedElement;
4191
 
4192
        this.focus();
4193
 
4194
    }
4195
 
4196
 
4197
},
4198
 
4199
 
4200
/**
4201
* @method _onBeforeHide
4202
* @description "beforehide" event handler for the menu.
4203
* @private
4204
* @param {String} p_sType String representing the name of the event that
4205
* was fired.
4206
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4207
*/
4208
_onBeforeHide: function (p_sType, p_aArgs) {
4209
 
4210
    var oActiveItem = this.activeItem,
4211
        oRoot = this.getRoot(),
4212
        oConfig,
4213
        oSubmenu;
4214
 
4215
 
4216
    if (oActiveItem) {
4217
 
4218
        oConfig = oActiveItem.cfg;
4219
 
4220
        oConfig.setProperty(_SELECTED, false);
4221
 
4222
        oSubmenu = oConfig.getProperty(_SUBMENU);
4223
 
4224
        if (oSubmenu) {
4225
 
4226
            oSubmenu.hide();
4227
 
4228
        }
4229
 
4230
    }
4231
 
4232
 
4233
    /*
4234
        Focus can get lost in IE when the mouse is moving from a submenu back to its parent Menu.
4235
        For this reason, it is necessary to maintain the focused state in a private property
4236
        so that the _onMouseOver event handler is able to determined whether or not to set focus
4237
        to MenuItems as the user is moving the mouse.
4238
    */
4239
 
4240
    if (UA.ie && this.cfg.getProperty(_POSITION) === _DYNAMIC && this.parent) {
4241
 
4242
        oRoot._hasFocus = this.hasFocus();
4243
 
4244
    }
4245
 
4246
 
4247
    if (oRoot == this) {
4248
 
4249
        oRoot.blur();
4250
 
4251
    }
4252
 
4253
},
4254
 
4255
 
4256
/**
4257
* @method _onParentMenuConfigChange
4258
* @description "configchange" event handler for a submenu.
4259
* @private
4260
* @param {String} p_sType String representing the name of the event that
4261
* was fired.
4262
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4263
* @param {YAHOO.widget.Menu} p_oSubmenu Object representing the submenu that
4264
* subscribed to the event.
4265
*/
4266
_onParentMenuConfigChange: function (p_sType, p_aArgs, p_oSubmenu) {
4267
 
4268
    var sPropertyName = p_aArgs[0][0],
4269
        oPropertyValue = p_aArgs[0][1];
4270
 
4271
    switch(sPropertyName) {
4272
 
4273
        case _IFRAME:
4274
        case _CONSTRAIN_TO_VIEWPORT:
4275
        case _HIDE_DELAY:
4276
        case _SHOW_DELAY:
4277
        case _SUBMENU_HIDE_DELAY:
4278
        case _CLICK_TO_HIDE:
4279
        case _EFFECT:
4280
        case _CLASSNAME:
4281
        case _SCROLL_INCREMENT:
4282
        case _MAX_HEIGHT:
4283
        case _MIN_SCROLL_HEIGHT:
4284
        case _MONITOR_RESIZE:
4285
        case _SHADOW:
4286
        case _PREVENT_CONTEXT_OVERLAP:
4287
        case _KEEP_OPEN:
4288
 
4289
            p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue);
4290
 
4291
        break;
4292
 
4293
        case _SUBMENU_ALIGNMENT:
4294
 
4295
            if (!(this.parent.parent instanceof YAHOO.widget.MenuBar)) {
4296
 
4297
                p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue);
4298
 
4299
            }
4300
 
4301
        break;
4302
 
4303
    }
4304
 
4305
},
4306
 
4307
 
4308
/**
4309
* @method _onParentMenuRender
4310
* @description "render" event handler for a submenu.  Renders a
4311
* submenu in response to the firing of its parent's "render" event.
4312
* @private
4313
* @param {String} p_sType String representing the name of the event that
4314
* was fired.
4315
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4316
* @param {YAHOO.widget.Menu} p_oSubmenu Object representing the submenu that
4317
* subscribed to the event.
4318
*/
4319
_onParentMenuRender: function (p_sType, p_aArgs, p_oSubmenu) {
4320
 
4321
    var oParentMenu = p_oSubmenu.parent.parent,
4322
        oParentCfg = oParentMenu.cfg,
4323
 
4324
        oConfig = {
4325
 
4326
            constraintoviewport: oParentCfg.getProperty(_CONSTRAIN_TO_VIEWPORT),
4327
 
4328
            xy: [0,0],
4329
 
4330
            clicktohide: oParentCfg.getProperty(_CLICK_TO_HIDE),
4331
 
4332
            effect: oParentCfg.getProperty(_EFFECT),
4333
 
4334
            showdelay: oParentCfg.getProperty(_SHOW_DELAY),
4335
 
4336
            hidedelay: oParentCfg.getProperty(_HIDE_DELAY),
4337
 
4338
            submenuhidedelay: oParentCfg.getProperty(_SUBMENU_HIDE_DELAY),
4339
 
4340
            classname: oParentCfg.getProperty(_CLASSNAME),
4341
 
4342
            scrollincrement: oParentCfg.getProperty(_SCROLL_INCREMENT),
4343
 
4344
            maxheight: oParentCfg.getProperty(_MAX_HEIGHT),
4345
 
4346
            minscrollheight: oParentCfg.getProperty(_MIN_SCROLL_HEIGHT),
4347
 
4348
            iframe: oParentCfg.getProperty(_IFRAME),
4349
 
4350
            shadow: oParentCfg.getProperty(_SHADOW),
4351
 
4352
            preventcontextoverlap: oParentCfg.getProperty(_PREVENT_CONTEXT_OVERLAP),
4353
 
4354
            monitorresize: oParentCfg.getProperty(_MONITOR_RESIZE),
4355
 
4356
            keepopen: oParentCfg.getProperty(_KEEP_OPEN)
4357
 
4358
        },
4359
 
4360
        oLI;
4361
 
4362
 
4363
 
4364
    if (!(oParentMenu instanceof YAHOO.widget.MenuBar)) {
4365
 
4366
        oConfig[_SUBMENU_ALIGNMENT] = oParentCfg.getProperty(_SUBMENU_ALIGNMENT);
4367
 
4368
    }
4369
 
4370
 
4371
    p_oSubmenu.cfg.applyConfig(oConfig);
4372
 
4373
 
4374
    if (!this.lazyLoad) {
4375
 
4376
        oLI = this.parent.element;
4377
 
4378
        if (this.element.parentNode == oLI) {
4379
 
4380
            this.render();
4381
 
4382
        }
4383
        else {
4384
 
4385
            this.render(oLI);
4386
 
4387
        }
4388
 
4389
    }
4390
 
4391
},
4392
 
4393
 
4394
/**
4395
* @method _onMenuItemDestroy
4396
* @description "destroy" event handler for the menu's items.
4397
* @private
4398
* @param {String} p_sType String representing the name of the event
4399
* that was fired.
4400
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4401
* @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
4402
* that fired the event.
4403
*/
4404
_onMenuItemDestroy: function (p_sType, p_aArgs, p_oItem) {
4405
 
4406
    this._removeItemFromGroupByValue(p_oItem.groupIndex, p_oItem);
4407
 
4408
},
4409
 
4410
 
4411
/**
4412
* @method _onMenuItemConfigChange
4413
* @description "configchange" event handler for the menu's items.
4414
* @private
4415
* @param {String} p_sType String representing the name of the event that
4416
* was fired.
4417
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4418
* @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
4419
* that fired the event.
4420
*/
4421
_onMenuItemConfigChange: function (p_sType, p_aArgs, p_oItem) {
4422
 
4423
    var sPropertyName = p_aArgs[0][0],
4424
        oPropertyValue = p_aArgs[0][1],
4425
        oSubmenu;
4426
 
4427
 
4428
    switch(sPropertyName) {
4429
 
4430
        case _SELECTED:
4431
 
4432
            if (oPropertyValue === true) {
4433
 
4434
                this.activeItem = p_oItem;
4435
 
4436
            }
4437
 
4438
        break;
4439
 
4440
        case _SUBMENU:
4441
 
4442
            oSubmenu = p_aArgs[0][1];
4443
 
4444
            if (oSubmenu) {
4445
 
4446
                this._configureSubmenu(p_oItem);
4447
 
4448
            }
4449
 
4450
        break;
4451
 
4452
    }
4453
 
4454
},
4455
 
4456
 
4457
 
4458
// Public event handlers for configuration properties
4459
 
4460
 
4461
/**
4462
* @method configVisible
4463
* @description Event handler for when the "visible" configuration property
4464
* the menu changes.
4465
* @param {String} p_sType String representing the name of the event that
4466
* was fired.
4467
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4468
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4469
* fired the event.
4470
*/
4471
configVisible: function (p_sType, p_aArgs, p_oMenu) {
4472
 
4473
    var bVisible,
4474
        sDisplay;
4475
 
4476
    if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
4477
 
4478
        Menu.superclass.configVisible.call(this, p_sType, p_aArgs, p_oMenu);
4479
 
4480
    }
4481
    else {
4482
 
4483
        bVisible = p_aArgs[0];
4484
        sDisplay = Dom.getStyle(this.element, _DISPLAY);
4485
 
4486
        Dom.setStyle(this.element, _VISIBILITY, _VISIBLE);
4487
 
4488
        if (bVisible) {
4489
 
4490
            if (sDisplay != _BLOCK) {
4491
                this.beforeShowEvent.fire();
4492
                Dom.setStyle(this.element, _DISPLAY, _BLOCK);
4493
                this.showEvent.fire();
4494
            }
4495
 
4496
        }
4497
        else {
4498
 
4499
            if (sDisplay == _BLOCK) {
4500
                this.beforeHideEvent.fire();
4501
                Dom.setStyle(this.element, _DISPLAY, _NONE);
4502
                this.hideEvent.fire();
4503
            }
4504
 
4505
        }
4506
 
4507
    }
4508
 
4509
},
4510
 
4511
 
4512
/**
4513
* @method configPosition
4514
* @description Event handler for when the "position" configuration property
4515
* of the menu changes.
4516
* @param {String} p_sType String representing the name of the event that
4517
* was fired.
4518
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4519
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4520
* fired the event.
4521
*/
4522
configPosition: function (p_sType, p_aArgs, p_oMenu) {
4523
 
4524
    var oElement = this.element,
4525
        sCSSPosition = p_aArgs[0] == _STATIC ? _STATIC : _ABSOLUTE,
4526
        oCfg = this.cfg,
4527
        nZIndex;
4528
 
4529
 
4530
    Dom.setStyle(oElement, _POSITION, sCSSPosition);
4531
 
4532
 
4533
    if (sCSSPosition == _STATIC) {
4534
 
4535
        // Statically positioned menus are visible by default
4536
 
4537
        Dom.setStyle(oElement, _DISPLAY, _BLOCK);
4538
 
4539
        oCfg.setProperty(_VISIBLE, true);
4540
 
4541
    }
4542
    else {
4543
 
4544
        /*
4545
            Even though the "visible" property is queued to
4546
            "false" by default, we need to set the "visibility" property to
4547
            "hidden" since Overlay's "configVisible" implementation checks the
4548
            element's "visibility" style property before deciding whether
4549
            or not to show an Overlay instance.
4550
        */
4551
 
4552
        Dom.setStyle(oElement, _VISIBILITY, _HIDDEN);
4553
 
4554
    }
4555
 
4556
 
4557
     if (sCSSPosition == _ABSOLUTE) {
4558
         nZIndex = oCfg.getProperty(_ZINDEX);
4559
 
4560
         if (!nZIndex || nZIndex === 0) {
4561
             oCfg.setProperty(_ZINDEX, 1);
4562
         }
4563
 
4564
     }
4565
 
4566
},
4567
 
4568
 
4569
/**
4570
* @method configIframe
4571
* @description Event handler for when the "iframe" configuration property of
4572
* the menu changes.
4573
* @param {String} p_sType String representing the name of the event that
4574
* was fired.
4575
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4576
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4577
* fired the event.
4578
*/
4579
configIframe: function (p_sType, p_aArgs, p_oMenu) {
4580
 
4581
    if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
4582
 
4583
        Menu.superclass.configIframe.call(this, p_sType, p_aArgs, p_oMenu);
4584
 
4585
    }
4586
 
4587
},
4588
 
4589
 
4590
/**
4591
* @method configHideDelay
4592
* @description Event handler for when the "hidedelay" configuration property
4593
* of the menu changes.
4594
* @param {String} p_sType String representing the name of the event that
4595
* was fired.
4596
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4597
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4598
* fired the event.
4599
*/
4600
configHideDelay: function (p_sType, p_aArgs, p_oMenu) {
4601
 
4602
    var nHideDelay = p_aArgs[0];
4603
 
4604
    this._useHideDelay = (nHideDelay > 0);
4605
 
4606
},
4607
 
4608
 
4609
/**
4610
* @method configContainer
4611
* @description Event handler for when the "container" configuration property
4612
* of the menu changes.
4613
* @param {String} p_sType String representing the name of the event that
4614
* was fired.
4615
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
4616
* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4617
* fired the event.
4618
*/
4619
configContainer: function (p_sType, p_aArgs, p_oMenu) {
4620
 
4621
    var oElement = p_aArgs[0];
4622
 
4623
    if (Lang.isString(oElement)) {
4624
 
4625
        this.cfg.setProperty(_CONTAINER, Dom.get(oElement), true);
4626
 
4627
    }
4628
 
4629
},
4630
 
4631
 
4632
/**
4633
* @method _clearSetWidthFlag
4634
* @description Change event listener for the "width" configuration property.  This listener is
4635
* added when a Menu's "width" configuration property is set by the "_setScrollHeight" method, and
4636
* is used to set the "_widthSetForScroll" property to "false" if the "width" configuration property
4637
* is changed after it was set by the "_setScrollHeight" method.  If the "_widthSetForScroll"
4638
* property is set to "false", and the "_setScrollHeight" method is in the process of tearing down
4639
* scrolling functionality, it will maintain the Menu's new width rather than reseting it.
4640
* @private
4641
*/
4642
_clearSetWidthFlag: function () {
4643
 
4644
    this._widthSetForScroll = false;
4645
 
4646
    this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4647
 
4648
},
4649
 
4650
/**
4651
 * @method _subscribeScrollHandlers
4652
 * @param {HTMLElement} oHeader The scroll header element
4653
 * @param {HTMLElement} oFooter The scroll footer element
4654
 */
4655
_subscribeScrollHandlers : function(oHeader, oFooter) {
4656
    var fnMouseOver = this._onScrollTargetMouseOver;
4657
    var fnMouseOut = this._onScrollTargetMouseOut;
4658
 
4659
    Event.on(oHeader, _MOUSEOVER, fnMouseOver, this, true);
4660
    Event.on(oHeader, _MOUSEOUT, fnMouseOut, this, true);
4661
    Event.on(oFooter, _MOUSEOVER, fnMouseOver, this, true);
4662
    Event.on(oFooter, _MOUSEOUT, fnMouseOut, this, true);
4663
},
4664
 
4665
/**
4666
 * @method _unsubscribeScrollHandlers
4667
 * @param {HTMLElement} oHeader The scroll header element
4668
 * @param {HTMLElement} oFooter The scroll footer element
4669
 */
4670
_unsubscribeScrollHandlers : function(oHeader, oFooter) {
4671
    var fnMouseOver = this._onScrollTargetMouseOver;
4672
    var fnMouseOut = this._onScrollTargetMouseOut;
4673
 
4674
    Event.removeListener(oHeader, _MOUSEOVER, fnMouseOver);
4675
    Event.removeListener(oHeader, _MOUSEOUT, fnMouseOut);
4676
    Event.removeListener(oFooter, _MOUSEOVER, fnMouseOver);
4677
    Event.removeListener(oFooter, _MOUSEOUT, fnMouseOut);
4678
},
4679
 
4680
/**
4681
* @method _setScrollHeight
4682
* @description
4683
* @param {String} p_nScrollHeight Number representing the scrolling height of the Menu.
4684
* @private
4685
*/
4686
_setScrollHeight: function (p_nScrollHeight) {
4687
 
4688
    var nScrollHeight = p_nScrollHeight,
4689
        bRefireIFrameAndShadow = false,
4690
        bSetWidth = false,
4691
        oElement,
4692
        oBody,
4693
        oHeader,
4694
        oFooter,
4695
        nMinScrollHeight,
4696
        nHeight,
4697
        nOffsetWidth,
4698
        sWidth;
4699
 
4700
    if (this.getItems().length > 0) {
4701
 
4702
        oElement = this.element;
4703
        oBody = this.body;
4704
        oHeader = this.header;
4705
        oFooter = this.footer;
4706
        nMinScrollHeight = this.cfg.getProperty(_MIN_SCROLL_HEIGHT);
4707
 
4708
        if (nScrollHeight > 0 && nScrollHeight < nMinScrollHeight) {
4709
            nScrollHeight = nMinScrollHeight;
4710
        }
4711
 
4712
        Dom.setStyle(oBody, _HEIGHT, _EMPTY_STRING);
4713
        Dom.removeClass(oBody, _YUI_MENU_BODY_SCROLLED);
4714
        oBody.scrollTop = 0;
4715
 
4716
        //	Need to set a width for the Menu to fix the following problems in
4717
        //	Firefox 2 and IE:
4718
 
4719
        //	#1) Scrolled Menus will render at 1px wide in Firefox 2
4720
 
4721
        //	#2) There is a bug in gecko-based browsers where an element whose
4722
        //	"position" property is set to "absolute" and "overflow" property is
4723
        //	set to "hidden" will not render at the correct width when its
4724
        //	offsetParent's "position" property is also set to "absolute."  It is
4725
        //	possible to work around this bug by specifying a value for the width
4726
        //	property in addition to overflow.
4727
 
4728
        //	#3) In IE it is necessary to give the Menu a width before the
4729
        //	scrollbars are rendered to prevent the Menu from rendering with a
4730
        //	width that is 100% of the browser viewport.
4731
 
4732
        bSetWidth = ((UA.gecko && UA.gecko < 1.9) || UA.ie);
4733
 
4734
        if (nScrollHeight > 0 && bSetWidth && !this.cfg.getProperty(_WIDTH)) {
4735
 
4736
            nOffsetWidth = oElement.offsetWidth;
4737
 
4738
            /*
4739
                Measuring the difference of the offsetWidth before and after
4740
                setting the "width" style attribute allows us to compute the
4741
                about of padding and borders applied to the element, which in
4742
                turn allows us to set the "width" property correctly.
4743
            */
4744
 
4745
            oElement.style.width = nOffsetWidth + _PX;
4746
 
4747
            sWidth = (nOffsetWidth - (oElement.offsetWidth - nOffsetWidth)) + _PX;
4748
 
4749
 
4750
            this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4751
 
4752
            YAHOO.log("Setting the \"width\" configuration property to " + sWidth + " for srolling.",
4753
                "info", this.toString());
4754
 
4755
            this.cfg.setProperty(_WIDTH, sWidth);
4756
 
4757
 
4758
            /*
4759
                Set a flag (_widthSetForScroll) to maintain some history regarding how the
4760
                "width" configuration property was set.  If the "width" configuration property
4761
                is set by something other than the "_setScrollHeight" method, it will be
4762
                necessary to maintain that new value and not clear the width if scrolling
4763
                is turned off.
4764
            */
4765
 
4766
            this._widthSetForScroll = true;
4767
 
4768
            this.cfg.subscribeToConfigEvent(_WIDTH, this._clearSetWidthFlag);
4769
 
4770
        }
4771
 
4772
 
4773
        if (nScrollHeight > 0 && (!oHeader && !oFooter)) {
4774
 
4775
            YAHOO.log("Creating header and footer for scrolling.", "info", this.toString());
4776
 
4777
            this.setHeader(_NON_BREAKING_SPACE);
4778
            this.setFooter(_NON_BREAKING_SPACE);
4779
 
4780
            oHeader = this.header;
4781
            oFooter = this.footer;
4782
 
4783
            Dom.addClass(oHeader, _TOP_SCROLLBAR);
4784
            Dom.addClass(oFooter, _BOTTOM_SCROLLBAR);
4785
 
4786
            oElement.insertBefore(oHeader, oBody);
4787
            oElement.appendChild(oFooter);
4788
 
4789
        }
4790
 
4791
        nHeight = nScrollHeight;
4792
 
4793
        if (oHeader && oFooter) {
4794
            nHeight = (nHeight - (oHeader.offsetHeight + oFooter.offsetHeight));
4795
        }
4796
 
4797
 
4798
        if ((nHeight > 0) && (oBody.offsetHeight > nScrollHeight)) {
4799
 
4800
            YAHOO.log("Setting up styles and event handlers for scrolling.",
4801
                "info", this.toString());
4802
 
4803
            Dom.addClass(oBody, _YUI_MENU_BODY_SCROLLED);
4804
            Dom.setStyle(oBody, _HEIGHT, (nHeight + _PX));
4805
 
4806
            if (!this._hasScrollEventHandlers) {
4807
                this._subscribeScrollHandlers(oHeader, oFooter);
4808
                this._hasScrollEventHandlers = true;
4809
            }
4810
 
4811
            this._disableScrollHeader();
4812
            this._enableScrollFooter();
4813
 
4814
            bRefireIFrameAndShadow = true;
4815
 
4816
        }
4817
        else if (oHeader && oFooter) {
4818
 
4819
            YAHOO.log("Removing styles and event handlers for scrolling.", "info", this.toString());
4820
 
4821
 
4822
            /*
4823
                Only clear the the "width" configuration property if it was set the
4824
                "_setScrollHeight" method and wasn't changed by some other means after it was set.
4825
            */
4826
 
4827
            if (this._widthSetForScroll) {
4828
 
4829
                YAHOO.log("Clearing width used for scrolling.", "info", this.toString());
4830
 
4831
                this._widthSetForScroll = false;
4832
 
4833
                this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4834
 
4835
                this.cfg.setProperty(_WIDTH, _EMPTY_STRING);
4836
 
4837
            }
4838
 
4839
 
4840
            this._enableScrollHeader();
4841
            this._enableScrollFooter();
4842
 
4843
            if (this._hasScrollEventHandlers) {
4844
                this._unsubscribeScrollHandlers(oHeader, oFooter);
4845
                this._hasScrollEventHandlers = false;
4846
            }
4847
 
4848
            oElement.removeChild(oHeader);
4849
            oElement.removeChild(oFooter);
4850
 
4851
            this.header = null;
4852
            this.footer = null;
4853
 
4854
            bRefireIFrameAndShadow = true;
4855
 
4856
        }
4857
 
4858
 
4859
        if (bRefireIFrameAndShadow) {
4860
 
4861
            this.cfg.refireEvent(_IFRAME);
4862
            this.cfg.refireEvent(_SHADOW);
4863
 
4864
        }
4865
 
4866
    }
4867
 
4868
},
4869
 
4870
 
4871
/**
4872
* @method _setMaxHeight
4873
* @description "renderEvent" handler used to defer the setting of the
4874
* "maxheight" configuration property until the menu is rendered in lazy
4875
* load scenarios.
4876
* @param {String} p_sType The name of the event that was fired.
4877
* @param {Array} p_aArgs Collection of arguments sent when the event
4878
* was fired.
4879
* @param {Number} p_nMaxHeight Number representing the value to set for the
4880
* "maxheight" configuration property.
4881
* @private
4882
*/
4883
_setMaxHeight: function (p_sType, p_aArgs, p_nMaxHeight) {
4884
 
4885
    this._setScrollHeight(p_nMaxHeight);
4886
    this.renderEvent.unsubscribe(this._setMaxHeight);
4887
 
4888
},
4889
 
4890
 
4891
/**
4892
* @method configMaxHeight
4893
* @description Event handler for when the "maxheight" configuration property of
4894
* a Menu changes.
4895
* @param {String} p_sType The name of the event that was fired.
4896
* @param {Array} p_aArgs Collection of arguments sent when the event
4897
* was fired.
4898
* @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired
4899
* the event.
4900
*/
4901
configMaxHeight: function (p_sType, p_aArgs, p_oMenu) {
4902
 
4903
    var nMaxHeight = p_aArgs[0];
4904
 
4905
    if (this.lazyLoad && !this.body && nMaxHeight > 0) {
4906
 
4907
        this.renderEvent.subscribe(this._setMaxHeight, nMaxHeight, this);
4908
 
4909
    }
4910
    else {
4911
 
4912
        this._setScrollHeight(nMaxHeight);
4913
 
4914
    }
4915
 
4916
},
4917
 
4918
 
4919
/**
4920
* @method configClassName
4921
* @description Event handler for when the "classname" configuration property of
4922
* a menu changes.
4923
* @param {String} p_sType The name of the event that was fired.
4924
* @param {Array} p_aArgs Collection of arguments sent when the event was fired.
4925
* @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
4926
*/
4927
configClassName: function (p_sType, p_aArgs, p_oMenu) {
4928
 
4929
    var sClassName = p_aArgs[0];
4930
 
4931
    if (this._sClassName) {
4932
 
4933
        Dom.removeClass(this.element, this._sClassName);
4934
 
4935
    }
4936
 
4937
    Dom.addClass(this.element, sClassName);
4938
    this._sClassName = sClassName;
4939
 
4940
},
4941
 
4942
 
4943
/**
4944
* @method _onItemAdded
4945
* @description "itemadded" event handler for a Menu instance.
4946
* @private
4947
* @param {String} p_sType The name of the event that was fired.
4948
* @param {Array} p_aArgs Collection of arguments sent when the event
4949
* was fired.
4950
*/
4951
_onItemAdded: function (p_sType, p_aArgs) {
4952
 
4953
    var oItem = p_aArgs[0];
4954
 
4955
    if (oItem) {
4956
 
4957
        oItem.cfg.setProperty(_DISABLED, true);
4958
 
4959
    }
4960
 
4961
},
4962
 
4963
 
4964
/**
4965
* @method configDisabled
4966
* @description Event handler for when the "disabled" configuration property of
4967
* a menu changes.
4968
* @param {String} p_sType The name of the event that was fired.
4969
* @param {Array} p_aArgs Collection of arguments sent when the event was fired.
4970
* @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
4971
*/
4972
configDisabled: function (p_sType, p_aArgs, p_oMenu) {
4973
 
4974
    var bDisabled = p_aArgs[0],
4975
        aItems = this.getItems(),
4976
        nItems,
4977
        i;
4978
 
4979
    if (Lang.isArray(aItems)) {
4980
 
4981
        nItems = aItems.length;
4982
 
4983
        if (nItems > 0) {
4984
 
4985
            i = nItems - 1;
4986
 
4987
            do {
4988
 
4989
                aItems[i].cfg.setProperty(_DISABLED, bDisabled);
4990
 
4991
            }
4992
            while (i--);
4993
 
4994
        }
4995
 
4996
 
4997
        if (bDisabled) {
4998
 
4999
            this.clearActiveItem(true);
5000
 
5001
            Dom.addClass(this.element, _DISABLED);
5002
 
5003
            this.itemAddedEvent.subscribe(this._onItemAdded);
5004
 
5005
        }
5006
        else {
5007
 
5008
            Dom.removeClass(this.element, _DISABLED);
5009
 
5010
            this.itemAddedEvent.unsubscribe(this._onItemAdded);
5011
 
5012
        }
5013
 
5014
    }
5015
 
5016
},
5017
 
5018
/**
5019
 * Resizes the shadow to match the container bounding element
5020
 *
5021
 * @method _sizeShadow
5022
 * @protected
5023
 */
5024
_sizeShadow : function () {
5025
 
5026
    var oElement = this.element,
5027
        oShadow = this._shadow;
5028
 
5029
    if (oShadow && oElement) {
5030
        // Clear the previous width
5031
        if (oShadow.style.width && oShadow.style.height) {
5032
            oShadow.style.width = _EMPTY_STRING;
5033
            oShadow.style.height = _EMPTY_STRING;
5034
        }
5035
 
5036
        oShadow.style.width = (oElement.offsetWidth + 6) + _PX;
5037
        oShadow.style.height = (oElement.offsetHeight + 1) + _PX;
5038
    }
5039
},
5040
 
5041
/**
5042
 * Replaces the shadow element in the DOM with the current shadow element (this._shadow)
5043
 *
5044
 * @method _replaceShadow
5045
 * @protected
5046
 */
5047
_replaceShadow : function () {
5048
    this.element.appendChild(this._shadow);
5049
},
5050
 
5051
/**
5052
 * Adds the classname marker for a visible shadow, to the shadow element
5053
 *
5054
 * @method _addShadowVisibleClass
5055
 * @protected
5056
 */
5057
_addShadowVisibleClass : function () {
5058
    Dom.addClass(this._shadow, _YUI_MENU_SHADOW_VISIBLE);
5059
},
5060
 
5061
/**
5062
 * Removes the classname marker for a visible shadow, from the shadow element
5063
 *
5064
 * @method _removeShadowVisibleClass
5065
 * @protected
5066
 */
5067
_removeShadowVisibleClass : function () {
5068
    Dom.removeClass(this._shadow, _YUI_MENU_SHADOW_VISIBLE);
5069
},
5070
 
5071
/**
5072
 * Removes the shadow element from the DOM, and unsubscribes all the listeners used to keep it in sync. Used
5073
 * to handle setting the shadow to false.
5074
 *
5075
 * @method _removeShadow
5076
 * @protected
5077
 */
5078
_removeShadow : function() {
5079
 
5080
    var p = (this._shadow && this._shadow.parentNode);
5081
 
5082
    if (p) {
5083
        p.removeChild(this._shadow);
5084
    }
5085
 
5086
    this.beforeShowEvent.unsubscribe(this._addShadowVisibleClass);
5087
    this.beforeHideEvent.unsubscribe(this._removeShadowVisibleClass);
5088
 
5089
    this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._sizeShadow);
5090
    this.cfg.unsubscribeFromConfigEvent(_HEIGHT, this._sizeShadow);
5091
    this.cfg.unsubscribeFromConfigEvent(_MAX_HEIGHT, this._sizeShadow);
5092
    this.cfg.unsubscribeFromConfigEvent(_MAX_HEIGHT, this._replaceShadow);
5093
 
5094
    this.changeContentEvent.unsubscribe(this._sizeShadow);
5095
 
5096
    Module.textResizeEvent.unsubscribe(this._sizeShadow);
5097
},
5098
 
5099
/**
5100
 * Used to create the shadow element, add it to the DOM, and subscribe listeners to keep it in sync.
5101
 *
5102
 * @method _createShadow
5103
 * @protected
5104
 */
5105
_createShadow : function () {
5106
 
5107
    var oShadow = this._shadow,
5108
        oElement;
5109
 
5110
    if (!oShadow) {
5111
        oElement = this.element;
5112
 
5113
        if (!m_oShadowTemplate) {
5114
            m_oShadowTemplate = document.createElement(_DIV_LOWERCASE);
5115
            m_oShadowTemplate.className = _YUI_MENU_SHADOW_YUI_MENU_SHADOW_VISIBLE;
5116
        }
5117
 
5118
        oShadow = m_oShadowTemplate.cloneNode(false);
5119
 
5120
        oElement.appendChild(oShadow);
5121
 
5122
        this._shadow = oShadow;
5123
 
5124
        this.beforeShowEvent.subscribe(this._addShadowVisibleClass);
5125
        this.beforeHideEvent.subscribe(this._removeShadowVisibleClass);
5126
 
5127
        if (UA.ie) {
5128
            /*
5129
                 Need to call sizeShadow & syncIframe via setTimeout for
5130
                 IE 7 Quirks Mode and IE 6 Standards Mode and Quirks Mode
5131
                 or the shadow and iframe shim will not be sized and
5132
                 positioned properly.
5133
            */
5134
            Lang.later(0, this, function () {
5135
                this._sizeShadow();
5136
                this.syncIframe();
5137
            });
5138
 
5139
            this.cfg.subscribeToConfigEvent(_WIDTH, this._sizeShadow);
5140
            this.cfg.subscribeToConfigEvent(_HEIGHT, this._sizeShadow);
5141
            this.cfg.subscribeToConfigEvent(_MAX_HEIGHT, this._sizeShadow);
5142
            this.changeContentEvent.subscribe(this._sizeShadow);
5143
 
5144
            Module.textResizeEvent.subscribe(this._sizeShadow, this, true);
5145
 
5146
            this.destroyEvent.subscribe(function () {
5147
                Module.textResizeEvent.unsubscribe(this._sizeShadow, this);
5148
            });
5149
        }
5150
 
5151
        this.cfg.subscribeToConfigEvent(_MAX_HEIGHT, this._replaceShadow);
5152
    }
5153
},
5154
 
5155
/**
5156
 * The beforeShow event handler used to set up the shadow lazily when the menu is made visible.
5157
 * @method _shadowBeforeShow
5158
 * @protected
5159
 */
5160
_shadowBeforeShow : function () {
5161
    if (this._shadow) {
5162
 
5163
        // If called because the "shadow" event was refired - just append again and resize
5164
        this._replaceShadow();
5165
 
5166
        if (UA.ie) {
5167
            this._sizeShadow();
5168
        }
5169
    } else {
5170
        this._createShadow();
5171
    }
5172
 
5173
    this.beforeShowEvent.unsubscribe(this._shadowBeforeShow);
5174
},
5175
 
5176
/**
5177
* @method configShadow
5178
* @description Event handler for when the "shadow" configuration property of
5179
* a menu changes.
5180
* @param {String} p_sType The name of the event that was fired.
5181
* @param {Array} p_aArgs Collection of arguments sent when the event was fired.
5182
* @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
5183
*/
5184
configShadow: function (p_sType, p_aArgs, p_oMenu) {
5185
 
5186
    var bShadow = p_aArgs[0];
5187
 
5188
    if (bShadow && this.cfg.getProperty(_POSITION) == _DYNAMIC) {
5189
        if (this.cfg.getProperty(_VISIBLE)) {
5190
            if (this._shadow) {
5191
                // If the "shadow" event was refired - just append again and resize
5192
                this._replaceShadow();
5193
 
5194
                if (UA.ie) {
5195
                    this._sizeShadow();
5196
                }
5197
            } else {
5198
                this._createShadow();
5199
            }
5200
        } else {
5201
            this.beforeShowEvent.subscribe(this._shadowBeforeShow);
5202
        }
5203
    } else if (!bShadow) {
5204
        this.beforeShowEvent.unsubscribe(this._shadowBeforeShow);
5205
        this._removeShadow();
5206
    }
5207
},
5208
 
5209
// Public methods
5210
 
5211
/**
5212
* @method initEvents
5213
* @description Initializes the custom events for the menu.
5214
*/
5215
initEvents: function () {
5216
 
5217
    Menu.superclass.initEvents.call(this);
5218
 
5219
    // Create custom events
5220
 
5221
    var i = EVENT_TYPES.length - 1,
5222
        aEventData,
5223
        oCustomEvent;
5224
 
5225
 
5226
    do {
5227
 
5228
        aEventData = EVENT_TYPES[i];
5229
 
5230
        oCustomEvent = this.createEvent(aEventData[1]);
5231
        oCustomEvent.signature = CustomEvent.LIST;
5232
 
5233
        this[aEventData[0]] = oCustomEvent;
5234
 
5235
    }
5236
    while (i--);
5237
 
5238
},
5239
 
5240
 
5241
/**
5242
* @method positionOffScreen
5243
* @description Positions the menu outside of the boundaries of the browser's
5244
* viewport.  Called automatically when a menu is hidden to ensure that
5245
* it doesn't force the browser to render uncessary scrollbars.
5246
*/
5247
positionOffScreen: function () {
5248
 
5249
    var oIFrame = this.iframe,
5250
        oElement = this.element,
5251
        sPos = this.OFF_SCREEN_POSITION;
5252
 
5253
    oElement.style.top = _EMPTY_STRING;
5254
    oElement.style.left = _EMPTY_STRING;
5255
 
5256
    if (oIFrame) {
5257
 
5258
        oIFrame.style.top = sPos;
5259
        oIFrame.style.left = sPos;
5260
 
5261
    }
5262
 
5263
},
5264
 
5265
 
5266
/**
5267
* @method getRoot
5268
* @description Finds the menu's root menu.
5269
*/
5270
getRoot: function () {
5271
 
5272
    var oItem = this.parent,
5273
        oParentMenu,
5274
        returnVal;
5275
 
5276
    if (oItem) {
5277
 
5278
        oParentMenu = oItem.parent;
5279
 
5280
        returnVal = oParentMenu ? oParentMenu.getRoot() : this;
5281
 
5282
    }
5283
    else {
5284
 
5285
        returnVal = this;
5286
 
5287
    }
5288
 
5289
    return returnVal;
5290
 
5291
},
5292
 
5293
 
5294
/**
5295
* @method toString
5296
* @description Returns a string representing the menu.
5297
* @return {String}
5298
*/
5299
toString: function () {
5300
 
5301
    var sReturnVal = _MENU,
5302
        sId = this.id;
5303
 
5304
    if (sId) {
5305
 
5306
        sReturnVal += (_SPACE + sId);
5307
 
5308
    }
5309
 
5310
    return sReturnVal;
5311
 
5312
},
5313
 
5314
 
5315
/**
5316
* @method setItemGroupTitle
5317
* @description Sets the title of a group of menu items.
5318
* @param {HTML} p_sGroupTitle String or markup specifying the title of the group. The title is inserted into the DOM as HTML, and should be escaped by the implementor if coming from an external source.
5319
* @param {Number} p_nGroupIndex Optional. Number specifying the group to which
5320
* the title belongs.
5321
*/
5322
setItemGroupTitle: function (p_sGroupTitle, p_nGroupIndex) {
5323
 
5324
    var nGroupIndex,
5325
        oTitle,
5326
        i,
5327
        nFirstIndex;
5328
 
5329
    if (Lang.isString(p_sGroupTitle) && p_sGroupTitle.length > 0) {
5330
 
5331
        nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0;
5332
        oTitle = this._aGroupTitleElements[nGroupIndex];
5333
 
5334
 
5335
        if (oTitle) {
5336
 
5337
            oTitle.innerHTML = p_sGroupTitle;
5338
 
5339
        }
5340
        else {
5341
 
5342
            oTitle = document.createElement(this.GROUP_TITLE_TAG_NAME);
5343
 
5344
            oTitle.innerHTML = p_sGroupTitle;
5345
 
5346
            this._aGroupTitleElements[nGroupIndex] = oTitle;
5347
 
5348
        }
5349
 
5350
 
5351
        i = this._aGroupTitleElements.length - 1;
5352
 
5353
        do {
5354
 
5355
            if (this._aGroupTitleElements[i]) {
5356
 
5357
                Dom.removeClass(this._aGroupTitleElements[i], _FIRST_OF_TYPE);
5358
 
5359
                nFirstIndex = i;
5360
 
5361
            }
5362
 
5363
        }
5364
        while (i--);
5365
 
5366
 
5367
        if (nFirstIndex !== null) {
5368
 
5369
            Dom.addClass(this._aGroupTitleElements[nFirstIndex],
5370
                _FIRST_OF_TYPE);
5371
 
5372
        }
5373
 
5374
        this.changeContentEvent.fire();
5375
 
5376
    }
5377
 
5378
},
5379
 
5380
 
5381
 
5382
/**
5383
* @method addItem
5384
* @description Appends an item to the menu.
5385
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
5386
* instance to be added to the menu.
5387
* @param {HTML} p_oItem String or markup specifying content of the item to be added
5388
* to the menu. The item text is inserted into the DOM as HTML, and should be escaped by the implementor if coming from an external source.
5389
* @param {Object} p_oItem Object literal containing a set of menu item
5390
* configuration properties.
5391
* @param {Number} p_nGroupIndex Optional. Number indicating the group to
5392
* which the item belongs.
5393
* @return {YAHOO.widget.MenuItem}
5394
*/
5395
addItem: function (p_oItem, p_nGroupIndex) {
5396
 
5397
    return this._addItemToGroup(p_nGroupIndex, p_oItem);
5398
 
5399
},
5400
 
5401
 
5402
/**
5403
* @method addItems
5404
* @description Adds an array of items to the menu.
5405
* @param {Array} p_aItems Array of items to be added to the menu.  The array
5406
* can contain strings specifying the markup for the content of each item to be created, object
5407
* literals specifying each of the menu item configuration properties,
5408
* or MenuItem instances. The item content if provided as a string is inserted into the DOM as HTML, and should be escaped by the implementor if coming from an external source.
5409
* @param {Number} p_nGroupIndex Optional. Number specifying the group to
5410
* which the items belongs.
5411
* @return {Array}
5412
*/
5413
addItems: function (p_aItems, p_nGroupIndex) {
5414
 
5415
    var nItems,
5416
        aItems,
5417
        oItem,
5418
        i,
5419
        returnVal;
5420
 
5421
 
5422
    if (Lang.isArray(p_aItems)) {
5423
 
5424
        nItems = p_aItems.length;
5425
        aItems = [];
5426
 
5427
        for(i=0; i<nItems; i++) {
5428
 
5429
            oItem = p_aItems[i];
5430
 
5431
            if (oItem) {
5432
 
5433
                if (Lang.isArray(oItem)) {
5434
 
5435
                    aItems[aItems.length] = this.addItems(oItem, i);
5436
 
5437
                }
5438
                else {
5439
 
5440
                    aItems[aItems.length] = this._addItemToGroup(p_nGroupIndex, oItem);
5441
 
5442
                }
5443
 
5444
            }
5445
 
5446
        }
5447
 
5448
 
5449
        if (aItems.length) {
5450
 
5451
            returnVal = aItems;
5452
 
5453
        }
5454
 
5455
    }
5456
 
5457
    return returnVal;
5458
 
5459
},
5460
 
5461
 
5462
/**
5463
* @method insertItem
5464
* @description Inserts an item into the menu at the specified index.
5465
* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
5466
* instance to be added to the menu.
5467
* @param {String} p_oItem String specifying the text of the item to be added
5468
* to the menu.
5469
* @param {Object} p_oItem Object literal containing a set of menu item
5470
* configuration properties.
5471
* @param {Number} p_nItemIndex Number indicating the ordinal position at which
5472
* the item should be added.
5473
* @param {Number} p_nGroupIndex Optional. Number indicating the group to which
5474
* the item belongs.
5475
* @return {YAHOO.widget.MenuItem}
5476
*/
5477
insertItem: function (p_oItem, p_nItemIndex, p_nGroupIndex) {
5478
 
5479
    return this._addItemToGroup(p_nGroupIndex, p_oItem, p_nItemIndex);
5480
 
5481
},
5482
 
5483
 
5484
/**
5485
* @method removeItem
5486
* @description Removes the specified item from the menu.
5487
* @param {YAHOO.widget.MenuItem} p_oObject Object reference for the MenuItem
5488
* instance to be removed from the menu.
5489
* @param {Number} p_oObject Number specifying the index of the item
5490
* to be removed.
5491
* @param {Number} p_nGroupIndex Optional. Number specifying the group to
5492
* which the item belongs.
5493
* @return {YAHOO.widget.MenuItem}
5494
*/
5495
removeItem: function (p_oObject, p_nGroupIndex) {
5496
 
5497
    var oItem,
5498
        returnVal;
5499
 
5500
    if (!Lang.isUndefined(p_oObject)) {
5501
 
5502
        if (p_oObject instanceof YAHOO.widget.MenuItem) {
5503
 
5504
            oItem = this._removeItemFromGroupByValue(p_nGroupIndex, p_oObject);
5505
 
5506
        }
5507
        else if (Lang.isNumber(p_oObject)) {
5508
 
5509
            oItem = this._removeItemFromGroupByIndex(p_nGroupIndex, p_oObject);
5510
 
5511
        }
5512
 
5513
        if (oItem) {
5514
 
5515
            oItem.destroy();
5516
 
5517
            YAHOO.log("Item removed." +
5518
                " Text: " + oItem.cfg.getProperty("text") + ", " +
5519
                " Index: " + oItem.index + ", " +
5520
                " Group Index: " + oItem.groupIndex, "info", this.toString());
5521
 
5522
            returnVal = oItem;
5523
 
5524
        }
5525
 
5526
    }
5527
 
5528
    return returnVal;
5529
 
5530
},
5531
 
5532
 
5533
/**
5534
* @method getItems
5535
* @description Returns an array of all of the items in the menu.
5536
* @return {Array}
5537
*/
5538
getItems: function () {
5539
 
5540
    var aGroups = this._aItemGroups,
5541
        nGroups,
5542
        returnVal,
5543
        aItems = [];
5544
 
5545
 
5546
    if (Lang.isArray(aGroups)) {
5547
 
5548
        nGroups = aGroups.length;
5549
 
5550
        returnVal = ((nGroups == 1) ? aGroups[0] : (Array.prototype.concat.apply(aItems, aGroups)));
5551
 
5552
    }
5553
 
5554
    return returnVal;
5555
 
5556
},
5557
 
5558
 
5559
/**
5560
* @method getItemGroups
5561
* @description Multi-dimensional Array representing the menu items as they
5562
* are grouped in the menu.
5563
* @return {Array}
5564
*/
5565
getItemGroups: function () {
5566
 
5567
    return this._aItemGroups;
5568
 
5569
},
5570
 
5571
 
5572
/**
5573
* @method getItem
5574
* @description Returns the item at the specified index.
5575
* @param {Number} p_nItemIndex Number indicating the ordinal position of the
5576
* item to be retrieved.
5577
* @param {Number} p_nGroupIndex Optional. Number indicating the group to which
5578
* the item belongs.
5579
* @return {YAHOO.widget.MenuItem}
5580
*/
5581
getItem: function (p_nItemIndex, p_nGroupIndex) {
5582
 
5583
    var aGroup,
5584
        returnVal;
5585
 
5586
    if (Lang.isNumber(p_nItemIndex)) {
5587
 
5588
        aGroup = this._getItemGroup(p_nGroupIndex);
5589
 
5590
        if (aGroup) {
5591
 
5592
            returnVal = aGroup[p_nItemIndex];
5593
 
5594
        }
5595
 
5596
    }
5597
 
5598
    return returnVal;
5599
 
5600
},
5601
 
5602
 
5603
/**
5604
* @method getSubmenus
5605
* @description Returns an array of all of the submenus that are immediate
5606
* children of the menu.
5607
* @return {Array}
5608
*/
5609
getSubmenus: function () {
5610
 
5611
    var aItems = this.getItems(),
5612
        nItems = aItems.length,
5613
        aSubmenus,
5614
        oSubmenu,
5615
        oItem,
5616
        i;
5617
 
5618
 
5619
    if (nItems > 0) {
5620
 
5621
        aSubmenus = [];
5622
 
5623
        for(i=0; i<nItems; i++) {
5624
 
5625
            oItem = aItems[i];
5626
 
5627
            if (oItem) {
5628
 
5629
                oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5630
 
5631
                if (oSubmenu) {
5632
 
5633
                    aSubmenus[aSubmenus.length] = oSubmenu;
5634
 
5635
                }
5636
 
5637
            }
5638
 
5639
        }
5640
 
5641
    }
5642
 
5643
    return aSubmenus;
5644
 
5645
},
5646
 
5647
 
5648
/**
5649
* @method clearContent
5650
* @description Removes all of the content from the menu, including the menu
5651
* items, group titles, header and footer.
5652
*/
5653
clearContent: function () {
5654
 
5655
    var aItems = this.getItems(),
5656
        nItems = aItems.length,
5657
        oElement = this.element,
5658
        oBody = this.body,
5659
        oHeader = this.header,
5660
        oFooter = this.footer,
5661
        oItem,
5662
        oSubmenu,
5663
        i;
5664
 
5665
 
5666
    if (nItems > 0) {
5667
 
5668
        i = nItems - 1;
5669
 
5670
        do {
5671
 
5672
            oItem = aItems[i];
5673
 
5674
            if (oItem) {
5675
 
5676
                oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5677
 
5678
                if (oSubmenu) {
5679
 
5680
                    this.cfg.configChangedEvent.unsubscribe(
5681
                        this._onParentMenuConfigChange, oSubmenu);
5682
 
5683
                    this.renderEvent.unsubscribe(this._onParentMenuRender,
5684
                        oSubmenu);
5685
 
5686
                }
5687
 
5688
                this.removeItem(oItem, oItem.groupIndex);
5689
 
5690
            }
5691
 
5692
        }
5693
        while (i--);
5694
 
5695
    }
5696
 
5697
 
5698
    if (oHeader) {
5699
 
5700
        Event.purgeElement(oHeader);
5701
        oElement.removeChild(oHeader);
5702
 
5703
    }
5704
 
5705
 
5706
    if (oFooter) {
5707
 
5708
        Event.purgeElement(oFooter);
5709
        oElement.removeChild(oFooter);
5710
    }
5711
 
5712
 
5713
    if (oBody) {
5714
 
5715
        Event.purgeElement(oBody);
5716
 
5717
        oBody.innerHTML = _EMPTY_STRING;
5718
 
5719
    }
5720
 
5721
    this.activeItem = null;
5722
 
5723
    this._aItemGroups = [];
5724
    this._aListElements = [];
5725
    this._aGroupTitleElements = [];
5726
 
5727
    this.cfg.setProperty(_WIDTH, null);
5728
 
5729
},
5730
 
5731
 
5732
/**
5733
* @method destroy
5734
* @description Removes the menu's <code>&#60;div&#62;</code> element
5735
* (and accompanying child nodes) from the document.
5736
* @param {boolean} shallowPurge If true, only the parent element's DOM event listeners are purged. If false, or not provided, all children are also purged of DOM event listeners.
5737
* NOTE: The flag is a "shallowPurge" flag, as opposed to what may be a more intuitive "purgeChildren" flag to maintain backwards compatibility with behavior prior to 2.9.0.
5738
*
5739
*/
5740
destroy: function (shallowPurge) {
5741
 
5742
    // Remove all items
5743
 
5744
    this.clearContent();
5745
 
5746
    this._aItemGroups = null;
5747
    this._aListElements = null;
5748
    this._aGroupTitleElements = null;
5749
 
5750
 
5751
    // Continue with the superclass implementation of this method
5752
 
5753
    Menu.superclass.destroy.call(this, shallowPurge);
5754
 
5755
    YAHOO.log("Destroyed.", "info", this.toString());
5756
 
5757
},
5758
 
5759
 
5760
/**
5761
* @method setInitialFocus
5762
* @description Sets focus to the menu's first enabled item.
5763
*/
5764
setInitialFocus: function () {
5765
 
5766
    var oItem = this._getFirstEnabledItem();
5767
 
5768
    if (oItem) {
5769
 
5770
        oItem.focus();
5771
 
5772
    }
5773
 
5774
},
5775
 
5776
 
5777
/**
5778
* @method setInitialSelection
5779
* @description Sets the "selected" configuration property of the menu's first
5780
* enabled item to "true."
5781
*/
5782
setInitialSelection: function () {
5783
 
5784
    var oItem = this._getFirstEnabledItem();
5785
 
5786
    if (oItem) {
5787
 
5788
        oItem.cfg.setProperty(_SELECTED, true);
5789
    }
5790
 
5791
},
5792
 
5793
 
5794
/**
5795
* @method clearActiveItem
5796
* @description Sets the "selected" configuration property of the menu's active
5797
* item to "false" and hides the item's submenu.
5798
* @param {Boolean} p_bBlur Boolean indicating if the menu's active item
5799
* should be blurred.
5800
*/
5801
clearActiveItem: function (p_bBlur) {
5802
 
5803
    if (this.cfg.getProperty(_SHOW_DELAY) > 0) {
5804
 
5805
        this._cancelShowDelay();
5806
 
5807
    }
5808
 
5809
 
5810
    var oActiveItem = this.activeItem,
5811
        oConfig,
5812
        oSubmenu;
5813
 
5814
    if (oActiveItem) {
5815
 
5816
        oConfig = oActiveItem.cfg;
5817
 
5818
        if (p_bBlur) {
5819
 
5820
            oActiveItem.blur();
5821
 
5822
            this.getRoot()._hasFocus = true;
5823
 
5824
        }
5825
 
5826
        oConfig.setProperty(_SELECTED, false);
5827
 
5828
        oSubmenu = oConfig.getProperty(_SUBMENU);
5829
 
5830
 
5831
        if (oSubmenu) {
5832
 
5833
            oSubmenu.hide();
5834
 
5835
        }
5836
 
5837
        this.activeItem = null;
5838
 
5839
    }
5840
 
5841
},
5842
 
5843
 
5844
/**
5845
* @method focus
5846
* @description Causes the menu to receive focus and fires the "focus" event.
5847
*/
5848
focus: function () {
5849
 
5850
    if (!this.hasFocus()) {
5851
 
5852
        this.setInitialFocus();
5853
 
5854
    }
5855
 
5856
},
5857
 
5858
 
5859
/**
5860
* @method blur
5861
* @description Causes the menu to lose focus and fires the "blur" event.
5862
*/
5863
blur: function () {
5864
 
5865
    var oItem;
5866
 
5867
    if (this.hasFocus()) {
5868
 
5869
        oItem = MenuManager.getFocusedMenuItem();
5870
 
5871
        if (oItem) {
5872
 
5873
            oItem.blur();
5874
 
5875
        }
5876
 
5877
    }
5878
 
5879
},
5880
 
5881
 
5882
/**
5883
* @method hasFocus
5884
* @description Returns a boolean indicating whether or not the menu has focus.
5885
* @return {Boolean}
5886
*/
5887
hasFocus: function () {
5888
 
5889
    return (MenuManager.getFocusedMenu() == this.getRoot());
5890
 
5891
},
5892
 
5893
 
5894
_doItemSubmenuSubscribe: function (p_sType, p_aArgs, p_oObject) {
5895
 
5896
    var oItem = p_aArgs[0],
5897
        oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5898
 
5899
    if (oSubmenu) {
5900
        oSubmenu.subscribe.apply(oSubmenu, p_oObject);
5901
    }
5902
 
5903
},
5904
 
5905
 
5906
_doSubmenuSubscribe: function (p_sType, p_aArgs, p_oObject) {
5907
 
5908
    var oSubmenu = this.cfg.getProperty(_SUBMENU);
5909
 
5910
    if (oSubmenu) {
5911
        oSubmenu.subscribe.apply(oSubmenu, p_oObject);
5912
    }
5913
 
5914
},
5915
 
5916
 
5917
/**
5918
* Adds the specified CustomEvent subscriber to the menu and each of
5919
* its submenus.
5920
* @method subscribe
5921
* @param p_type     {string}   the type, or name of the event
5922
* @param p_fn       {function} the function to exectute when the event fires
5923
* @param p_obj      {Object}   An object to be passed along when the event
5924
*                              fires
5925
* @param p_override {boolean}  If true, the obj passed in becomes the
5926
*                              execution scope of the listener
5927
*/
5928
subscribe: function () {
5929
 
5930
    //	Subscribe to the event for this Menu instance
5931
    Menu.superclass.subscribe.apply(this, arguments);
5932
 
5933
    //	Subscribe to the "itemAdded" event so that all future submenus
5934
    //	also subscribe to this event
5935
    Menu.superclass.subscribe.call(this, _ITEM_ADDED, this._doItemSubmenuSubscribe, arguments);
5936
 
5937
 
5938
    var aItems = this.getItems(),
5939
        nItems,
5940
        oItem,
5941
        oSubmenu,
5942
        i;
5943
 
5944
 
5945
    if (aItems) {
5946
 
5947
        nItems = aItems.length;
5948
 
5949
        if (nItems > 0) {
5950
 
5951
            i = nItems - 1;
5952
 
5953
            do {
5954
 
5955
                oItem = aItems[i];
5956
                oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5957
 
5958
                if (oSubmenu) {
5959
                    oSubmenu.subscribe.apply(oSubmenu, arguments);
5960
                }
5961
                else {
5962
                    oItem.cfg.subscribeToConfigEvent(_SUBMENU, this._doSubmenuSubscribe, arguments);
5963
                }
5964
 
5965
            }
5966
            while (i--);
5967
 
5968
        }
5969
 
5970
    }
5971
 
5972
},
5973
 
5974
 
5975
unsubscribe: function () {
5976
 
5977
    //	Remove the event for this Menu instance
5978
    Menu.superclass.unsubscribe.apply(this, arguments);
5979
 
5980
    //	Remove the "itemAdded" event so that all future submenus don't have
5981
    //	the event handler
5982
    Menu.superclass.unsubscribe.call(this, _ITEM_ADDED, this._doItemSubmenuSubscribe, arguments);
5983
 
5984
 
5985
    var aItems = this.getItems(),
5986
        nItems,
5987
        oItem,
5988
        oSubmenu,
5989
        i;
5990
 
5991
 
5992
    if (aItems) {
5993
 
5994
        nItems = aItems.length;
5995
 
5996
        if (nItems > 0) {
5997
 
5998
            i = nItems - 1;
5999
 
6000
            do {
6001
 
6002
                oItem = aItems[i];
6003
                oSubmenu = oItem.cfg.getProperty(_SUBMENU);
6004
 
6005
                if (oSubmenu) {
6006
                    oSubmenu.unsubscribe.apply(oSubmenu, arguments);
6007
                }
6008
                else {
6009
                    oItem.cfg.unsubscribeFromConfigEvent(_SUBMENU, this._doSubmenuSubscribe, arguments);
6010
                }
6011
 
6012
            }
6013
            while (i--);
6014
 
6015
        }
6016
 
6017
    }
6018
 
6019
},
6020
 
6021
 
6022
/**
6023
* @description Initializes the class's configurable properties which can be
6024
* changed using the menu's Config object ("cfg").
6025
* @method initDefaultConfig
6026
*/
6027
initDefaultConfig: function () {
6028
 
6029
    Menu.superclass.initDefaultConfig.call(this);
6030
 
6031
    var oConfig = this.cfg;
6032
 
6033
 
6034
    // Module documentation overrides
6035
 
6036
    /**
6037
    * @config effect
6038
    * @description Object or array of objects representing the ContainerEffect
6039
    * classes that are active for animating the container.  When set this
6040
    * property is automatically applied to all submenus.
6041
    * @type Object
6042
    * @default null
6043
    */
6044
 
6045
    // Overlay documentation overrides
6046
 
6047
 
6048
    /**
6049
    * @config x
6050
    * @description Number representing the absolute x-coordinate position of
6051
    * the Menu.  This property is only applied when the "position"
6052
    * configuration property is set to dynamic.
6053
    * @type Number
6054
    * @default null
6055
    */
6056
 
6057
 
6058
    /**
6059
    * @config y
6060
    * @description Number representing the absolute y-coordinate position of
6061
    * the Menu.  This property is only applied when the "position"
6062
    * configuration property is set to dynamic.
6063
    * @type Number
6064
    * @default null
6065
    */
6066
 
6067
 
6068
    /**
6069
    * @description Array of the absolute x and y positions of the Menu.  This
6070
    * property is only applied when the "position" configuration property is
6071
    * set to dynamic.
6072
    * @config xy
6073
    * @type Number[]
6074
    * @default null
6075
    */
6076
 
6077
 
6078
    /**
6079
    * @config context
6080
    * @description Array of context arguments for context-sensitive positioning.
6081
    * The format is: [id or element, element corner, context corner].
6082
    * For example, setting this property to ["img1", "tl", "bl"] would
6083
    * align the Menu's top left corner to the context element's
6084
    * bottom left corner.  This property is only applied when the "position"
6085
    * configuration property is set to dynamic.
6086
    * @type Array
6087
    * @default null
6088
    */
6089
 
6090
 
6091
    /**
6092
    * @config fixedcenter
6093
    * @description Boolean indicating if the Menu should be anchored to the
6094
    * center of the viewport.  This property is only applied when the
6095
    * "position" configuration property is set to dynamic.
6096
    * @type Boolean
6097
    * @default false
6098
    */
6099
 
6100
 
6101
    /**
6102
    * @config iframe
6103
    * @description Boolean indicating whether or not the Menu should
6104
    * have an IFRAME shim; used to prevent SELECT elements from
6105
    * poking through an Overlay instance in IE6.  When set to "true",
6106
    * the iframe shim is created when the Menu instance is intially
6107
    * made visible.  This property is only applied when the "position"
6108
    * configuration property is set to dynamic and is automatically applied
6109
    * to all submenus.
6110
    * @type Boolean
6111
    * @default true for IE6 and below, false for all other browsers.
6112
    */
6113
 
6114
 
6115
    // Add configuration attributes
6116
 
6117
    /*
6118
        Change the default value for the "visible" configuration
6119
        property to "false" by re-adding the property.
6120
    */
6121
 
6122
    /**
6123
    * @config visible
6124
    * @description Boolean indicating whether or not the menu is visible.  If
6125
    * the menu's "position" configuration property is set to "dynamic" (the
6126
    * default), this property toggles the menu's <code>&#60;div&#62;</code>
6127
    * element's "visibility" style property between "visible" (true) or
6128
    * "hidden" (false).  If the menu's "position" configuration property is
6129
    * set to "static" this property toggles the menu's
6130
    * <code>&#60;div&#62;</code> element's "display" style property
6131
    * between "block" (true) or "none" (false).
6132
    * @default false
6133
    * @type Boolean
6134
    */
6135
    oConfig.addProperty(
6136
        VISIBLE_CONFIG.key,
6137
        {
6138
            handler: this.configVisible,
6139
            value: VISIBLE_CONFIG.value,
6140
            validator: VISIBLE_CONFIG.validator
6141
        }
6142
     );
6143
 
6144
 
6145
    /*
6146
        Change the default value for the "constraintoviewport" configuration
6147
        property (inherited by YAHOO.widget.Overlay) to "true" by re-adding the property.
6148
    */
6149
 
6150
    /**
6151
    * @config constraintoviewport
6152
    * @description Boolean indicating if the menu will try to remain inside
6153
    * the boundaries of the size of viewport.  This property is only applied
6154
    * when the "position" configuration property is set to dynamic and is
6155
    * automatically applied to all submenus.
6156
    * @default true
6157
    * @type Boolean
6158
    */
6159
    oConfig.addProperty(
6160
        CONSTRAIN_TO_VIEWPORT_CONFIG.key,
6161
        {
6162
            handler: this.configConstrainToViewport,
6163
            value: CONSTRAIN_TO_VIEWPORT_CONFIG.value,
6164
            validator: CONSTRAIN_TO_VIEWPORT_CONFIG.validator,
6165
            supercedes: CONSTRAIN_TO_VIEWPORT_CONFIG.supercedes
6166
        }
6167
    );
6168
 
6169
 
6170
    /*
6171
        Change the default value for the "preventcontextoverlap" configuration
6172
        property (inherited by YAHOO.widget.Overlay) to "true" by re-adding the property.
6173
    */
6174
 
6175
    /**
6176
    * @config preventcontextoverlap
6177
    * @description Boolean indicating whether or not a submenu should overlap its parent MenuItem
6178
    * when the "constraintoviewport" configuration property is set to "true".
6179
    * @type Boolean
6180
    * @default true
6181
    */
6182
    oConfig.addProperty(PREVENT_CONTEXT_OVERLAP_CONFIG.key, {
6183
 
6184
        value: PREVENT_CONTEXT_OVERLAP_CONFIG.value,
6185
        validator: PREVENT_CONTEXT_OVERLAP_CONFIG.validator,
6186
        supercedes: PREVENT_CONTEXT_OVERLAP_CONFIG.supercedes
6187
 
6188
    });
6189
 
6190
 
6191
    /**
6192
    * @config position
6193
    * @description String indicating how a menu should be positioned on the
6194
    * screen.  Possible values are "static" and "dynamic."  Static menus are
6195
    * visible by default and reside in the normal flow of the document
6196
    * (CSS position: static).  Dynamic menus are hidden by default, reside
6197
    * out of the normal flow of the document (CSS position: absolute), and
6198
    * can overlay other elements on the screen.
6199
    * @default dynamic
6200
    * @type String
6201
    */
6202
    oConfig.addProperty(
6203
        POSITION_CONFIG.key,
6204
        {
6205
            handler: this.configPosition,
6206
            value: POSITION_CONFIG.value,
6207
            validator: POSITION_CONFIG.validator,
6208
            supercedes: POSITION_CONFIG.supercedes
6209
        }
6210
    );
6211
 
6212
 
6213
    /**
6214
    * @config submenualignment
6215
    * @description Array defining how submenus should be aligned to their
6216
    * parent menu item. The format is: [itemCorner, submenuCorner]. By default
6217
    * a submenu's top left corner is aligned to its parent menu item's top
6218
    * right corner.
6219
    * @default ["tl","tr"]
6220
    * @type Array
6221
    */
6222
    oConfig.addProperty(
6223
        SUBMENU_ALIGNMENT_CONFIG.key,
6224
        {
6225
            value: SUBMENU_ALIGNMENT_CONFIG.value,
6226
            suppressEvent: SUBMENU_ALIGNMENT_CONFIG.suppressEvent
6227
        }
6228
    );
6229
 
6230
 
6231
    /**
6232
    * @config autosubmenudisplay
6233
    * @description Boolean indicating if submenus are automatically made
6234
    * visible when the user mouses over the menu's items.
6235
    * @default true
6236
    * @type Boolean
6237
    */
6238
    oConfig.addProperty(
6239
       AUTO_SUBMENU_DISPLAY_CONFIG.key,
6240
       {
6241
           value: AUTO_SUBMENU_DISPLAY_CONFIG.value,
6242
           validator: AUTO_SUBMENU_DISPLAY_CONFIG.validator,
6243
           suppressEvent: AUTO_SUBMENU_DISPLAY_CONFIG.suppressEvent
6244
       }
6245
    );
6246
 
6247
 
6248
    /**
6249
    * @config showdelay
6250
    * @description Number indicating the time (in milliseconds) that should
6251
    * expire before a submenu is made visible when the user mouses over
6252
    * the menu's items.  This property is only applied when the "position"
6253
    * configuration property is set to dynamic and is automatically applied
6254
    * to all submenus.
6255
    * @default 250
6256
    * @type Number
6257
    */
6258
    oConfig.addProperty(
6259
       SHOW_DELAY_CONFIG.key,
6260
       {
6261
           value: SHOW_DELAY_CONFIG.value,
6262
           validator: SHOW_DELAY_CONFIG.validator,
6263
           suppressEvent: SHOW_DELAY_CONFIG.suppressEvent
6264
       }
6265
    );
6266
 
6267
 
6268
    /**
6269
    * @config hidedelay
6270
    * @description Number indicating the time (in milliseconds) that should
6271
    * expire before the menu is hidden.  This property is only applied when
6272
    * the "position" configuration property is set to dynamic and is
6273
    * automatically applied to all submenus.
6274
    * @default 0
6275
    * @type Number
6276
    */
6277
    oConfig.addProperty(
6278
       HIDE_DELAY_CONFIG.key,
6279
       {
6280
           handler: this.configHideDelay,
6281
           value: HIDE_DELAY_CONFIG.value,
6282
           validator: HIDE_DELAY_CONFIG.validator,
6283
           suppressEvent: HIDE_DELAY_CONFIG.suppressEvent
6284
       }
6285
    );
6286
 
6287
 
6288
    /**
6289
    * @config submenuhidedelay
6290
    * @description Number indicating the time (in milliseconds) that should
6291
    * expire before a submenu is hidden when the user mouses out of a menu item
6292
    * heading in the direction of a submenu.  The value must be greater than or
6293
    * equal to the value specified for the "showdelay" configuration property.
6294
    * This property is only applied when the "position" configuration property
6295
    * is set to dynamic and is automatically applied to all submenus.
6296
    * @default 250
6297
    * @type Number
6298
    */
6299
    oConfig.addProperty(
6300
       SUBMENU_HIDE_DELAY_CONFIG.key,
6301
       {
6302
           value: SUBMENU_HIDE_DELAY_CONFIG.value,
6303
           validator: SUBMENU_HIDE_DELAY_CONFIG.validator,
6304
           suppressEvent: SUBMENU_HIDE_DELAY_CONFIG.suppressEvent
6305
       }
6306
    );
6307
 
6308
 
6309
    /**
6310
    * @config clicktohide
6311
    * @description Boolean indicating if the menu will automatically be
6312
    * hidden if the user clicks outside of it.  This property is only
6313
    * applied when the "position" configuration property is set to dynamic
6314
    * and is automatically applied to all submenus.
6315
    * @default true
6316
    * @type Boolean
6317
    */
6318
    oConfig.addProperty(
6319
        CLICK_TO_HIDE_CONFIG.key,
6320
        {
6321
            value: CLICK_TO_HIDE_CONFIG.value,
6322
            validator: CLICK_TO_HIDE_CONFIG.validator,
6323
            suppressEvent: CLICK_TO_HIDE_CONFIG.suppressEvent
6324
        }
6325
    );
6326
 
6327
 
6328
    /**
6329
    * @config container
6330
    * @description HTML element reference or string specifying the id
6331
    * attribute of the HTML element that the menu's markup should be
6332
    * rendered into.
6333
    * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
6334
    * level-one-html.html#ID-58190037">HTMLElement</a>|String
6335
    * @default document.body
6336
    */
6337
    oConfig.addProperty(
6338
       CONTAINER_CONFIG.key,
6339
       {
6340
           handler: this.configContainer,
6341
           value: document.body,
6342
           suppressEvent: CONTAINER_CONFIG.suppressEvent
6343
       }
6344
   );
6345
 
6346
 
6347
    /**
6348
    * @config scrollincrement
6349
    * @description Number used to control the scroll speed of a menu.  Used to
6350
    * increment the "scrollTop" property of the menu's body by when a menu's
6351
    * content is scrolling.  When set this property is automatically applied
6352
    * to all submenus.
6353
    * @default 1
6354
    * @type Number
6355
    */
6356
    oConfig.addProperty(
6357
        SCROLL_INCREMENT_CONFIG.key,
6358
        {
6359
            value: SCROLL_INCREMENT_CONFIG.value,
6360
            validator: SCROLL_INCREMENT_CONFIG.validator,
6361
            supercedes: SCROLL_INCREMENT_CONFIG.supercedes,
6362
            suppressEvent: SCROLL_INCREMENT_CONFIG.suppressEvent
6363
        }
6364
    );
6365
 
6366
 
6367
    /**
6368
    * @config minscrollheight
6369
    * @description Number defining the minimum threshold for the "maxheight"
6370
    * configuration property.  When set this property is automatically applied
6371
    * to all submenus.
6372
    * @default 90
6373
    * @type Number
6374
    */
6375
    oConfig.addProperty(
6376
        MIN_SCROLL_HEIGHT_CONFIG.key,
6377
        {
6378
            value: MIN_SCROLL_HEIGHT_CONFIG.value,
6379
            validator: MIN_SCROLL_HEIGHT_CONFIG.validator,
6380
            supercedes: MIN_SCROLL_HEIGHT_CONFIG.supercedes,
6381
            suppressEvent: MIN_SCROLL_HEIGHT_CONFIG.suppressEvent
6382
        }
6383
    );
6384
 
6385
 
6386
    /**
6387
    * @config maxheight
6388
    * @description Number defining the maximum height (in pixels) for a menu's
6389
    * body element (<code>&#60;div class="bd"&#62;</code>).  Once a menu's body
6390
    * exceeds this height, the contents of the body are scrolled to maintain
6391
    * this value.  This value cannot be set lower than the value of the
6392
    * "minscrollheight" configuration property.
6393
    * @default 0
6394
    * @type Number
6395
    */
6396
    oConfig.addProperty(
6397
       MAX_HEIGHT_CONFIG.key,
6398
       {
6399
            handler: this.configMaxHeight,
6400
            value: MAX_HEIGHT_CONFIG.value,
6401
            validator: MAX_HEIGHT_CONFIG.validator,
6402
            suppressEvent: MAX_HEIGHT_CONFIG.suppressEvent,
6403
            supercedes: MAX_HEIGHT_CONFIG.supercedes
6404
       }
6405
    );
6406
 
6407
 
6408
    /**
6409
    * @config classname
6410
    * @description String representing the CSS class to be applied to the
6411
    * menu's root <code>&#60;div&#62;</code> element.  The specified class(es)
6412
    * are appended in addition to the default class as specified by the menu's
6413
    * CSS_CLASS_NAME constant. When set this property is automatically
6414
    * applied to all submenus.
6415
    * @default null
6416
    * @type String
6417
    */
6418
    oConfig.addProperty(
6419
        CLASS_NAME_CONFIG.key,
6420
        {
6421
            handler: this.configClassName,
6422
            value: CLASS_NAME_CONFIG.value,
6423
            validator: CLASS_NAME_CONFIG.validator,
6424
            supercedes: CLASS_NAME_CONFIG.supercedes
6425
        }
6426
    );
6427
 
6428
 
6429
    /**
6430
    * @config disabled
6431
    * @description Boolean indicating if the menu should be disabled.
6432
    * Disabling a menu disables each of its items.  (Disabled menu items are
6433
    * dimmed and will not respond to user input or fire events.)  Disabled
6434
    * menus have a corresponding "disabled" CSS class applied to their root
6435
    * <code>&#60;div&#62;</code> element.
6436
    * @default false
6437
    * @type Boolean
6438
    */
6439
    oConfig.addProperty(
6440
        DISABLED_CONFIG.key,
6441
        {
6442
            handler: this.configDisabled,
6443
            value: DISABLED_CONFIG.value,
6444
            validator: DISABLED_CONFIG.validator,
6445
            suppressEvent: DISABLED_CONFIG.suppressEvent
6446
        }
6447
    );
6448
 
6449
 
6450
    /**
6451
    * @config shadow
6452
    * @description Boolean indicating if the menu should have a shadow.
6453
    * @default true
6454
    * @type Boolean
6455
    */
6456
    oConfig.addProperty(
6457
        SHADOW_CONFIG.key,
6458
        {
6459
            handler: this.configShadow,
6460
            value: SHADOW_CONFIG.value,
6461
            validator: SHADOW_CONFIG.validator
6462
        }
6463
    );
6464
 
6465
 
6466
    /**
6467
    * @config keepopen
6468
    * @description Boolean indicating if the menu should remain open when clicked.
6469
    * @default false
6470
    * @type Boolean
6471
    */
6472
    oConfig.addProperty(
6473
        KEEP_OPEN_CONFIG.key,
6474
        {
6475
            value: KEEP_OPEN_CONFIG.value,
6476
            validator: KEEP_OPEN_CONFIG.validator
6477
        }
6478
    );
6479
 
6480
}
6481
 
6482
}); // END YAHOO.lang.extend
6483
 
6484
})();
6485
 
6486
 
6487
 
6488
(function () {
6489
 
6490
/**
6491
* Creates an item for a menu.
6492
*
6493
* @param {HTML} p_oObject Markup for the menu item content. The markup is inserted into the DOM as HTML, and should be escaped by the implementor if coming from an external source.
6494
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6495
* one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying
6496
* the <code>&#60;li&#62;</code> element of the menu item.
6497
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6498
* one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
6499
* specifying the <code>&#60;optgroup&#62;</code> element of the menu item.
6500
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6501
* one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object
6502
* specifying the <code>&#60;option&#62;</code> element of the menu item.
6503
* @param {Object} p_oConfig Optional. Object literal specifying the
6504
* configuration for the menu item. See configuration class documentation
6505
* for more details.
6506
* @class MenuItem
6507
* @constructor
6508
*/
6509
YAHOO.widget.MenuItem = function (p_oObject, p_oConfig) {
6510
 
6511
    if (p_oObject) {
6512
 
6513
        if (p_oConfig) {
6514
 
6515
            this.parent = p_oConfig.parent;
6516
            this.value = p_oConfig.value;
6517
            this.id = p_oConfig.id;
6518
 
6519
        }
6520
 
6521
        this.init(p_oObject, p_oConfig);
6522
 
6523
    }
6524
 
6525
};
6526
 
6527
 
6528
var Dom = YAHOO.util.Dom,
6529
    Module = YAHOO.widget.Module,
6530
    Menu = YAHOO.widget.Menu,
6531
    MenuItem = YAHOO.widget.MenuItem,
6532
    CustomEvent = YAHOO.util.CustomEvent,
6533
    UA = YAHOO.env.ua,
6534
    Lang = YAHOO.lang,
6535
 
6536
    // Private string constants
6537
 
6538
    _TEXT = "text",
6539
    _HASH = "#",
6540
    _HYPHEN = "-",
6541
    _HELP_TEXT = "helptext",
6542
    _URL = "url",
6543
    _TARGET = "target",
6544
    _EMPHASIS = "emphasis",
6545
    _STRONG_EMPHASIS = "strongemphasis",
6546
    _CHECKED = "checked",
6547
    _SUBMENU = "submenu",
6548
    _DISABLED = "disabled",
6549
    _SELECTED = "selected",
6550
    _HAS_SUBMENU = "hassubmenu",
6551
    _CHECKED_DISABLED = "checked-disabled",
6552
    _HAS_SUBMENU_DISABLED = "hassubmenu-disabled",
6553
    _HAS_SUBMENU_SELECTED = "hassubmenu-selected",
6554
    _CHECKED_SELECTED = "checked-selected",
6555
    _ONCLICK = "onclick",
6556
    _CLASSNAME = "classname",
6557
    _EMPTY_STRING = "",
6558
    _OPTION = "OPTION",
6559
    _OPTGROUP = "OPTGROUP",
6560
    _LI_UPPERCASE = "LI",
6561
    _HREF = "href",
6562
    _SELECT = "SELECT",
6563
    _DIV = "DIV",
6564
    _START_HELP_TEXT = "<em class=\"helptext\">",
6565
    _START_EM = "<em>",
6566
    _END_EM = "</em>",
6567
    _START_STRONG = "<strong>",
6568
    _END_STRONG = "</strong>",
6569
    _PREVENT_CONTEXT_OVERLAP = "preventcontextoverlap",
6570
    _OBJ = "obj",
6571
    _SCOPE = "scope",
6572
    _NONE = "none",
6573
    _VISIBLE = "visible",
6574
    _SPACE = " ",
6575
    _MENUITEM = "MenuItem",
6576
    _CLICK = "click",
6577
    _SHOW = "show",
6578
    _HIDE = "hide",
6579
    _LI_LOWERCASE = "li",
6580
    _ANCHOR_TEMPLATE = "<a href=\"#\"></a>",
6581
 
6582
    EVENT_TYPES = [
6583
 
6584
        ["mouseOverEvent", "mouseover"],
6585
        ["mouseOutEvent", "mouseout"],
6586
        ["mouseDownEvent", "mousedown"],
6587
        ["mouseUpEvent", "mouseup"],
6588
        ["clickEvent", _CLICK],
6589
        ["keyPressEvent", "keypress"],
6590
        ["keyDownEvent", "keydown"],
6591
        ["keyUpEvent", "keyup"],
6592
        ["focusEvent", "focus"],
6593
        ["blurEvent", "blur"],
6594
        ["destroyEvent", "destroy"]
6595
 
6596
    ],
6597
 
6598
    TEXT_CONFIG = {
6599
        key: _TEXT,
6600
        value: _EMPTY_STRING,
6601
        validator: Lang.isString,
6602
        suppressEvent: true
6603
    },
6604
 
6605
    HELP_TEXT_CONFIG = {
6606
        key: _HELP_TEXT,
6607
        supercedes: [_TEXT],
6608
        suppressEvent: true
6609
    },
6610
 
6611
    URL_CONFIG = {
6612
        key: _URL,
6613
        value: _HASH,
6614
        suppressEvent: true
6615
    },
6616
 
6617
    TARGET_CONFIG = {
6618
        key: _TARGET,
6619
        suppressEvent: true
6620
    },
6621
 
6622
    EMPHASIS_CONFIG = {
6623
        key: _EMPHASIS,
6624
        value: false,
6625
        validator: Lang.isBoolean,
6626
        suppressEvent: true,
6627
        supercedes: [_TEXT]
6628
    },
6629
 
6630
    STRONG_EMPHASIS_CONFIG = {
6631
        key: _STRONG_EMPHASIS,
6632
        value: false,
6633
        validator: Lang.isBoolean,
6634
        suppressEvent: true,
6635
        supercedes: [_TEXT]
6636
    },
6637
 
6638
    CHECKED_CONFIG = {
6639
        key: _CHECKED,
6640
        value: false,
6641
        validator: Lang.isBoolean,
6642
        suppressEvent: true,
6643
        supercedes: [_DISABLED, _SELECTED]
6644
    },
6645
 
6646
    SUBMENU_CONFIG = {
6647
        key: _SUBMENU,
6648
        suppressEvent: true,
6649
        supercedes: [_DISABLED, _SELECTED]
6650
    },
6651
 
6652
    DISABLED_CONFIG = {
6653
        key: _DISABLED,
6654
        value: false,
6655
        validator: Lang.isBoolean,
6656
        suppressEvent: true,
6657
        supercedes: [_TEXT, _SELECTED]
6658
    },
6659
 
6660
    SELECTED_CONFIG = {
6661
        key: _SELECTED,
6662
        value: false,
6663
        validator: Lang.isBoolean,
6664
        suppressEvent: true
6665
    },
6666
 
6667
    ONCLICK_CONFIG = {
6668
        key: _ONCLICK,
6669
        suppressEvent: true
6670
    },
6671
 
6672
    CLASS_NAME_CONFIG = {
6673
        key: _CLASSNAME,
6674
        value: null,
6675
        validator: Lang.isString,
6676
        suppressEvent: true
6677
    },
6678
 
6679
    KEY_LISTENER_CONFIG = {
6680
        key: "keylistener",
6681
        value: null,
6682
        suppressEvent: true
6683
    },
6684
 
6685
    m_oMenuItemTemplate = null,
6686
 
6687
    CLASS_NAMES = {};
6688
 
6689
 
6690
/**
6691
* @method getClassNameForState
6692
* @description Returns a class name for the specified prefix and state.  If the class name does not
6693
* yet exist, it is created and stored in the CLASS_NAMES object to increase performance.
6694
* @private
6695
* @param {String} prefix String representing the prefix for the class name
6696
* @param {String} state String representing a state - "disabled," "checked," etc.
6697
*/
6698
var getClassNameForState = function (prefix, state) {
6699
 
6700
    var oClassNames = CLASS_NAMES[prefix];
6701
 
6702
    if (!oClassNames) {
6703
        CLASS_NAMES[prefix] = {};
6704
        oClassNames = CLASS_NAMES[prefix];
6705
    }
6706
 
6707
 
6708
    var sClassName = oClassNames[state];
6709
 
6710
    if (!sClassName) {
6711
        sClassName = prefix + _HYPHEN + state;
6712
        oClassNames[state] = sClassName;
6713
    }
6714
 
6715
    return sClassName;
6716
 
6717
};
6718
 
6719
 
6720
/**
6721
* @method addClassNameForState
6722
* @description Applies a class name to a MenuItem instance's &#60;LI&#62; and &#60;A&#62; elements
6723
* that represents a MenuItem's state - "disabled," "checked," etc.
6724
* @private
6725
* @param {String} state String representing a state - "disabled," "checked," etc.
6726
*/
6727
var addClassNameForState = function (state) {
6728
 
6729
    Dom.addClass(this.element, getClassNameForState(this.CSS_CLASS_NAME, state));
6730
    Dom.addClass(this._oAnchor, getClassNameForState(this.CSS_LABEL_CLASS_NAME, state));
6731
 
6732
};
6733
 
6734
/**
6735
* @method removeClassNameForState
6736
* @description Removes a class name from a MenuItem instance's &#60;LI&#62; and &#60;A&#62; elements
6737
* that represents a MenuItem's state - "disabled," "checked," etc.
6738
* @private
6739
* @param {String} state String representing a state - "disabled," "checked," etc.
6740
*/
6741
var removeClassNameForState = function (state) {
6742
 
6743
    Dom.removeClass(this.element, getClassNameForState(this.CSS_CLASS_NAME, state));
6744
    Dom.removeClass(this._oAnchor, getClassNameForState(this.CSS_LABEL_CLASS_NAME, state));
6745
 
6746
};
6747
 
6748
 
6749
MenuItem.prototype = {
6750
 
6751
    /**
6752
    * @property CSS_CLASS_NAME
6753
    * @description String representing the CSS class(es) to be applied to the
6754
    * <code>&#60;li&#62;</code> element of the menu item.
6755
    * @default "yuimenuitem"
6756
    * @final
6757
    * @type String
6758
    */
6759
    CSS_CLASS_NAME: "yuimenuitem",
6760
 
6761
 
6762
    /**
6763
    * @property CSS_LABEL_CLASS_NAME
6764
    * @description String representing the CSS class(es) to be applied to the
6765
    * menu item's <code>&#60;a&#62;</code> element.
6766
    * @default "yuimenuitemlabel"
6767
    * @final
6768
    * @type String
6769
    */
6770
    CSS_LABEL_CLASS_NAME: "yuimenuitemlabel",
6771
 
6772
 
6773
    /**
6774
    * @property SUBMENU_TYPE
6775
    * @description Object representing the type of menu to instantiate and
6776
    * add when parsing the child nodes of the menu item's source HTML element.
6777
    * @final
6778
    * @type YAHOO.widget.Menu
6779
    */
6780
    SUBMENU_TYPE: null,
6781
 
6782
 
6783
 
6784
    // Private member variables
6785
 
6786
 
6787
    /**
6788
    * @property _oAnchor
6789
    * @description Object reference to the menu item's
6790
    * <code>&#60;a&#62;</code> element.
6791
    * @default null
6792
    * @private
6793
    * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6794
    * one-html.html#ID-48250443">HTMLAnchorElement</a>
6795
    */
6796
    _oAnchor: null,
6797
 
6798
 
6799
    /**
6800
    * @property _oHelpTextEM
6801
    * @description Object reference to the menu item's help text
6802
    * <code>&#60;em&#62;</code> element.
6803
    * @default null
6804
    * @private
6805
    * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6806
    * one-html.html#ID-58190037">HTMLElement</a>
6807
    */
6808
    _oHelpTextEM: null,
6809
 
6810
 
6811
    /**
6812
    * @property _oSubmenu
6813
    * @description Object reference to the menu item's submenu.
6814
    * @default null
6815
    * @private
6816
    * @type YAHOO.widget.Menu
6817
    */
6818
    _oSubmenu: null,
6819
 
6820
 
6821
    /**
6822
    * @property _oOnclickAttributeValue
6823
    * @description Object reference to the menu item's current value for the
6824
    * "onclick" configuration attribute.
6825
    * @default null
6826
    * @private
6827
    * @type Object
6828
    */
6829
    _oOnclickAttributeValue: null,
6830
 
6831
 
6832
    /**
6833
    * @property _sClassName
6834
    * @description The current value of the "classname" configuration attribute.
6835
    * @default null
6836
    * @private
6837
    * @type String
6838
    */
6839
    _sClassName: null,
6840
 
6841
 
6842
 
6843
    // Public properties
6844
 
6845
 
6846
    /**
6847
    * @property constructor
6848
    * @description Object reference to the menu item's constructor function.
6849
    * @default YAHOO.widget.MenuItem
6850
    * @type YAHOO.widget.MenuItem
6851
    */
6852
    constructor: MenuItem,
6853
 
6854
 
6855
    /**
6856
    * @property index
6857
    * @description Number indicating the ordinal position of the menu item in
6858
    * its group.
6859
    * @default null
6860
    * @type Number
6861
    */
6862
    index: null,
6863
 
6864
 
6865
    /**
6866
    * @property groupIndex
6867
    * @description Number indicating the index of the group to which the menu
6868
    * item belongs.
6869
    * @default null
6870
    * @type Number
6871
    */
6872
    groupIndex: null,
6873
 
6874
 
6875
    /**
6876
    * @property parent
6877
    * @description Object reference to the menu item's parent menu.
6878
    * @default null
6879
    * @type YAHOO.widget.Menu
6880
    */
6881
    parent: null,
6882
 
6883
 
6884
    /**
6885
    * @property element
6886
    * @description Object reference to the menu item's
6887
    * <code>&#60;li&#62;</code> element.
6888
    * @default <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level
6889
    * -one-html.html#ID-74680021">HTMLLIElement</a>
6890
    * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6891
    * one-html.html#ID-74680021">HTMLLIElement</a>
6892
    */
6893
    element: null,
6894
 
6895
 
6896
    /**
6897
    * @property srcElement
6898
    * @description Object reference to the HTML element (either
6899
    * <code>&#60;li&#62;</code>, <code>&#60;optgroup&#62;</code> or
6900
    * <code>&#60;option&#62;</code>) used create the menu item.
6901
    * @default <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
6902
    * level-one-html.html#ID-74680021">HTMLLIElement</a>|<a href="http://www.
6903
    * w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-38450247"
6904
    * >HTMLOptGroupElement</a>|<a href="http://www.w3.org/TR/2000/WD-DOM-
6905
    * Level-1-20000929/level-one-html.html#ID-70901257">HTMLOptionElement</a>
6906
    * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6907
    * one-html.html#ID-74680021">HTMLLIElement</a>|<a href="http://www.w3.
6908
    * org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-38450247">
6909
    * HTMLOptGroupElement</a>|<a href="http://www.w3.org/TR/2000/WD-DOM-
6910
    * Level-1-20000929/level-one-html.html#ID-70901257">HTMLOptionElement</a>
6911
    */
6912
    srcElement: null,
6913
 
6914
 
6915
    /**
6916
    * @property value
6917
    * @description Object reference to the menu item's value.
6918
    * @default null
6919
    * @type Object
6920
    */
6921
    value: null,
6922
 
6923
 
6924
    /**
6925
    * @property browser
6926
    * @deprecated Use YAHOO.env.ua
6927
    * @description String representing the browser.
6928
    * @type String
6929
    */
6930
    browser: Module.prototype.browser,
6931
 
6932
 
6933
    /**
6934
    * @property id
6935
    * @description Id of the menu item's root <code>&#60;li&#62;</code>
6936
    * element.  This property should be set via the constructor using the
6937
    * configuration object literal.  If an id is not specified, then one will
6938
    * be created using the "generateId" method of the Dom utility.
6939
    * @default null
6940
    * @type String
6941
    */
6942
    id: null,
6943
 
6944
 
6945
 
6946
    // Events
6947
 
6948
 
6949
    /**
6950
    * @event destroyEvent
6951
    * @description Fires when the menu item's <code>&#60;li&#62;</code>
6952
    * element is removed from its parent <code>&#60;ul&#62;</code> element.
6953
    * @type YAHOO.util.CustomEvent
6954
    */
6955
 
6956
 
6957
    /**
6958
    * @event mouseOverEvent
6959
    * @description Fires when the mouse has entered the menu item.  Passes
6960
    * back the DOM Event object as an argument.
6961
    * @type YAHOO.util.CustomEvent
6962
    */
6963
 
6964
 
6965
    /**
6966
    * @event mouseOutEvent
6967
    * @description Fires when the mouse has left the menu item.  Passes back
6968
    * the DOM Event object as an argument.
6969
    * @type YAHOO.util.CustomEvent
6970
    */
6971
 
6972
 
6973
    /**
6974
    * @event mouseDownEvent
6975
    * @description Fires when the user mouses down on the menu item.  Passes
6976
    * back the DOM Event object as an argument.
6977
    * @type YAHOO.util.CustomEvent
6978
    */
6979
 
6980
 
6981
    /**
6982
    * @event mouseUpEvent
6983
    * @description Fires when the user releases a mouse button while the mouse
6984
    * is over the menu item.  Passes back the DOM Event object as an argument.
6985
    * @type YAHOO.util.CustomEvent
6986
    */
6987
 
6988
 
6989
    /**
6990
    * @event clickEvent
6991
    * @description Fires when the user clicks the on the menu item.  Passes
6992
    * back the DOM Event object as an argument.
6993
    * @type YAHOO.util.CustomEvent
6994
    */
6995
 
6996
 
6997
    /**
6998
    * @event keyPressEvent
6999
    * @description Fires when the user presses an alphanumeric key when the
7000
    * menu item has focus.  Passes back the DOM Event object as an argument.
7001
    * @type YAHOO.util.CustomEvent
7002
    */
7003
 
7004
 
7005
    /**
7006
    * @event keyDownEvent
7007
    * @description Fires when the user presses a key when the menu item has
7008
    * focus.  Passes back the DOM Event object as an argument.
7009
    * @type YAHOO.util.CustomEvent
7010
    */
7011
 
7012
 
7013
    /**
7014
    * @event keyUpEvent
7015
    * @description Fires when the user releases a key when the menu item has
7016
    * focus.  Passes back the DOM Event object as an argument.
7017
    * @type YAHOO.util.CustomEvent
7018
    */
7019
 
7020
 
7021
    /**
7022
    * @event focusEvent
7023
    * @description Fires when the menu item receives focus.
7024
    * @type YAHOO.util.CustomEvent
7025
    */
7026
 
7027
 
7028
    /**
7029
    * @event blurEvent
7030
    * @description Fires when the menu item loses the input focus.
7031
    * @type YAHOO.util.CustomEvent
7032
    */
7033
 
7034
 
7035
    /**
7036
    * @method init
7037
    * @description The MenuItem class's initialization method. This method is
7038
    * automatically called by the constructor, and sets up all DOM references
7039
    * for pre-existing markup, and creates required markup if it is not
7040
    * already present.
7041
    * @param {HTML} p_oObject Markup for the menu item content. The markup is inserted into the DOM as HTML, and should be escaped by the implementor if coming from an external source.
7042
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
7043
    * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying
7044
    * the <code>&#60;li&#62;</code> element of the menu item.
7045
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
7046
    * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
7047
    * specifying the <code>&#60;optgroup&#62;</code> element of the menu item.
7048
    * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
7049
    * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object
7050
    * specifying the <code>&#60;option&#62;</code> element of the menu item.
7051
    * @param {Object} p_oConfig Optional. Object literal specifying the
7052
    * configuration for the menu item. See configuration class documentation
7053
    * for more details.
7054
    */
7055
    init: function (p_oObject, p_oConfig) {
7056
 
7057
 
7058
        if (!this.SUBMENU_TYPE) {
7059
 
7060
            this.SUBMENU_TYPE = Menu;
7061
 
7062
        }
7063
 
7064
 
7065
        // Create the config object
7066
 
7067
        this.cfg = new YAHOO.util.Config(this);
7068
 
7069
        this.initDefaultConfig();
7070
 
7071
        var oConfig = this.cfg,
7072
            sURL = _HASH,
7073
            oCustomEvent,
7074
            aEventData,
7075
            oAnchor,
7076
            sTarget,
7077
            sText,
7078
            sId,
7079
            i;
7080
 
7081
 
7082
        if (Lang.isString(p_oObject)) {
7083
 
7084
            this._createRootNodeStructure();
7085
 
7086
            oConfig.queueProperty(_TEXT, p_oObject);
7087
 
7088
        }
7089
        else if (p_oObject && p_oObject.tagName) {
7090
 
7091
            switch(p_oObject.tagName.toUpperCase()) {
7092
 
7093
                case _OPTION:
7094
 
7095
                    this._createRootNodeStructure();
7096
 
7097
                    oConfig.queueProperty(_TEXT, p_oObject.text);
7098
                    oConfig.queueProperty(_DISABLED, p_oObject.disabled);
7099
 
7100
                    this.value = p_oObject.value;
7101
 
7102
                    this.srcElement = p_oObject;
7103
 
7104
                break;
7105
 
7106
                case _OPTGROUP:
7107
 
7108
                    this._createRootNodeStructure();
7109
 
7110
                    oConfig.queueProperty(_TEXT, p_oObject.label);
7111
                    oConfig.queueProperty(_DISABLED, p_oObject.disabled);
7112
 
7113
                    this.srcElement = p_oObject;
7114
 
7115
                    this._initSubTree();
7116
 
7117
                break;
7118
 
7119
                case _LI_UPPERCASE:
7120
 
7121
                    // Get the anchor node (if it exists)
7122
 
7123
                    oAnchor = Dom.getFirstChild(p_oObject);
7124
 
7125
 
7126
                    // Capture the "text" and/or the "URL"
7127
 
7128
                    if (oAnchor) {
7129
 
7130
                        sURL = oAnchor.getAttribute(_HREF, 2);
7131
                        sTarget = oAnchor.getAttribute(_TARGET);
7132
 
7133
                        sText = oAnchor.innerHTML;
7134
 
7135
                    }
7136
 
7137
                    this.srcElement = p_oObject;
7138
                    this.element = p_oObject;
7139
                    this._oAnchor = oAnchor;
7140
 
7141
                    /*
7142
                        Set these properties silently to sync up the
7143
                        configuration object without making changes to the
7144
                        element's DOM
7145
                    */
7146
 
7147
                    oConfig.setProperty(_TEXT, sText, true);
7148
                    oConfig.setProperty(_URL, sURL, true);
7149
                    oConfig.setProperty(_TARGET, sTarget, true);
7150
 
7151
                    this._initSubTree();
7152
 
7153
                break;
7154
 
7155
            }
7156
 
7157
        }
7158
 
7159
 
7160
        if (this.element) {
7161
 
7162
            sId = (this.srcElement || this.element).id;
7163
 
7164
            if (!sId) {
7165
 
7166
                sId = this.id || Dom.generateId();
7167
 
7168
                this.element.id = sId;
7169
 
7170
            }
7171
 
7172
            this.id = sId;
7173
 
7174
 
7175
            Dom.addClass(this.element, this.CSS_CLASS_NAME);
7176
            Dom.addClass(this._oAnchor, this.CSS_LABEL_CLASS_NAME);
7177
 
7178
 
7179
            i = EVENT_TYPES.length - 1;
7180
 
7181
            do {
7182
 
7183
                aEventData = EVENT_TYPES[i];
7184
 
7185
                oCustomEvent = this.createEvent(aEventData[1]);
7186
                oCustomEvent.signature = CustomEvent.LIST;
7187
 
7188
                this[aEventData[0]] = oCustomEvent;
7189
 
7190
            }
7191
            while (i--);
7192
 
7193
 
7194
            if (p_oConfig) {
7195
 
7196
                oConfig.applyConfig(p_oConfig);
7197
 
7198
            }
7199
 
7200
            oConfig.fireQueue();
7201
 
7202
        }
7203
 
7204
    },
7205
 
7206
 
7207
 
7208
    // Private methods
7209
 
7210
    /**
7211
    * @method _createRootNodeStructure
7212
    * @description Creates the core DOM structure for the menu item.
7213
    * @private
7214
    */
7215
    _createRootNodeStructure: function () {
7216
 
7217
        var oElement,
7218
            oAnchor;
7219
 
7220
        if (!m_oMenuItemTemplate) {
7221
 
7222
            m_oMenuItemTemplate = document.createElement(_LI_LOWERCASE);
7223
            m_oMenuItemTemplate.innerHTML = _ANCHOR_TEMPLATE;
7224
 
7225
        }
7226
 
7227
        oElement = m_oMenuItemTemplate.cloneNode(true);
7228
        oElement.className = this.CSS_CLASS_NAME;
7229
 
7230
        oAnchor = oElement.firstChild;
7231
        oAnchor.className = this.CSS_LABEL_CLASS_NAME;
7232
 
7233
        this.element = oElement;
7234
        this._oAnchor = oAnchor;
7235
 
7236
    },
7237
 
7238
 
7239
    /**
7240
    * @method _initSubTree
7241
    * @description Iterates the source element's childNodes collection and uses
7242
    * the child nodes to instantiate other menus.
7243
    * @private
7244
    */
7245
    _initSubTree: function () {
7246
 
7247
        var oSrcEl = this.srcElement,
7248
            oConfig = this.cfg,
7249
            oNode,
7250
            aOptions,
7251
            nOptions,
7252
            oMenu,
7253
            n;
7254
 
7255
 
7256
        if (oSrcEl.childNodes.length > 0) {
7257
 
7258
            if (this.parent.lazyLoad && this.parent.srcElement &&
7259
                this.parent.srcElement.tagName.toUpperCase() == _SELECT) {
7260
 
7261
                oConfig.setProperty(
7262
                        _SUBMENU,
7263
                        { id: Dom.generateId(), itemdata: oSrcEl.childNodes }
7264
                    );
7265
 
7266
            }
7267
            else {
7268
 
7269
                oNode = oSrcEl.firstChild;
7270
                aOptions = [];
7271
 
7272
                do {
7273
 
7274
                    if (oNode && oNode.tagName) {
7275
 
7276
                        switch(oNode.tagName.toUpperCase()) {
7277
 
7278
                            case _DIV:
7279
 
7280
                                oConfig.setProperty(_SUBMENU, oNode);
7281
 
7282
                            break;
7283
 
7284
                            case _OPTION:
7285
 
7286
                                aOptions[aOptions.length] = oNode;
7287
 
7288
                            break;
7289
 
7290
                        }
7291
 
7292
                    }
7293
 
7294
                }
7295
                while((oNode = oNode.nextSibling));
7296
 
7297
 
7298
                nOptions = aOptions.length;
7299
 
7300
                if (nOptions > 0) {
7301
 
7302
                    oMenu = new this.SUBMENU_TYPE(Dom.generateId());
7303
 
7304
                    oConfig.setProperty(_SUBMENU, oMenu);
7305
 
7306
                    for(n=0; n<nOptions; n++) {
7307
 
7308
                        oMenu.addItem((new oMenu.ITEM_TYPE(aOptions[n])));
7309
 
7310
                    }
7311
 
7312
                }
7313
 
7314
            }
7315
 
7316
        }
7317
 
7318
    },
7319
 
7320
 
7321
 
7322
    // Event handlers for configuration properties
7323
 
7324
 
7325
    /**
7326
    * @method configText
7327
    * @description Event handler for when the "text" configuration property of
7328
    * the menu item changes.
7329
    * @param {String} p_sType String representing the name of the event that
7330
    * was fired.
7331
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7332
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7333
    * that fired the event.
7334
    */
7335
    configText: function (p_sType, p_aArgs, p_oItem) {
7336
 
7337
        var sText = p_aArgs[0],
7338
            oConfig = this.cfg,
7339
            oAnchor = this._oAnchor,
7340
            sHelpText = oConfig.getProperty(_HELP_TEXT),
7341
            sHelpTextHTML = _EMPTY_STRING,
7342
            sEmphasisStartTag = _EMPTY_STRING,
7343
            sEmphasisEndTag = _EMPTY_STRING;
7344
 
7345
 
7346
        if (sText) {
7347
 
7348
 
7349
            if (sHelpText) {
7350
 
7351
                sHelpTextHTML = _START_HELP_TEXT + sHelpText + _END_EM;
7352
 
7353
            }
7354
 
7355
 
7356
            if (oConfig.getProperty(_EMPHASIS)) {
7357
 
7358
                sEmphasisStartTag = _START_EM;
7359
                sEmphasisEndTag = _END_EM;
7360
 
7361
            }
7362
 
7363
 
7364
            if (oConfig.getProperty(_STRONG_EMPHASIS)) {
7365
 
7366
                sEmphasisStartTag = _START_STRONG;
7367
                sEmphasisEndTag = _END_STRONG;
7368
 
7369
            }
7370
 
7371
 
7372
            oAnchor.innerHTML = (sEmphasisStartTag + sText + sEmphasisEndTag + sHelpTextHTML);
7373
 
7374
        }
7375
 
7376
    },
7377
 
7378
 
7379
    /**
7380
    * @method configHelpText
7381
    * @description Event handler for when the "helptext" configuration property
7382
    * of the menu item changes.
7383
    * @param {String} p_sType String representing the name of the event that
7384
    * was fired.
7385
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7386
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7387
    * that fired the event.
7388
    */
7389
    configHelpText: function (p_sType, p_aArgs, p_oItem) {
7390
 
7391
        this.cfg.refireEvent(_TEXT);
7392
 
7393
    },
7394
 
7395
 
7396
    /**
7397
    * @method configURL
7398
    * @description Event handler for when the "url" configuration property of
7399
    * the menu item changes.
7400
    * @param {String} p_sType String representing the name of the event that
7401
    * was fired.
7402
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7403
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7404
    * that fired the event.
7405
    */
7406
    configURL: function (p_sType, p_aArgs, p_oItem) {
7407
 
7408
        var sURL = p_aArgs[0];
7409
 
7410
        if (!sURL) {
7411
 
7412
            sURL = _HASH;
7413
 
7414
        }
7415
 
7416
        var oAnchor = this._oAnchor;
7417
 
7418
        if (UA.opera) {
7419
 
7420
            oAnchor.removeAttribute(_HREF);
7421
 
7422
        }
7423
 
7424
        oAnchor.setAttribute(_HREF, sURL);
7425
 
7426
    },
7427
 
7428
 
7429
    /**
7430
    * @method configTarget
7431
    * @description Event handler for when the "target" configuration property
7432
    * of the menu item changes.
7433
    * @param {String} p_sType String representing the name of the event that
7434
    * was fired.
7435
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7436
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7437
    * that fired the event.
7438
    */
7439
    configTarget: function (p_sType, p_aArgs, p_oItem) {
7440
 
7441
        var sTarget = p_aArgs[0],
7442
            oAnchor = this._oAnchor;
7443
 
7444
        if (sTarget && sTarget.length > 0) {
7445
 
7446
            oAnchor.setAttribute(_TARGET, sTarget);
7447
 
7448
        }
7449
        else {
7450
 
7451
            oAnchor.removeAttribute(_TARGET);
7452
 
7453
        }
7454
 
7455
    },
7456
 
7457
 
7458
    /**
7459
    * @method configEmphasis
7460
    * @description Event handler for when the "emphasis" configuration property
7461
    * of the menu item changes.
7462
    * @param {String} p_sType String representing the name of the event that
7463
    * was fired.
7464
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7465
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7466
    * that fired the event.
7467
    */
7468
    configEmphasis: function (p_sType, p_aArgs, p_oItem) {
7469
 
7470
        var bEmphasis = p_aArgs[0],
7471
            oConfig = this.cfg;
7472
 
7473
 
7474
        if (bEmphasis && oConfig.getProperty(_STRONG_EMPHASIS)) {
7475
 
7476
            oConfig.setProperty(_STRONG_EMPHASIS, false);
7477
 
7478
        }
7479
 
7480
 
7481
        oConfig.refireEvent(_TEXT);
7482
 
7483
    },
7484
 
7485
 
7486
    /**
7487
    * @method configStrongEmphasis
7488
    * @description Event handler for when the "strongemphasis" configuration
7489
    * property of the menu item changes.
7490
    * @param {String} p_sType String representing the name of the event that
7491
    * was fired.
7492
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7493
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7494
    * that fired the event.
7495
    */
7496
    configStrongEmphasis: function (p_sType, p_aArgs, p_oItem) {
7497
 
7498
        var bStrongEmphasis = p_aArgs[0],
7499
            oConfig = this.cfg;
7500
 
7501
 
7502
        if (bStrongEmphasis && oConfig.getProperty(_EMPHASIS)) {
7503
 
7504
            oConfig.setProperty(_EMPHASIS, false);
7505
 
7506
        }
7507
 
7508
        oConfig.refireEvent(_TEXT);
7509
 
7510
    },
7511
 
7512
 
7513
    /**
7514
    * @method configChecked
7515
    * @description Event handler for when the "checked" configuration property
7516
    * of the menu item changes.
7517
    * @param {String} p_sType String representing the name of the event that
7518
    * was fired.
7519
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7520
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7521
    * that fired the event.
7522
    */
7523
    configChecked: function (p_sType, p_aArgs, p_oItem) {
7524
 
7525
        var bChecked = p_aArgs[0],
7526
            oConfig = this.cfg;
7527
 
7528
 
7529
        if (bChecked) {
7530
 
7531
            addClassNameForState.call(this, _CHECKED);
7532
 
7533
        }
7534
        else {
7535
 
7536
            removeClassNameForState.call(this, _CHECKED);
7537
        }
7538
 
7539
 
7540
        oConfig.refireEvent(_TEXT);
7541
 
7542
 
7543
        if (oConfig.getProperty(_DISABLED)) {
7544
 
7545
            oConfig.refireEvent(_DISABLED);
7546
 
7547
        }
7548
 
7549
 
7550
        if (oConfig.getProperty(_SELECTED)) {
7551
 
7552
            oConfig.refireEvent(_SELECTED);
7553
 
7554
        }
7555
 
7556
    },
7557
 
7558
 
7559
 
7560
    /**
7561
    * @method configDisabled
7562
    * @description Event handler for when the "disabled" configuration property
7563
    * of the menu item changes.
7564
    * @param {String} p_sType String representing the name of the event that
7565
    * was fired.
7566
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7567
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7568
    * that fired the event.
7569
    */
7570
    configDisabled: function (p_sType, p_aArgs, p_oItem) {
7571
 
7572
        var bDisabled = p_aArgs[0],
7573
            oConfig = this.cfg,
7574
            oSubmenu = oConfig.getProperty(_SUBMENU),
7575
            bChecked = oConfig.getProperty(_CHECKED);
7576
 
7577
 
7578
        if (bDisabled) {
7579
 
7580
            if (oConfig.getProperty(_SELECTED)) {
7581
 
7582
                oConfig.setProperty(_SELECTED, false);
7583
 
7584
            }
7585
 
7586
 
7587
            addClassNameForState.call(this, _DISABLED);
7588
 
7589
 
7590
            if (oSubmenu) {
7591
 
7592
                addClassNameForState.call(this, _HAS_SUBMENU_DISABLED);
7593
 
7594
            }
7595
 
7596
 
7597
            if (bChecked) {
7598
 
7599
                addClassNameForState.call(this, _CHECKED_DISABLED);
7600
 
7601
            }
7602
 
7603
        }
7604
        else {
7605
 
7606
            removeClassNameForState.call(this, _DISABLED);
7607
 
7608
 
7609
            if (oSubmenu) {
7610
 
7611
                removeClassNameForState.call(this, _HAS_SUBMENU_DISABLED);
7612
 
7613
            }
7614
 
7615
 
7616
            if (bChecked) {
7617
 
7618
                removeClassNameForState.call(this, _CHECKED_DISABLED);
7619
 
7620
            }
7621
 
7622
        }
7623
 
7624
    },
7625
 
7626
 
7627
    /**
7628
    * @method configSelected
7629
    * @description Event handler for when the "selected" configuration property
7630
    * of the menu item changes.
7631
    * @param {String} p_sType String representing the name of the event that
7632
    * was fired.
7633
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7634
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7635
    * that fired the event.
7636
    */
7637
    configSelected: function (p_sType, p_aArgs, p_oItem) {
7638
 
7639
        var oConfig = this.cfg,
7640
            oAnchor = this._oAnchor,
7641
 
7642
            bSelected = p_aArgs[0],
7643
            bChecked = oConfig.getProperty(_CHECKED),
7644
            oSubmenu = oConfig.getProperty(_SUBMENU);
7645
 
7646
 
7647
        if (UA.opera) {
7648
 
7649
            oAnchor.blur();
7650
 
7651
        }
7652
 
7653
 
7654
        if (bSelected && !oConfig.getProperty(_DISABLED)) {
7655
 
7656
            addClassNameForState.call(this, _SELECTED);
7657
 
7658
 
7659
            if (oSubmenu) {
7660
 
7661
                addClassNameForState.call(this, _HAS_SUBMENU_SELECTED);
7662
 
7663
            }
7664
 
7665
 
7666
            if (bChecked) {
7667
 
7668
                addClassNameForState.call(this, _CHECKED_SELECTED);
7669
 
7670
            }
7671
 
7672
        }
7673
        else {
7674
 
7675
            removeClassNameForState.call(this, _SELECTED);
7676
 
7677
 
7678
            if (oSubmenu) {
7679
 
7680
                removeClassNameForState.call(this, _HAS_SUBMENU_SELECTED);
7681
 
7682
            }
7683
 
7684
 
7685
            if (bChecked) {
7686
 
7687
                removeClassNameForState.call(this, _CHECKED_SELECTED);
7688
 
7689
            }
7690
 
7691
        }
7692
 
7693
 
7694
        if (this.hasFocus() && UA.opera) {
7695
 
7696
            oAnchor.focus();
7697
 
7698
        }
7699
 
7700
    },
7701
 
7702
 
7703
    /**
7704
    * @method _onSubmenuBeforeHide
7705
    * @description "beforehide" Custom Event handler for a submenu.
7706
    * @private
7707
    * @param {String} p_sType String representing the name of the event that
7708
    * was fired.
7709
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7710
    */
7711
    _onSubmenuBeforeHide: function (p_sType, p_aArgs) {
7712
 
7713
        var oItem = this.parent,
7714
            oMenu;
7715
 
7716
        function onHide() {
7717
 
7718
            oItem._oAnchor.blur();
7719
            oMenu.beforeHideEvent.unsubscribe(onHide);
7720
 
7721
        }
7722
 
7723
 
7724
        if (oItem.hasFocus()) {
7725
 
7726
            oMenu = oItem.parent;
7727
 
7728
            oMenu.beforeHideEvent.subscribe(onHide);
7729
 
7730
        }
7731
 
7732
    },
7733
 
7734
 
7735
    /**
7736
    * @method configSubmenu
7737
    * @description Event handler for when the "submenu" configuration property
7738
    * of the menu item changes.
7739
    * @param {String} p_sType String representing the name of the event that
7740
    * was fired.
7741
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7742
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7743
    * that fired the event.
7744
    */
7745
    configSubmenu: function (p_sType, p_aArgs, p_oItem) {
7746
 
7747
        var oSubmenu = p_aArgs[0],
7748
            oConfig = this.cfg,
7749
            bLazyLoad = this.parent && this.parent.lazyLoad,
7750
            oMenu,
7751
            sSubmenuId,
7752
            oSubmenuConfig;
7753
 
7754
 
7755
        if (oSubmenu) {
7756
 
7757
            if (oSubmenu instanceof Menu) {
7758
 
7759
                oMenu = oSubmenu;
7760
                oMenu.parent = this;
7761
                oMenu.lazyLoad = bLazyLoad;
7762
 
7763
            }
7764
            else if (Lang.isObject(oSubmenu) && oSubmenu.id && !oSubmenu.nodeType) {
7765
 
7766
                sSubmenuId = oSubmenu.id;
7767
                oSubmenuConfig = oSubmenu;
7768
 
7769
                oSubmenuConfig.lazyload = bLazyLoad;
7770
                oSubmenuConfig.parent = this;
7771
 
7772
                oMenu = new this.SUBMENU_TYPE(sSubmenuId, oSubmenuConfig);
7773
 
7774
 
7775
                // Set the value of the property to the Menu instance
7776
 
7777
                oConfig.setProperty(_SUBMENU, oMenu, true);
7778
 
7779
            }
7780
            else {
7781
 
7782
                oMenu = new this.SUBMENU_TYPE(oSubmenu, { lazyload: bLazyLoad, parent: this });
7783
 
7784
 
7785
                // Set the value of the property to the Menu instance
7786
 
7787
                oConfig.setProperty(_SUBMENU, oMenu, true);
7788
 
7789
            }
7790
 
7791
 
7792
            if (oMenu) {
7793
 
7794
                oMenu.cfg.setProperty(_PREVENT_CONTEXT_OVERLAP, true);
7795
 
7796
                addClassNameForState.call(this, _HAS_SUBMENU);
7797
 
7798
 
7799
                if (oConfig.getProperty(_URL) === _HASH) {
7800
 
7801
                    oConfig.setProperty(_URL, (_HASH + oMenu.id));
7802
 
7803
                }
7804
 
7805
 
7806
                this._oSubmenu = oMenu;
7807
 
7808
 
7809
                if (UA.opera) {
7810
 
7811
                    oMenu.beforeHideEvent.subscribe(this._onSubmenuBeforeHide);
7812
 
7813
                }
7814
 
7815
            }
7816
 
7817
        }
7818
        else {
7819
 
7820
            removeClassNameForState.call(this, _HAS_SUBMENU);
7821
 
7822
            if (this._oSubmenu) {
7823
 
7824
                this._oSubmenu.destroy();
7825
 
7826
            }
7827
 
7828
        }
7829
 
7830
 
7831
        if (oConfig.getProperty(_DISABLED)) {
7832
 
7833
            oConfig.refireEvent(_DISABLED);
7834
 
7835
        }
7836
 
7837
 
7838
        if (oConfig.getProperty(_SELECTED)) {
7839
 
7840
            oConfig.refireEvent(_SELECTED);
7841
 
7842
        }
7843
 
7844
    },
7845
 
7846
 
7847
    /**
7848
    * @method configOnClick
7849
    * @description Event handler for when the "onclick" configuration property
7850
    * of the menu item changes.
7851
    * @param {String} p_sType String representing the name of the event that
7852
    * was fired.
7853
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7854
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7855
    * that fired the event.
7856
    */
7857
    configOnClick: function (p_sType, p_aArgs, p_oItem) {
7858
 
7859
        var oObject = p_aArgs[0];
7860
 
7861
        /*
7862
            Remove any existing listeners if a "click" event handler has
7863
            already been specified.
7864
        */
7865
 
7866
        if (this._oOnclickAttributeValue && (this._oOnclickAttributeValue != oObject)) {
7867
 
7868
            this.clickEvent.unsubscribe(this._oOnclickAttributeValue.fn,
7869
                                this._oOnclickAttributeValue.obj);
7870
 
7871
            this._oOnclickAttributeValue = null;
7872
 
7873
        }
7874
 
7875
 
7876
        if (!this._oOnclickAttributeValue && Lang.isObject(oObject) &&
7877
            Lang.isFunction(oObject.fn)) {
7878
 
7879
            this.clickEvent.subscribe(oObject.fn,
7880
                ((_OBJ in oObject) ? oObject.obj : this),
7881
                ((_SCOPE in oObject) ? oObject.scope : null) );
7882
 
7883
            this._oOnclickAttributeValue = oObject;
7884
 
7885
        }
7886
 
7887
    },
7888
 
7889
 
7890
    /**
7891
    * @method configClassName
7892
    * @description Event handler for when the "classname" configuration
7893
    * property of a menu item changes.
7894
    * @param {String} p_sType String representing the name of the event that
7895
    * was fired.
7896
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7897
    * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7898
    * that fired the event.
7899
    */
7900
    configClassName: function (p_sType, p_aArgs, p_oItem) {
7901
 
7902
        var sClassName = p_aArgs[0];
7903
 
7904
        if (this._sClassName) {
7905
 
7906
            Dom.removeClass(this.element, this._sClassName);
7907
 
7908
        }
7909
 
7910
        Dom.addClass(this.element, sClassName);
7911
        this._sClassName = sClassName;
7912
 
7913
    },
7914
 
7915
 
7916
    /**
7917
    * @method _dispatchClickEvent
7918
    * @description Dispatches a DOM "click" event to the anchor element of a
7919
    * MenuItem instance.
7920
    * @private
7921
    */
7922
    _dispatchClickEvent: function () {
7923
 
7924
        var oMenuItem = this,
7925
            oAnchor;
7926
 
7927
        if (!oMenuItem.cfg.getProperty(_DISABLED)) {
7928
            oAnchor = Dom.getFirstChild(oMenuItem.element);
7929
 
7930
            //	Dispatch a "click" event to the MenuItem's anchor so that its
7931
            //	"click" event handlers will get called in response to the user
7932
            //	pressing the keyboard shortcut defined by the "keylistener"
7933
            //	configuration property.
7934
 
7935
            this._dispatchDOMClick(oAnchor);
7936
        }
7937
    },
7938
 
7939
    /**
7940
     * Utility method to dispatch a DOM click event on the HTMLElement passed in
7941
     *
7942
     * @method _dispatchDOMClick
7943
     * @protected
7944
     * @param {HTMLElement} el
7945
     */
7946
    _dispatchDOMClick : function(el) {
7947
        var oEvent;
7948
 
7949
        // Choose the standards path for IE9
7950
        if (UA.ie && UA.ie < 9) {
7951
            el.fireEvent(_ONCLICK);
7952
        } else {
7953
            if ((UA.gecko && UA.gecko >= 1.9) || UA.opera || UA.webkit) {
7954
                oEvent = document.createEvent("HTMLEvents");
7955
                oEvent.initEvent(_CLICK, true, true);
7956
            } else {
7957
                oEvent = document.createEvent("MouseEvents");
7958
                oEvent.initMouseEvent(_CLICK, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
7959
            }
7960
            el.dispatchEvent(oEvent);
7961
        }
7962
    },
7963
 
7964
    /**
7965
    * @method _createKeyListener
7966
    * @description "show" event handler for a Menu instance - responsible for
7967
    * setting up the KeyListener instance for a MenuItem.
7968
    * @private
7969
    * @param {String} type String representing the name of the event that
7970
    * was fired.
7971
    * @param {Array} args Array of arguments sent when the event was fired.
7972
    * @param {Array} keyData Array of arguments sent when the event was fired.
7973
    */
7974
    _createKeyListener: function (type, args, keyData) {
7975
 
7976
        var oMenuItem = this,
7977
            oMenu = oMenuItem.parent;
7978
 
7979
        var oKeyListener = new YAHOO.util.KeyListener(
7980
                                        oMenu.element.ownerDocument,
7981
                                        keyData,
7982
                                        {
7983
                                            fn: oMenuItem._dispatchClickEvent,
7984
                                            scope: oMenuItem,
7985
                                            correctScope: true });
7986
 
7987
 
7988
        if (oMenu.cfg.getProperty(_VISIBLE)) {
7989
            oKeyListener.enable();
7990
        }
7991
 
7992
 
7993
        oMenu.subscribe(_SHOW, oKeyListener.enable, null, oKeyListener);
7994
        oMenu.subscribe(_HIDE, oKeyListener.disable, null, oKeyListener);
7995
 
7996
        oMenuItem._keyListener = oKeyListener;
7997
 
7998
        oMenu.unsubscribe(_SHOW, oMenuItem._createKeyListener, keyData);
7999
 
8000
    },
8001
 
8002
 
8003
    /**
8004
    * @method configKeyListener
8005
    * @description Event handler for when the "keylistener" configuration
8006
    * property of a menu item changes.
8007
    * @param {String} p_sType String representing the name of the event that
8008
    * was fired.
8009
    * @param {Array} p_aArgs Array of arguments sent when the event was fired.
8010
    */
8011
    configKeyListener: function (p_sType, p_aArgs) {
8012
 
8013
        var oKeyData = p_aArgs[0],
8014
            oMenuItem = this,
8015
            oMenu = oMenuItem.parent;
8016
 
8017
        if (oMenuItem._keyData) {
8018
 
8019
            //	Unsubscribe from the "show" event in case the keylistener
8020
            //	config was changed before the Menu was ever made visible.
8021
 
8022
            oMenu.unsubscribe(_SHOW,
8023
                    oMenuItem._createKeyListener, oMenuItem._keyData);
8024
 
8025
            oMenuItem._keyData = null;
8026
 
8027
        }
8028
 
8029
 
8030
        //	Tear down for the previous value of the "keylistener" property
8031
 
8032
        if (oMenuItem._keyListener) {
8033
 
8034
            oMenu.unsubscribe(_SHOW, oMenuItem._keyListener.enable);
8035
            oMenu.unsubscribe(_HIDE, oMenuItem._keyListener.disable);
8036
 
8037
            oMenuItem._keyListener.disable();
8038
            oMenuItem._keyListener = null;
8039
 
8040
        }
8041
 
8042
 
8043
        if (oKeyData) {
8044
 
8045
            oMenuItem._keyData = oKeyData;
8046
 
8047
            //	Defer the creation of the KeyListener instance until the
8048
            //	parent Menu is visible.  This is necessary since the
8049
            //	KeyListener instance needs to be bound to the document the
8050
            //	Menu has been rendered into.  Deferring creation of the
8051
            //	KeyListener instance also improves performance.
8052
 
8053
            oMenu.subscribe(_SHOW, oMenuItem._createKeyListener,
8054
                oKeyData, oMenuItem);
8055
        }
8056
 
8057
    },
8058
 
8059
 
8060
    // Public methods
8061
 
8062
 
8063
    /**
8064
    * @method initDefaultConfig
8065
    * @description Initializes an item's configurable properties.
8066
    */
8067
    initDefaultConfig : function () {
8068
 
8069
        var oConfig = this.cfg;
8070
 
8071
 
8072
        // Define the configuration attributes
8073
 
8074
        /**
8075
        * @config text
8076
        * @description String or markup specifying the text label for the menu item.
8077
        * When building a menu from existing HTML the value of this property
8078
        * will be interpreted from the menu's markup. The text is inserted into the DOM as HTML, and should be escaped by the implementor if coming from an external source.
8079
        * @default ""
8080
        * @type HTML
8081
        */
8082
        oConfig.addProperty(
8083
            TEXT_CONFIG.key,
8084
            {
8085
                handler: this.configText,
8086
                value: TEXT_CONFIG.value,
8087
                validator: TEXT_CONFIG.validator,
8088
                suppressEvent: TEXT_CONFIG.suppressEvent
8089
            }
8090
        );
8091
 
8092
 
8093
        /**
8094
        * @config helptext
8095
        * @description String or markup specifying additional instructional text to
8096
        * accompany the text for the menu item. The helptext is inserted into the DOM as HTML, and should be escaped by the implementor if coming from an external source.
8097
        * @deprecated Use "text" configuration property to add help text markup.
8098
        * For example: <code>oMenuItem.cfg.setProperty("text", "Copy &#60;em
8099
        * class=\"helptext\"&#62;Ctrl + C&#60;/em&#62;");</code>
8100
        * @default null
8101
        * @type HTML|<a href="http://www.w3.org/TR/
8102
        * 2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-58190037">
8103
        * HTMLElement</a>
8104
        */
8105
        oConfig.addProperty(
8106
            HELP_TEXT_CONFIG.key,
8107
            {
8108
                handler: this.configHelpText,
8109
                supercedes: HELP_TEXT_CONFIG.supercedes,
8110
                suppressEvent: HELP_TEXT_CONFIG.suppressEvent
8111
            }
8112
        );
8113
 
8114
 
8115
        /**
8116
        * @config url
8117
        * @description String specifying the URL for the menu item's anchor's
8118
        * "href" attribute.  When building a menu from existing HTML the value
8119
        * of this property will be interpreted from the menu's markup. Markup for the menu item content. The url is inserted into the DOM as an attribute value, and should be escaped by the implementor if coming from an external source.
8120
        * @default "#"
8121
        * @type String
8122
        */
8123
        oConfig.addProperty(
8124
            URL_CONFIG.key,
8125
            {
8126
                handler: this.configURL,
8127
                value: URL_CONFIG.value,
8128
                suppressEvent: URL_CONFIG.suppressEvent
8129
            }
8130
        );
8131
 
8132
 
8133
        /**
8134
        * @config target
8135
        * @description String specifying the value for the "target" attribute
8136
        * of the menu item's anchor element. <strong>Specifying a target will
8137
        * require the user to click directly on the menu item's anchor node in
8138
        * order to cause the browser to navigate to the specified URL.</strong>
8139
        * When building a menu from existing HTML the value of this property
8140
        * will be interpreted from the menu's markup. The target is inserted into the DOM as an attribute value, and should be escaped by the implementor if coming from an external source.
8141
        * @default null
8142
        * @type String
8143
        */
8144
        oConfig.addProperty(
8145
            TARGET_CONFIG.key,
8146
            {
8147
                handler: this.configTarget,
8148
                suppressEvent: TARGET_CONFIG.suppressEvent
8149
            }
8150
        );
8151
 
8152
 
8153
        /**
8154
        * @config emphasis
8155
        * @description Boolean indicating if the text of the menu item will be
8156
        * rendered with emphasis.
8157
        * @deprecated Use the "text" configuration property to add emphasis.
8158
        * For example: <code>oMenuItem.cfg.setProperty("text", "&#60;em&#62;Some
8159
        * Text&#60;/em&#62;");</code>
8160
        * @default false
8161
        * @type Boolean
8162
        */
8163
        oConfig.addProperty(
8164
            EMPHASIS_CONFIG.key,
8165
            {
8166
                handler: this.configEmphasis,
8167
                value: EMPHASIS_CONFIG.value,
8168
                validator: EMPHASIS_CONFIG.validator,
8169
                suppressEvent: EMPHASIS_CONFIG.suppressEvent,
8170
                supercedes: EMPHASIS_CONFIG.supercedes
8171
            }
8172
        );
8173
 
8174
 
8175
        /**
8176
        * @config strongemphasis
8177
        * @description Boolean indicating if the text of the menu item will be
8178
        * rendered with strong emphasis.
8179
        * @deprecated Use the "text" configuration property to add strong emphasis.
8180
        * For example: <code>oMenuItem.cfg.setProperty("text", "&#60;strong&#62;
8181
        * Some Text&#60;/strong&#62;");</code>
8182
        * @default false
8183
        * @type Boolean
8184
        */
8185
        oConfig.addProperty(
8186
            STRONG_EMPHASIS_CONFIG.key,
8187
            {
8188
                handler: this.configStrongEmphasis,
8189
                value: STRONG_EMPHASIS_CONFIG.value,
8190
                validator: STRONG_EMPHASIS_CONFIG.validator,
8191
                suppressEvent: STRONG_EMPHASIS_CONFIG.suppressEvent,
8192
                supercedes: STRONG_EMPHASIS_CONFIG.supercedes
8193
            }
8194
        );
8195
 
8196
 
8197
        /**
8198
        * @config checked
8199
        * @description Boolean indicating if the menu item should be rendered
8200
        * with a checkmark.
8201
        * @default false
8202
        * @type Boolean
8203
        */
8204
        oConfig.addProperty(
8205
            CHECKED_CONFIG.key,
8206
            {
8207
                handler: this.configChecked,
8208
                value: CHECKED_CONFIG.value,
8209
                validator: CHECKED_CONFIG.validator,
8210
                suppressEvent: CHECKED_CONFIG.suppressEvent,
8211
                supercedes: CHECKED_CONFIG.supercedes
8212
            }
8213
        );
8214
 
8215
 
8216
        /**
8217
        * @config disabled
8218
        * @description Boolean indicating if the menu item should be disabled.
8219
        * (Disabled menu items are  dimmed and will not respond to user input
8220
        * or fire events.)
8221
        * @default false
8222
        * @type Boolean
8223
        */
8224
        oConfig.addProperty(
8225
            DISABLED_CONFIG.key,
8226
            {
8227
                handler: this.configDisabled,
8228
                value: DISABLED_CONFIG.value,
8229
                validator: DISABLED_CONFIG.validator,
8230
                suppressEvent: DISABLED_CONFIG.suppressEvent
8231
            }
8232
        );
8233
 
8234
 
8235
        /**
8236
        * @config selected
8237
        * @description Boolean indicating if the menu item should
8238
        * be highlighted.
8239
        * @default false
8240
        * @type Boolean
8241
        */
8242
        oConfig.addProperty(
8243
            SELECTED_CONFIG.key,
8244
            {
8245
                handler: this.configSelected,
8246
                value: SELECTED_CONFIG.value,
8247
                validator: SELECTED_CONFIG.validator,
8248
                suppressEvent: SELECTED_CONFIG.suppressEvent
8249
            }
8250
        );
8251
 
8252
 
8253
        /**
8254
        * @config submenu
8255
        * @description Object specifying the submenu to be appended to the
8256
        * menu item.  The value can be one of the following: <ul><li>Object
8257
        * specifying a Menu instance.</li><li>Object literal specifying the
8258
        * menu to be created.  Format: <code>{ id: [menu id], itemdata:
8259
        * [<a href="YAHOO.widget.Menu.html#itemData">array of values for
8260
        * items</a>] }</code>.</li><li>String specifying the id attribute
8261
        * of the <code>&#60;div&#62;</code> element of the menu.</li><li>
8262
        * Object specifying the <code>&#60;div&#62;</code> element of the
8263
        * menu.</li></ul>
8264
        * @default null
8265
        * @type Menu|String|Object|<a href="http://www.w3.org/TR/2000/
8266
        * WD-DOM-Level-1-20000929/level-one-html.html#ID-58190037">
8267
        * HTMLElement</a>
8268
        */
8269
        oConfig.addProperty(
8270
            SUBMENU_CONFIG.key,
8271
            {
8272
                handler: this.configSubmenu,
8273
                supercedes: SUBMENU_CONFIG.supercedes,
8274
                suppressEvent: SUBMENU_CONFIG.suppressEvent
8275
            }
8276
        );
8277
 
8278
 
8279
        /**
8280
        * @config onclick
8281
        * @description Object literal representing the code to be executed when
8282
        * the item is clicked.  Format:<br> <code> {<br>
8283
        * <strong>fn:</strong> Function,   &#47;&#47; The handler to call when
8284
        * the event fires.<br> <strong>obj:</strong> Object, &#47;&#47; An
8285
        * object to  pass back to the handler.<br> <strong>scope:</strong>
8286
        * Object &#47;&#47; The object to use for the scope of the handler.
8287
        * <br> } </code>
8288
        * @type Object
8289
        * @default null
8290
        */
8291
        oConfig.addProperty(
8292
            ONCLICK_CONFIG.key,
8293
            {
8294
                handler: this.configOnClick,
8295
                suppressEvent: ONCLICK_CONFIG.suppressEvent
8296
            }
8297
        );
8298
 
8299
 
8300
        /**
8301
        * @config classname
8302
        * @description CSS class to be applied to the menu item's root
8303
        * <code>&#60;li&#62;</code> element.  The specified class(es) are
8304
        * appended in addition to the default class as specified by the menu
8305
        * item's CSS_CLASS_NAME constant.
8306
        * @default null
8307
        * @type String
8308
        */
8309
        oConfig.addProperty(
8310
            CLASS_NAME_CONFIG.key,
8311
            {
8312
                handler: this.configClassName,
8313
                value: CLASS_NAME_CONFIG.value,
8314
                validator: CLASS_NAME_CONFIG.validator,
8315
                suppressEvent: CLASS_NAME_CONFIG.suppressEvent
8316
            }
8317
        );
8318
 
8319
 
8320
        /**
8321
        * @config keylistener
8322
        * @description Object literal representing the key(s) that can be used
8323
        * to trigger the MenuItem's "click" event.  Possible attributes are
8324
        * shift (boolean), alt (boolean), ctrl (boolean) and keys (either an int
8325
        * or an array of ints representing keycodes).
8326
        * @default null
8327
        * @type Object
8328
        */
8329
        oConfig.addProperty(
8330
            KEY_LISTENER_CONFIG.key,
8331
            {
8332
                handler: this.configKeyListener,
8333
                value: KEY_LISTENER_CONFIG.value,
8334
                suppressEvent: KEY_LISTENER_CONFIG.suppressEvent
8335
            }
8336
        );
8337
 
8338
    },
8339
 
8340
    /**
8341
    * @method getNextSibling
8342
    * @description Finds the menu item's next sibling.
8343
    * @return YAHOO.widget.MenuItem
8344
    */
8345
    getNextSibling: function () {
8346
 
8347
        var isUL = function (el) {
8348
                return (el.nodeName.toLowerCase() === "ul");
8349
            },
8350
 
8351
            menuitemEl = this.element,
8352
            next = Dom.getNextSibling(menuitemEl),
8353
            parent,
8354
            sibling,
8355
            list;
8356
 
8357
        if (!next) {
8358
 
8359
            parent = menuitemEl.parentNode;
8360
            sibling = Dom.getNextSiblingBy(parent, isUL);
8361
 
8362
            if (sibling) {
8363
                list = sibling;
8364
            }
8365
            else {
8366
                list = Dom.getFirstChildBy(parent.parentNode, isUL);
8367
            }
8368
 
8369
            next = Dom.getFirstChild(list);
8370
 
8371
        }
8372
 
8373
        return YAHOO.widget.MenuManager.getMenuItem(next.id);
8374
 
8375
    },
8376
 
8377
    /**
8378
    * @method getNextEnabledSibling
8379
    * @description Finds the menu item's next enabled sibling.
8380
    * @return YAHOO.widget.MenuItem
8381
    */
8382
    getNextEnabledSibling: function () {
8383
 
8384
        var next = this.getNextSibling();
8385
 
8386
        return (next.cfg.getProperty(_DISABLED) || next.element.style.display == _NONE) ? next.getNextEnabledSibling() : next;
8387
 
8388
    },
8389
 
8390
 
8391
    /**
8392
    * @method getPreviousSibling
8393
    * @description Finds the menu item's previous sibling.
8394
    * @return {YAHOO.widget.MenuItem}
8395
    */
8396
    getPreviousSibling: function () {
8397
 
8398
        var isUL = function (el) {
8399
                return (el.nodeName.toLowerCase() === "ul");
8400
            },
8401
 
8402
            menuitemEl = this.element,
8403
            next = Dom.getPreviousSibling(menuitemEl),
8404
            parent,
8405
            sibling,
8406
            list;
8407
 
8408
        if (!next) {
8409
 
8410
            parent = menuitemEl.parentNode;
8411
            sibling = Dom.getPreviousSiblingBy(parent, isUL);
8412
 
8413
            if (sibling) {
8414
                list = sibling;
8415
            }
8416
            else {
8417
                list = Dom.getLastChildBy(parent.parentNode, isUL);
8418
            }
8419
 
8420
            next = Dom.getLastChild(list);
8421
 
8422
        }
8423
 
8424
        return YAHOO.widget.MenuManager.getMenuItem(next.id);
8425
 
8426
    },
8427
 
8428
 
8429
    /**
8430
    * @method getPreviousEnabledSibling
8431
    * @description Finds the menu item's previous enabled sibling.
8432
    * @return {YAHOO.widget.MenuItem}
8433
    */
8434
    getPreviousEnabledSibling: function () {
8435
 
8436
        var next = this.getPreviousSibling();
8437
 
8438
        return (next.cfg.getProperty(_DISABLED) || next.element.style.display == _NONE) ? next.getPreviousEnabledSibling() : next;
8439
 
8440
    },
8441
 
8442
 
8443
    /**
8444
    * @method focus
8445
    * @description Causes the menu item to receive the focus and fires the
8446
    * focus event.
8447
    */
8448
    focus: function () {
8449
 
8450
        var oParent = this.parent,
8451
            oAnchor = this._oAnchor,
8452
            oActiveItem = oParent.activeItem;
8453
 
8454
 
8455
        function setFocus() {
8456
 
8457
            try {
8458
 
8459
                if (!(UA.ie && !document.hasFocus())) {
8460
 
8461
                    if (oActiveItem) {
8462
 
8463
                        oActiveItem.blurEvent.fire();
8464
 
8465
                    }
8466
 
8467
                    oAnchor.focus();
8468
 
8469
                    this.focusEvent.fire();
8470
 
8471
                }
8472
 
8473
            }
8474
            catch(e) {
8475
 
8476
            }
8477
 
8478
        }
8479
 
8480
 
8481
        if (!this.cfg.getProperty(_DISABLED) && oParent && oParent.cfg.getProperty(_VISIBLE) &&
8482
            this.element.style.display != _NONE) {
8483
 
8484
 
8485
            /*
8486
                Setting focus via a timer fixes a race condition in Firefox, IE
8487
                and Opera where the browser viewport jumps as it trys to
8488
                position and focus the menu.
8489
            */
8490
 
8491
            Lang.later(0, this, setFocus);
8492
 
8493
        }
8494
 
8495
    },
8496
 
8497
 
8498
    /**
8499
    * @method blur
8500
    * @description Causes the menu item to lose focus and fires the
8501
    * blur event.
8502
    */
8503
    blur: function () {
8504
 
8505
        var oParent = this.parent;
8506
 
8507
        if (!this.cfg.getProperty(_DISABLED) && oParent && oParent.cfg.getProperty(_VISIBLE)) {
8508
 
8509
            Lang.later(0, this, function () {
8510
 
8511
                try {
8512
 
8513
                    this._oAnchor.blur();
8514
                    this.blurEvent.fire();
8515
 
8516
                }
8517
                catch (e) {
8518
 
8519
                }
8520
 
8521
            }, 0);
8522
 
8523
        }
8524
 
8525
    },
8526
 
8527
 
8528
    /**
8529
    * @method hasFocus
8530
    * @description Returns a boolean indicating whether or not the menu item
8531
    * has focus.
8532
    * @return {Boolean}
8533
    */
8534
    hasFocus: function () {
8535
 
8536
        return (YAHOO.widget.MenuManager.getFocusedMenuItem() == this);
8537
 
8538
    },
8539
 
8540
 
8541
    /**
8542
    * @method destroy
8543
    * @description Removes the menu item's <code>&#60;li&#62;</code> element
8544
    * from its parent <code>&#60;ul&#62;</code> element.
8545
    */
8546
    destroy: function () {
8547
 
8548
        var oEl = this.element,
8549
            oSubmenu,
8550
            oParentNode,
8551
            aEventData,
8552
            i;
8553
 
8554
 
8555
        if (oEl) {
8556
 
8557
 
8558
            // If the item has a submenu, destroy it first
8559
 
8560
            oSubmenu = this.cfg.getProperty(_SUBMENU);
8561
 
8562
            if (oSubmenu) {
8563
 
8564
                oSubmenu.destroy();
8565
 
8566
            }
8567
 
8568
 
8569
            // Remove the element from the parent node
8570
 
8571
            oParentNode = oEl.parentNode;
8572
 
8573
            if (oParentNode) {
8574
 
8575
                oParentNode.removeChild(oEl);
8576
 
8577
                this.destroyEvent.fire();
8578
 
8579
            }
8580
 
8581
 
8582
            // Remove CustomEvent listeners
8583
 
8584
            i = EVENT_TYPES.length - 1;
8585
 
8586
            do {
8587
 
8588
                aEventData = EVENT_TYPES[i];
8589
 
8590
                this[aEventData[0]].unsubscribeAll();
8591
 
8592
            }
8593
            while (i--);
8594
 
8595
 
8596
            this.cfg.configChangedEvent.unsubscribeAll();
8597
 
8598
        }
8599
 
8600
    },
8601
 
8602
 
8603
    /**
8604
    * @method toString
8605
    * @description Returns a string representing the menu item.
8606
    * @return {String}
8607
    */
8608
    toString: function () {
8609
 
8610
        var sReturnVal = _MENUITEM,
8611
            sId = this.id;
8612
 
8613
        if (sId) {
8614
 
8615
            sReturnVal += (_SPACE + sId);
8616
 
8617
        }
8618
 
8619
        return sReturnVal;
8620
 
8621
    }
8622
 
8623
};
8624
 
8625
Lang.augmentProto(MenuItem, YAHOO.util.EventProvider);
8626
 
8627
})();
8628
(function () {
8629
 
8630
    var _XY = "xy",
8631
        _MOUSEDOWN = "mousedown",
8632
        _CONTEXTMENU = "ContextMenu",
8633
        _SPACE = " ";
8634
 
8635
/**
8636
* Creates a list of options or commands which are made visible in response to
8637
* an HTML element's "contextmenu" event ("mousedown" for Opera).
8638
*
8639
* @param {String} p_oElement String specifying the id attribute of the
8640
* <code>&#60;div&#62;</code> element of the context menu.
8641
* @param {String} p_oElement String specifying the id attribute of the
8642
* <code>&#60;select&#62;</code> element to be used as the data source for the
8643
* context menu.
8644
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8645
* html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying the
8646
* <code>&#60;div&#62;</code> element of the context menu.
8647
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8648
* html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object specifying
8649
* the <code>&#60;select&#62;</code> element to be used as the data source for
8650
* the context menu.
8651
* @param {Object} p_oConfig Optional. Object literal specifying the
8652
* configuration for the context menu. See configuration class documentation
8653
* for more details.
8654
* @class ContextMenu
8655
* @constructor
8656
* @extends YAHOO.widget.Menu
8657
* @namespace YAHOO.widget
8658
*/
8659
YAHOO.widget.ContextMenu = function(p_oElement, p_oConfig) {
8660
    YAHOO.widget.ContextMenu.superclass.constructor.call(this, p_oElement, p_oConfig);
8661
};
8662
 
8663
 
8664
var Event = YAHOO.util.Event,
8665
    UA = YAHOO.env.ua,
8666
    ContextMenu = YAHOO.widget.ContextMenu,
8667
 
8668
 
8669
 
8670
    /**
8671
    * Constant representing the name of the ContextMenu's events
8672
    * @property EVENT_TYPES
8673
    * @private
8674
    * @final
8675
    * @type Object
8676
    */
8677
    EVENT_TYPES = {
8678
 
8679
        "TRIGGER_CONTEXT_MENU": "triggerContextMenu",
8680
        "CONTEXT_MENU": (UA.opera ? _MOUSEDOWN : "contextmenu"),
8681
        "CLICK": "click"
8682
 
8683
    },
8684
 
8685
 
8686
    /**
8687
    * Constant representing the ContextMenu's configuration properties
8688
    * @property DEFAULT_CONFIG
8689
    * @private
8690
    * @final
8691
    * @type Object
8692
    */
8693
    TRIGGER_CONFIG = {
8694
        key: "trigger",
8695
        suppressEvent: true
8696
    };
8697
 
8698
 
8699
/**
8700
* @method position
8701
* @description "beforeShow" event handler used to position the contextmenu.
8702
* @private
8703
* @param {String} p_sType String representing the name of the event that
8704
* was fired.
8705
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
8706
* @param {Array} p_aPos Array representing the xy position for the context menu.
8707
*/
8708
function position(p_sType, p_aArgs, p_aPos) {
8709
    this.cfg.setProperty(_XY, p_aPos);
8710
    this.beforeShowEvent.unsubscribe(position, p_aPos);
8711
}
8712
 
8713
 
8714
YAHOO.lang.extend(ContextMenu, YAHOO.widget.Menu, {
8715
 
8716
 
8717
 
8718
// Private properties
8719
 
8720
 
8721
/**
8722
* @property _oTrigger
8723
* @description Object reference to the current value of the "trigger"
8724
* configuration property.
8725
* @default null
8726
* @private
8727
* @type String|<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/leve
8728
* l-one-html.html#ID-58190037">HTMLElement</a>|Array
8729
*/
8730
_oTrigger: null,
8731
 
8732
 
8733
/**
8734
* @property _bCancelled
8735
* @description Boolean indicating if the display of the context menu should
8736
* be cancelled.
8737
* @default false
8738
* @private
8739
* @type Boolean
8740
*/
8741
_bCancelled: false,
8742
 
8743
 
8744
 
8745
// Public properties
8746
 
8747
 
8748
/**
8749
* @property contextEventTarget
8750
* @description Object reference for the HTML element that was the target of the
8751
* "contextmenu" DOM event ("mousedown" for Opera) that triggered the display of
8752
* the context menu.
8753
* @default null
8754
* @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8755
* html.html#ID-58190037">HTMLElement</a>
8756
*/
8757
contextEventTarget: null,
8758
 
8759
 
8760
 
8761
// Events
8762
 
8763
 
8764
/**
8765
* @event triggerContextMenuEvent
8766
* @param type {String} The name of the event, "triggerContextMenu"
8767
* @param args {Array} The array of event arguments. For this event, the underlying
8768
* DOM event is the only argument, available from args[0].
8769
* @description Custom Event wrapper for the "contextmenu" DOM event
8770
* ("mousedown" for Opera) fired by the element(s) that trigger the display of
8771
* the context menu.
8772
*/
8773
triggerContextMenuEvent: null,
8774
 
8775
 
8776
 
8777
/**
8778
* @method init
8779
* @description The ContextMenu class's initialization method. This method is
8780
* automatically called by the constructor, and sets up all DOM references for
8781
* pre-existing markup, and creates required markup if it is not already present.
8782
* @param {String} p_oElement String specifying the id attribute of the
8783
* <code>&#60;div&#62;</code> element of the context menu.
8784
* @param {String} p_oElement String specifying the id attribute of the
8785
* <code>&#60;select&#62;</code> element to be used as the data source for
8786
* the context menu.
8787
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8788
* html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying the
8789
* <code>&#60;div&#62;</code> element of the context menu.
8790
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8791
* html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object specifying
8792
* the <code>&#60;select&#62;</code> element to be used as the data source for
8793
* the context menu.
8794
* @param {Object} p_oConfig Optional. Object literal specifying the
8795
* configuration for the context menu. See configuration class documentation
8796
* for more details.
8797
*/
8798
init: function(p_oElement, p_oConfig) {
8799
 
8800
 
8801
    // Call the init of the superclass (YAHOO.widget.Menu)
8802
 
8803
    ContextMenu.superclass.init.call(this, p_oElement);
8804
 
8805
    this.beforeInitEvent.fire(ContextMenu);
8806
 
8807
    if (p_oConfig) {
8808
        this.cfg.applyConfig(p_oConfig, true);
8809
    }
8810
 
8811
    this.initEvent.fire(ContextMenu);
8812
},
8813
 
8814
 
8815
/**
8816
* @method initEvents
8817
* @description Initializes the custom events for the context menu.
8818
*/
8819
initEvents: function() {
8820
    ContextMenu.superclass.initEvents.call(this);
8821
 
8822
    // Create custom events
8823
    this.triggerContextMenuEvent = this.createEvent(EVENT_TYPES.TRIGGER_CONTEXT_MENU);
8824
    this.triggerContextMenuEvent.signature = YAHOO.util.CustomEvent.LIST;
8825
},
8826
 
8827
/**
8828
* @method cancel
8829
* @description Cancels the display of the context menu.
8830
*/
8831
cancel: function() {
8832
    this._bCancelled = true;
8833
},
8834
 
8835
// Private methods
8836
 
8837
 
8838
/**
8839
* @method _removeEventHandlers
8840
* @description Removes all of the DOM event handlers from the HTML element(s)
8841
* whose "context menu" event ("click" for Opera) trigger the display of
8842
* the context menu.
8843
* @private
8844
*/
8845
_removeEventHandlers: function() {
8846
 
8847
    var oTrigger = this._oTrigger;
8848
 
8849
    // Remove the event handlers from the trigger(s)
8850
    if (oTrigger) {
8851
        Event.removeListener(oTrigger, EVENT_TYPES.CONTEXT_MENU, this._onTriggerContextMenu);
8852
 
8853
        if (UA.opera) {
8854
            Event.removeListener(oTrigger, EVENT_TYPES.CLICK, this._onTriggerClick);
8855
        }
8856
    }
8857
 
8858
},
8859
 
8860
// Private event handlers
8861
 
8862
/**
8863
* @method _onTriggerClick
8864
* @description "click" event handler for the HTML element(s) identified as the
8865
* "trigger" for the context menu.  Used to cancel default behaviors in Opera.
8866
* @private
8867
* @param {Event} p_oEvent Object representing the DOM event object passed back
8868
* by the event utility (YAHOO.util.Event).
8869
* @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context
8870
* menu that is handling the event.
8871
*/
8872
_onTriggerClick: function(p_oEvent, p_oMenu) {
8873
 
8874
    if (p_oEvent.ctrlKey) {
8875
        Event.stopEvent(p_oEvent);
8876
    }
8877
 
8878
},
8879
 
8880
 
8881
/**
8882
* @method _onTriggerContextMenu
8883
* @description "contextmenu" event handler ("mousedown" for Opera) for the HTML
8884
* element(s) that trigger the display of the context menu.
8885
* @private
8886
* @param {Event} p_oEvent Object representing the DOM event object passed back
8887
* by the event utility (YAHOO.util.Event).
8888
* @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context
8889
* menu that is handling the event.
8890
*/
8891
_onTriggerContextMenu: function(p_oEvent, p_oMenu) {
8892
 
8893
    var aXY;
8894
 
8895
    if (!(p_oEvent.type == _MOUSEDOWN && !p_oEvent.ctrlKey)) {
8896
 
8897
        this.contextEventTarget = Event.getTarget(p_oEvent);
8898
 
8899
        this.triggerContextMenuEvent.fire(p_oEvent);
8900
 
8901
 
8902
        if (!this._bCancelled) {
8903
 
8904
            /*
8905
                Prevent the browser's default context menu from appearing and
8906
                stop the propagation of the "contextmenu" event so that
8907
                other ContextMenu instances are not displayed.
8908
            */
8909
 
8910
            Event.stopEvent(p_oEvent);
8911
 
8912
 
8913
            // Hide any other Menu instances that might be visible
8914
 
8915
            YAHOO.widget.MenuManager.hideVisible();
8916
 
8917
 
8918
 
8919
            // Position and display the context menu
8920
 
8921
            aXY = Event.getXY(p_oEvent);
8922
 
8923
 
8924
            if (!YAHOO.util.Dom.inDocument(this.element)) {
8925
 
8926
                this.beforeShowEvent.subscribe(position, aXY);
8927
 
8928
            }
8929
            else {
8930
 
8931
                this.cfg.setProperty(_XY, aXY);
8932
 
8933
            }
8934
 
8935
 
8936
            this.show();
8937
 
8938
        }
8939
 
8940
        this._bCancelled = false;
8941
 
8942
    }
8943
 
8944
},
8945
 
8946
 
8947
 
8948
// Public methods
8949
 
8950
 
8951
/**
8952
* @method toString
8953
* @description Returns a string representing the context menu.
8954
* @return {String}
8955
*/
8956
toString: function() {
8957
 
8958
    var sReturnVal = _CONTEXTMENU,
8959
        sId = this.id;
8960
 
8961
    if (sId) {
8962
 
8963
        sReturnVal += (_SPACE + sId);
8964
 
8965
    }
8966
 
8967
    return sReturnVal;
8968
 
8969
},
8970
 
8971
 
8972
/**
8973
* @method initDefaultConfig
8974
* @description Initializes the class's configurable properties which can be
8975
* changed using the context menu's Config object ("cfg").
8976
*/
8977
initDefaultConfig: function() {
8978
 
8979
    ContextMenu.superclass.initDefaultConfig.call(this);
8980
 
8981
    /**
8982
    * @config trigger
8983
    * @description The HTML element(s) whose "contextmenu" event ("mousedown"
8984
    * for Opera) trigger the display of the context menu.  Can be a string
8985
    * representing the id attribute of the HTML element, an object reference
8986
    * for the HTML element, or an array of strings or HTML element references.
8987
    * @default null
8988
    * @type String|<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
8989
    * level-one-html.html#ID-58190037">HTMLElement</a>|Array
8990
    */
8991
    this.cfg.addProperty(TRIGGER_CONFIG.key,
8992
        {
8993
            handler: this.configTrigger,
8994
            suppressEvent: TRIGGER_CONFIG.suppressEvent
8995
        }
8996
    );
8997
 
8998
},
8999
 
9000
 
9001
/**
9002
* @method destroy
9003
* @description Removes the context menu's <code>&#60;div&#62;</code> element
9004
* (and accompanying child nodes) from the document.
9005
* @param {boolean} shallowPurge If true, only the parent element's DOM event listeners are purged. If false, or not provided, all children are also purged of DOM event listeners.
9006
* NOTE: The flag is a "shallowPurge" flag, as opposed to what may be a more intuitive "purgeChildren" flag to maintain backwards compatibility with behavior prior to 2.9.0.
9007
*/
9008
destroy: function(shallowPurge) {
9009
 
9010
    // Remove the DOM event handlers from the current trigger(s)
9011
 
9012
    this._removeEventHandlers();
9013
 
9014
 
9015
    // Continue with the superclass implementation of this method
9016
 
9017
    ContextMenu.superclass.destroy.call(this, shallowPurge);
9018
 
9019
},
9020
 
9021
 
9022
 
9023
// Public event handlers for configuration properties
9024
 
9025
 
9026
/**
9027
* @method configTrigger
9028
* @description Event handler for when the value of the "trigger" configuration
9029
* property changes.
9030
* @param {String} p_sType String representing the name of the event that
9031
* was fired.
9032
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
9033
* @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context
9034
* menu that fired the event.
9035
*/
9036
configTrigger: function(p_sType, p_aArgs, p_oMenu) {
9037
 
9038
    var oTrigger = p_aArgs[0];
9039
 
9040
    if (oTrigger) {
9041
 
9042
        /*
9043
            If there is a current "trigger" - remove the event handlers
9044
            from that element(s) before assigning new ones
9045
        */
9046
 
9047
        if (this._oTrigger) {
9048
 
9049
            this._removeEventHandlers();
9050
 
9051
        }
9052
 
9053
        this._oTrigger = oTrigger;
9054
 
9055
 
9056
        /*
9057
            Listen for the "mousedown" event in Opera b/c it does not
9058
            support the "contextmenu" event
9059
        */
9060
 
9061
        Event.on(oTrigger, EVENT_TYPES.CONTEXT_MENU, this._onTriggerContextMenu, this, true);
9062
 
9063
 
9064
        /*
9065
            Assign a "click" event handler to the trigger element(s) for
9066
            Opera to prevent default browser behaviors.
9067
        */
9068
 
9069
        if (UA.opera) {
9070
 
9071
            Event.on(oTrigger, EVENT_TYPES.CLICK, this._onTriggerClick, this, true);
9072
 
9073
        }
9074
 
9075
    }
9076
    else {
9077
 
9078
        this._removeEventHandlers();
9079
 
9080
    }
9081
 
9082
}
9083
 
9084
}); // END YAHOO.lang.extend
9085
 
9086
}());
9087
 
9088
 
9089
 
9090
/**
9091
* Creates an item for a context menu.
9092
*
9093
* @param {String} p_oObject String specifying the text of the context menu item.
9094
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9095
* one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the
9096
* <code>&#60;li&#62;</code> element of the context menu item.
9097
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9098
* one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
9099
* specifying the <code>&#60;optgroup&#62;</code> element of the context
9100
* menu item.
9101
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9102
* one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying
9103
* the <code>&#60;option&#62;</code> element of the context menu item.
9104
* @param {Object} p_oConfig Optional. Object literal specifying the
9105
* configuration for the context menu item. See configuration class
9106
* documentation for more details.
9107
* @class ContextMenuItem
9108
* @constructor
9109
* @extends YAHOO.widget.MenuItem
9110
* @deprecated As of version 2.4.0 items for YAHOO.widget.ContextMenu instances
9111
* are of type YAHOO.widget.MenuItem.
9112
*/
9113
YAHOO.widget.ContextMenuItem = YAHOO.widget.MenuItem;
9114
(function () {
9115
 
9116
    var Lang = YAHOO.lang,
9117
 
9118
        // String constants
9119
 
9120
        _STATIC = "static",
9121
        _DYNAMIC_STATIC = "dynamic," + _STATIC,
9122
        _DISABLED = "disabled",
9123
        _SELECTED = "selected",
9124
        _AUTO_SUBMENU_DISPLAY = "autosubmenudisplay",
9125
        _SUBMENU = "submenu",
9126
        _VISIBLE = "visible",
9127
        _SPACE = " ",
9128
        _SUBMENU_TOGGLE_REGION = "submenutoggleregion",
9129
        _MENUBAR = "MenuBar";
9130
 
9131
/**
9132
* Horizontal collection of items, each of which can contain a submenu.
9133
*
9134
* @param {String} p_oElement String specifying the id attribute of the
9135
* <code>&#60;div&#62;</code> element of the menu bar.
9136
* @param {String} p_oElement String specifying the id attribute of the
9137
* <code>&#60;select&#62;</code> element to be used as the data source for the
9138
* menu bar.
9139
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9140
* one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying
9141
* the <code>&#60;div&#62;</code> element of the menu bar.
9142
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9143
* one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object
9144
* specifying the <code>&#60;select&#62;</code> element to be used as the data
9145
* source for the menu bar.
9146
* @param {Object} p_oConfig Optional. Object literal specifying the
9147
* configuration for the menu bar. See configuration class documentation for
9148
* more details.
9149
* @class MenuBar
9150
* @constructor
9151
* @extends YAHOO.widget.Menu
9152
* @namespace YAHOO.widget
9153
*/
9154
YAHOO.widget.MenuBar = function(p_oElement, p_oConfig) {
9155
 
9156
    YAHOO.widget.MenuBar.superclass.constructor.call(this, p_oElement, p_oConfig);
9157
 
9158
};
9159
 
9160
 
9161
/**
9162
* @method checkPosition
9163
* @description Checks to make sure that the value of the "position" property
9164
* is one of the supported strings. Returns true if the position is supported.
9165
* @private
9166
* @param {Object} p_sPosition String specifying the position of the menu.
9167
* @return {Boolean}
9168
*/
9169
function checkPosition(p_sPosition) {
9170
 
9171
    var returnVal = false;
9172
 
9173
    if (Lang.isString(p_sPosition)) {
9174
 
9175
        returnVal = (_DYNAMIC_STATIC.indexOf((p_sPosition.toLowerCase())) != -1);
9176
 
9177
    }
9178
 
9179
    return returnVal;
9180
 
9181
}
9182
 
9183
 
9184
var Event = YAHOO.util.Event,
9185
    MenuBar = YAHOO.widget.MenuBar,
9186
 
9187
    POSITION_CONFIG =  {
9188
        key: "position",
9189
        value: _STATIC,
9190
        validator: checkPosition,
9191
        supercedes: [_VISIBLE]
9192
    },
9193
 
9194
    SUBMENU_ALIGNMENT_CONFIG =  {
9195
        key: "submenualignment",
9196
        value: ["tl","bl"]
9197
    },
9198
 
9199
    AUTO_SUBMENU_DISPLAY_CONFIG =  {
9200
        key: _AUTO_SUBMENU_DISPLAY,
9201
        value: false,
9202
        validator: Lang.isBoolean,
9203
        suppressEvent: true
9204
    },
9205
 
9206
    SUBMENU_TOGGLE_REGION_CONFIG = {
9207
        key: _SUBMENU_TOGGLE_REGION,
9208
        value: false,
9209
        validator: Lang.isBoolean
9210
    };
9211
 
9212
 
9213
 
9214
Lang.extend(MenuBar, YAHOO.widget.Menu, {
9215
 
9216
/**
9217
* @method init
9218
* @description The MenuBar class's initialization method. This method is
9219
* automatically called by the constructor, and sets up all DOM references for
9220
* pre-existing markup, and creates required markup if it is not already present.
9221
* @param {String} p_oElement String specifying the id attribute of the
9222
* <code>&#60;div&#62;</code> element of the menu bar.
9223
* @param {String} p_oElement String specifying the id attribute of the
9224
* <code>&#60;select&#62;</code> element to be used as the data source for the
9225
* menu bar.
9226
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9227
* one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying
9228
* the <code>&#60;div&#62;</code> element of the menu bar.
9229
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9230
* one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object
9231
* specifying the <code>&#60;select&#62;</code> element to be used as the data
9232
* source for the menu bar.
9233
* @param {Object} p_oConfig Optional. Object literal specifying the
9234
* configuration for the menu bar. See configuration class documentation for
9235
* more details.
9236
*/
9237
init: function(p_oElement, p_oConfig) {
9238
 
9239
    if(!this.ITEM_TYPE) {
9240
 
9241
        this.ITEM_TYPE = YAHOO.widget.MenuBarItem;
9242
 
9243
    }
9244
 
9245
 
9246
    // Call the init of the superclass (YAHOO.widget.Menu)
9247
 
9248
    MenuBar.superclass.init.call(this, p_oElement);
9249
 
9250
 
9251
    this.beforeInitEvent.fire(MenuBar);
9252
 
9253
 
9254
    if(p_oConfig) {
9255
 
9256
        this.cfg.applyConfig(p_oConfig, true);
9257
 
9258
    }
9259
 
9260
    this.initEvent.fire(MenuBar);
9261
 
9262
},
9263
 
9264
 
9265
 
9266
// Constants
9267
 
9268
 
9269
/**
9270
* @property CSS_CLASS_NAME
9271
* @description String representing the CSS class(es) to be applied to the menu
9272
* bar's <code>&#60;div&#62;</code> element.
9273
* @default "yuimenubar"
9274
* @final
9275
* @type String
9276
*/
9277
CSS_CLASS_NAME: "yuimenubar",
9278
 
9279
 
9280
/**
9281
* @property SUBMENU_TOGGLE_REGION_WIDTH
9282
* @description Width (in pixels) of the area of a MenuBarItem that, when pressed, will toggle the
9283
* display of the MenuBarItem's submenu.
9284
* @default 20
9285
* @final
9286
* @type Number
9287
*/
9288
SUBMENU_TOGGLE_REGION_WIDTH: 20,
9289
 
9290
 
9291
// Protected event handlers
9292
 
9293
 
9294
/**
9295
* @method _onKeyDown
9296
* @description "keydown" Custom Event handler for the menu bar.
9297
* @private
9298
* @param {String} p_sType String representing the name of the event that
9299
* was fired.
9300
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
9301
* @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar
9302
* that fired the event.
9303
*/
9304
_onKeyDown: function(p_sType, p_aArgs, p_oMenuBar) {
9305
 
9306
    var oEvent = p_aArgs[0],
9307
        oItem = p_aArgs[1],
9308
        oSubmenu,
9309
        oItemCfg,
9310
        oNextItem;
9311
 
9312
 
9313
    if(oItem && !oItem.cfg.getProperty(_DISABLED)) {
9314
 
9315
        oItemCfg = oItem.cfg;
9316
 
9317
        switch(oEvent.keyCode) {
9318
 
9319
            case 37:    // Left arrow
9320
            case 39:    // Right arrow
9321
 
9322
                if(oItem == this.activeItem && !oItemCfg.getProperty(_SELECTED)) {
9323
 
9324
                    oItemCfg.setProperty(_SELECTED, true);
9325
 
9326
                }
9327
                else {
9328
 
9329
                    oNextItem = (oEvent.keyCode == 37) ?
9330
                        oItem.getPreviousEnabledSibling() :
9331
                        oItem.getNextEnabledSibling();
9332
 
9333
                    if(oNextItem) {
9334
 
9335
                        this.clearActiveItem();
9336
 
9337
                        oNextItem.cfg.setProperty(_SELECTED, true);
9338
 
9339
                        oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
9340
 
9341
                        if(oSubmenu) {
9342
 
9343
                            oSubmenu.show();
9344
                            oSubmenu.setInitialFocus();
9345
 
9346
                        }
9347
                        else {
9348
                            oNextItem.focus();
9349
                        }
9350
 
9351
                    }
9352
 
9353
                }
9354
 
9355
                Event.preventDefault(oEvent);
9356
 
9357
            break;
9358
 
9359
            case 40:    // Down arrow
9360
 
9361
                if(this.activeItem != oItem) {
9362
 
9363
                    this.clearActiveItem();
9364
 
9365
                    oItemCfg.setProperty(_SELECTED, true);
9366
                    oItem.focus();
9367
 
9368
                }
9369
 
9370
                oSubmenu = oItemCfg.getProperty(_SUBMENU);
9371
 
9372
                if(oSubmenu) {
9373
 
9374
                    if(oSubmenu.cfg.getProperty(_VISIBLE)) {
9375
 
9376
                        oSubmenu.setInitialSelection();
9377
                        oSubmenu.setInitialFocus();
9378
 
9379
                    }
9380
                    else {
9381
 
9382
                        oSubmenu.show();
9383
                        oSubmenu.setInitialFocus();
9384
 
9385
                    }
9386
 
9387
                }
9388
 
9389
                Event.preventDefault(oEvent);
9390
 
9391
            break;
9392
 
9393
        }
9394
 
9395
    }
9396
 
9397
 
9398
    if(oEvent.keyCode == 27 && this.activeItem) { // Esc key
9399
 
9400
        oSubmenu = this.activeItem.cfg.getProperty(_SUBMENU);
9401
 
9402
        if(oSubmenu && oSubmenu.cfg.getProperty(_VISIBLE)) {
9403
 
9404
            oSubmenu.hide();
9405
            this.activeItem.focus();
9406
 
9407
        }
9408
        else {
9409
 
9410
            this.activeItem.cfg.setProperty(_SELECTED, false);
9411
            this.activeItem.blur();
9412
 
9413
        }
9414
 
9415
        Event.preventDefault(oEvent);
9416
 
9417
    }
9418
 
9419
},
9420
 
9421
 
9422
/**
9423
* @method _onClick
9424
* @description "click" event handler for the menu bar.
9425
* @protected
9426
* @param {String} p_sType String representing the name of the event that
9427
* was fired.
9428
* @param {Array} p_aArgs Array of arguments sent when the event was fired.
9429
* @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar
9430
* that fired the event.
9431
*/
9432
_onClick: function(p_sType, p_aArgs, p_oMenuBar) {
9433
 
9434
    MenuBar.superclass._onClick.call(this, p_sType, p_aArgs, p_oMenuBar);
9435
 
9436
    var oItem = p_aArgs[1],
9437
        bReturnVal = true,
9438
        oItemEl,
9439
        oEvent,
9440
        oTarget,
9441
        oActiveItem,
9442
        oConfig,
9443
        oSubmenu,
9444
        nMenuItemX,
9445
        nToggleRegion;
9446
 
9447
 
9448
    var toggleSubmenuDisplay = function () {
9449
 
9450
        if(oSubmenu.cfg.getProperty(_VISIBLE)) {
9451
 
9452
            oSubmenu.hide();
9453
 
9454
        }
9455
        else {
9456
 
9457
            oSubmenu.show();
9458
 
9459
        }
9460
 
9461
    };
9462
 
9463
 
9464
    if(oItem && !oItem.cfg.getProperty(_DISABLED)) {
9465
 
9466
        oEvent = p_aArgs[0];
9467
        oTarget = Event.getTarget(oEvent);
9468
        oActiveItem = this.activeItem;
9469
        oConfig = this.cfg;
9470
 
9471
 
9472
        // Hide any other submenus that might be visible
9473
 
9474
        if(oActiveItem && oActiveItem != oItem) {
9475
 
9476
            this.clearActiveItem();
9477
 
9478
        }
9479
 
9480
 
9481
        oItem.cfg.setProperty(_SELECTED, true);
9482
 
9483
 
9484
        // Show the submenu for the item
9485
 
9486
        oSubmenu = oItem.cfg.getProperty(_SUBMENU);
9487
 
9488
 
9489
        if(oSubmenu) {
9490
 
9491
            oItemEl = oItem.element;
9492
            nMenuItemX = YAHOO.util.Dom.getX(oItemEl);
9493
            nToggleRegion = nMenuItemX + (oItemEl.offsetWidth - this.SUBMENU_TOGGLE_REGION_WIDTH);
9494
 
9495
            if (oConfig.getProperty(_SUBMENU_TOGGLE_REGION)) {
9496
 
9497
                if (Event.getPageX(oEvent) > nToggleRegion) {
9498
 
9499
                    toggleSubmenuDisplay();
9500
 
9501
                    Event.preventDefault(oEvent);
9502
 
9503
                    /*
9504
                         Return false so that other click event handlers are not called when the
9505
                         user clicks inside the toggle region.
9506
                    */
9507
                    bReturnVal = false;
9508
 
9509
                }
9510
 
9511
            }
9512
            else {
9513
 
9514
                toggleSubmenuDisplay();
9515
 
9516
            }
9517
 
9518
        }
9519
 
9520
    }
9521
 
9522
 
9523
    return bReturnVal;
9524
 
9525
},
9526
 
9527
 
9528
 
9529
// Public methods
9530
 
9531
/**
9532
* @method configSubmenuToggle
9533
* @description Event handler for when the "submenutoggleregion" configuration property of
9534
* a MenuBar changes.
9535
* @param {String} p_sType The name of the event that was fired.
9536
* @param {Array} p_aArgs Collection of arguments sent when the event was fired.
9537
*/
9538
configSubmenuToggle: function (p_sType, p_aArgs) {
9539
 
9540
    var bSubmenuToggle = p_aArgs[0];
9541
 
9542
    if (bSubmenuToggle) {
9543
 
9544
        this.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, false);
9545
 
9546
    }
9547
 
9548
},
9549
 
9550
 
9551
/**
9552
* @method toString
9553
* @description Returns a string representing the menu bar.
9554
* @return {String}
9555
*/
9556
toString: function() {
9557
 
9558
    var sReturnVal = _MENUBAR,
9559
        sId = this.id;
9560
 
9561
    if(sId) {
9562
 
9563
        sReturnVal += (_SPACE + sId);
9564
 
9565
    }
9566
 
9567
    return sReturnVal;
9568
 
9569
},
9570
 
9571
 
9572
/**
9573
* @description Initializes the class's configurable properties which can be
9574
* changed using the menu bar's Config object ("cfg").
9575
* @method initDefaultConfig
9576
*/
9577
initDefaultConfig: function() {
9578
 
9579
    MenuBar.superclass.initDefaultConfig.call(this);
9580
 
9581
    var oConfig = this.cfg;
9582
 
9583
    // Add configuration properties
9584
 
9585
 
9586
    /*
9587
        Set the default value for the "position" configuration property
9588
        to "static" by re-adding the property.
9589
    */
9590
 
9591
 
9592
    /**
9593
    * @config position
9594
    * @description String indicating how a menu bar should be positioned on the
9595
    * screen.  Possible values are "static" and "dynamic."  Static menu bars
9596
    * are visible by default and reside in the normal flow of the document
9597
    * (CSS position: static).  Dynamic menu bars are hidden by default, reside
9598
    * out of the normal flow of the document (CSS position: absolute), and can
9599
    * overlay other elements on the screen.
9600
    * @default static
9601
    * @type String
9602
    */
9603
    oConfig.addProperty(
9604
        POSITION_CONFIG.key,
9605
        {
9606
            handler: this.configPosition,
9607
            value: POSITION_CONFIG.value,
9608
            validator: POSITION_CONFIG.validator,
9609
            supercedes: POSITION_CONFIG.supercedes
9610
        }
9611
    );
9612
 
9613
 
9614
    /*
9615
        Set the default value for the "submenualignment" configuration property
9616
        to ["tl","bl"] by re-adding the property.
9617
    */
9618
 
9619
    /**
9620
    * @config submenualignment
9621
    * @description Array defining how submenus should be aligned to their
9622
    * parent menu bar item. The format is: [itemCorner, submenuCorner].
9623
    * @default ["tl","bl"]
9624
    * @type Array
9625
    */
9626
    oConfig.addProperty(
9627
        SUBMENU_ALIGNMENT_CONFIG.key,
9628
        {
9629
            value: SUBMENU_ALIGNMENT_CONFIG.value,
9630
            suppressEvent: SUBMENU_ALIGNMENT_CONFIG.suppressEvent
9631
        }
9632
    );
9633
 
9634
 
9635
    /*
9636
        Change the default value for the "autosubmenudisplay" configuration
9637
        property to "false" by re-adding the property.
9638
    */
9639
 
9640
    /**
9641
    * @config autosubmenudisplay
9642
    * @description Boolean indicating if submenus are automatically made
9643
    * visible when the user mouses over the menu bar's items.
9644
    * @default false
9645
    * @type Boolean
9646
    */
9647
    oConfig.addProperty(
9648
       AUTO_SUBMENU_DISPLAY_CONFIG.key,
9649
       {
9650
           value: AUTO_SUBMENU_DISPLAY_CONFIG.value,
9651
           validator: AUTO_SUBMENU_DISPLAY_CONFIG.validator,
9652
           suppressEvent: AUTO_SUBMENU_DISPLAY_CONFIG.suppressEvent
9653
       }
9654
    );
9655
 
9656
 
9657
    /**
9658
    * @config submenutoggleregion
9659
    * @description Boolean indicating if only a specific region of a MenuBarItem should toggle the
9660
    * display of a submenu.  The default width of the region is determined by the value of the
9661
    * SUBMENU_TOGGLE_REGION_WIDTH property.  If set to true, the autosubmenudisplay
9662
    * configuration property will be set to false, and any click event listeners will not be
9663
    * called when the user clicks inside the submenu toggle region of a MenuBarItem.  If the
9664
    * user clicks outside of the submenu toggle region, the MenuBarItem will maintain its
9665
    * standard behavior.
9666
    * @default false
9667
    * @type Boolean
9668
    */
9669
    oConfig.addProperty(
9670
       SUBMENU_TOGGLE_REGION_CONFIG.key,
9671
       {
9672
           value: SUBMENU_TOGGLE_REGION_CONFIG.value,
9673
           validator: SUBMENU_TOGGLE_REGION_CONFIG.validator,
9674
           handler: this.configSubmenuToggle
9675
       }
9676
    );
9677
 
9678
}
9679
 
9680
}); // END YAHOO.lang.extend
9681
 
9682
}());
9683
 
9684
 
9685
 
9686
/**
9687
* Creates an item for a menu bar.
9688
*
9689
* @param {HTML} p_oObject Markup for the menu item content. The markup is inserted into the DOM as HTML, and should be escaped by the implementor if coming from an external source.
9690
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9691
* one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the
9692
* <code>&#60;li&#62;</code> element of the menu bar item.
9693
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9694
* one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
9695
* specifying the <code>&#60;optgroup&#62;</code> element 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-70901257">HTMLOptionElement</a>} p_oObject Object specifying
9698
* the <code>&#60;option&#62;</code> element of the menu bar item.
9699
* @param {Object} p_oConfig Optional. Object literal specifying the
9700
* configuration for the menu bar item. See configuration class documentation
9701
* for more details.
9702
* @class MenuBarItem
9703
* @constructor
9704
* @extends YAHOO.widget.MenuItem
9705
*/
9706
YAHOO.widget.MenuBarItem = function(p_oObject, p_oConfig) {
9707
 
9708
    YAHOO.widget.MenuBarItem.superclass.constructor.call(this, p_oObject, p_oConfig);
9709
 
9710
};
9711
 
9712
YAHOO.lang.extend(YAHOO.widget.MenuBarItem, YAHOO.widget.MenuItem, {
9713
 
9714
 
9715
 
9716
/**
9717
* @method init
9718
* @description The MenuBarItem class's initialization method. This method is
9719
* automatically called by the constructor, and sets up all DOM references for
9720
* pre-existing markup, and creates required markup if it is not already present.
9721
* @param {HTML} p_oObject Markup for the menu item content. The markup is inserted into the DOM as HTML, and should be escaped by the implementor if coming from an external source.
9722
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9723
* one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the
9724
* <code>&#60;li&#62;</code> element of the menu bar item.
9725
* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9726
* one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
9727
* specifying the <code>&#60;optgroup&#62;</code> element 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-70901257">HTMLOptionElement</a>} p_oObject Object specifying
9730
* the <code>&#60;option&#62;</code> element of the menu bar item.
9731
* @param {Object} p_oConfig Optional. Object literal specifying the
9732
* configuration for the menu bar item. See configuration class documentation
9733
* for more details.
9734
*/
9735
init: function(p_oObject, p_oConfig) {
9736
 
9737
    if(!this.SUBMENU_TYPE) {
9738
 
9739
        this.SUBMENU_TYPE = YAHOO.widget.Menu;
9740
 
9741
    }
9742
 
9743
 
9744
    /*
9745
        Call the init of the superclass (YAHOO.widget.MenuItem)
9746
        Note: We don't pass the user config in here yet
9747
        because we only want it executed once, at the lowest
9748
        subclass level.
9749
    */
9750
 
9751
    YAHOO.widget.MenuBarItem.superclass.init.call(this, p_oObject);
9752
 
9753
 
9754
    var oConfig = this.cfg;
9755
 
9756
    if(p_oConfig) {
9757
 
9758
        oConfig.applyConfig(p_oConfig, true);
9759
 
9760
    }
9761
 
9762
    oConfig.fireQueue();
9763
 
9764
},
9765
 
9766
 
9767
 
9768
// Constants
9769
 
9770
 
9771
/**
9772
* @property CSS_CLASS_NAME
9773
* @description String representing the CSS class(es) to be applied to the
9774
* <code>&#60;li&#62;</code> element of the menu bar item.
9775
* @default "yuimenubaritem"
9776
* @final
9777
* @type String
9778
*/
9779
CSS_CLASS_NAME: "yuimenubaritem",
9780
 
9781
 
9782
/**
9783
* @property CSS_LABEL_CLASS_NAME
9784
* @description String representing the CSS class(es) to be applied to the
9785
* menu bar item's <code>&#60;a&#62;</code> element.
9786
* @default "yuimenubaritemlabel"
9787
* @final
9788
* @type String
9789
*/
9790
CSS_LABEL_CLASS_NAME: "yuimenubaritemlabel",
9791
 
9792
 
9793
 
9794
// Public methods
9795
 
9796
 
9797
/**
9798
* @method toString
9799
* @description Returns a string representing the menu bar item.
9800
* @return {String}
9801
*/
9802
toString: function() {
9803
 
9804
    var sReturnVal = "MenuBarItem";
9805
 
9806
    if(this.cfg && this.cfg.getProperty("text")) {
9807
 
9808
        sReturnVal += (": " + this.cfg.getProperty("text"));
9809
 
9810
    }
9811
 
9812
    return sReturnVal;
9813
 
9814
}
9815
 
9816
}); // END YAHOO.lang.extend
9817
YAHOO.register("menu", YAHOO.widget.Menu, {version: "2.9.0", build: "2800"});
9818
 
9819
}, '2.9.0' ,{"requires": ["yui2-yahoo", "yui2-dom", "yui2-event", "yui2-containercore", "yui2-skin-sam-menu"]});