fix button # triggering url change
[roojs1] / Roo / bootstrap / nav / Item.js
1 /**
2  * @class Roo.bootstrap.nav.Item
3  * @extends Roo.bootstrap.Component
4  * @children Roo.bootstrap.Container Roo.bootstrap.Button
5  * @parent Roo.bootstrap.nav.Group
6  * @licence LGPL
7  * Bootstrap Navbar.NavItem class
8  * 
9  * @cfg {String} href  link to
10  * @cfg {String} button_weight (default|primary|secondary|success|info|warning|danger|link|light|dark) default none
11  * @cfg {Boolean} button_outline show and outlined button
12  * @cfg {String} html content of button
13  * @cfg {String} badge text inside badge
14  * @cfg {String} badgecls (bg-green|bg-red|bg-yellow)the extra classes for the badge
15  * @cfg {String} glyphicon DEPRICATED - use fa
16  * @cfg {String} icon DEPRICATED - use fa
17  * @cfg {String} fa - Fontawsome icon name (can add stuff to it like fa-2x)
18  * @cfg {Boolean} active Is item active
19  * @cfg {Boolean} disabled Is item disabled
20  * @cfg {String} linkcls  Link Class
21  * @cfg {Boolean} preventDefault (true | false) default false
22  * @cfg {String} tabId the tab that this item activates.
23  * @cfg {String} tagtype (a|span) render as a href or span?
24  * @cfg {Boolean} animateRef (true|false) link to element default false  
25  * @cfg {Roo.bootstrap.menu.Menu} menu a Menu 
26   
27  * @constructor
28  * Create a new Navbar Item
29  * @param {Object} config The config object
30  */
31 Roo.bootstrap.nav.Item = function(config){
32     Roo.bootstrap.nav.Item.superclass.constructor.call(this, config);
33     this.addEvents({
34         // raw events
35         /**
36          * @event click
37          * The raw click event for the entire grid.
38          * @param {Roo.EventObject} e
39          */
40         "click" : true,
41          /**
42             * @event changed
43             * Fires when the active item active state changes
44             * @param {Roo.bootstrap.nav.Item} this
45             * @param {boolean} state the new state
46              
47          */
48         'changed': true,
49         /**
50             * @event scrollto
51             * Fires when scroll to element
52             * @param {Roo.bootstrap.nav.Item} this
53             * @param {Object} options
54             * @param {Roo.EventObject} e
55              
56          */
57         'scrollto': true
58     });
59    
60 };
61
62 Roo.extend(Roo.bootstrap.nav.Item, Roo.bootstrap.Component,  {
63     
64     href: false,
65     html: '',
66     badge: '',
67     icon: false,
68     fa : false,
69     glyphicon: false,
70     active: false,
71     preventDefault : false,
72     tabId : false,
73     tagtype : 'a',
74     tag: 'li',
75     disabled : false,
76     animateRef : false,
77     was_active : false,
78     button_weight : '',
79     button_outline : false,
80     linkcls : '',
81     navLink: false,
82     
83     getAutoCreate : function(){
84          
85         var cfg = {
86             tag: this.tag,
87             cls: 'nav-item'
88         };
89         
90         cfg.cls =  typeof(cfg.cls) == 'undefined'  ? '' : cfg.cls;
91         
92         if (this.active) {
93             cfg.cls +=  ' active' ;
94         }
95         if (this.disabled) {
96             cfg.cls += ' disabled';
97         }
98         
99         // BS4 only?
100         if (this.button_weight.length) {
101             cfg.tag = this.href ? 'a' : 'button';
102             cfg.html = this.html || '';
103             cfg.cls += ' btn btn' + (this.button_outline ? '-outline' : '') + '-' + this.button_weight;
104             if (this.href) {
105                 cfg.href = this.href;
106             }
107             if (this.fa) {
108                 cfg.html = '<i class="fa fas fa-'+this.fa+'"></i> <span class="nav-html">' + this.html + '</span>';
109             } else {
110                 cfg.cls += " nav-html";
111             }
112             
113             // menu .. should add dropdown-menu class - so no need for carat..
114             
115             if (this.badge !== '') {
116                  
117                 cfg.html += ' <span class="badge badge-secondary">' + this.badge + '</span>';
118             }
119             return cfg;
120         }
121         
122         if (this.href || this.html || this.glyphicon || this.icon || this.fa) {
123             cfg.cn = [
124                 {
125                     tag: this.tagtype,
126                     href : this.href || "#",
127                     html: this.html || '',
128                     cls : ''
129                 }
130             ];
131             if (this.tagtype == 'a') {
132                 cfg.cn[0].cls = 'nav-link' +  (this.active ?  ' active'  : '') + ' ' + this.linkcls;
133         
134             }
135             if (this.icon) {
136                 cfg.cn[0].html = '<i class="'+this.icon+'"></i> <span class="nav-html">' + cfg.cn[0].html + '</span>';
137             } else  if (this.fa) {
138                 cfg.cn[0].html = '<i class="fa fas fa-'+this.fa+'"></i> <span class="nav-html">' + cfg.cn[0].html + '</span>';
139             } else if(this.glyphicon) {
140                 cfg.cn[0].html = '<span class="glyphicon glyphicon-' + this.glyphicon + '"></span> '  + cfg.cn[0].html;
141             } else {
142                 cfg.cn[0].cls += " nav-html";
143             }
144             
145             if (this.menu) {
146                 cfg.cn[0].html += " <span class='caret'></span>";
147              
148             }
149             
150             if (this.badge !== '') {
151                 cfg.cn[0].html += ' <span class="badge badge-secondary">' + this.badge + '</span>';
152             }
153         }
154         
155         
156         
157         return cfg;
158     },
159     onRender : function(ct, position)
160     {
161        // Roo.log("Call onRender: " + this.xtype);
162         if (Roo.bootstrap.version == 4 && ct.dom.type != 'ul') {
163             this.tag = 'div';
164         }
165         
166         var ret = Roo.bootstrap.nav.Item.superclass.onRender.call(this, ct, position);
167         this.navLink = this.el.select('.nav-link',true).first();
168         this.htmlEl = this.el.hasClass('nav-html') ? this.el : this.el.select('.nav-html',true).first();
169         return ret;
170     },
171       
172     
173     initEvents: function() 
174     {
175         if (typeof (this.menu) != 'undefined') {
176             this.menu.parentType = this.xtype;
177             this.menu.triggerEl = this.el;
178             this.menu = this.addxtype(Roo.apply({}, this.menu));
179         }
180         
181         this.el.on('click', this.onClick, this);
182         
183         //if(this.tagtype == 'span'){
184         //    this.el.select('span',true).on('click', this.onClick, this);
185         //}
186        
187         // at this point parent should be available..
188         this.parent().register(this);
189     },
190     
191     onClick : function(e)
192     {
193         if (e.getTarget('.dropdown-menu-item')) {
194             // did you click on a menu itemm.... - then don't trigger onclick..
195             return;
196         }
197         
198         if(
199                 this.preventDefault ||
200                                 this.href === false ||
201                 this.href === '#' 
202         ){
203             //Roo.log("NavItem - prevent Default?");
204             e.preventDefault();
205         }
206         
207         if (this.disabled) {
208             return;
209         }
210         
211         var tg = Roo.bootstrap.TabGroup.get(this.navId);
212         if (tg && tg.transition) {
213             Roo.log("waiting for the transitionend");
214             return;
215         }
216         
217         
218         
219         //Roo.log("fire event clicked");
220         if(this.fireEvent('click', this, e) === false){
221             return;
222         };
223         
224         if(this.tagtype == 'span'){
225             return;
226         }
227         
228         //Roo.log(this.href);
229         var ael = this.el.select('a',true).first();
230         //Roo.log(ael);
231         
232         if(ael && this.animateRef && this.href.indexOf('#') > -1){
233             //Roo.log(["test:",ael.dom.href.split("#")[0], document.location.toString().split("#")[0]]);
234             if (ael.dom.href.split("#")[0] != document.location.toString().split("#")[0]) {
235                 return; // ignore... - it's a 'hash' to another page.
236             }
237             Roo.log("NavItem - prevent Default?");
238             e.preventDefault();
239             this.scrollToElement(e);
240         }
241         
242         
243         var p =  this.parent();
244    
245         if (['tabs','pills'].indexOf(p.type)!==-1 && p.pilltype) {
246             if (typeof(p.setActiveItem) !== 'undefined') {
247                 p.setActiveItem(this);
248             }
249         }
250         
251         // if parent is a navbarheader....- and link is probably a '#' page ref.. then remove the expanded menu.
252         if (p.parentType == 'NavHeaderbar' && !this.menu) {
253             // remove the collapsed menu expand...
254             p.parent().el.select('.roo-navbar-collapse',true).removeClass('in');  
255         }
256     },
257     
258     isActive: function () {
259         return this.active
260     },
261     setActive : function(state, fire, is_was_active)
262     {
263         if (this.active && !state && this.navId) {
264             this.was_active = true;
265             var nv = Roo.bootstrap.nav.Group.get(this.navId);
266             if (nv) {
267                 nv.clearWasActive(this);
268             }
269             
270         }
271         this.active = state;
272         
273         if (!state ) {
274             this.el.removeClass('active');
275             this.navLink ? this.navLink.removeClass('active') : false;
276         } else if (!this.el.hasClass('active')) {
277             
278             this.el.addClass('active');
279             if (Roo.bootstrap.version == 4 && this.navLink ) {
280                 this.navLink.addClass('active');
281             }
282             
283         }
284         if (fire) {
285             this.fireEvent('changed', this, state);
286         }
287         
288         // show a panel if it's registered and related..
289         
290         if (!this.navId || !this.tabId || !state || is_was_active) {
291             return;
292         }
293         
294         var tg = Roo.bootstrap.TabGroup.get(this.navId);
295         if (!tg) {
296             return;
297         }
298         var pan = tg.getPanelByName(this.tabId);
299         if (!pan) {
300             return;
301         }
302         // if we can not flip to new panel - go back to old nav highlight..
303         if (false == tg.showPanel(pan)) {
304             var nv = Roo.bootstrap.nav.Group.get(this.navId);
305             if (nv) {
306                 var onav = nv.getWasActive();
307                 if (onav) {
308                     onav.setActive(true, false, true);
309                 }
310             }
311             
312         }
313         
314         
315         
316     },
317      // this should not be here...
318     setDisabled : function(state)
319     {
320         this.disabled = state;
321         if (!state ) {
322             this.el.removeClass('disabled');
323         } else if (!this.el.hasClass('disabled')) {
324             this.el.addClass('disabled');
325         }
326         
327     },
328     
329     /**
330      * Fetch the element to display the tooltip on.
331      * @return {Roo.Element} defaults to this.el
332      */
333     tooltipEl : function()
334     {
335         return this.el; //this.tagtype  == 'a' ? this.el  : this.el.select('' + this.tagtype + '', true).first();
336     },
337     
338     scrollToElement : function(e)
339     {
340         var c = document.body;
341         
342         /*
343          * Firefox / IE places the overflow at the html level, unless specifically styled to behave differently.
344          */
345         if(Roo.isFirefox || Roo.isIE || Roo.isIE11){
346             c = document.documentElement;
347         }
348         
349         var target = Roo.get(c).select('a[name=' + this.href.split('#')[1] +']', true).first();
350         
351         if(!target){
352             return;
353         }
354
355         var o = target.calcOffsetsTo(c);
356         
357         var options = {
358             target : target,
359             value : o[1]
360         };
361         
362         this.fireEvent('scrollto', this, options, e);
363         
364         Roo.get(c).scrollTo('top', options.value, true);
365         
366         return;
367     },
368     /**
369      * Set the HTML (text content) of the item
370      * @param {string} html  content for the nav item
371      */
372     setHtml : function(html)
373     {
374         this.html = html;
375         this.htmlEl.dom.innerHTML = html;
376         
377     } 
378 });
379  
380
381