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