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