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