| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608 | 
							- <!DOCTYPE html>
 
- <html>
 
- <head>
 
-   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 
-   <title>The source code</title>
 
-   <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
 
-   <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
 
-   <style type="text/css">
 
-     .highlight { display: block; background-color: #ddd; }
 
-   </style>
 
-   <script type="text/javascript">
 
-     function highlight() {
 
-       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
 
-     }
 
-   </script>
 
- </head>
 
- <body onload="prettyPrint(); highlight();">
 
-   <pre class="prettyprint lang-js"><span id='Ext-menu-Menu'>/**
 
- </span> * A menu object. This is the container to which you may add {@link Ext.menu.Item menu items}.
 
-  *
 
-  * Menus may contain either {@link Ext.menu.Item menu items}, or general {@link Ext.Component Components}.
 
-  * Menus may also contain {@link Ext.panel.AbstractPanel#dockedItems docked items} because it extends {@link Ext.panel.Panel}.
 
-  *
 
-  * To make a contained general {@link Ext.Component Component} line up with other {@link Ext.menu.Item menu items},
 
-  * specify `{@link Ext.menu.Item#plain plain}: true`. This reserves a space for an icon, and indents the Component
 
-  * in line with the other menu items.
 
-  *
 
-  * By default, Menus are absolutely positioned, floating Components. By configuring a Menu with `{@link #floating}: false`,
 
-  * a Menu may be used as a child of a {@link Ext.container.Container Container}.
 
-  *
 
-  *     @example
 
-  *     Ext.create('Ext.menu.Menu', {
 
-  *         width: 100,
 
-  *         margin: '0 0 10 0',
 
-  *         floating: false,  // usually you want this set to True (default)
 
-  *         renderTo: Ext.getBody(),  // usually rendered by it's containing component
 
-  *         items: [{
 
-  *             text: 'regular item 1'
 
-  *         },{
 
-  *             text: 'regular item 2'
 
-  *         },{
 
-  *             text: 'regular item 3'
 
-  *         }]
 
-  *     });
 
-  *
 
-  *     Ext.create('Ext.menu.Menu', {
 
-  *         width: 100,
 
-  *         plain: true,
 
-  *         floating: false,  // usually you want this set to True (default)
 
-  *         renderTo: Ext.getBody(),  // usually rendered by it's containing component
 
-  *         items: [{
 
-  *             text: 'plain item 1'
 
-  *         },{
 
-  *             text: 'plain item 2'
 
-  *         },{
 
-  *             text: 'plain item 3'
 
-  *         }]
 
-  *     });
 
-  */
 
- Ext.define('Ext.menu.Menu', {
 
-     extend: 'Ext.panel.Panel',
 
-     alias: 'widget.menu',
 
-     requires: [
 
-         'Ext.layout.container.Fit',
 
-         'Ext.layout.container.VBox',
 
-         'Ext.menu.CheckItem',
 
-         'Ext.menu.Item',
 
-         'Ext.menu.KeyNav',
 
-         'Ext.menu.Manager',
 
-         'Ext.menu.Separator'
 
-     ],
 
- <span id='Ext-menu-Menu-property-parentMenu'>    /**
 
- </span>     * @property {Ext.menu.Menu} parentMenu
 
-      * The parent Menu of this Menu.
 
-      */
 
-     
 
- <span id='Ext-menu-Menu-cfg-enableKeyNav'>    /**
 
- </span>     * @cfg {Boolean} [enableKeyNav=true]
 
-      * True to enable keyboard navigation for controlling the menu.
 
-      * This option should generally be disabled when form fields are
 
-      * being used inside the menu.
 
-      */
 
-     enableKeyNav: true,
 
- <span id='Ext-menu-Menu-cfg-allowOtherMenus'>    /**
 
- </span>     * @cfg {Boolean} [allowOtherMenus=false]
 
-      * True to allow multiple menus to be displayed at the same time.
 
-      */
 
-     allowOtherMenus: false,
 
- <span id='Ext-menu-Menu-cfg-ariaRole'>    /**
 
- </span>     * @cfg {String} ariaRole
 
-      * @private
 
-      */
 
-     ariaRole: 'menu',
 
- <span id='Ext-menu-Menu-cfg-autoRender'>    /**
 
- </span>     * @cfg {Boolean} autoRender
 
-      * Floating is true, so autoRender always happens.
 
-      * @private
 
-      */
 
- <span id='Ext-menu-Menu-cfg-defaultAlign'>    /**
 
- </span>     * @cfg {String} [defaultAlign="tl-bl?"]
 
-      * The default {@link Ext.Element#getAlignToXY Ext.Element#getAlignToXY} anchor position value for this menu
 
-      * relative to its element of origin.
 
-      */
 
-     defaultAlign: 'tl-bl?',
 
- <span id='Ext-menu-Menu-cfg-floating'>    /**
 
- </span>     * @cfg {Boolean} [floating=true]
 
-      * A Menu configured as `floating: true` (the default) will be rendered as an absolutely positioned,
 
-      * {@link Ext.Component#floating floating} {@link Ext.Component Component}. If configured as `floating: false`, the Menu may be
 
-      * used as a child item of another {@link Ext.container.Container Container}.
 
-      */
 
-     floating: true,
 
- <span id='Ext-menu-Menu-cfg-constrain'>    /**
 
- </span>     * @cfg {Boolean} constrain
 
-      * Menus are constrained to the document body by default.
 
-      * @private
 
-      */
 
-     constrain: true,
 
- <span id='Ext-menu-Menu-cfg-hidden'>    /**
 
- </span>     * @cfg {Boolean} [hidden=undefined]
 
-      * True to initially render the Menu as hidden, requiring to be shown manually.
 
-      *
 
-      * Defaults to `true` when `floating: true`, and defaults to `false` when `floating: false`.
 
-      */
 
-     hidden: true,
 
-     hideMode: 'visibility',
 
- <span id='Ext-menu-Menu-cfg-ignoreParentClicks'>    /**
 
- </span>     * @cfg {Boolean} [ignoreParentClicks=false]
 
-      * True to ignore clicks on any item in this menu that is a parent item (displays a submenu)
 
-      * so that the submenu is not dismissed when clicking the parent item.
 
-      */
 
-     ignoreParentClicks: false,
 
- <span id='Ext-menu-Menu-property-isMenu'>    /**
 
- </span>     * @property {Boolean} isMenu
 
-      * `true` in this class to identify an object as an instantiated Menu, or subclass thereof.
 
-      */
 
-     isMenu: true,
 
- <span id='Ext-menu-Menu-cfg-layout'>    /**
 
- </span>     * @cfg {String/Object} layout
 
-      * @private
 
-      */
 
- <span id='Ext-menu-Menu-cfg-showSeparator'>    /**
 
- </span>     * @cfg {Boolean} [showSeparator=true]
 
-      * True to show the icon separator.
 
-      */
 
-     showSeparator : true,
 
- <span id='Ext-menu-Menu-cfg-minWidth'>    /**
 
- </span>     * @cfg {Number} [minWidth=120]
 
-      * The minimum width of the Menu. The default minWidth only applies when the {@link #floating} config is true.
 
-      */
 
-     minWidth: undefined,
 
-     
 
-     defaultMinWidth: 120,
 
- <span id='Ext-menu-Menu-cfg-plain'>    /**
 
- </span>     * @cfg {Boolean} [plain=false]
 
-      * True to remove the incised line down the left side of the menu and to not indent general Component items.
 
-      */
 
-     initComponent: function() {
 
-         var me = this,
 
-             prefix = Ext.baseCSSPrefix,
 
-             cls = [prefix + 'menu'],
 
-             bodyCls = me.bodyCls ? [me.bodyCls] : [],
 
-             isFloating = me.floating !== false;
 
-         me.addEvents(
 
- <span id='Ext-menu-Menu-event-click'>            /**
 
- </span>             * @event click
 
-              * Fires when this menu is clicked
 
-              * @param {Ext.menu.Menu} menu The menu which has been clicked
 
-              * @param {Ext.Component} item The menu item that was clicked. `undefined` if not applicable.
 
-              * @param {Ext.EventObject} e The underlying {@link Ext.EventObject}.
 
-              */
 
-             'click',
 
- <span id='Ext-menu-Menu-event-mouseenter'>            /**
 
- </span>             * @event mouseenter
 
-              * Fires when the mouse enters this menu
 
-              * @param {Ext.menu.Menu} menu The menu
 
-              * @param {Ext.EventObject} e The underlying {@link Ext.EventObject}
 
-              */
 
-             'mouseenter',
 
- <span id='Ext-menu-Menu-event-mouseleave'>            /**
 
- </span>             * @event mouseleave
 
-              * Fires when the mouse leaves this menu
 
-              * @param {Ext.menu.Menu} menu The menu
 
-              * @param {Ext.EventObject} e The underlying {@link Ext.EventObject}
 
-              */
 
-             'mouseleave',
 
- <span id='Ext-menu-Menu-event-mouseover'>            /**
 
- </span>             * @event mouseover
 
-              * Fires when the mouse is hovering over this menu
 
-              * @param {Ext.menu.Menu} menu The menu
 
-              * @param {Ext.Component} item The menu item that the mouse is over. `undefined` if not applicable.
 
-              * @param {Ext.EventObject} e The underlying {@link Ext.EventObject}
 
-              */
 
-             'mouseover'
 
-         );
 
-         Ext.menu.Manager.register(me);
 
-         // Menu classes
 
-         if (me.plain) {
 
-             cls.push(prefix + 'menu-plain');
 
-         }
 
-         me.cls = cls.join(' ');
 
-         // Menu body classes
 
-         bodyCls.unshift(prefix + 'menu-body');
 
-         me.bodyCls = bodyCls.join(' ');
 
-         // Internal vbox layout, with scrolling overflow
 
-         // Placed in initComponent (rather than prototype) in order to support dynamic layout/scroller
 
-         // options if we wish to allow for such configurations on the Menu.
 
-         // e.g., scrolling speed, vbox align stretch, etc.
 
-         if (!me.layout) {
 
-             me.layout = {
 
-                 type: 'vbox',
 
-                 align: 'stretchmax',
 
-                 overflowHandler: 'Scroller'
 
-             };
 
-         }
 
-         
 
-         // only apply the minWidth when we're floating & one hasn't already been set
 
-         if (isFloating && me.minWidth === undefined) {
 
-             me.minWidth = me.defaultMinWidth;
 
-         }
 
-         // hidden defaults to false if floating is configured as false
 
-         if (!isFloating && me.initialConfig.hidden !== true) {
 
-             me.hidden = false;
 
-         }
 
-         me.callParent(arguments);
 
-         me.on('beforeshow', function() {
 
-             var hasItems = !!me.items.length;
 
-             // FIXME: When a menu has its show cancelled because of no items, it
 
-             // gets a visibility: hidden applied to it (instead of the default display: none)
 
-             // Not sure why, but we remove this style when we want to show again.
 
-             if (hasItems && me.rendered) {
 
-                 me.el.setStyle('visibility', null);
 
-             }
 
-             return hasItems;
 
-         });
 
-     },
 
-     beforeRender: function() {
 
-         this.callParent(arguments);
 
-         // Menus are usually floating: true, which means they shrink wrap their items.
 
-         // However, when they are contained, and not auto sized, we must stretch the items.
 
-         if (!this.getSizeModel().width.shrinkWrap) {
 
-             this.layout.align = 'stretch';
 
-         }
 
-     },
 
-     onBoxReady: function() {
 
-         var me = this,
 
-             separatorSpec;
 
-         me.callParent(arguments);
 
-         // TODO: Move this to a subTemplate When we support them in the future
 
-         if (me.showSeparator) {
 
-             separatorSpec = {
 
-                 cls: Ext.baseCSSPrefix + 'menu-icon-separator',
 
-                 html: '&#160;'
 
-             };
 
-             if ((!Ext.isStrict && Ext.isIE) || Ext.isIE6) {
 
-                 separatorSpec.style = 'height:' + me.el.getHeight() + 'px';
 
-             }
 
-             me.iconSepEl = me.layout.getElementTarget().insertFirst(separatorSpec);
 
-         }
 
-         me.mon(me.el, {
 
-             click: me.onClick,
 
-             mouseover: me.onMouseOver,
 
-             scope: me
 
-         });
 
-         me.mouseMonitor = me.el.monitorMouseLeave(100, me.onMouseLeave, me);
 
-         if (me.enableKeyNav) {
 
-             me.keyNav = new Ext.menu.KeyNav(me);
 
-         }
 
-     },
 
-     getBubbleTarget: function() {
 
-         // If a submenu, this will have a parentMenu property
 
-         // If a menu of a Button, it will have an ownerButton property
 
-         // Else use the default method.
 
-         return this.parentMenu || this.ownerButton || this.callParent(arguments);
 
-     },
 
- <span id='Ext-menu-Menu-method-canActivateItem'>    /**
 
- </span>     * Returns whether a menu item can be activated or not.
 
-      * @return {Boolean}
 
-      */
 
-     canActivateItem: function(item) {
 
-         return item && !item.isDisabled() && item.isVisible() && (item.canActivate || item.getXTypes().indexOf('menuitem') < 0);
 
-     },
 
- <span id='Ext-menu-Menu-method-deactivateActiveItem'>    /**
 
- </span>     * Deactivates the current active item on the menu, if one exists.
 
-      */
 
-     deactivateActiveItem: function(andBlurFocusedItem) {
 
-         var me = this,
 
-             activeItem = me.activeItem,
 
-             focusedItem = me.focusedItem;
 
-         if (activeItem) {
 
-             activeItem.deactivate();
 
-             if (!activeItem.activated) {
 
-                 delete me.activeItem;
 
-             }
 
-         }
 
-         // Blur the focused item if we are being asked to do that too
 
-         // Only needed if we are being hidden - mouseout does not blur.
 
-         if (focusedItem && andBlurFocusedItem) {
 
-             focusedItem.blur();
 
-             delete me.focusedItem;
 
-         }
 
-     },
 
-     // inherit docs
 
-     getFocusEl: function() {
 
-         return this.focusedItem || this.el;
 
-     },
 
-     // inherit docs
 
-     hide: function() {
 
-         this.deactivateActiveItem(true);
 
-         this.callParent(arguments);
 
-     },
 
-     // private
 
-     getItemFromEvent: function(e) {
 
-         return this.getChildByElement(e.getTarget());
 
-     },
 
-     lookupComponent: function(cmp) {
 
-         var me = this;
 
-         if (typeof cmp == 'string') {
 
-             cmp = me.lookupItemFromString(cmp);
 
-         } else if (Ext.isObject(cmp)) {
 
-             cmp = me.lookupItemFromObject(cmp);
 
-         }
 
-         // Apply our minWidth to all of our child components so it's accounted
 
-         // for in our VBox layout
 
-         cmp.minWidth = cmp.minWidth || me.minWidth;
 
-         return cmp;
 
-     },
 
-     // private
 
-     lookupItemFromObject: function(cmp) {
 
-         var me = this,
 
-             prefix = Ext.baseCSSPrefix,
 
-             cls;
 
-         if (!cmp.isComponent) {
 
-             if (!cmp.xtype) {
 
-                 cmp = Ext.create('Ext.menu.' + (Ext.isBoolean(cmp.checked) ? 'Check': '') + 'Item', cmp);
 
-             } else {
 
-                 cmp = Ext.ComponentManager.create(cmp, cmp.xtype);
 
-             }
 
-         }
 
-         if (cmp.isMenuItem) {
 
-             cmp.parentMenu = me;
 
-         }
 
-         if (!cmp.isMenuItem && !cmp.dock) {
 
-             cls = [prefix + 'menu-item', prefix + 'menu-item-cmp'];
 
-             if (!me.plain && (cmp.indent === true || cmp.iconCls === 'no-icon')) {
 
-                 cls.push(prefix + 'menu-item-indent');
 
-             }
 
-             if (cmp.rendered) {
 
-                 cmp.el.addCls(cls);
 
-             } else {
 
-                 cmp.cls = (cmp.cls ? cmp.cls : '') + ' ' + cls.join(' ');
 
-             }
 
-         }
 
-         return cmp;
 
-     },
 
-     // private
 
-     lookupItemFromString: function(cmp) {
 
-         return (cmp == 'separator' || cmp == '-') ?
 
-             new Ext.menu.Separator()
 
-             : new Ext.menu.Item({
 
-                 canActivate: false,
 
-                 hideOnClick: false,
 
-                 plain: true,
 
-                 text: cmp
 
-             });
 
-     },
 
-     onClick: function(e) {
 
-         var me = this,
 
-             item;
 
-         if (me.disabled) {
 
-             e.stopEvent();
 
-             return;
 
-         }
 
-         item = (e.type === 'click') ? me.getItemFromEvent(e) : me.activeItem;
 
-         if (item && item.isMenuItem) {
 
-             if (!item.menu || !me.ignoreParentClicks) {
 
-                 item.onClick(e);
 
-             } else {
 
-                 e.stopEvent();
 
-             }
 
-         }
 
-         // Click event may be fired without an item, so we need a second check
 
-         if (!item || item.disabled) {
 
-             item = undefined;
 
-         }
 
-         me.fireEvent('click', me, item, e);
 
-     },
 
-     onDestroy: function() {
 
-         var me = this;
 
-         Ext.menu.Manager.unregister(me);
 
-         delete me.parentMenu;
 
-         delete me.ownerButton;
 
-         if (me.rendered) {
 
-             me.el.un(me.mouseMonitor);
 
-             Ext.destroy(me.keyNav);
 
-             delete me.keyNav;
 
-         }
 
-         me.callParent(arguments);
 
-     },
 
-     onMouseLeave: function(e) {
 
-         var me = this;
 
-         me.deactivateActiveItem();
 
-         if (me.disabled) {
 
-             return;
 
-         }
 
-         me.fireEvent('mouseleave', me, e);
 
-     },
 
-     onMouseOver: function(e) {
 
-         var me = this,
 
-             fromEl = e.getRelatedTarget(),
 
-             mouseEnter = !me.el.contains(fromEl),
 
-             item = me.getItemFromEvent(e),
 
-             parentMenu = me.parentMenu,
 
-             parentItem = me.parentItem;
 
-         if (mouseEnter && parentMenu) {
 
-             parentMenu.setActiveItem(parentItem);
 
-             parentItem.cancelDeferHide();
 
-             parentMenu.mouseMonitor.mouseenter();
 
-         }
 
-         if (me.disabled) {
 
-             return;
 
-         }
 
-         // Do not activate the item if the mouseover was within the item, and it's already active
 
-         if (item && !item.activated) {
 
-             me.setActiveItem(item);
 
-             if (item.activated && item.expandMenu) {
 
-                 item.expandMenu();
 
-             }
 
-         }
 
-         if (mouseEnter) {
 
-             me.fireEvent('mouseenter', me, e);
 
-         }
 
-         me.fireEvent('mouseover', me, item, e);
 
-     },
 
-     setActiveItem: function(item) {
 
-         var me = this;
 
-         if (item && (item != me.activeItem)) {
 
-             me.deactivateActiveItem();
 
-             if (me.canActivateItem(item)) {
 
-                 if (item.activate) {
 
-                     item.activate();
 
-                     if (item.activated) {
 
-                         me.activeItem = item;
 
-                         me.focusedItem = item;
 
-                         me.focus();
 
-                     }
 
-                 } else {
 
-                     item.focus();
 
-                     me.focusedItem = item;
 
-                 }
 
-             }
 
-             item.el.scrollIntoView(me.layout.getRenderTarget());
 
-         }
 
-     },
 
- <span id='Ext-menu-Menu-method-showBy'>    /**
 
- </span>     * Shows the floating menu by the specified {@link Ext.Component Component} or {@link Ext.Element Element}.
 
-      * @param {Ext.Component/Ext.Element} component The {@link Ext.Component} or {@link Ext.Element} to show the menu by.
 
-      * @param {String} [position] Alignment position as used by {@link Ext.Element#getAlignToXY}.
 
-      * Defaults to `{@link #defaultAlign}`.
 
-      * @param {Number[]} [offsets] Alignment offsets as used by {@link Ext.Element#getAlignToXY}.
 
-      * @return {Ext.menu.Menu} This Menu.
 
-      */
 
-     showBy: function(cmp, pos, off) {
 
-         var me = this;
 
-         if (me.floating && cmp) {
 
-             me.show();
 
-             // Align to Component or Element using setPagePosition because normal show
 
-             // methods are container-relative, and we must align to the requested element
 
-             // or Component:
 
-             me.setPagePosition(me.el.getAlignToXY(cmp.el || cmp, pos || me.defaultAlign, off));
 
-             me.setVerticalPosition();
 
-         }
 
-         return me;
 
-     },
 
-     show: function() {
 
-         var me = this,
 
-             parentEl, viewHeight, result,
 
-             maxWas = me.maxHeight;
 
-         // we need to get scope parent for height constraint
 
-         if (!me.rendered){
 
-             me.doAutoRender();
 
-         }
 
-         // constrain the height to the curren viewable area
 
-         if (me.floating) {
 
-             //if our reset css is scoped, there will be a x-reset wrapper on this menu which we need to skip
 
-             parentEl = Ext.fly(me.el.getScopeParent());
 
-             viewHeight = parentEl.getViewSize().height;
 
-             me.maxHeight  =  Math.min(maxWas || viewHeight, viewHeight);
 
-         }
 
-         result = me.callParent(arguments);
 
-         me.maxHeight = maxWas;
 
-         return result;
 
-     },
 
-     afterComponentLayout: function(width, height, oldWidth, oldHeight){
 
-         var me = this;
 
-         me.callParent(arguments);
 
-         // fixup the separator
 
-         if (me.showSeparator){
 
-             me.iconSepEl.setHeight(me.componentLayout.lastComponentSize.contentHeight);
 
-         }
 
-     },
 
-     // private
 
-     // adjust the vertical position of the menu if the height of the
 
-     // menu is equal (or greater than) the viewport size
 
-     setVerticalPosition: function(){
 
-         var me = this,
 
-             max,
 
-             y = me.el.getY(),
 
-             returnY = y,
 
-             height = me.getHeight(),
 
-             viewportHeight = Ext.Element.getViewportHeight().height,
 
-             parentEl = Ext.fly(me.el.getScopeParent()),
 
-             viewHeight = parentEl.getViewSize().height,
 
-             normalY = y - parentEl.getScroll().top; // factor in scrollTop of parent
 
-         parentEl = null;
 
-         if (me.floating) {
 
-             max = me.maxHeight ? me.maxHeight : viewHeight - normalY;
 
-             if (height > viewHeight) {
 
-                 returnY = y - normalY;
 
-             } else if (max < height) {
 
-                 returnY = y - (height - max);
 
-             } else if((y + height) > viewportHeight){ // keep the document from scrolling
 
-                 returnY = viewportHeight - height;
 
-             }
 
-         }
 
-         me.el.setY(returnY);
 
-     }
 
- });</pre>
 
- </body>
 
- </html>
 
 
  |