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 (dropdown|treeview|submenu) 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         
112         
113         var cfg = {
114             tag : 'ul',
115             cls : 'dropdown-menu' ,
116             style : 'z-index:1000'
117             
118         }
119         
120         if (this.type === 'submenu') {
121             cfg.cls = 'submenu active';
122         }
123         if (this.type === 'treeview') {
124             cfg.cls = 'treeview-menu';
125         }
126         
127         return cfg;
128     },
129     initEvents : function() {
130         
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);
136
137         this.el.on("mouseover", this.onMouseOver, this);
138         this.el.on("mouseout", this.onMouseOut, this);
139         
140         
141     },
142     findTargetItem : function(e){
143         var t = e.getTarget(".dropdown-menu-item", this.el,  true);
144         if(!t){
145             return false;
146         }
147         //Roo.log(t);         Roo.log(t.id);
148         if(t && t.id){
149             //Roo.log(this.menuitems);
150             return this.menuitems.get(t.id);
151             
152             //return this.items.get(t.menuItemId);
153         }
154         
155         return false;
156     },
157     onClick : function(e){
158         Roo.log("menu.onClick");
159         var t = this.findTargetItem(e);
160         if(!t){
161             return;
162         }
163         Roo.log(e);
164         /*
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;
169                 return;
170             }
171             if(t.canActivate){
172                 this.setActiveItem(t, true);
173             }
174             return;
175             
176             
177         }
178         */
179        
180         Roo.log('pass click event');
181         
182         t.onClick(e);
183         
184         this.fireEvent("click", this, t, e);
185         
186         this.hide();
187     },
188      onMouseOver : function(e){
189         var t  = this.findTargetItem(e);
190         //Roo.log(t);
191         //if(t){
192         //    if(t.canActivate && !t.disabled){
193         //        this.setActiveItem(t, true);
194         //    }
195         //}
196         
197         this.fireEvent("mouseover", this, e, t);
198     },
199     isVisible : function(){
200         return !this.hidden;
201     },
202      onMouseOut : function(e){
203         var t  = this.findTargetItem(e);
204         
205         //if(t ){
206         //    if(t == this.activeItem && t.shouldDeactivate(e)){
207         //        this.activeItem.deactivate();
208         //        delete this.activeItem;
209         //    }
210         //}
211         this.fireEvent("mouseout", this, e, t);
212     },
213     
214     
215     /**
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)
221      */
222     show : function(el, pos, parentMenu){
223         this.parentMenu = parentMenu;
224         if(!this.el){
225             this.render();
226         }
227         this.fireEvent("beforeshow", this);
228         this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign), parentMenu, false);
229     },
230      /**
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)
234      */
235     showAt : function(xy, parentMenu, /* private: */_e){
236         this.parentMenu = parentMenu;
237         if(!this.el){
238             this.render();
239         }
240         if(_e !== false){
241             this.fireEvent("beforeshow", this);
242             
243             //xy = this.el.adjustForConstraints(xy);
244         }
245         //this.el.setXY(xy);
246         //this.el.show();
247         this.hideMenuItems();
248         this.hidden = false;
249         this.triggerEl.addClass('open');
250         this.focus();
251         this.fireEvent("show", this);
252     },
253     
254     focus : function(){
255         return;
256         if(!this.hidden){
257             this.doFocus.defer(50, this);
258         }
259     },
260
261     doFocus : function(){
262         if(!this.hidden){
263             this.focusEl.focus();
264         }
265     },
266
267     /**
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)
270      */
271     hide : function(deep){
272         
273         this.hideMenuItems();
274         if(this.el && this.isVisible()){
275             this.fireEvent("beforehide", this);
276             if(this.activeItem){
277                 this.activeItem.deactivate();
278                 this.activeItem = null;
279             }
280             this.triggerEl.removeClass('open');;
281             this.hidden = true;
282             this.fireEvent("hide", this);
283         }
284         if(deep === true && this.parentMenu){
285             this.parentMenu.hide(true);
286         }
287     },
288     
289     onTriggerPress  : function(e)
290     {
291         
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')) {
296             return;
297         }
298         
299         var t = this.findTargetItem(e);
300         if(t && t.isContainer){
301             return;
302         }
303         
304         if (this.isVisible()) {
305             Roo.log('hide');
306             this.hide();
307         } else {
308             this.show(this.triggerEl, false, false);
309         }
310         
311         
312     },
313     
314          
315        
316     
317     hideMenuItems : function()
318     {
319         //$(backdrop).remove()
320         Roo.select('.open',true).each(function(aa) {
321             
322             aa.removeClass('open');
323           //var parent = getParent($(this))
324           //var relatedTarget = { relatedTarget: this }
325           
326            //$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
327           //if (e.isDefaultPrevented()) return
328            //$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
329         })
330     },
331     addxtypeChild : function (tree, cntr) {
332         var comp= Roo.bootstrap.Menu.superclass.addxtypeChild.call(this, tree, cntr);
333           
334         this.menuitems.add(comp);
335         return comp;
336
337     },
338     getEl : function()
339     {
340         Roo.log(this.el);
341         return this.el;
342     }
343 });
344
345  
346