565d09272a1400b903ac7fd735d3271ec7dcabcf
[roojs1] / Roo / bootstrap / Button.js
1 /*
2  * - LGPL
3  *
4  * button
5  * 
6  */
7
8 /**
9  * @class Roo.bootstrap.Button
10  * @extends Roo.bootstrap.Component
11  * Bootstrap Button class
12  * @cfg {String} html The button content
13  * @cfg {String} weight (default|primary|secondary|success|info|warning|danger|link|light|dark) default
14  * @cfg {String} badge_weight (default|primary|secondary|success|info|warning|danger|link|light|dark) default (same as button)
15  * @cfg {Boolean} outline default false (except for weight=default which emulates old behaveiour with an outline)
16  * @cfg {String} size (lg|sm|xs)
17  * @cfg {String} tag (a|input|submit)
18  * @cfg {String} href empty or href
19  * @cfg {Boolean} disabled default false;
20  * @cfg {Boolean} isClose default false;
21  * @cfg {String} glyphicon depricated - use fa
22  * @cfg {String} fa fontawesome icon - eg. 'comment' - without the fa/fas etc..
23  * @cfg {String} badge text for badge
24  * @cfg {String} theme (default|glow)  
25  * @cfg {Boolean} inverse dark themed version
26  * @cfg {Boolean} toggle is it a slidy toggle button
27  * @cfg {Boolean} pressed   default null - if the button ahs active state
28  * @cfg {String} ontext text for on slidy toggle state
29  * @cfg {String} offtext text for off slidy toggle state
30  * @cfg {Boolean} preventDefault  default true (stop click event triggering the URL if it's a link.)
31  * @cfg {Boolean} removeClass remove the standard class..
32  * @cfg {String} target (_self|_blank|_parent|_top|other) target for a href. 
33  * @cfg {Boolean} grpup if parent is a btn group - then it turns it into a toogleGroup.
34  * 
35  * @constructor
36  * Create a new button
37  * @param {Object} config The config object
38  */
39
40
41 Roo.bootstrap.Button = function(config){
42     Roo.bootstrap.Button.superclass.constructor.call(this, config);
43     
44     this.addEvents({
45         // raw events
46         /**
47          * @event click
48          * When a button is pressed
49          * @param {Roo.bootstrap.Button} btn
50          * @param {Roo.EventObject} e
51          */
52         "click" : true,
53         /**
54          * @event dblclick
55          * When a button is double clicked
56          * @param {Roo.bootstrap.Button} btn
57          * @param {Roo.EventObject} e
58          */
59         "dblclick" : true,
60          /**
61          * @event toggle
62          * After the button has been toggles
63          * @param {Roo.bootstrap.Button} btn
64          * @param {Roo.EventObject} e
65          * @param {boolean} pressed (also available as button.pressed)
66          */
67         "toggle" : true
68     });
69 };
70
71 Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component,  {
72     html: false,
73     active: false,
74     weight: '',
75     badge_weight: '',
76     outline : false,
77     size: '',
78     tag: 'button',
79     href: '',
80     disabled: false,
81     isClose: false,
82     glyphicon: '',
83     fa: '',
84     badge: '',
85     theme: 'default',
86     inverse: false,
87     
88     toggle: false,
89     ontext: 'ON',
90     offtext: 'OFF',
91     defaulton: true,
92     preventDefault: true,
93     removeClass: false,
94     name: false,
95     target: false,
96     group : false,
97      
98     pressed : null,
99      
100     
101     getAutoCreate : function(){
102         
103         var cfg = {
104             tag : 'button',
105             cls : 'roo-button',
106             html: ''
107         };
108         
109         if (['a', 'button', 'input', 'submit'].indexOf(this.tag) < 0) {
110             throw "Invalid value for tag: " + this.tag + ". must be a, button, input or submit.";
111             this.tag = 'button';
112         } else {
113             cfg.tag = this.tag;
114         }
115         cfg.html = '<span class="roo-button-text">' + (this.html || cfg.html) + '</span>';
116         
117         if (this.toggle == true) {
118             cfg={
119                 tag: 'div',
120                 cls: 'slider-frame roo-button',
121                 cn: [
122                     {
123                         tag: 'span',
124                         'data-on-text':'ON',
125                         'data-off-text':'OFF',
126                         cls: 'slider-button',
127                         html: this.offtext
128                     }
129                 ]
130             };
131             // why are we validating the weights?
132             if (Roo.bootstrap.Button.weights.indexOf(this.weight) > -1) {
133                 cfg.cls +=  ' ' + this.weight;
134             }
135             
136             return cfg;
137         }
138         
139         if (this.isClose) {
140             cfg.cls += ' close';
141             
142             cfg["aria-hidden"] = true;
143             
144             cfg.html = "&times;";
145             
146             return cfg;
147         }
148              
149         
150         if (this.theme==='default') {
151             cfg.cls = 'btn roo-button';
152             
153             //if (this.parentType != 'Navbar') {
154             this.weight = this.weight.length ?  this.weight : 'default';
155             //}
156             if (Roo.bootstrap.Button.weights.indexOf(this.weight) > -1) {
157                 
158                 var outline = this.outline || this.weight == 'default' ? 'outline-' : '';
159                 var weight = this.weight == 'default' ? 'secondary' : this.weight;
160                 cfg.cls += ' btn-' + outline + weight;
161                 if (this.weight == 'default') {
162                     // BC
163                     cfg.cls += ' btn-' + this.weight;
164                 }
165             }
166         } else if (this.theme==='glow') {
167             
168             cfg.tag = 'a';
169             cfg.cls = 'btn-glow roo-button';
170             
171             if (Roo.bootstrap.Button.weights.indexOf(this.weight) > -1) {
172                 
173                 cfg.cls += ' ' + this.weight;
174             }
175         }
176    
177         
178         if (this.inverse) {
179             this.cls += ' inverse';
180         }
181         
182         
183         if (this.active || this.pressed === true) {
184             cfg.cls += ' active';
185         }
186         
187         if (this.disabled) {
188             cfg.disabled = 'disabled';
189         }
190         
191         if (this.items) {
192             Roo.log('changing to ul' );
193             cfg.tag = 'ul';
194             this.glyphicon = 'caret';
195             if (Roo.bootstrap.version == 4) {
196                 this.fa = 'caret-down';
197             }
198             
199         }
200         
201         cfg.cls += this.size.length ? (' btn-' + this.size) : '';
202          
203         //gsRoo.log(this.parentType);
204         if (this.parentType === 'Navbar' && !this.parent().bar) {
205             Roo.log('changing to li?');
206             
207             cfg.tag = 'li';
208             
209             cfg.cls = '';
210             cfg.cn =  [{
211                 tag : 'a',
212                 cls : 'roo-button',
213                 html : this.html,
214                 href : this.href || '#'
215             }];
216             if (this.menu) {
217                 cfg.cn[0].html = this.html  + ' <span class="caret"></span>';
218                 cfg.cls += ' dropdown';
219             }   
220             
221             delete cfg.html;
222             
223         }
224         
225        cfg.cls += this.parentType === 'Navbar' ?  ' navbar-btn' : '';
226         
227         if (this.glyphicon) {
228             cfg.html = ' ' + cfg.html;
229             
230             cfg.cn = [
231                 {
232                     tag: 'span',
233                     cls: 'glyphicon glyphicon-' + this.glyphicon
234                 }
235             ];
236         }
237         if (this.fa) {
238             cfg.html = ' ' + cfg.html;
239             
240             cfg.cn = [
241                 {
242                     tag: 'i',
243                     cls: 'fa fas fa-' + this.fa
244                 }
245             ];
246         }
247         
248         if (this.badge) {
249             cfg.html += ' ';
250             
251             cfg.tag = 'a';
252             
253 //            cfg.cls='btn roo-button';
254             
255             cfg.href=this.href;
256             
257             var value = cfg.html;
258             
259             if(this.glyphicon){
260                 value = {
261                     tag: 'span',
262                     cls: 'glyphicon glyphicon-' + this.glyphicon,
263                     html: this.html
264                 };
265             }
266             if(this.fa){
267                 value = {
268                     tag: 'i',
269                     cls: 'fa fas fa-' + this.fa,
270                     html: this.html
271                 };
272             }
273             
274             var bw = this.badge_weight.length ? this.badge_weight :
275                 (this.weight.length ? this.weight : 'secondary');
276             bw = bw == 'default' ? 'secondary' : bw;
277             
278             cfg.cn = [
279                 value,
280                 {
281                     tag: 'span',
282                     cls: 'badge badge-' + bw,
283                     html: this.badge
284                 }
285             ];
286             
287             cfg.html='';
288         }
289         
290         if (this.menu) {
291             cfg.cls += ' dropdown';
292             cfg.html = typeof(cfg.html) != 'undefined' ?
293                     cfg.html + ' <span class="caret"></span>' : '<span class="caret"></span>';
294         }
295         
296         if (cfg.tag !== 'a' && this.href !== '') {
297             throw "Tag must be a to set href.";
298         } else if (this.href.length > 0) {
299             cfg.href = this.href;
300         }
301         
302         if(this.removeClass){
303             cfg.cls = '';
304         }
305         
306         if(this.target){
307             cfg.target = this.target;
308         }
309         
310         return cfg;
311     },
312     initEvents: function() {
313        // Roo.log('init events?');
314 //        Roo.log(this.el.dom);
315         // add the menu...
316         
317         if (typeof (this.menu) != 'undefined') {
318             this.menu.parentType = this.xtype;
319             this.menu.triggerEl = this.el;
320             this.addxtype(Roo.apply({}, this.menu));
321         }
322
323
324         if (this.el.hasClass('roo-button')) {
325              this.el.on('click', this.onClick, this);
326              this.el.on('dblclick', this.onDblClick, this);
327         } else {
328              this.el.select('.roo-button').on('click', this.onClick, this);
329              this.el.select('.roo-button').on('dblclick', this.onDblClick, this);
330              
331         }
332         // why?
333         if(this.removeClass){
334             this.el.on('click', this.onClick, this);
335         }
336         
337         if (this.group === true) {
338              if (this.pressed === false || this.pressed === true) {
339                 // nothing
340             } else {
341                 this.pressed = false;
342                 this.setActive(this.pressed);
343             }
344             
345         }
346         
347         this.el.enableDisplayMode();
348         
349     },
350     onClick : function(e)
351     {
352         if (this.disabled) {
353             return;
354         }
355         
356         Roo.log('button on click ');
357         if(this.preventDefault){
358             e.preventDefault();
359         }
360         
361         if (this.group) {
362             if (this.pressed) {
363                 // do nothing -
364                 return;
365             }
366             this.setActive(true);
367             var pi = this.parent().items;
368             for (var i = 0;i < pi.length;i++) {
369                 if (this == pi[i]) {
370                     continue;
371                 }
372                 if (pi[i].el.hasClass('roo-button')) {
373                     pi[i].setActive(false);
374                 }
375             }
376             this.fireEvent('click', this, e);            
377             return;
378         }
379         
380         if (this.pressed === true || this.pressed === false) {
381             this.toggleActive(e);
382         }
383         
384         
385         this.fireEvent('click', this, e);
386     },
387     onDblClick: function(e)
388     {
389         if (this.disabled) {
390             return;
391         }
392         if(this.preventDefault){
393             e.preventDefault();
394         }
395         this.fireEvent('dblclick', this, e);
396     },
397     /**
398      * Enables this button
399      */
400     enable : function()
401     {
402         this.disabled = false;
403         this.el.removeClass('disabled');
404     },
405     
406     /**
407      * Disable this button
408      */
409     disable : function()
410     {
411         this.disabled = true;
412         this.el.addClass('disabled');
413     },
414      /**
415      * sets the active state on/off, 
416      * @param {Boolean} state (optional) Force a particular state
417      */
418     setActive : function(v) {
419         
420         this.el[v ? 'addClass' : 'removeClass']('active');
421         this.pressed = v;
422     },
423      /**
424      * toggles the current active state 
425      */
426     toggleActive : function(e)
427     {
428         this.setActive(!this.pressed); // this modifies pressed...
429         this.fireEvent('toggle', this, e, this.pressed);
430     },
431      /**
432      * get the current active state
433      * @return {boolean} true if it's active
434      */
435     isActive : function()
436     {
437         return this.el.hasClass('active');
438     },
439     /**
440      * set the text of the first selected button
441      */
442     setText : function(str)
443     {
444         this.el.select('.roo-button-text',true).first().dom.innerHTML = str;
445     },
446     /**
447      * get the text of the first selected button
448      */
449     getText : function()
450     {
451         return this.el.select('.roo-button-text',true).first().dom.innerHTML;
452     },
453     
454     setWeight : function(str)
455     {
456         this.el.removeClass(Roo.bootstrap.Button.weights.map(function(w) { return 'btn-' + w; } ) );
457         this.el.removeClass(Roo.bootstrap.Button.weights.map(function(w) { return 'btn-outline-' + w; } ) );
458         this.weight = str;
459         var outline = this.outline ? 'outline-' : '';
460         if (str == 'default') {
461             this.el.addClass('btn-default btn-outline-secondary');        
462             return;
463         }
464         this.el.addClass('btn-' + outline + str);        
465     }
466     
467     
468 });
469 // fixme - this is probably generic bootstrap - should go in some kind of enum file.. - like sizes.
470
471 Roo.bootstrap.Button.weights = [
472     'default',
473     'secondary' ,
474     'primary',
475     'success',
476     'info',
477     'warning',
478     'danger',
479     'link',
480     'light',
481     'dark'              
482    
483 ];