9 * @class Roo.bootstrap.Menu
10 * @extends Roo.bootstrap.Component
11 * Bootstrap Menu class - container for MenuItems
12 * @cfg {String} type (dropdown|treeview|submenu) type of menu
16 * @param {Object} config The config object
20 Roo.bootstrap.Menu = function(config){
21 Roo.bootstrap.Menu.superclass.constructor.call(this, config);
22 if (this.registerMenu) {
23 Roo.bootstrap.MenuMgr.register(this);
28 * Fires before this menu is displayed
29 * @param {Roo.menu.Menu} this
34 * Fires before this menu is hidden
35 * @param {Roo.menu.Menu} this
40 * Fires after this menu is displayed
41 * @param {Roo.menu.Menu} this
46 * Fires after this menu is hidden
47 * @param {Roo.menu.Menu} this
52 * Fires when this menu is clicked (or when the enter key is pressed while it is active)
53 * @param {Roo.menu.Menu} this
54 * @param {Roo.menu.Item} menuItem The menu item that was clicked
55 * @param {Roo.EventObject} e
60 * Fires when the mouse is hovering over this menu
61 * @param {Roo.menu.Menu} this
62 * @param {Roo.EventObject} e
63 * @param {Roo.menu.Item} menuItem The menu item that was clicked
68 * Fires when the mouse exits this menu
69 * @param {Roo.menu.Menu} this
70 * @param {Roo.EventObject} e
71 * @param {Roo.menu.Item} menuItem The menu item that was clicked
76 * Fires when a menu item contained in this menu is clicked
77 * @param {Roo.menu.BaseItem} baseItem The BaseItem that was clicked
78 * @param {Roo.EventObject} e
82 this.menuitems = new Roo.util.MixedCollection(false, function(o) { return o.el.id; });
85 Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component, {
89 triggerEl : false, // is this set by component builder? -- it should really be fetched from parent()???
92 * @cfg {Boolean} registerMenu True (default) - means that clicking on screen etc. hides it.
96 menuItems :false, // stores the menu items..
102 getChildContainer : function() {
106 getAutoCreate : function(){
108 //if (['right'].indexOf(this.align)!==-1) {
109 // cfg.cn[1].cls += ' pull-right'
115 cls : 'dropdown-menu' ,
116 style : 'z-index:1000'
120 if (this.type === 'submenu') {
121 cfg.cls = 'submenu active';
123 if (this.type === 'treeview') {
124 cfg.cls = 'treeview-menu';
129 initEvents : function() {
131 // Roo.log("ADD event");
132 // Roo.log(this.triggerEl.dom);
133 this.triggerEl.on('click', this.onTriggerPress, this);
134 this.triggerEl.addClass('dropdown-toggle');
135 this.el.on(Roo.isTouch ? 'touchstart' : 'click' , this.onClick, this);
137 this.el.on("mouseover", this.onMouseOver, this);
138 this.el.on("mouseout", this.onMouseOut, this);
142 findTargetItem : function(e){
143 var t = e.getTarget(".dropdown-menu-item", this.el, true);
147 //Roo.log(t); Roo.log(t.id);
149 //Roo.log(this.menuitems);
150 return this.menuitems.get(t.id);
152 //return this.items.get(t.menuItemId);
157 onClick : function(e){
158 Roo.log("menu.onClick");
159 var t = this.findTargetItem(e);
165 if (Roo.isTouch && e.type == 'touchstart' && t.menu && !t.disabled) {
166 if(t == this.activeItem && t.shouldDeactivate(e)){
167 this.activeItem.deactivate();
168 delete this.activeItem;
172 this.setActiveItem(t, true);
180 Roo.log('pass click event');
184 this.fireEvent("click", this, t, e);
188 onMouseOver : function(e){
189 var t = this.findTargetItem(e);
192 // if(t.canActivate && !t.disabled){
193 // this.setActiveItem(t, true);
197 this.fireEvent("mouseover", this, e, t);
199 isVisible : function(){
202 onMouseOut : function(e){
203 var t = this.findTargetItem(e);
206 // if(t == this.activeItem && t.shouldDeactivate(e)){
207 // this.activeItem.deactivate();
208 // delete this.activeItem;
211 this.fireEvent("mouseout", this, e, t);
216 * Displays this menu relative to another element
217 * @param {String/HTMLElement/Roo.Element} element The element to align to
218 * @param {String} position (optional) The {@link Roo.Element#alignTo} anchor position to use in aligning to
219 * the element (defaults to this.defaultAlign)
220 * @param {Roo.menu.Menu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)
222 show : function(el, pos, parentMenu){
223 this.parentMenu = parentMenu;
227 this.fireEvent("beforeshow", this);
228 this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign), parentMenu, false);
231 * Displays this menu at a specific xy position
232 * @param {Array} xyPosition Contains X & Y [x, y] values for the position at which to show the menu (coordinates are page-based)
233 * @param {Roo.menu.Menu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)
235 showAt : function(xy, parentMenu, /* private: */_e){
236 this.parentMenu = parentMenu;
241 this.fireEvent("beforeshow", this);
243 //xy = this.el.adjustForConstraints(xy);
247 this.hideMenuItems();
249 this.triggerEl.addClass('open');
251 this.fireEvent("show", this);
257 this.doFocus.defer(50, this);
261 doFocus : function(){
263 this.focusEl.focus();
268 * Hides this menu and optionally all parent menus
269 * @param {Boolean} deep (optional) True to hide all parent menus recursively, if any (defaults to false)
271 hide : function(deep){
273 this.hideMenuItems();
274 if(this.el && this.isVisible()){
275 this.fireEvent("beforehide", this);
277 this.activeItem.deactivate();
278 this.activeItem = null;
280 this.triggerEl.removeClass('open');;
282 this.fireEvent("hide", this);
284 if(deep === true && this.parentMenu){
285 this.parentMenu.hide(true);
289 onTriggerPress : function(e)
292 Roo.log('trigger press');
293 //Roo.log(e.getTarget());
294 // Roo.log(this.triggerEl.dom);
295 if (Roo.get(e.getTarget()).findParent('.dropdown-menu')) {
299 var t = this.findTargetItem(e);
300 if(t && t.isContainer){
304 if (this.isVisible()) {
308 this.show(this.triggerEl, false, false);
317 hideMenuItems : function()
319 //$(backdrop).remove()
320 Roo.select('.open',true).each(function(aa) {
322 aa.removeClass('open');
323 //var parent = getParent($(this))
324 //var relatedTarget = { relatedTarget: this }
326 //$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
327 //if (e.isDefaultPrevented()) return
328 //$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
331 addxtypeChild : function (tree, cntr) {
332 var comp= Roo.bootstrap.Menu.superclass.addxtypeChild.call(this, tree, cntr);
334 this.menuitems.add(comp);