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