PageRenderTime 60ms CodeModel.GetById 12ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 1ms

/hippo/src/main/webapp/yui/menu/menu.js

http://hdbc.googlecode.com/
JavaScript | 2672 lines | 1057 code | 903 blank | 712 comment | 212 complexity | a7e26f3d475ea2390af24915b94adc59 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2Copyright (c) 2009, Yahoo! Inc. All rights reserved.
   3Code licensed under the BSD License:
   4http://developer.yahoo.net/yui/license.txt
   5version: 2.7.0
   6*/
   7
   8
   9/**
  10* @module menu
  11* @description <p>The Menu family of components features a collection of 
  12* controls that make it easy to add menus to your website or web application.  
  13* With the Menu Controls you can create website fly-out menus, customized 
  14* context menus, or application-style menu bars with just a small amount of 
  15* scripting.</p><p>The Menu family of controls features:</p>
  16* <ul>
  17*    <li>Keyboard and mouse navigation.</li>
  18*    <li>A rich event model that provides access to all of a menu's 
  19*    interesting moments.</li>
  20*    <li>Support for 
  21*    <a href="http://en.wikipedia.org/wiki/Progressive_Enhancement">Progressive
  22*    Enhancement</a>; Menus can be created from simple, 
  23*    semantic markup on the page or purely through JavaScript.</li>
  24* </ul>
  25* @title Menu
  26* @namespace YAHOO.widget
  27* @requires Event, Dom, Container
  28*/
  29(function () {
  30
  31    var _DIV = "DIV",
  32    	_HD = "hd",
  33    	_BD = "bd",
  34    	_FT = "ft",
  35    	_LI = "LI",
  36    	_DISABLED = "disabled",
  37		_MOUSEOVER = "mouseover",
  38		_MOUSEOUT = "mouseout",
  39		_MOUSEDOWN = "mousedown",
  40		_MOUSEUP = "mouseup",
  41		_FOCUS = YAHOO.env.ua.ie ? "focusin" : "focus",		
  42		_CLICK = "click",
  43		_KEYDOWN = "keydown",
  44		_KEYUP = "keyup",
  45		_KEYPRESS = "keypress",
  46		_CLICK_TO_HIDE = "clicktohide",
  47		_POSITION = "position", 
  48		_DYNAMIC = "dynamic",
  49		_SHOW_DELAY = "showdelay",
  50		_SELECTED = "selected",
  51		_VISIBLE = "visible",
  52		_UL = "UL",
  53		_MENUMANAGER = "MenuManager",
  54    	
  55    
  56    	Dom = YAHOO.util.Dom,
  57        Event = YAHOO.util.Event,
  58        Lang = YAHOO.lang;
  59
  60
  61    /**
  62    * Singleton that manages a collection of all menus and menu items.  Listens 
  63    * for DOM events at the document level and dispatches the events to the 
  64    * corresponding menu or menu item.
  65    *
  66    * @namespace YAHOO.widget
  67    * @class MenuManager
  68    * @static
  69    */
  70    YAHOO.widget.MenuManager = function () {
  71    
  72        // Private member variables
  73    
  74    
  75        // Flag indicating if the DOM event handlers have been attached
  76    
  77        var m_bInitializedEventHandlers = false,
  78    
  79    
  80        // Collection of menus
  81
  82        m_oMenus = {},
  83
  84
  85        // Collection of visible menus
  86    
  87        m_oVisibleMenus = {},
  88    
  89    
  90        //  Collection of menu items 
  91
  92        m_oItems = {},
  93
  94
  95        // Map of DOM event types to their equivalent CustomEvent types
  96        
  97        m_oEventTypes = {
  98            "click": "clickEvent",
  99            "mousedown": "mouseDownEvent",
 100            "mouseup": "mouseUpEvent",
 101            "mouseover": "mouseOverEvent",
 102            "mouseout": "mouseOutEvent",
 103            "keydown": "keyDownEvent",
 104            "keyup": "keyUpEvent",
 105            "keypress": "keyPressEvent",
 106            "focus": "focusEvent",
 107            "focusin": "focusEvent",
 108            "blur": "blurEvent",
 109            "focusout": "blurEvent"
 110        },
 111
 112
 113    	// The element in the DOM that currently has focus
 114    
 115		m_oFocusedElement = null,
 116    
 117    
 118        m_oFocusedMenuItem = null;
 119    
 120    
 121    
 122        // Private methods
 123    
 124    
 125        /**
 126        * @method getMenuRootElement
 127        * @description Finds the root DIV node of a menu or the root LI node of 
 128        * a menu item.
 129        * @private
 130        * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
 131        * level-one-html.html#ID-58190037">HTMLElement</a>} p_oElement Object 
 132        * specifying an HTML element.
 133        */
 134        function getMenuRootElement(p_oElement) {
 135        
 136            var oParentNode,
 137            	returnVal;
 138    
 139            if (p_oElement && p_oElement.tagName) {
 140            
 141                switch (p_oElement.tagName.toUpperCase()) {
 142                        
 143                case _DIV:
 144    
 145                    oParentNode = p_oElement.parentNode;
 146    
 147                    // Check if the DIV is the inner "body" node of a menu
 148
 149                    if ((
 150                            Dom.hasClass(p_oElement, _HD) ||
 151                            Dom.hasClass(p_oElement, _BD) ||
 152                            Dom.hasClass(p_oElement, _FT)
 153                        ) && 
 154                        oParentNode && 
 155                        oParentNode.tagName && 
 156                        oParentNode.tagName.toUpperCase() == _DIV) {
 157                    
 158                        returnVal = oParentNode;
 159                    
 160                    }
 161                    else {
 162                    
 163                        returnVal = p_oElement;
 164                    
 165                    }
 166                
 167                    break;
 168
 169                case _LI:
 170    
 171                    returnVal = p_oElement;
 172                    
 173                    break;
 174
 175                default:
 176    
 177                    oParentNode = p_oElement.parentNode;
 178    
 179                    if (oParentNode) {
 180                    
 181                        returnVal = getMenuRootElement(oParentNode);
 182                    
 183                    }
 184                
 185                    break;
 186                
 187                }
 188    
 189            }
 190            
 191            return returnVal;
 192            
 193        }
 194    
 195    
 196    
 197        // Private event handlers
 198    
 199    
 200        /**
 201        * @method onDOMEvent
 202        * @description Generic, global event handler for all of a menu's 
 203        * DOM-based events.  This listens for events against the document 
 204        * object.  If the target of a given event is a member of a menu or 
 205        * menu item's DOM, the instance's corresponding Custom Event is fired.
 206        * @private
 207        * @param {Event} p_oEvent Object representing the DOM event object  
 208        * passed back by the event utility (YAHOO.util.Event).
 209        */
 210        function onDOMEvent(p_oEvent) {
 211    
 212            // Get the target node of the DOM event
 213        
 214            var oTarget = Event.getTarget(p_oEvent),
 215                
 216            // See if the target of the event was a menu, or a menu item
 217    
 218            oElement = getMenuRootElement(oTarget),
 219            sCustomEventType,
 220            sTagName,
 221            sId,
 222            oMenuItem,
 223            oMenu; 
 224    
 225    
 226            if (oElement) {
 227    
 228                sTagName = oElement.tagName.toUpperCase();
 229        
 230                if (sTagName == _LI) {
 231            
 232                    sId = oElement.id;
 233            
 234                    if (sId && m_oItems[sId]) {
 235            
 236                        oMenuItem = m_oItems[sId];
 237                        oMenu = oMenuItem.parent;
 238            
 239                    }
 240                
 241                }
 242                else if (sTagName == _DIV) {
 243                
 244                    if (oElement.id) {
 245                    
 246                        oMenu = m_oMenus[oElement.id];
 247                    
 248                    }
 249                
 250                }
 251    
 252            }
 253    
 254    
 255            if (oMenu) {
 256    
 257                sCustomEventType = m_oEventTypes[p_oEvent.type];
 258    
 259    
 260                // Fire the Custom Event that corresponds the current DOM event    
 261        
 262                if (oMenuItem && !oMenuItem.cfg.getProperty(_DISABLED)) {
 263    
 264                    oMenuItem[sCustomEventType].fire(p_oEvent);                   
 265    
 266                }
 267        
 268                oMenu[sCustomEventType].fire(p_oEvent, oMenuItem);
 269            
 270            }
 271            else if (p_oEvent.type == _MOUSEDOWN) {
 272    
 273                /*
 274                    If the target of the event wasn't a menu, hide all 
 275                    dynamically positioned menus
 276                */
 277                
 278                for (var i in m_oVisibleMenus) {
 279        
 280                    if (Lang.hasOwnProperty(m_oVisibleMenus, i)) {
 281        
 282                        oMenu = m_oVisibleMenus[i];
 283
 284                        if (oMenu.cfg.getProperty(_CLICK_TO_HIDE) && 
 285                            !(oMenu instanceof YAHOO.widget.MenuBar) && 
 286                            oMenu.cfg.getProperty(_POSITION) == _DYNAMIC) {
 287        
 288                            oMenu.hide();
 289        
 290                        }
 291                        else {
 292                            
 293							if (oMenu.cfg.getProperty(_SHOW_DELAY) > 0) {
 294							
 295								oMenu._cancelShowDelay();
 296							
 297							}
 298
 299
 300							if (oMenu.activeItem) {
 301						
 302								oMenu.activeItem.blur();
 303								oMenu.activeItem.cfg.setProperty(_SELECTED, false);
 304						
 305								oMenu.activeItem = null;            
 306						
 307							}
 308        
 309                        }
 310        
 311                    }
 312        
 313                } 
 314    
 315            }
 316            else if (p_oEvent.type == _FOCUS) {
 317            
 318            	m_oFocusedElement = oTarget;
 319            
 320            }
 321            
 322        }
 323    
 324    
 325        /**
 326        * @method onMenuDestroy
 327        * @description "destroy" event handler for a menu.
 328        * @private
 329        * @param {String} p_sType String representing the name of the event 
 330        * that was fired.
 331        * @param {Array} p_aArgs Array of arguments sent when the event 
 332        * was fired.
 333        * @param {YAHOO.widget.Menu} p_oMenu The menu that fired the event.
 334        */
 335        function onMenuDestroy(p_sType, p_aArgs, p_oMenu) {
 336    
 337            if (m_oMenus[p_oMenu.id]) {
 338    
 339                this.removeMenu(p_oMenu);
 340    
 341            }
 342    
 343        }
 344    
 345    
 346        /**
 347        * @method onMenuFocus
 348        * @description "focus" event handler for a MenuItem instance.
 349        * @private
 350        * @param {String} p_sType String representing the name of the event 
 351        * that was fired.
 352        * @param {Array} p_aArgs Array of arguments sent when the event 
 353        * was fired.
 354        */
 355        function onMenuFocus(p_sType, p_aArgs) {
 356    
 357            var oItem = p_aArgs[1];
 358    
 359            if (oItem) {
 360    
 361                m_oFocusedMenuItem = oItem;
 362            
 363            }
 364    
 365        }
 366    
 367    
 368        /**
 369        * @method onMenuBlur
 370        * @description "blur" event handler for a MenuItem instance.
 371        * @private
 372        * @param {String} p_sType String representing the name of the event  
 373        * that was fired.
 374        * @param {Array} p_aArgs Array of arguments sent when the event 
 375        * was fired.
 376        */
 377        function onMenuBlur(p_sType, p_aArgs) {
 378    
 379            m_oFocusedMenuItem = null;
 380    
 381        }
 382    
 383
 384        /**
 385        * @method onMenuHide
 386        * @description "hide" event handler for a Menu instance.
 387        * @private
 388        * @param {String} p_sType String representing the name of the event  
 389        * that was fired.
 390        * @param {Array} p_aArgs Array of arguments sent when the event 
 391        * was fired.
 392		* @param <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
 393		* level-one-html.html#ID-58190037">p_oFocusedElement</a> The HTML element that had focus
 394		* prior to the Menu being made visible
 395        */    
 396    	function onMenuHide(p_sType, p_aArgs, p_oFocusedElement) {
 397
 398			/*
 399				Restore focus to the element in the DOM that had focus prior to the Menu 
 400				being made visible
 401			*/
 402
 403			if (p_oFocusedElement && p_oFocusedElement.focus) {
 404			
 405				try {
 406					p_oFocusedElement.focus();
 407				}
 408				catch(ex) {
 409				}
 410			
 411			}
 412			
 413    		this.hideEvent.unsubscribe(onMenuHide, p_oFocusedElement);
 414    	
 415    	}
 416    
 417
 418        /**
 419        * @method onMenuShow
 420        * @description "show" event handler for a MenuItem instance.
 421        * @private
 422        * @param {String} p_sType String representing the name of the event  
 423        * that was fired.
 424        * @param {Array} p_aArgs Array of arguments sent when the event 
 425        * was fired.
 426        */    	
 427    	function onMenuShow(p_sType, p_aArgs) {
 428
 429			/*
 430				Dynamically positioned, root Menus focus themselves when visible, and will then, 
 431				when hidden, restore focus to the UI control that had focus before the Menu was 
 432				made visible
 433			*/ 
 434
 435			if (this === this.getRoot() && this.cfg.getProperty(_POSITION) === _DYNAMIC) {
 436    	
 437				this.hideEvent.subscribe(onMenuHide, m_oFocusedElement);
 438				this.focus();
 439			
 440			}
 441    	
 442    	}    
 443    
 444    
 445        /**
 446        * @method onMenuVisibleConfigChange
 447        * @description Event handler for when the "visible" configuration  
 448        * property of a Menu instance changes.
 449        * @private
 450        * @param {String} p_sType String representing the name of the event  
 451        * that was fired.
 452        * @param {Array} p_aArgs Array of arguments sent when the event 
 453        * was fired.
 454        */
 455        function onMenuVisibleConfigChange(p_sType, p_aArgs) {
 456    
 457            var bVisible = p_aArgs[0],
 458                sId = this.id;
 459            
 460            if (bVisible) {
 461    
 462                m_oVisibleMenus[sId] = this;
 463                
 464            
 465            }
 466            else if (m_oVisibleMenus[sId]) {
 467            
 468                delete m_oVisibleMenus[sId];
 469                
 470            
 471            }
 472        
 473        }
 474    
 475    
 476        /**
 477        * @method onItemDestroy
 478        * @description "destroy" event handler for a MenuItem instance.
 479        * @private
 480        * @param {String} p_sType String representing the name of the event  
 481        * that was fired.
 482        * @param {Array} p_aArgs Array of arguments sent when the event 
 483        * was fired.
 484        */
 485        function onItemDestroy(p_sType, p_aArgs) {
 486    
 487            removeItem(this);
 488    
 489        }
 490
 491
 492        /**
 493        * @method removeItem
 494        * @description Removes a MenuItem instance from the MenuManager's collection of MenuItems.
 495        * @private
 496        * @param {MenuItem} p_oMenuItem The MenuItem instance to be removed.
 497        */    
 498        function removeItem(p_oMenuItem) {
 499
 500            var sId = p_oMenuItem.id;
 501    
 502            if (sId && m_oItems[sId]) {
 503    
 504                if (m_oFocusedMenuItem == p_oMenuItem) {
 505    
 506                    m_oFocusedMenuItem = null;
 507    
 508                }
 509    
 510                delete m_oItems[sId];
 511                
 512                p_oMenuItem.destroyEvent.unsubscribe(onItemDestroy);
 513    
 514    
 515            }
 516
 517        }
 518    
 519    
 520        /**
 521        * @method onItemAdded
 522        * @description "itemadded" event handler for a Menu instance.
 523        * @private
 524        * @param {String} p_sType String representing the name of the event  
 525        * that was fired.
 526        * @param {Array} p_aArgs Array of arguments sent when the event 
 527        * was fired.
 528        */
 529        function onItemAdded(p_sType, p_aArgs) {
 530    
 531            var oItem = p_aArgs[0],
 532                sId;
 533    
 534            if (oItem instanceof YAHOO.widget.MenuItem) { 
 535    
 536                sId = oItem.id;
 537        
 538                if (!m_oItems[sId]) {
 539            
 540                    m_oItems[sId] = oItem;
 541        
 542                    oItem.destroyEvent.subscribe(onItemDestroy);
 543        
 544        
 545                }
 546    
 547            }
 548        
 549        }
 550    
 551    
 552        return {
 553    
 554            // Privileged methods
 555    
 556    
 557            /**
 558            * @method addMenu
 559            * @description Adds a menu to the collection of known menus.
 560            * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu  
 561            * instance to be added.
 562            */
 563            addMenu: function (p_oMenu) {
 564    
 565                var oDoc;
 566    
 567                if (p_oMenu instanceof YAHOO.widget.Menu && p_oMenu.id && 
 568                    !m_oMenus[p_oMenu.id]) {
 569        
 570                    m_oMenus[p_oMenu.id] = p_oMenu;
 571                
 572            
 573                    if (!m_bInitializedEventHandlers) {
 574            
 575                        oDoc = document;
 576                
 577                        Event.on(oDoc, _MOUSEOVER, onDOMEvent, this, true);
 578                        Event.on(oDoc, _MOUSEOUT, onDOMEvent, this, true);
 579                        Event.on(oDoc, _MOUSEDOWN, onDOMEvent, this, true);
 580                        Event.on(oDoc, _MOUSEUP, onDOMEvent, this, true);
 581                        Event.on(oDoc, _CLICK, onDOMEvent, this, true);
 582                        Event.on(oDoc, _KEYDOWN, onDOMEvent, this, true);
 583                        Event.on(oDoc, _KEYUP, onDOMEvent, this, true);
 584                        Event.on(oDoc, _KEYPRESS, onDOMEvent, this, true);
 585    
 586						Event.onFocus(oDoc, onDOMEvent, this, true);
 587						Event.onBlur(oDoc, onDOMEvent, this, true);						
 588    
 589                        m_bInitializedEventHandlers = true;
 590                        
 591            
 592                    }
 593            
 594                    p_oMenu.cfg.subscribeToConfigEvent(_VISIBLE, onMenuVisibleConfigChange);
 595                    p_oMenu.destroyEvent.subscribe(onMenuDestroy, p_oMenu, this);
 596                    p_oMenu.itemAddedEvent.subscribe(onItemAdded);
 597                    p_oMenu.focusEvent.subscribe(onMenuFocus);
 598                    p_oMenu.blurEvent.subscribe(onMenuBlur);
 599                    p_oMenu.showEvent.subscribe(onMenuShow);
 600        
 601        
 602                }
 603        
 604            },
 605    
 606        
 607            /**
 608            * @method removeMenu
 609            * @description Removes a menu from the collection of known menus.
 610            * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu  
 611            * instance to be removed.
 612            */
 613            removeMenu: function (p_oMenu) {
 614    
 615                var sId,
 616                    aItems,
 617                    i;
 618        
 619                if (p_oMenu) {
 620    
 621                    sId = p_oMenu.id;
 622        
 623                    if ((sId in m_oMenus) && (m_oMenus[sId] == p_oMenu)) {
 624
 625                        // Unregister each menu item
 626
 627                        aItems = p_oMenu.getItems();
 628
 629                        if (aItems && aItems.length > 0) {
 630
 631                            i = aItems.length - 1;
 632
 633                            do {
 634
 635                                removeItem(aItems[i]);
 636
 637                            }
 638                            while (i--);
 639
 640                        }
 641
 642
 643                        // Unregister the menu
 644
 645                        delete m_oMenus[sId];
 646            
 647        
 648
 649                        /*
 650                             Unregister the menu from the collection of 
 651                             visible menus
 652                        */
 653
 654                        if ((sId in m_oVisibleMenus) && (m_oVisibleMenus[sId] == p_oMenu)) {
 655            
 656                            delete m_oVisibleMenus[sId];
 657                            
 658       
 659                        }
 660
 661
 662                        // Unsubscribe event listeners
 663
 664                        if (p_oMenu.cfg) {
 665
 666                            p_oMenu.cfg.unsubscribeFromConfigEvent(_VISIBLE, 
 667                                onMenuVisibleConfigChange);
 668                            
 669                        }
 670
 671                        p_oMenu.destroyEvent.unsubscribe(onMenuDestroy, 
 672                            p_oMenu);
 673                
 674                        p_oMenu.itemAddedEvent.unsubscribe(onItemAdded);
 675                        p_oMenu.focusEvent.unsubscribe(onMenuFocus);
 676                        p_oMenu.blurEvent.unsubscribe(onMenuBlur);
 677
 678                    }
 679                
 680                }
 681    
 682            },
 683        
 684        
 685            /**
 686            * @method hideVisible
 687            * @description Hides all visible, dynamically positioned menus 
 688            * (excluding instances of YAHOO.widget.MenuBar).
 689            */
 690            hideVisible: function () {
 691        
 692                var oMenu;
 693        
 694                for (var i in m_oVisibleMenus) {
 695        
 696                    if (Lang.hasOwnProperty(m_oVisibleMenus, i)) {
 697        
 698                        oMenu = m_oVisibleMenus[i];
 699        
 700                        if (!(oMenu instanceof YAHOO.widget.MenuBar) && 
 701                            oMenu.cfg.getProperty(_POSITION) == _DYNAMIC) {
 702        
 703                            oMenu.hide();
 704        
 705                        }
 706        
 707                    }
 708        
 709                }        
 710    
 711            },
 712
 713
 714            /**
 715            * @method getVisible
 716            * @description Returns a collection of all visible menus registered
 717            * with the menu manger.
 718            * @return {Object}
 719            */
 720            getVisible: function () {
 721            
 722                return m_oVisibleMenus;
 723            
 724            },
 725
 726    
 727            /**
 728            * @method getMenus
 729            * @description Returns a collection of all menus registered with the 
 730            * menu manger.
 731            * @return {Object}
 732            */
 733            getMenus: function () {
 734    
 735                return m_oMenus;
 736            
 737            },
 738    
 739    
 740            /**
 741            * @method getMenu
 742            * @description Returns a menu with the specified id.
 743            * @param {String} p_sId String specifying the id of the 
 744            * <code>&#60;div&#62;</code> element representing the menu to
 745            * be retrieved.
 746            * @return {YAHOO.widget.Menu}
 747            */
 748            getMenu: function (p_sId) {
 749                
 750                var returnVal;
 751                
 752                if (p_sId in m_oMenus) {
 753                
 754					returnVal = m_oMenus[p_sId];
 755				
 756				}
 757            
 758            	return returnVal;
 759            
 760            },
 761    
 762    
 763            /**
 764            * @method getMenuItem
 765            * @description Returns a menu item with the specified id.
 766            * @param {String} p_sId String specifying the id of the 
 767            * <code>&#60;li&#62;</code> element representing the menu item to
 768            * be retrieved.
 769            * @return {YAHOO.widget.MenuItem}
 770            */
 771            getMenuItem: function (p_sId) {
 772    
 773    			var returnVal;
 774    
 775    			if (p_sId in m_oItems) {
 776    
 777					returnVal = m_oItems[p_sId];
 778				
 779				}
 780				
 781				return returnVal;
 782            
 783            },
 784
 785
 786            /**
 787            * @method getMenuItemGroup
 788            * @description Returns an array of menu item instances whose 
 789            * corresponding <code>&#60;li&#62;</code> elements are child 
 790            * nodes of the <code>&#60;ul&#62;</code> element with the 
 791            * specified id.
 792            * @param {String} p_sId String specifying the id of the 
 793            * <code>&#60;ul&#62;</code> element representing the group of 
 794            * menu items to be retrieved.
 795            * @return {Array}
 796            */
 797            getMenuItemGroup: function (p_sId) {
 798
 799                var oUL = Dom.get(p_sId),
 800                    aItems,
 801                    oNode,
 802                    oItem,
 803                    sId,
 804                    returnVal;
 805    
 806
 807                if (oUL && oUL.tagName && oUL.tagName.toUpperCase() == _UL) {
 808
 809                    oNode = oUL.firstChild;
 810
 811                    if (oNode) {
 812
 813                        aItems = [];
 814                        
 815                        do {
 816
 817                            sId = oNode.id;
 818
 819                            if (sId) {
 820                            
 821                                oItem = this.getMenuItem(sId);
 822                                
 823                                if (oItem) {
 824                                
 825                                    aItems[aItems.length] = oItem;
 826                                
 827                                }
 828                            
 829                            }
 830                        
 831                        }
 832                        while ((oNode = oNode.nextSibling));
 833
 834
 835                        if (aItems.length > 0) {
 836
 837                            returnVal = aItems;
 838                        
 839                        }
 840
 841                    }
 842                
 843                }
 844
 845				return returnVal;
 846            
 847            },
 848
 849    
 850            /**
 851            * @method getFocusedMenuItem
 852            * @description Returns a reference to the menu item that currently 
 853            * has focus.
 854            * @return {YAHOO.widget.MenuItem}
 855            */
 856            getFocusedMenuItem: function () {
 857    
 858                return m_oFocusedMenuItem;
 859    
 860            },
 861    
 862    
 863            /**
 864            * @method getFocusedMenu
 865            * @description Returns a reference to the menu that currently 
 866            * has focus.
 867            * @return {YAHOO.widget.Menu}
 868            */
 869            getFocusedMenu: function () {
 870
 871				var returnVal;
 872    
 873                if (m_oFocusedMenuItem) {
 874    
 875                    returnVal = m_oFocusedMenuItem.parent.getRoot();
 876                
 877                }
 878    
 879    			return returnVal;
 880    
 881            },
 882    
 883        
 884            /**
 885            * @method toString
 886            * @description Returns a string representing the menu manager.
 887            * @return {String}
 888            */
 889            toString: function () {
 890            
 891                return _MENUMANAGER;
 892            
 893            }
 894    
 895        };
 896    
 897    }();
 898
 899})();
 900
 901
 902
 903(function () {
 904
 905	var Lang = YAHOO.lang,
 906
 907	// String constants
 908	
 909		_MENU = "Menu",
 910		_DIV_UPPERCASE = "DIV",
 911		_DIV_LOWERCASE = "div",
 912		_ID = "id",
 913		_SELECT = "SELECT",
 914		_XY = "xy",
 915		_Y = "y",
 916		_UL_UPPERCASE = "UL",
 917		_UL_LOWERCASE = "ul",
 918		_FIRST_OF_TYPE = "first-of-type",
 919		_LI = "LI",
 920		_OPTGROUP = "OPTGROUP",
 921		_OPTION = "OPTION",
 922		_DISABLED = "disabled",
 923		_NONE = "none",
 924		_SELECTED = "selected",
 925		_GROUP_INDEX = "groupindex",
 926		_INDEX = "index",
 927		_SUBMENU = "submenu",
 928		_VISIBLE = "visible",
 929		_HIDE_DELAY = "hidedelay",
 930		_POSITION = "position",
 931		_DYNAMIC = "dynamic",
 932		_STATIC = "static",
 933		_DYNAMIC_STATIC = _DYNAMIC + "," + _STATIC,
 934		_WINDOWS = "windows",
 935		_URL = "url",
 936		_HASH = "#",
 937		_TARGET = "target",
 938		_MAX_HEIGHT = "maxheight",
 939        _TOP_SCROLLBAR = "topscrollbar",
 940        _BOTTOM_SCROLLBAR = "bottomscrollbar",
 941        _UNDERSCORE = "_",
 942		_TOP_SCROLLBAR_DISABLED = _TOP_SCROLLBAR + _UNDERSCORE + _DISABLED,
 943		_BOTTOM_SCROLLBAR_DISABLED = _BOTTOM_SCROLLBAR + _UNDERSCORE + _DISABLED,
 944		_MOUSEMOVE = "mousemove",
 945		_SHOW_DELAY = "showdelay",
 946		_SUBMENU_HIDE_DELAY = "submenuhidedelay",
 947		_IFRAME = "iframe",
 948		_CONSTRAIN_TO_VIEWPORT = "constraintoviewport",
 949		_PREVENT_CONTEXT_OVERLAP = "preventcontextoverlap",
 950		_SUBMENU_ALIGNMENT = "submenualignment",
 951		_AUTO_SUBMENU_DISPLAY = "autosubmenudisplay",
 952		_CLICK_TO_HIDE = "clicktohide",
 953		_CONTAINER = "container",
 954		_SCROLL_INCREMENT = "scrollincrement",
 955		_MIN_SCROLL_HEIGHT = "minscrollheight",
 956		_CLASSNAME = "classname",
 957		_SHADOW = "shadow",
 958		_KEEP_OPEN = "keepopen",
 959		_HD = "hd",
 960		_HAS_TITLE = "hastitle",
 961		_CONTEXT = "context",
 962		_EMPTY_STRING = "",
 963		_MOUSEDOWN = "mousedown",
 964		_KEYDOWN = "keydown",
 965		_HEIGHT = "height",
 966		_WIDTH = "width",
 967		_PX = "px",
 968		_EFFECT = "effect",
 969		_MONITOR_RESIZE = "monitorresize",
 970		_DISPLAY = "display",
 971		_BLOCK = "block",
 972		_VISIBILITY = "visibility",
 973		_ABSOLUTE = "absolute",
 974		_ZINDEX = "zindex",
 975		_YUI_MENU_BODY_SCROLLED = "yui-menu-body-scrolled",
 976		_NON_BREAKING_SPACE = "&#32;",
 977		_SPACE = " ",
 978		_MOUSEOVER = "mouseover",
 979		_MOUSEOUT = "mouseout",
 980        _ITEM_ADDED = "itemAdded",
 981        _ITEM_REMOVED = "itemRemoved",
 982        _HIDDEN = "hidden",
 983        _YUI_MENU_SHADOW = "yui-menu-shadow",
 984        _YUI_MENU_SHADOW_VISIBLE = _YUI_MENU_SHADOW + "-visible",
 985        _YUI_MENU_SHADOW_YUI_MENU_SHADOW_VISIBLE = _YUI_MENU_SHADOW + _SPACE + _YUI_MENU_SHADOW_VISIBLE;
 986
 987
 988/**
 989* The Menu class creates a container that holds a vertical list representing 
 990* a set of options or commands.  Menu is the base class for all 
 991* menu containers. 
 992* @param {String} p_oElement String specifying the id attribute of the 
 993* <code>&#60;div&#62;</code> element of the menu.
 994* @param {String} p_oElement String specifying the id attribute of the 
 995* <code>&#60;select&#62;</code> element to be used as the data source 
 996* for the menu.
 997* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
 998* level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object 
 999* specifying the <code>&#60;div&#62;</code> element of the menu.
1000* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1001* level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement 
1002* Object specifying the <code>&#60;select&#62;</code> element to be used as 
1003* the data source for the menu.
1004* @param {Object} p_oConfig Optional. Object literal specifying the 
1005* configuration for the menu. See configuration class documentation for 
1006* more details.
1007* @namespace YAHOO.widget
1008* @class Menu
1009* @constructor
1010* @extends YAHOO.widget.Overlay
1011*/
1012YAHOO.widget.Menu = function (p_oElement, p_oConfig) {
1013
1014    if (p_oConfig) {
1015
1016        this.parent = p_oConfig.parent;
1017        this.lazyLoad = p_oConfig.lazyLoad || p_oConfig.lazyload;
1018        this.itemData = p_oConfig.itemData || p_oConfig.itemdata;
1019
1020    }
1021
1022
1023    YAHOO.widget.Menu.superclass.constructor.call(this, p_oElement, p_oConfig);
1024
1025};
1026
1027
1028
1029/**
1030* @method checkPosition
1031* @description Checks to make sure that the value of the "position" property 
1032* is one of the supported strings. Returns true if the position is supported.
1033* @private
1034* @param {Object} p_sPosition String specifying the position of the menu.
1035* @return {Boolean}
1036*/
1037function checkPosition(p_sPosition) {
1038
1039	var returnVal = false;
1040
1041    if (Lang.isString(p_sPosition)) {
1042
1043        returnVal = (_DYNAMIC_STATIC.indexOf((p_sPosition.toLowerCase())) != -1);
1044
1045    }
1046
1047	return returnVal;
1048
1049}
1050
1051
1052var Dom = YAHOO.util.Dom,
1053    Event = YAHOO.util.Event,
1054    Module = YAHOO.widget.Module,
1055    Overlay = YAHOO.widget.Overlay,
1056    Menu = YAHOO.widget.Menu,
1057    MenuManager = YAHOO.widget.MenuManager,
1058    CustomEvent = YAHOO.util.CustomEvent,
1059    UA = YAHOO.env.ua,
1060    
1061    m_oShadowTemplate,
1062
1063	EVENT_TYPES = [
1064    
1065		["mouseOverEvent", _MOUSEOVER],
1066		["mouseOutEvent", _MOUSEOUT],
1067		["mouseDownEvent", _MOUSEDOWN],
1068		["mouseUpEvent", "mouseup"],
1069		["clickEvent", "click"],
1070		["keyPressEvent", "keypress"],
1071		["keyDownEvent", _KEYDOWN],
1072		["keyUpEvent", "keyup"],
1073		["focusEvent", "focus"],
1074		["blurEvent", "blur"],
1075		["itemAddedEvent", _ITEM_ADDED],
1076		["itemRemovedEvent", _ITEM_REMOVED]
1077
1078	],
1079
1080	VISIBLE_CONFIG =  { 
1081		key: _VISIBLE, 
1082		value: false, 
1083		validator: Lang.isBoolean
1084	}, 
1085
1086	CONSTRAIN_TO_VIEWPORT_CONFIG =  {
1087		key: _CONSTRAIN_TO_VIEWPORT, 
1088		value: true, 
1089		validator: Lang.isBoolean, 
1090		supercedes: [_IFRAME,"x",_Y,_XY]
1091	}, 
1092
1093	PREVENT_CONTEXT_OVERLAP_CONFIG =  {
1094		key: _PREVENT_CONTEXT_OVERLAP,
1095		value: true,
1096		validator: Lang.isBoolean,  
1097		supercedes: [_CONSTRAIN_TO_VIEWPORT]
1098	},
1099
1100	POSITION_CONFIG =  { 
1101		key: _POSITION, 
1102		value: _DYNAMIC, 
1103		validator: checkPosition, 
1104		supercedes: [_VISIBLE, _IFRAME]
1105	}, 
1106
1107	SUBMENU_ALIGNMENT_CONFIG =  { 
1108		key: _SUBMENU_ALIGNMENT, 
1109		value: ["tl","tr"]
1110	},
1111
1112	AUTO_SUBMENU_DISPLAY_CONFIG =  { 
1113		key: _AUTO_SUBMENU_DISPLAY, 
1114		value: true, 
1115		validator: Lang.isBoolean,
1116		suppressEvent: true
1117	}, 
1118
1119	SHOW_DELAY_CONFIG =  { 
1120		key: _SHOW_DELAY, 
1121		value: 250, 
1122		validator: Lang.isNumber, 
1123		suppressEvent: true
1124	}, 
1125
1126	HIDE_DELAY_CONFIG =  { 
1127		key: _HIDE_DELAY, 
1128		value: 0, 
1129		validator: Lang.isNumber, 
1130		suppressEvent: true
1131	}, 
1132
1133	SUBMENU_HIDE_DELAY_CONFIG =  { 
1134		key: _SUBMENU_HIDE_DELAY, 
1135		value: 250, 
1136		validator: Lang.isNumber,
1137		suppressEvent: true
1138	}, 
1139
1140	CLICK_TO_HIDE_CONFIG =  { 
1141		key: _CLICK_TO_HIDE, 
1142		value: true, 
1143		validator: Lang.isBoolean,
1144		suppressEvent: true
1145	},
1146
1147	CONTAINER_CONFIG =  { 
1148		key: _CONTAINER,
1149		suppressEvent: true
1150	}, 
1151
1152	SCROLL_INCREMENT_CONFIG =  { 
1153		key: _SCROLL_INCREMENT, 
1154		value: 1, 
1155		validator: Lang.isNumber,
1156		supercedes: [_MAX_HEIGHT],
1157		suppressEvent: true
1158	},
1159
1160	MIN_SCROLL_HEIGHT_CONFIG =  { 
1161		key: _MIN_SCROLL_HEIGHT, 
1162		value: 90, 
1163		validator: Lang.isNumber,
1164		supercedes: [_MAX_HEIGHT],
1165		suppressEvent: true
1166	},    
1167
1168	MAX_HEIGHT_CONFIG =  { 
1169		key: _MAX_HEIGHT, 
1170		value: 0, 
1171		validator: Lang.isNumber,
1172		supercedes: [_IFRAME],
1173		suppressEvent: true
1174	}, 
1175
1176	CLASS_NAME_CONFIG =  { 
1177		key: _CLASSNAME, 
1178		value: null, 
1179		validator: Lang.isString,
1180		suppressEvent: true
1181	}, 
1182
1183	DISABLED_CONFIG =  { 
1184		key: _DISABLED, 
1185		value: false, 
1186		validator: Lang.isBoolean,
1187		suppressEvent: true
1188	},
1189	
1190	SHADOW_CONFIG =  { 
1191		key: _SHADOW, 
1192		value: true, 
1193		validator: Lang.isBoolean,
1194		suppressEvent: true,
1195		supercedes: [_VISIBLE]
1196	},
1197	
1198	KEEP_OPEN_CONFIG = {
1199		key: _KEEP_OPEN, 
1200		value: false, 
1201		validator: Lang.isBoolean
1202	};
1203
1204
1205
1206YAHOO.lang.extend(Menu, Overlay, {
1207
1208
1209// Constants
1210
1211
1212/**
1213* @property CSS_CLASS_NAME
1214* @description String representing the CSS class(es) to be applied to the 
1215* menu's <code>&#60;div&#62;</code> element.
1216* @default "yuimenu"
1217* @final
1218* @type String
1219*/
1220CSS_CLASS_NAME: "yuimenu",
1221
1222
1223/**
1224* @property ITEM_TYPE
1225* @description Object representing the type of menu item to instantiate and 
1226* add when parsing the child nodes (either <code>&#60;li&#62;</code> element, 
1227* <code>&#60;optgroup&#62;</code> element or <code>&#60;option&#62;</code>) 
1228* of the menu's source HTML element.
1229* @default YAHOO.widget.MenuItem
1230* @final
1231* @type YAHOO.widget.MenuItem
1232*/
1233ITEM_TYPE: null,
1234
1235
1236/**
1237* @property GROUP_TITLE_TAG_NAME
1238* @description String representing the tagname of the HTML element used to 
1239* title the menu's item groups.
1240* @default H6
1241* @final
1242* @type String
1243*/
1244GROUP_TITLE_TAG_NAME: "h6",
1245
1246
1247/**
1248* @property OFF_SCREEN_POSITION
1249* @description Array representing the default x and y position that a menu 
1250* should have when it is positioned outside the viewport by the 
1251* "poistionOffScreen" method.
1252* @default "-999em"
1253* @final
1254* @type String
1255*/
1256OFF_SCREEN_POSITION: "-999em",
1257
1258
1259// Private properties
1260
1261
1262/** 
1263* @property _useHideDelay
1264* @description Boolean indicating if the "mouseover" and "mouseout" event 
1265* handlers used for hiding the menu via a call to "YAHOO.lang.later" have 
1266* already been assigned.
1267* @default false
1268* @private
1269* @type Boolean
1270*/
1271_useHideDelay: false,
1272
1273
1274/**
1275* @property _bHandledMouseOverEvent
1276* @description Boolean indicating the current state of the menu's 
1277* "mouseover" event.
1278* @default false
1279* @private
1280* @type Boolean
1281*/
1282_bHandledMouseOverEvent: false,
1283
1284
1285/**
1286* @property _bHandledMouseOutEvent
1287* @description Boolean indicating the current state of the menu's
1288* "mouseout" event.
1289* @default false
1290* @private
1291* @type Boolean
1292*/
1293_bHandledMouseOutEvent: false,
1294
1295
1296/**
1297* @property _aGroupTitleElements
1298* @description Array of HTML element used to title groups of menu items.
1299* @default []
1300* @private
1301* @type Array
1302*/
1303_aGroupTitleElements: null,
1304
1305
1306/**
1307* @property _aItemGroups
1308* @description Multi-dimensional Array representing the menu items as they
1309* are grouped in the menu.
1310* @default []
1311* @private
1312* @type Array
1313*/
1314_aItemGroups: null,
1315
1316
1317/**
1318* @property _aListElements
1319* @description Array of <code>&#60;ul&#62;</code> elements, each of which is 
1320* the parent node for each item's <code>&#60;li&#62;</code> element.
1321* @default []
1322* @private
1323* @type Array
1324*/
1325_aListElements: null,
1326
1327
1328/**
1329* @property _nCurrentMouseX
1330* @description The current x coordinate of the mouse inside the area of 
1331* the menu.
1332* @default 0
1333* @private
1334* @type Number
1335*/
1336_nCurrentMouseX: 0,
1337
1338
1339/**
1340* @property _bStopMouseEventHandlers
1341* @description Stops "mouseover," "mouseout," and "mousemove" event handlers 
1342* from executing.
1343* @default false
1344* @private
1345* @type Boolean
1346*/
1347_bStopMouseEventHandlers: false,
1348
1349
1350/**
1351* @property _sClassName
1352* @description The current value of the "classname" configuration attribute.
1353* @default null
1354* @private
1355* @type String
1356*/
1357_sClassName: null,
1358
1359
1360
1361// Public properties
1362
1363
1364/**
1365* @property lazyLoad
1366* @description Boolean indicating if the menu's "lazy load" feature is 
1367* enabled.  If set to "true," initialization and rendering of the menu's 
1368* items will be deferred until the first time it is made visible.  This 
1369* property should be set via the constructor using the configuration 
1370* object literal.
1371* @default false
1372* @type Boolean
1373*/
1374lazyLoad: false,
1375
1376
1377/**
1378* @property itemData
1379* @description Array of items to be added to the menu.  The array can contain 
1380* strings representing the text for each item to be created, object literals 
1381* representing the menu item configuration properties, or MenuItem instances.  
1382* This property should be set via the constructor using the configuration 
1383* object literal.
1384* @default null
1385* @type Array
1386*/
1387itemData: null,
1388
1389
1390/**
1391* @property activeItem
1392* @description Object reference to the item in the menu that has is selected.
1393* @default null
1394* @type YAHOO.widget.MenuItem
1395*/
1396activeItem: null,
1397
1398
1399/**
1400* @property parent
1401* @description Object reference to the menu's parent menu or menu item.  
1402* This property can be set via the constructor using the configuration 
1403* object literal.
1404* @default null
1405* @type YAHOO.widget.MenuItem
1406*/
1407parent: null,
1408
1409
1410/**
1411* @property srcElement
1412* @description Object reference to the HTML element (either 
1413* <code>&#60;select&#62;</code> or <code>&#60;div&#62;</code>) used to 
1414* create the menu.
1415* @default null
1416* @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1417* level-one-html.html#ID-94282980">HTMLSelectElement</a>|<a 
1418* href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.
1419* html#ID-22445964">HTMLDivElement</a>
1420*/
1421srcElement: null,
1422
1423
1424
1425// Events
1426
1427
1428/**
1429* @event mouseOverEvent
1430* @description Fires when the mouse has entered the menu.  Passes back 
1431* the DOM Event object as an argument.
1432*/
1433
1434
1435/**
1436* @event mouseOutEvent
1437* @description Fires when the mouse has left the menu.  Passes back the DOM 
1438* Event object as an argument.
1439* @type YAHOO.util.CustomEvent
1440*/
1441
1442
1443/**
1444* @event mouseDownEvent
1445* @description Fires when the user mouses down on the menu.  Passes back the 
1446* DOM Event object as an argument.
1447* @type YAHOO.util.CustomEvent
1448*/
1449
1450
1451/**
1452* @event mouseUpEvent
1453* @description Fires when the user releases a mouse button while the mouse is 
1454* over the menu.  Passes back the DOM Event object as an argument.
1455* @type YAHOO.util.CustomEvent
1456*/
1457
1458
1459/**
1460* @event clickEvent
1461* @description Fires when the user clicks the on the menu.  Passes back the 
1462* DOM Event object as an argument.
1463* @type YAHOO.util.CustomEvent
1464*/
1465
1466
1467/**
1468* @event keyPressEvent
1469* @description Fires when the user presses an alphanumeric key when one of the
1470* menu's items has focus.  Passes back the DOM Event object as an argument.
1471* @type YAHOO.util.CustomEvent
1472*/
1473
1474
1475/**
1476* @event keyDownEvent
1477* @description Fires when the user presses a key when one of the menu's items 
1478* has focus.  Passes back the DOM Event object as an argument.
1479* @type YAHOO.util.CustomEvent
1480*/
1481
1482
1483/**
1484* @event keyUpEvent
1485* @description Fires when the user releases a key when one of the menu's items 
1486* has focus.  Passes back the DOM Event object as an argument.
1487* @type YAHOO.util.CustomEvent
1488*/
1489
1490
1491/**
1492* @event itemAddedEvent
1493* @description Fires when an item is added to the menu.
1494* @type YAHOO.util.CustomEvent
1495*/
1496
1497
1498/**
1499* @event itemRemovedEvent
1500* @description Fires when an item is removed to the menu.
1501* @type YAHOO.util.CustomEvent
1502*/
1503
1504
1505/**
1506* @method init
1507* @description The Menu class's initialization method. This method is 
1508* automatically called by the constructor, and sets up all DOM references 
1509* for pre-existing markup, and creates required markup if it is not 
1510* already present.
1511* @param {String} p_oElement String specifying the id attribute of the 
1512* <code>&#60;div&#62;</code> element of the menu.
1513* @param {String} p_oElement String specifying the id attribute of the 
1514* <code>&#60;select&#62;</code> element to be used as the data source 
1515* for the menu.
1516* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1517* level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object 
1518* specifying the <code>&#60;div&#62;</code> element of the menu.
1519* @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1520* level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement 
1521* Object specifying the <code>&#60;select&#62;</code> element to be used as 
1522* the data source for the menu.
1523* @param {Object} p_oConfig Optional. Object literal specifying the 
1524* configuration for the menu. See configuration class documentation for 
1525* more details.
1526*/
1527init: function (p_oElement, p_oConfig) {
1528
1529    this._aItemGroups = [];
1530    this._aListElements = [];
1531    this._aGroupTitleElements = [];
1532
1533    if (!this.ITEM_TYPE) {
1534
1535        this.ITEM_TYPE = YAHOO.widget.MenuItem;
1536
1537    }
1538
1539
1540    var oElement;
1541
1542    if (Lang.isString(p_oElement)) {
1543
1544        oElement = Dom.get(p_oElement);
1545
1546    }
1547    else if (p_oElement.tagName) {
1548
1549        oElement = p_oElement;
1550
1551    }
1552
1553
1554    if (oElement && oElement.tagName) {
1555
1556        switch(oElement.tagName.toUpperCase()) {
1557    
1558            case _DIV_UPPERCASE:
1559
1560                this.srcElement = oElement;
1561
1562                if (!oElement.id) {
1563
1564                    oElement.setAttribute(_ID, Dom.generateId());
1565
1566                }
1567
1568
1569                /* 
1570                    Note: we don't pass the user config in here yet 
1571                    because we only want it executed once, at the lowest 
1572                    subclass level.
1573                */ 
1574            
1575                Menu.superclass.init.call(this, oElement);
1576
1577                this.beforeInitEvent.fire(Menu);
1578
1579    
1580            break;
1581    
1582            case _SELECT:
1583    
1584                this.srcElement = oElement;
1585
1586    
1587                /*
1588                    The source element is not something that we can use 
1589                    outright, so we need to create a new Overlay
1590
1591                    Note: we don't pass the user config in here yet 
1592                    because we only want it executed once, at the lowest 
1593                    subclass level.
1594                */ 
1595
1596                Menu.superclass.init.call(this, Dom.generateId());
1597
1598                this.beforeInitEvent.fire(Menu);
1599
1600
1601            break;
1602
1603        }
1604
1605    }
1606    else {
1607
1608        /* 
1609            Note: we don't pass the user config in here yet 
1610            because we only want it executed once, at the lowest 
1611            subclass level.
1612        */ 
1613    
1614        Menu.superclass.init.call(this, p_oElement);
1615
1616        this.beforeInitEvent.fire(Menu);
1617
1618
1619    }
1620
1621
1622    if (this.element) {
1623
1624        Dom.addClass(this.element, this.CSS_CLASS_NAME);
1625
1626
1627        // Subscribe to Custom Events
1628
1629        this.initEvent.subscribe(this._onInit);
1630        this.beforeRenderEvent.subscribe(this._onBeforeRender);
1631        this.renderEvent.subscribe(this._onRender);
1632        this.beforeShowEvent.subscribe(this._onBeforeShow);
1633        this.hideEvent.subscribe(this._onHide);
1634        this.showEvent.subscribe(this._onShow);
1635        this.beforeHideEvent.subscribe(this._onBeforeHide);
1636        this.mouseOverEvent.subscribe(this._onMouseOver);
1637        this.mouseOutEvent.subscribe(this._onMouseOut);
1638        this.clickEvent.subscribe(this._onClick);
1639        this.keyDownEvent.subscribe(this._onKeyDown);
1640        this.keyPressEvent.subscribe(this._onKeyPress);
1641        this.blurEvent.subscribe(this._onBlur);
1642
1643
1644		//	Fixes an issue in Firefox 2 and Webkit where Dom's "getX" and "getY" 
1645		//	methods return values that don't take scrollTop into consideration 
1646
1647        if ((UA.gecko && UA.gecko < 1.9) || UA.webkit) {
1648
1649            this.cfg.subscribeToConfigEvent(_Y, this._onYChange);
1650
1651        }
1652
1653
1654        if (p_oConfig) {
1655    
1656            this.cfg.applyConfig(p_oConfig, true);
1657    
1658        }
1659
1660
1661        // Register the Menu instance with the MenuManager
1662
1663        MenuManager.addMenu(this);
1664        
1665
1666        this.initEvent.fire(Menu);
1667
1668    }
1669
1670},
1671
1672
1673
1674// Private methods
1675
1676
1677/**
1678* @method _initSubTree
1679* @description Iterates the childNodes of the source element to find nodes 
1680* used to instantiate menu and menu items.
1681* @private
1682*/
1683_initSubTree: function () {
1684
1685    var oSrcElement = this.srcElement,
1686        sSrcElementTagName,
1687        nGroup,
1688        sGroupTitleTagName,
1689        oNode,
1690        aListElements,
1691        nListElements,
1692        i;
1693
1694
1695    if (oSrcElement) {
1696    
1697        sSrcElementTagName = 
1698            (oSrcElement.tagName && oSrcElement.tagName.toUpperCase());
1699
1700
1701        if (sSrcElementTagName == _DIV_UPPERCASE) {
1702    
1703            //  Populate the collection of item groups and item group titles
1704    
1705            oNode = this.body.firstChild;
1706    
1707
1708            if (oNode) {
1709    
1710                nGroup = 0;
1711                sGroupTitleTagName = this.GROUP_TITLE_TAG_NAME.toUpperCase();
1712        
1713                do {
1714        
1715
1716                    if (oNode && oNode.tagName) {
1717        
1718                        switch (oNode.tagName.toUpperCase()) {
1719        
1720                            case sGroupTitleTagName:
1721                            
1722                                this._aGroupTitleElements[nGroup] = oNode;
1723        
1724                            break;
1725        
1726                            case _UL_UPPERCASE:
1727        
1728                                this._aListElements[nGroup] = oNode;
1729                                this._aItemGroups[nGroup] = [];
1730                                nGroup++;
1731        
1732                            break;
1733        
1734                        }
1735                    
1736                    }
1737        
1738                }
1739                while ((oNode = oNode.nextSibling));
1740        
1741        
1742                /*
1743                    Apply the "first-of-type" class to the first UL to mimic 
1744                    the ":first-of-type" CSS3 psuedo class.
1745                */
1746        
1747                if (this._aListElements[0]) {
1748        
1749                    Dom.addClass(this._aListElements[0], _FIRST_OF_TYPE);
1750        
1751                }
1752            
1753            }
1754    
1755        }
1756    
1757    
1758        oNode = null;
1759    
1760    
1761
1762        if (sSrcElementTagName) {
1763    
1764            switch (sSrcElementTagName) {
1765        
1766                case _DIV_UPPERCASE:
1767
1768                    aListElements = this._aListElements;
1769                    nListElements = aListElements.length;
1770        
1771                    if (nListElements > 0) {
1772        
1773        
1774                        i = nListElements - 1;
1775        
1776                        do {
1777        
1778                            oNode = aListElements[i].firstChild;
1779            
1780                            if (oNode) {
1781
1782            
1783                                do {
1784                
1785                                    if (oNode && oNode.tagName && 
1786                                        oNode.tagName.toUpperCase() == _LI) {
1787                
1788        
1789                                        this.addItem(new this.ITEM_TYPE(oNode, 
1790                                                    { parent: this }), i);
1791            
1792                                    }
1793                        
1794                                }
1795                                while ((oNode = oNode.nextSibling));
1796                            
1797                            }
1798                    
1799                        }
1800                        while (i--);
1801        
1802                    }
1803        
1804                break;
1805        
1806                case _SELECT:
1807        
1808        
1809                    oNode = oSrcElement.firstChild;
1810        
1811                    do {
1812        
1813                        if (oNode && oNode.tagName) {
1814                        
1815                            switch (oNode.tagName.toUpperCase()) {
1816            
1817                                case _OPTGROUP:
1818                                case _OPTION:
1819            
1820            
1821                                    this.addItem(
1822                                            new this.ITEM_TYPE(
1823                                                    oNode, 
1824                                                    { parent: this }
1825                                                )
1826                                            );
1827            
1828                                break;
1829            
1830                            }
1831    
1832                        }
1833        
1834                    }
1835                    while ((oNode = oNode.nextSibling));
1836        
1837                break;
1838        
1839            }
1840    
1841        }    
1842    
1843    }
1844
1845},
1846
1847
1848/**
1849* @method _getFirstEnabledItem
1850* @description Returns the first enabled item in the menu.
1851* @return {YAHOO.widget.MenuItem}
1852* @private
1853*/
1854_getFirstEnabledItem: function () {
1855
1856    var aItems = this.getItems(),
1857        nItems = aItems.length,
1858        oItem,
1859        returnVal;
1860    
1861
1862    for(var i=0; i<nItems; i++) {
1863
1864        oItem = aItems[i];
1865
1866        if (oItem && !oItem.cfg.getProperty(_DISABLED) && oItem.element.style.display != _NONE) {
1867
1868            returnVal = oItem;
1869            break;
1870
1871        }
1872    
1873    }
1874    
1875    return returnVal;
1876    
1877},
1878
1879
1880/**
1881* @method _addItemToGroup
1882* @description Adds a menu item to a group.
1883* @private
1884* @param {Number} p_nGroupIndex Number indicating the group to which the 
1885* item belongs.
1886* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem 
1887* instance to be added to the menu.
1888* @param {String} p_oItem String specifying the text of the item to be added 
1889* to the menu.
1890* @param {Object} p_oItem Object literal containing a set of menu item 
1891* configuration properties.
1892* @param {Number} p_nItemIndex Optional. Number indicating the index at 
1893* which the menu item should be added.
1894* @return {YAHOO.widget.MenuItem}
1895*/
1896_addItemToGroup: function (p_nGroupIndex, p_oItem, p_nItemIndex) {
1897
1898    var oItem,
1899        nGroupIndex,
1900        aGroup,
1901        oGroupItem,
1902        bAppend,
1903        oNextItemSibling,
1904        nItemIndex,
1905        returnVal;
1906
1907
1908    function getNextItemSibling(p_aArray, p_nStartIndex) {
1909
1910        return (p_aArray[p_nStartIndex] || getNextItemSibling(p_aArray, (p_nStartIndex+1)));
1911
1912    }
1913
1914
1915    if (p_oItem instanceof this.ITEM_TYPE) {
1916
1917        oItem = p_oItem;
1918        oItem.parent = this;
1919
1920    }
1921    else if (Lang.isString(p_oItem)) {
1922
1923        oItem = new this.ITEM_TYPE(p_oItem, { parent: this });
1924    
1925    }
1926    else if (Lang.isObject(p_oItem)) {
1927
1928        p_oItem.parent = this;
1929
1930        oItem = new this.ITEM_TYPE(p_oItem.text, p_oItem);
1931
1932    }
1933
1934
1935    if (oItem) {
1936
1937        if (oItem.cfg.getProperty(_SELECTED)) {
1938
1939            this.activeItem = oItem;
1940        
1941        }
1942
1943
1944        nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0;
1945        aGroup = this._getItemGrou

Large files files are truncated, but you can click here to view the full file