+++ /dev/null
-/*\r
- * Ext JS Library 2.2.1\r
- * Copyright(c) 2006-2009, Ext JS, LLC.\r
- * licensing@extjs.com\r
- * \r
- * http://extjs.com/license\r
- */\r
-\r
-/**\r
- * @class Ext.menu.Menu\r
- * @extends Ext.util.Observable\r
- * A menu object. This is the container to which you add all other menu items. Menu can also serve as a base class\r
- * when you want a specialized menu based off of another component (like {@link Ext.menu.DateMenu} for example).\r
- * @constructor\r
- * Creates a new Menu\r
- * @param {Object} config Configuration options\r
- */\r
-Ext.menu.Menu = function(config){\r
- if(Ext.isArray(config)){\r
- config = {items:config};\r
- }\r
- Ext.apply(this, config);\r
- this.id = this.id || Ext.id();\r
- this.addEvents(\r
- /**\r
- * @event beforeshow\r
- * Fires before this menu is displayed\r
- * @param {Ext.menu.Menu} this\r
- */\r
- 'beforeshow',\r
- /**\r
- * @event beforehide\r
- * Fires before this menu is hidden\r
- * @param {Ext.menu.Menu} this\r
- */\r
- 'beforehide',\r
- /**\r
- * @event show\r
- * Fires after this menu is displayed\r
- * @param {Ext.menu.Menu} this\r
- */\r
- 'show',\r
- /**\r
- * @event hide\r
- * Fires after this menu is hidden\r
- * @param {Ext.menu.Menu} this\r
- */\r
- 'hide',\r
- /**\r
- * @event click\r
- * Fires when this menu is clicked (or when the enter key is pressed while it is active)\r
- * @param {Ext.menu.Menu} this\r
- * @param {Ext.menu.Item} menuItem The menu item that was clicked\r
- * @param {Ext.EventObject} e\r
- */\r
- 'click',\r
- /**\r
- * @event mouseover\r
- * Fires when the mouse is hovering over this menu\r
- * @param {Ext.menu.Menu} this\r
- * @param {Ext.EventObject} e\r
- * @param {Ext.menu.Item} menuItem The menu item that was clicked\r
- */\r
- 'mouseover',\r
- /**\r
- * @event mouseout\r
- * Fires when the mouse exits this menu\r
- * @param {Ext.menu.Menu} this\r
- * @param {Ext.EventObject} e\r
- * @param {Ext.menu.Item} menuItem The menu item that was clicked\r
- */\r
- 'mouseout',\r
- /**\r
- * @event itemclick\r
- * Fires when a menu item contained in this menu is clicked\r
- * @param {Ext.menu.BaseItem} baseItem The BaseItem that was clicked\r
- * @param {Ext.EventObject} e\r
- */\r
- 'itemclick'\r
- );\r
- Ext.menu.MenuMgr.register(this);\r
- Ext.menu.Menu.superclass.constructor.call(this);\r
- var mis = this.items;\r
- /**\r
- * A MixedCollection of this Menu's items\r
- * @property items\r
- * @type Ext.util.MixedCollection\r
- */\r
-\r
- this.items = new Ext.util.MixedCollection();\r
- if(mis){\r
- this.add.apply(this, mis);\r
- }\r
-};\r
-\r
-Ext.extend(Ext.menu.Menu, Ext.util.Observable, {\r
- /**\r
- * @cfg {Object} defaults\r
- * A config object that will be applied to all items added to this container either via the {@link #items}\r
- * config or via the {@link #add} method. The defaults config can contain any number of\r
- * name/value property pairs to be added to each item, and should be valid for the types of items\r
- * being added to the menu.\r
- */\r
- /**\r
- * @cfg {Mixed} items\r
- * An array of items to be added to this menu. See {@link #add} for a list of valid item types.\r
- */\r
- /**\r
- * @cfg {Number} minWidth The minimum width of the menu in pixels (defaults to 120)\r
- */\r
- minWidth : 120,\r
- /**\r
- * @cfg {Boolean/String} shadow True or "sides" for the default effect, "frame" for 4-way shadow, and "drop"\r
- * for bottom-right shadow (defaults to "sides")\r
- */\r
- shadow : "sides",\r
- /**\r
- * @cfg {String} subMenuAlign The {@link Ext.Element#alignTo} anchor position value to use for submenus of\r
- * this menu (defaults to "tl-tr?")\r
- */\r
- subMenuAlign : "tl-tr?",\r
- /**\r
- * @cfg {String} defaultAlign The default {@link Ext.Element#alignTo} anchor position value for this menu\r
- * relative to its element of origin (defaults to "tl-bl?")\r
- */\r
- defaultAlign : "tl-bl?",\r
- /**\r
- * @cfg {Boolean} allowOtherMenus True to allow multiple menus to be displayed at the same time (defaults to false)\r
- */\r
- allowOtherMenus : false,\r
- /**\r
- * @cfg {Boolean} ignoreParentClicks True to ignore clicks on any item in this menu that is a parent item (displays\r
- * a submenu) so that the submenu is not dismissed when clicking the parent item (defaults to false).\r
- */\r
- ignoreParentClicks : false,\r
-\r
- // private\r
- hidden:true,\r
-\r
- // private\r
- createEl : function(){\r
- return new Ext.Layer({\r
- cls: "x-menu",\r
- shadow:this.shadow,\r
- constrain: false,\r
- parentEl: this.parentEl || document.body,\r
- zindex:15000\r
- });\r
- },\r
-\r
- // private\r
- render : function(){\r
- if(this.el){\r
- return;\r
- }\r
- var el = this.el = this.createEl();\r
-\r
- if(!this.keyNav){\r
- this.keyNav = new Ext.menu.MenuNav(this);\r
- }\r
- if(this.plain){\r
- el.addClass("x-menu-plain");\r
- }\r
- if(this.cls){\r
- el.addClass(this.cls);\r
- }\r
- // generic focus element\r
- this.focusEl = el.createChild({\r
- tag: "a", cls: "x-menu-focus", href: "#", onclick: "return false;", tabIndex:"-1"\r
- });\r
- var ul = el.createChild({tag: "ul", cls: "x-menu-list"});\r
- ul.on("click", this.onClick, this);\r
- ul.on("mouseover", this.onMouseOver, this);\r
- ul.on("mouseout", this.onMouseOut, this);\r
- this.items.each(function(item){\r
- var li = document.createElement("li");\r
- li.className = "x-menu-list-item";\r
- ul.dom.appendChild(li);\r
- item.render(li, this);\r
- }, this);\r
- this.ul = ul;\r
- this.autoWidth();\r
- },\r
-\r
- // private\r
- autoWidth : function(){\r
- var el = this.el, ul = this.ul;\r
- if(!el){\r
- return;\r
- }\r
- var w = this.width;\r
- if(w){\r
- el.setWidth(w);\r
- }else if(Ext.isIE){\r
- el.setWidth(this.minWidth);\r
- var t = el.dom.offsetWidth; // force recalc\r
- el.setWidth(ul.getWidth()+el.getFrameWidth("lr"));\r
- }\r
- },\r
-\r
- // private\r
- delayAutoWidth : function(){\r
- if(this.el){\r
- if(!this.awTask){\r
- this.awTask = new Ext.util.DelayedTask(this.autoWidth, this);\r
- }\r
- this.awTask.delay(20);\r
- }\r
- },\r
-\r
- // private\r
- findTargetItem : function(e){\r
- var t = e.getTarget(".x-menu-list-item", this.ul, true);\r
- if(t && t.menuItemId){\r
- return this.items.get(t.menuItemId);\r
- }\r
- },\r
-\r
- // private\r
- onClick : function(e){\r
- var t;\r
- if(t = this.findTargetItem(e)){\r
- if(t.menu && this.ignoreParentClicks){\r
- t.expandMenu();\r
- }else{\r
- t.onClick(e);\r
- this.fireEvent("click", this, t, e);\r
- }\r
- }\r
- },\r
-\r
- // private\r
- setActiveItem : function(item, autoExpand){\r
- if(item != this.activeItem){\r
- if(this.activeItem){\r
- this.activeItem.deactivate();\r
- }\r
- this.activeItem = item;\r
- item.activate(autoExpand);\r
- }else if(autoExpand){\r
- item.expandMenu();\r
- }\r
- },\r
-\r
- // private\r
- tryActivate : function(start, step){\r
- var items = this.items;\r
- for(var i = start, len = items.length; i >= 0 && i < len; i+= step){\r
- var item = items.get(i);\r
- if(!item.disabled && item.canActivate){\r
- this.setActiveItem(item, false);\r
- return item;\r
- }\r
- }\r
- return false;\r
- },\r
-\r
- // private\r
- onMouseOver : function(e){\r
- var t;\r
- if(t = this.findTargetItem(e)){\r
- if(t.canActivate && !t.disabled){\r
- this.setActiveItem(t, true);\r
- }\r
- }\r
- this.over = true;\r
- this.fireEvent("mouseover", this, e, t);\r
- },\r
-\r
- // private\r
- onMouseOut : function(e){\r
- var t;\r
- if(t = this.findTargetItem(e)){\r
- if(t == this.activeItem && t.shouldDeactivate(e)){\r
- this.activeItem.deactivate();\r
- delete this.activeItem;\r
- }\r
- }\r
- this.over = false;\r
- this.fireEvent("mouseout", this, e, t);\r
- },\r
-\r
- /**\r
- * Read-only. Returns true if the menu is currently displayed, else false.\r
- * @type Boolean\r
- */\r
- isVisible : function(){\r
- return this.el && !this.hidden;\r
- },\r
-\r
- /**\r
- * Displays this menu relative to another element\r
- * @param {Mixed} element The element to align to\r
- * @param {String} position (optional) The {@link Ext.Element#alignTo} anchor position to use in aligning to\r
- * the element (defaults to this.defaultAlign)\r
- * @param {Ext.menu.Menu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)\r
- */\r
- show : function(el, pos, parentMenu){\r
- this.parentMenu = parentMenu;\r
- if(!this.el){\r
- this.render();\r
- }\r
- this.fireEvent("beforeshow", this);\r
- this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign), parentMenu, false);\r
- },\r
-\r
- /**\r
- * Displays this menu at a specific xy position\r
- * @param {Array} xyPosition Contains X & Y [x, y] values for the position at which to show the menu (coordinates are page-based)\r
- * @param {Ext.menu.Menu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)\r
- */\r
- showAt : function(xy, parentMenu, /* private: */_e){\r
- this.parentMenu = parentMenu;\r
- if(!this.el){\r
- this.render();\r
- }\r
- if(_e !== false){\r
- this.fireEvent("beforeshow", this);\r
- xy = this.el.adjustForConstraints(xy);\r
- }\r
- this.el.setXY(xy);\r
- this.el.show();\r
- this.hidden = false;\r
- this.focus();\r
- this.fireEvent("show", this);\r
- },\r
-\r
-\r
-\r
- focus : function(){\r
- if(!this.hidden){\r
- this.doFocus.defer(50, this);\r
- }\r
- },\r
-\r
- doFocus : function(){\r
- if(!this.hidden){\r
- this.focusEl.focus();\r
- }\r
- },\r
-\r
- /**\r
- * Hides this menu and optionally all parent menus\r
- * @param {Boolean} deep (optional) True to hide all parent menus recursively, if any (defaults to false)\r
- */\r
- hide : function(deep){\r
- if(this.el && this.isVisible()){\r
- this.fireEvent("beforehide", this);\r
- if(this.activeItem){\r
- this.activeItem.deactivate();\r
- this.activeItem = null;\r
- }\r
- this.el.hide();\r
- this.hidden = true;\r
- this.fireEvent("hide", this);\r
- }\r
- if(deep === true && this.parentMenu){\r
- this.parentMenu.hide(true);\r
- }\r
- },\r
-\r
- /**\r
- * Adds one or more items of any type supported by the Menu class, or that can be converted into menu items.\r
- * Any of the following are valid:\r
- * <ul>\r
- * <li>Any menu item object based on {@link Ext.menu.BaseItem}</li>\r
- * <li>An HTMLElement object which will be converted to a menu item</li>\r
- * <li>A menu item config object that will be created as a new menu item</li>\r
- * <li>A string, which can either be '-' or 'separator' to add a menu separator, otherwise\r
- * it will be converted into a {@link Ext.menu.TextItem} and added</li>\r
- * </ul>\r
- * Usage:\r
- * <pre><code>\r
-// Create the menu\r
-var menu = new Ext.menu.Menu();\r
-\r
-// Create a menu item to add by reference\r
-var menuItem = new Ext.menu.Item({ text: 'New Item!' });\r
-\r
-// Add a bunch of items at once using different methods.\r
-// Only the last item added will be returned.\r
-var item = menu.add(\r
- menuItem, // add existing item by ref\r
- 'Dynamic Item', // new TextItem\r
- '-', // new separator\r
- { text: 'Config Item' } // new item by config\r
-);\r
-</code></pre>\r
- * @param {Mixed} args One or more menu items, menu item configs or other objects that can be converted to menu items\r
- * @return {Ext.menu.Item} The menu item that was added, or the last one if multiple items were added\r
- */\r
- add : function(){\r
- var a = arguments, l = a.length, item;\r
- for(var i = 0; i < l; i++){\r
- var el = a[i];\r
- if(el.render){ // some kind of Item\r
- item = this.addItem(el);\r
- }else if(typeof el == "string"){ // string\r
- if(el == "separator" || el == "-"){\r
- item = this.addSeparator();\r
- }else{\r
- item = this.addText(el);\r
- }\r
- }else if(el.tagName || el.el){ // element\r
- item = this.addElement(el);\r
- }else if(typeof el == "object"){ // must be menu item config?\r
- Ext.applyIf(el, this.defaults);\r
- item = this.addMenuItem(el);\r
- }\r
- }\r
- return item;\r
- },\r
-\r
- /**\r
- * Returns this menu's underlying {@link Ext.Element} object\r
- * @return {Ext.Element} The element\r
- */\r
- getEl : function(){\r
- if(!this.el){\r
- this.render();\r
- }\r
- return this.el;\r
- },\r
-\r
- /**\r
- * Adds a separator bar to the menu\r
- * @return {Ext.menu.Item} The menu item that was added\r
- */\r
- addSeparator : function(){\r
- return this.addItem(new Ext.menu.Separator());\r
- },\r
-\r
- /**\r
- * Adds an {@link Ext.Element} object to the menu\r
- * @param {Mixed} el The element or DOM node to add, or its id\r
- * @return {Ext.menu.Item} The menu item that was added\r
- */\r
- addElement : function(el){\r
- return this.addItem(new Ext.menu.BaseItem(el));\r
- },\r
-\r
- /**\r
- * Adds an existing object based on {@link Ext.menu.BaseItem} to the menu\r
- * @param {Ext.menu.Item} item The menu item to add\r
- * @return {Ext.menu.Item} The menu item that was added\r
- */\r
- addItem : function(item){\r
- this.items.add(item);\r
- if(this.ul){\r
- var li = document.createElement("li");\r
- li.className = "x-menu-list-item";\r
- this.ul.dom.appendChild(li);\r
- item.render(li, this);\r
- this.delayAutoWidth();\r
- }\r
- return item;\r
- },\r
-\r
- /**\r
- * Creates a new {@link Ext.menu.Item} based an the supplied config object and adds it to the menu\r
- * @param {Object} config A MenuItem config object\r
- * @return {Ext.menu.Item} The menu item that was added\r
- */\r
- addMenuItem : function(config){\r
- if(!(config instanceof Ext.menu.Item)){\r
- if(typeof config.checked == "boolean"){ // must be check menu item config?\r
- config = new Ext.menu.CheckItem(config);\r
- }else{\r
- config = new Ext.menu.Item(config);\r
- }\r
- }\r
- return this.addItem(config);\r
- },\r
-\r
- /**\r
- * Creates a new {@link Ext.menu.TextItem} with the supplied text and adds it to the menu\r
- * @param {String} text The text to display in the menu item\r
- * @return {Ext.menu.Item} The menu item that was added\r
- */\r
- addText : function(text){\r
- return this.addItem(new Ext.menu.TextItem(text));\r
- },\r
-\r
- /**\r
- * Inserts an existing object based on {@link Ext.menu.BaseItem} to the menu at a specified index\r
- * @param {Number} index The index in the menu's list of current items where the new item should be inserted\r
- * @param {Ext.menu.Item} item The menu item to add\r
- * @return {Ext.menu.Item} The menu item that was added\r
- */\r
- insert : function(index, item){\r
- this.items.insert(index, item);\r
- if(this.ul){\r
- var li = document.createElement("li");\r
- li.className = "x-menu-list-item";\r
- this.ul.dom.insertBefore(li, this.ul.dom.childNodes[index]);\r
- item.render(li, this);\r
- this.delayAutoWidth();\r
- }\r
- return item;\r
- },\r
-\r
- /**\r
- * Removes an {@link Ext.menu.Item} from the menu and destroys the object\r
- * @param {Ext.menu.Item} item The menu item to remove\r
- */\r
- remove : function(item){\r
- this.items.removeKey(item.id);\r
- item.destroy();\r
- },\r
-\r
- /**\r
- * Removes and destroys all items in the menu\r
- */\r
- removeAll : function(){\r
- if(this.items){\r
- var f;\r
- while(f = this.items.first()){\r
- this.remove(f);\r
- }\r
- }\r
- },\r
-\r
- /**\r
- * Destroys the menu by unregistering it from {@link Ext.menu.MenuMgr}, purging event listeners,\r
- * removing all of the menus items, then destroying the underlying {@link Ext.Element}\r
- */\r
- destroy : function(){\r
- this.beforeDestroy();\r
- Ext.menu.MenuMgr.unregister(this);\r
- if (this.keyNav) {\r
- this.keyNav.disable();\r
- }\r
- this.removeAll();\r
- if (this.ul) {\r
- this.ul.removeAllListeners();\r
- }\r
- if (this.el) {\r
- this.el.destroy();\r
- }\r
- },\r
-\r
- // private\r
- beforeDestroy : Ext.emptyFn\r
-\r
-});\r
-\r
-// MenuNav is a private utility class used internally by the Menu\r
-Ext.menu.MenuNav = function(menu){\r
- Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);\r
- this.scope = this.menu = menu;\r
-};\r
-\r
-Ext.extend(Ext.menu.MenuNav, Ext.KeyNav, {\r
- doRelay : function(e, h){\r
- var k = e.getKey();\r
- if(!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN){\r
- this.menu.tryActivate(0, 1);\r
- return false;\r
- }\r
- return h.call(this.scope || this, e, this.menu);\r
- },\r
-\r
- up : function(e, m){\r
- if(!m.tryActivate(m.items.indexOf(m.activeItem)-1, -1)){\r
- m.tryActivate(m.items.length-1, -1);\r
- }\r
- },\r
-\r
- down : function(e, m){\r
- if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){\r
- m.tryActivate(0, 1);\r
- }\r
- },\r
-\r
- right : function(e, m){\r
- if(m.activeItem){\r
- m.activeItem.expandMenu(true);\r
- }\r
- },\r
-\r
- left : function(e, m){\r
- m.hide();\r
- if(m.parentMenu && m.parentMenu.activeItem){\r
- m.parentMenu.activeItem.activate();\r
- }\r
- },\r
-\r
- enter : function(e, m){\r
- if(m.activeItem){\r
- e.stopPropagation();\r
- m.activeItem.onClick(e);\r
- m.fireEvent("click", this, m.activeItem);\r
- return true;\r
- }\r
- }\r
-});
\ No newline at end of file