Roo/bootstrap/Menu.js
[roojs1] / Roo / bootstrap / Menu.js
1 /*
2  * - LGPL
3  *
4  * menu
5  * 
6  */
7
8 /**
9  * @class Roo.bootstrap.Menu
10  * @extends Roo.bootstrap.Component
11  * Bootstrap Menu class - container for MenuItems
12  * @cfg {String} type type of menu
13  * 
14  * @constructor
15  * Create a new Menu
16  * @param {Object} config The config object
17  */
18
19
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);
24     }
25     this.addEvents({
26         /**
27          * @event beforeshow
28          * Fires before this menu is displayed
29          * @param {Roo.menu.Menu} this
30          */
31         beforeshow : true,
32         /**
33          * @event beforehide
34          * Fires before this menu is hidden
35          * @param {Roo.menu.Menu} this
36          */
37         beforehide : true,
38         /**
39          * @event show
40          * Fires after this menu is displayed
41          * @param {Roo.menu.Menu} this
42          */
43         show : true,
44         /**
45          * @event hide
46          * Fires after this menu is hidden
47          * @param {Roo.menu.Menu} this
48          */
49         hide : true,
50         /**
51          * @event click
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
56          */
57         click : true,
58         /**
59          * @event mouseover
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
64          */
65         mouseover : true,
66         /**
67          * @event mouseout
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
72          */
73         mouseout : true,
74         /**
75          * @event itemclick
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
79          */
80         itemclick: true
81     });
82     this.menuitems = new Roo.util.MixedCollection(false, function(o) { return o.el.id; });
83 };
84
85 Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
86     
87    /// html : false,
88     //align : '',
89     triggerEl : false,  // is this set by component builder? -- it should really be fetched from parent()???
90     type: false,
91     /**
92      * @cfg {Boolean} registerMenu True (default) - means that clicking on screen etc. hides it.
93      */
94     registerMenu : true,
95     
96     menuItems :false, // stores the menu items..
97     
98     hidden:true,
99     
100     parentMenu : false,
101     
102     getChildContainer : function() {
103         return this.el;  
104     },
105     
106     getAutoCreate : function(){
107          
108         //if (['right'].indexOf(this.align)!==-1) {
109         //    cfg.cn[1].cls += ' pull-right'
110         //}
111         var cfg = {
112             tag : 'ul',
113             cls : 'dropdown-menu' ,
114             style : 'z-index:1000'
115             
116         }
117         
118         if (this.type === 'submenu') {
119             cfg.cls = 'submenu active'
120         }
121         
122         return cfg;
123     },
124     initEvents : function() {
125         
126        // Roo.log("ADD event");
127        // Roo.log(this.triggerEl.dom);
128         this.triggerEl.on('click', this.onTriggerPress, this);
129         this.triggerEl.addClass('dropdown-toggle');
130         this.el.on(Roo.isTouch ? 'touchstart' : 'click'   , this.onClick, this);
131
132         this.el.on("mouseover", this.onMouseOver, this);
133         this.el.on("mouseout", this.onMouseOut, this);
134         
135         
136     },
137     findTargetItem : function(e){
138         var t = e.getTarget(".dropdown-menu-item", this.el,  true);
139         if(!t){
140             return false;
141         }
142         //Roo.log(t);         Roo.log(t.id);
143         if(t && t.id){
144             //Roo.log(this.menuitems);
145             return this.menuitems.get(t.id);
146             
147             //return this.items.get(t.menuItemId);
148         }
149         
150         return false;
151     },
152     onClick : function(e){
153         Roo.log("menu.onClick");
154         var t = this.findTargetItem(e);
155         if(!t){
156             return;
157         }
158         Roo.log(e);
159         /*
160         if (Roo.isTouch && e.type == 'touchstart' && t.menu  && !t.disabled) {
161             if(t == this.activeItem && t.shouldDeactivate(e)){
162                 this.activeItem.deactivate();
163                 delete this.activeItem;
164                 return;
165             }
166             if(t.canActivate){
167                 this.setActiveItem(t, true);
168             }
169             return;
170             
171             
172         }
173         */
174         Roo.log('pass click event');
175         
176         t.onClick(e);
177         
178         this.fireEvent("click", this, t, e);
179         
180         this.hide();
181     },
182      onMouseOver : function(e){
183         var t  = this.findTargetItem(e);
184         //Roo.log(t);
185         //if(t){
186         //    if(t.canActivate && !t.disabled){
187         //        this.setActiveItem(t, true);
188         //    }
189         //}
190         
191         this.fireEvent("mouseover", this, e, t);
192     },
193     isVisible : function(){
194         return !this.hidden;
195     },
196      onMouseOut : function(e){
197         var t  = this.findTargetItem(e);
198         
199         //if(t ){
200         //    if(t == this.activeItem && t.shouldDeactivate(e)){
201         //        this.activeItem.deactivate();
202         //        delete this.activeItem;
203         //    }
204         //}
205         this.fireEvent("mouseout", this, e, t);
206     },
207     
208     
209     /**
210      * Displays this menu relative to another element
211      * @param {String/HTMLElement/Roo.Element} element The element to align to
212      * @param {String} position (optional) The {@link Roo.Element#alignTo} anchor position to use in aligning to
213      * the element (defaults to this.defaultAlign)
214      * @param {Roo.menu.Menu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)
215      */
216     show : function(el, pos, parentMenu){
217         this.parentMenu = parentMenu;
218         if(!this.el){
219             this.render();
220         }
221         this.fireEvent("beforeshow", this);
222         this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign), parentMenu, false);
223     },
224      /**
225      * Displays this menu at a specific xy position
226      * @param {Array} xyPosition Contains X & Y [x, y] values for the position at which to show the menu (coordinates are page-based)
227      * @param {Roo.menu.Menu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)
228      */
229     showAt : function(xy, parentMenu, /* private: */_e){
230         this.parentMenu = parentMenu;
231         if(!this.el){
232             this.render();
233         }
234         if(_e !== false){
235             this.fireEvent("beforeshow", this);
236             
237             //xy = this.el.adjustForConstraints(xy);
238         }
239         //this.el.setXY(xy);
240         //this.el.show();
241         this.hideMenuItems();
242         this.hidden = false;
243         this.triggerEl.addClass('open');
244         this.focus();
245         this.fireEvent("show", this);
246     },
247     
248     focus : function(){
249         return;
250         if(!this.hidden){
251             this.doFocus.defer(50, this);
252         }
253     },
254
255     doFocus : function(){
256         if(!this.hidden){
257             this.focusEl.focus();
258         }
259     },
260
261     /**
262      * Hides this menu and optionally all parent menus
263      * @param {Boolean} deep (optional) True to hide all parent menus recursively, if any (defaults to false)
264      */
265     hide : function(deep){
266         
267         this.hideMenuItems();
268         if(this.el && this.isVisible()){
269             this.fireEvent("beforehide", this);
270             if(this.activeItem){
271                 this.activeItem.deactivate();
272                 this.activeItem = null;
273             }
274             this.triggerEl.removeClass('open');;
275             this.hidden = true;
276             this.fireEvent("hide", this);
277         }
278         if(deep === true && this.parentMenu){
279             this.parentMenu.hide(true);
280         }
281     },
282     
283     onTriggerPress  : function(e)
284     {
285         
286         Roo.log('trigger press');
287         //Roo.log(e.getTarget());
288        // Roo.log(this.triggerEl.dom);
289         if (Roo.get(e.getTarget()).findParent('.dropdown-menu')) {
290             return;
291         }
292         if (this.isVisible()) {
293             Roo.log('hide');
294             this.hide();
295         } else {
296             this.show(this.triggerEl, false, false);
297         }
298         
299         
300     },
301     
302          
303        
304     
305     hideMenuItems : function()
306     {
307         //$(backdrop).remove()
308         Roo.select('.open',true).each(function(aa) {
309             
310             aa.removeClass('open');
311           //var parent = getParent($(this))
312           //var relatedTarget = { relatedTarget: this }
313           
314            //$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
315           //if (e.isDefaultPrevented()) return
316            //$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
317         })
318     },
319     addxtypeChild : function (tree, cntr) {
320         var comp= Roo.bootstrap.Menu.superclass.addxtypeChild.call(this, tree, cntr);
321           
322         this.menuitems.add(comp);
323         return comp;
324
325     },
326     getEl : function()
327     {
328         Roo.log(this.el);
329         return this.el;
330     }
331 });
332
333  
334