* Bootstrap Menu class - container for MenuItems
* @cfg {String} type (dropdown|treeview|submenu) type of menu
* @cfg {bool} hidden if the menu should be hidden when rendered.
+ * @cfg {bool} stopEvent (true|false) Stop event after trigger press (default true)
+ * @cfg {bool} isLink (true|false) the menu has link disable auto expand and collaspe (default false)
*
* @constructor
* Create a new Menu
if (this.registerMenu && this.type != 'treeview') {
Roo.bootstrap.MenuMgr.register(this);
}
+
+
this.addEvents({
/**
* @event beforeshow
- * Fires before this menu is displayed
+ * Fires before this menu is displayed (return false to block)
* @param {Roo.menu.Menu} this
*/
beforeshow : true,
/**
* @event beforehide
- * Fires before this menu is hidden
+ * Fires before this menu is hidden (return false to block)
* @param {Roo.menu.Menu} this
*/
beforehide : true,
menuItems :false, // stores the menu items..
hidden:true,
-
parentMenu : false,
+ stopEvent : true,
+
+ isLink : false,
+
+ container_method : 'getDocumentBody',
+
+
getChildContainer : function() {
return this.el;
},
this.triggerEl.on(Roo.isTouch ? 'touchstart' : 'mouseup', this.onTriggerPress, this);
- this.triggerEl.addClass('dropdown-toggle');
-
-
+
+ if (this.triggerEl.hasClass('nav-item') && this.triggerEl.select('.nav-link',true).length) {
+ // dropdown toggle on the 'a' in BS4?
+ this.triggerEl.select('.nav-link',true).first().addClass('dropdown-toggle');
+ } else if (!this.triggerEl.hasClass('no-dropdown-toggle')) {
+ this.triggerEl.addClass('dropdown-toggle');
+ }
if (Roo.isTouch) {
this.el.on('touchstart' , this.onTouch, this);
}
this.fireEvent("click", this, t, e);
- this.hide();
+ var _this = this;
+
+ if(!t.href.length || t.href == '#'){
+ (function() { _this.hide(); }).defer(100);
+ }
+
},
- onMouseOver : function(e){
+
+ onMouseOver : function(e){
var t = this.findTargetItem(e);
//Roo.log(t);
//if(t){
isVisible : function(){
return !this.hidden;
},
- onMouseOut : function(e){
+ onMouseOut : function(e){
var t = this.findTargetItem(e);
//if(t ){
* the element (defaults to this.defaultAlign)
* @param {Roo.menu.Menu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)
*/
- show : function(el, pos, parentMenu){
- this.parentMenu = parentMenu;
+ show : function(el, pos, parentMenu)
+ {
+ if (false === this.fireEvent("beforeshow", this)) {
+ Roo.log("show canceled");
+ return;
+ }
+ this.parentMenu = parentMenu;
if(!this.el){
this.render();
}
- this.fireEvent("beforeshow", this);
+
this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign), parentMenu, false);
},
/**
this.hideMenuItems();
this.hidden = false;
this.triggerEl.addClass('open');
+ this.el.addClass('show');
- if(this.el.getWidth() + xy[0] > Roo.lib.Dom.getViewWidth()){
+ // reassign x when hitting right
+ if(this.el.getWidth() + xy[0] >= Roo.lib.Dom.getViewWidth()){
xy[0] = xy[0] - this.el.getWidth() + this.triggerEl.getWidth();
}
- if(this.el.getStyle('top').slice(-1) != "%"){
+ // reassign y when hitting bottom
+ if(this.el.getHeight() + xy[1] >= Roo.lib.Dom.getViewHeight()){
+ xy[1] = xy[1] - this.el.getHeight() - this.triggerEl.getHeight();
+ }
+
+ // but the list may align on trigger left or trigger top... should it be a properity?
+
+ if(this.el.getStyle('top') != 'auto' && this.el.getStyle('top').slice(-1) != "%"){
this.el.setXY(xy);
}
*/
hide : function(deep)
{
-
+ if (false === this.fireEvent("beforehide", this)) {
+ Roo.log("hide canceled");
+ return;
+ }
this.hideMenuItems();
if(this.el && this.isVisible()){
- this.fireEvent("beforehide", this);
+
if(this.activeItem){
this.activeItem.deactivate();
this.activeItem = null;
}
this.triggerEl.removeClass('open');;
+ this.el.removeClass('show');
this.hidden = true;
this.fireEvent("hide", this);
}
// trigger only occurs on normal menu's -- if it's a treeview or dropdown... do not hide/show..
var pel = Roo.get(e.getTarget());
if (pel.findParent('.dropdown-menu') || pel.findParent('.treeview-menu') ) {
-
+ Roo.log('is treeview or dropdown?');
+ return;
+ }
+
+ if(e.getTarget().nodeName.toLowerCase() !== 'i' && this.isLink){
return;
}
this.hide();
} else {
Roo.log('show');
- this.show(this.triggerEl, false, false);
+ this.show(this.triggerEl, '?', false);
+ }
+
+ if(this.stopEvent || e.getTarget().nodeName.toLowerCase() === 'i'){
+ e.stopEvent();
}
- e.stopEvent();
},
-
-
hideMenuItems : function()
if (!this.el) {
return;
}
- //$(backdrop).remove()
+
this.el.select('.open',true).each(function(aa) {
aa.removeClass('open');
- //var parent = getParent($(this))
- //var relatedTarget = { relatedTarget: this }
-
- //$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
- //if (e.isDefaultPrevented()) return
- //$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
+
});
},
addxtypeChild : function (tree, cntr) {
{
Roo.log(this.el);
return this.el;
+ },
+
+ clear : function()
+ {
+ this.getEl().dom.innerHTML = '';
+ this.menuitems.clear();
}
});