Roo/bootstrap/CheckBox.js
[roojs1] / Roo / bootstrap / CheckBox.js
1 /*
2  * - LGPL
3  *
4  * CheckBox
5  * 
6  */
7
8 /**
9  * @class Roo.bootstrap.CheckBox
10  * @extends Roo.bootstrap.Input
11  * Bootstrap CheckBox class
12  * 
13  * @cfg {String} valueOff The value that should go into the generated input element's value when unchecked.
14  * @cfg {String} inputValue The value that should go into the generated input element's value when checked.
15  * @cfg {String} boxLabel The text that appears beside the checkbox
16  * @cfg {String} weight (primary|warning|info|danger|success) The text that appears beside the checkbox
17  * @cfg {Boolean} checked initnal the element
18  * @cfg {Boolean} inline inline the element (default false)
19  * @cfg {String} groupId the checkbox group id // normal just use for checkbox
20  * @cfg {String} tooltip label tooltip
21  * 
22  * @constructor
23  * Create a new CheckBox
24  * @param {Object} config The config object
25  */
26
27 Roo.bootstrap.CheckBox = function(config){
28     Roo.bootstrap.CheckBox.superclass.constructor.call(this, config);
29    
30     this.addEvents({
31         /**
32         * @event check
33         * Fires when the element is checked or unchecked.
34         * @param {Roo.bootstrap.CheckBox} this This input
35         * @param {Boolean} checked The new checked value
36         */
37        check : true
38     });
39     
40 };
41
42 Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
43   
44     inputType: 'checkbox',
45     inputValue: 1,
46     valueOff: 0,
47     boxLabel: false,
48     checked: false,
49     weight : false,
50     inline: false,
51     tooltip : '',
52     
53     getAutoCreate : function()
54     {
55         var align = (!this.labelAlign) ? this.parentLabelAlign() : this.labelAlign;
56         
57         var id = Roo.id();
58         
59         var cfg = {};
60         
61         cfg.cls = 'form-group ' + this.inputType; //input-group
62         
63         if(this.inline){
64             cfg.cls += ' ' + this.inputType + '-inline';
65         }
66         
67         var input =  {
68             tag: 'input',
69             id : id,
70             type : this.inputType,
71             value : this.inputValue,
72             cls : 'roo-' + this.inputType, //'form-box',
73             placeholder : this.placeholder || ''
74             
75         };
76         
77         if(this.inputType != 'radio'){
78             var hidden =  {
79                 tag: 'input',
80                 type : 'hidden',
81                 cls : 'roo-hidden-value',
82                 value : this.checked ? this.valueOff : this.inputValue
83             };
84         }
85         
86             
87         if (this.weight) { // Validity check?
88             cfg.cls += " " + this.inputType + "-" + this.weight;
89         }
90         
91         if (this.disabled) {
92             input.disabled=true;
93         }
94         
95         if(this.checked){
96             input.checked = this.checked;
97         }
98         
99         if (this.name) {
100             
101             input.name = this.name;
102             
103             if(this.inputType != 'radio'){
104                 hidden.name = this.name;
105                 input.name = '_hidden_' + this.name;
106             }
107         }
108         
109         if (this.size) {
110             input.cls += ' input-' + this.size;
111         }
112         
113         var settings=this;
114         
115         ['xs','sm','md','lg'].map(function(size){
116             if (settings[size]) {
117                 cfg.cls += ' col-' + size + '-' + settings[size];
118             }
119         });
120         
121         var inputblock = input;
122          
123         if (this.before || this.after) {
124             
125             inputblock = {
126                 cls : 'input-group',
127                 cn :  [] 
128             };
129             
130             if (this.before) {
131                 inputblock.cn.push({
132                     tag :'span',
133                     cls : 'input-group-addon',
134                     html : this.before
135                 });
136             }
137             
138             inputblock.cn.push(input);
139             
140             if(this.inputType != 'radio'){
141                 inputblock.cn.push(hidden);
142             }
143             
144             if (this.after) {
145                 inputblock.cn.push({
146                     tag :'span',
147                     cls : 'input-group-addon',
148                     html : this.after
149                 });
150             }
151             
152         }
153         
154         if (align ==='left' && this.fieldLabel.length) {
155 //                Roo.log("left and has label");
156             cfg.cn = [
157                 {
158                     tag: 'label',
159                     'for' :  id,
160                     cls : 'control-label',
161                     html : this.fieldLabel
162                 },
163                 {
164                     cls : "", 
165                     cn: [
166                         inputblock
167                     ]
168                 }
169             ];
170             
171             if(this.labelWidth > 12){
172                 cfg.cn[0].style = "width: " + this.labelWidth + 'px';
173             }
174             
175             if(this.labelWidth < 13 && this.labelmd == 0){
176                 this.labelmd = this.labelWidth;
177             }
178             
179             if(this.labellg > 0){
180                 cfg.cn[0].cls += ' col-lg-' + this.labellg;
181                 cfg.cn[1].cls += ' col-lg-' + (12 - this.labellg);
182             }
183             
184             if(this.labelmd > 0){
185                 cfg.cn[0].cls += ' col-md-' + this.labelmd;
186                 cfg.cn[1].cls += ' col-md-' + (12 - this.labelmd);
187             }
188             
189             if(this.labelsm > 0){
190                 cfg.cn[0].cls += ' col-sm-' + this.labelsm;
191                 cfg.cn[1].cls += ' col-sm-' + (12 - this.labelsm);
192             }
193             
194             if(this.labelxs > 0){
195                 cfg.cn[0].cls += ' col-xs-' + this.labelxs;
196                 cfg.cn[1].cls += ' col-xs-' + (12 - this.labelxs);
197             }
198             
199         } else if ( this.fieldLabel.length) {
200 //                Roo.log(" label");
201                 cfg.cn = [
202                    
203                     {
204                         tag: this.boxLabel ? 'span' : 'label',
205                         'for': id,
206                         cls: 'control-label box-input-label',
207                         //cls : 'input-group-addon',
208                         html : this.fieldLabel
209                     },
210                     
211                     inputblock
212                     
213                 ];
214
215         } else {
216             
217 //                Roo.log(" no label && no align");
218                 cfg.cn = [  inputblock ] ;
219                 
220                 
221         }
222         
223         if(this.boxLabel){
224              var boxLabelCfg = {
225                 tag: 'label',
226                 //'for': id, // box label is handled by onclick - so no for...
227                 cls: 'box-label',
228                 html: this.boxLabel
229             };
230             
231             if(this.tooltip){
232                 boxLabelCfg.tooltip = this.tooltip;
233             }
234              
235             cfg.cn.push(boxLabelCfg);
236         }
237         
238         if(this.inputType != 'radio'){
239             cfg.cn.push(hidden);
240         }
241         
242         return cfg;
243         
244     },
245     
246     /**
247      * return the real input element.
248      */
249     inputEl: function ()
250     {
251         return this.el.select('input.roo-' + this.inputType,true).first();
252     },
253     hiddenEl: function ()
254     {
255         return this.el.select('input.roo-hidden-value',true).first();
256     },
257     
258     labelEl: function()
259     {
260         return this.el.select('label.control-label',true).first();
261     },
262     /* depricated... */
263     
264     label: function()
265     {
266         return this.labelEl();
267     },
268     
269     boxLabelEl: function()
270     {
271         return this.el.select('label.box-label',true).first();
272     },
273     
274     initEvents : function()
275     {
276 //        Roo.bootstrap.CheckBox.superclass.initEvents.call(this);
277         
278         this.inputEl().on('click', this.onClick,  this);
279         
280         if (this.boxLabel) { 
281             this.el.select('label.box-label',true).first().on('click', this.onClick,  this);
282         }
283         
284         this.startValue = this.getValue();
285         
286         if(this.groupId){
287             Roo.bootstrap.CheckBox.register(this);
288         }
289     },
290     
291     onClick : function()
292     {   
293         this.setChecked(!this.checked);
294     },
295     
296     setChecked : function(state,suppressEvent)
297     {
298         this.startValue = this.getValue();
299
300         if(this.inputType == 'radio'){
301             
302             Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
303                 e.dom.checked = false;
304             });
305             
306             this.inputEl().dom.checked = true;
307             
308             this.inputEl().dom.value = this.inputValue;
309             
310             if(suppressEvent !== true){
311                 this.fireEvent('check', this, true);
312             }
313             
314             this.validate();
315             
316             return;
317         }
318         
319         this.checked = state;
320         
321         this.inputEl().dom.checked = state;
322         
323         
324         this.hiddenEl().dom.value = state ? this.inputValue : this.valueOff;
325         
326         if(suppressEvent !== true){
327             this.fireEvent('check', this, state);
328         }
329         
330         this.validate();
331     },
332     
333     getValue : function()
334     {
335         if(this.inputType == 'radio'){
336             return this.getGroupValue();
337         }
338         
339         return this.hiddenEl().dom.value;
340         
341     },
342     
343     getGroupValue : function()
344     {
345         if(typeof(this.el.up('form').child('input[name='+this.name+']:checked', true)) == 'undefined'){
346             return '';
347         }
348         
349         return this.el.up('form').child('input[name='+this.name+']:checked', true).value;
350     },
351     
352     setValue : function(v,suppressEvent)
353     {
354         if(this.inputType == 'radio'){
355             this.setGroupValue(v, suppressEvent);
356             return;
357         }
358         
359         this.setChecked(((typeof(v) == 'undefined') ? this.checked : (String(v) === String(this.inputValue))), suppressEvent);
360         
361         this.validate();
362     },
363     
364     setGroupValue : function(v, suppressEvent)
365     {
366         this.startValue = this.getValue();
367         
368         Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
369             e.dom.checked = false;
370             
371             if(e.dom.value == v){
372                 e.dom.checked = true;
373             }
374         });
375         
376         if(suppressEvent !== true){
377             this.fireEvent('check', this, true);
378         }
379
380         this.validate();
381         
382         return;
383     },
384     
385     validate : function()
386     {
387         if(
388                 this.disabled || 
389                 (this.inputType == 'radio' && this.validateRadio()) ||
390                 (this.inputType == 'checkbox' && this.validateCheckbox())
391         ){
392             this.markValid();
393             return true;
394         }
395         
396         this.markInvalid();
397         return false;
398     },
399     
400     validateRadio : function()
401     {
402         if(this.allowBlank){
403             return true;
404         }
405         
406         var valid = false;
407         
408         Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
409             if(!e.dom.checked){
410                 return;
411             }
412             
413             valid = true;
414             
415             return false;
416         });
417         
418         return valid;
419     },
420     
421     validateCheckbox : function()
422     {
423         if(!this.groupId){
424             return (this.getValue() == this.inputValue || this.allowBlank) ? true : false;
425             //return (this.getValue() == this.inputValue) ? true : false;
426         }
427         
428         var group = Roo.bootstrap.CheckBox.get(this.groupId);
429         
430         if(!group){
431             return false;
432         }
433         
434         var r = false;
435         
436         for(var i in group){
437             if(r){
438                 break;
439             }
440             
441             r = (group[i].getValue() == group[i].inputValue) ? true : false;
442         }
443         
444         return r;
445     },
446     
447     /**
448      * Mark this field as valid
449      */
450     markValid : function()
451     {
452         var _this = this;
453         
454         this.fireEvent('valid', this);
455         
456         var label = Roo.bootstrap.FieldLabel.get(this.name + '-group');
457         
458         if(this.groupId){
459             label = Roo.bootstrap.FieldLabel.get(this.groupId + '-group');
460         }
461         
462         if(label){
463             label.markValid();
464         }
465
466         if(this.inputType == 'radio'){
467             Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
468                 e.findParent('.form-group', false, true).removeClass([_this.invalidClass, _this.validClass]);
469                 e.findParent('.form-group', false, true).addClass(_this.validClass);
470             });
471             
472             return;
473         }
474
475         if(!this.groupId){
476             this.el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
477             this.el.findParent('.form-group', false, true).addClass(this.validClass);
478             return;
479         }
480         
481         var group = Roo.bootstrap.CheckBox.get(this.groupId);
482         
483         if(!group){
484             return;
485         }
486         
487         for(var i in group){
488             group[i].el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
489             group[i].el.findParent('.form-group', false, true).addClass(this.validClass);
490         }
491     },
492     
493      /**
494      * Mark this field as invalid
495      * @param {String} msg The validation message
496      */
497     markInvalid : function(msg)
498     {
499         if(this.allowBlank){
500             return;
501         }
502         
503         var _this = this;
504         
505         this.fireEvent('invalid', this, msg);
506         
507         var label = Roo.bootstrap.FieldLabel.get(this.name + '-group');
508         
509         if(this.groupId){
510             label = Roo.bootstrap.FieldLabel.get(this.groupId + '-group');
511         }
512         
513         if(label){
514             label.markInvalid();
515         }
516             
517         if(this.inputType == 'radio'){
518             Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
519                 e.findParent('.form-group', false, true).removeClass([_this.invalidClass, _this.validClass]);
520                 e.findParent('.form-group', false, true).addClass(_this.invalidClass);
521             });
522             
523             return;
524         }
525         
526         if(!this.groupId){
527             this.el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
528             this.el.findParent('.form-group', false, true).addClass(this.invalidClass);
529             return;
530         }
531         
532         var group = Roo.bootstrap.CheckBox.get(this.groupId);
533         
534         if(!group){
535             return;
536         }
537         
538         for(var i in group){
539             group[i].el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
540             group[i].el.findParent('.form-group', false, true).addClass(this.invalidClass);
541         }
542         
543     },
544     
545     clearInvalid : function()
546     {
547         Roo.bootstrap.Input.prototype.clearInvalid.call(this);
548         
549         // this.el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
550         
551         var label = Roo.bootstrap.FieldLabel.get(this.name + '-group');
552         
553         if (label) {
554             label.iconEl.removeClass(label.validClass);
555             label.iconEl.removeClass(label.invalidClass);
556         }
557     },
558     
559     disable : function()
560     {
561         if(this.inputType != 'radio'){
562             Roo.bootstrap.CheckBox.superclass.disable.call(this);
563             return;
564         }
565         
566         var _this = this;
567         
568         if(this.rendered){
569             Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
570                 _this.getActionEl().addClass(this.disabledClass);
571                 e.dom.disabled = true;
572             });
573         }
574         
575         this.disabled = true;
576         this.fireEvent("disable", this);
577         return this;
578     },
579
580     enable : function()
581     {
582         if(this.inputType != 'radio'){
583             Roo.bootstrap.CheckBox.superclass.enable.call(this);
584             return;
585         }
586         
587         var _this = this;
588         
589         if(this.rendered){
590             Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
591                 _this.getActionEl().removeClass(this.disabledClass);
592                 e.dom.disabled = false;
593             });
594         }
595         
596         this.disabled = false;
597         this.fireEvent("enable", this);
598         return this;
599     }
600
601 });
602
603 Roo.apply(Roo.bootstrap.CheckBox, {
604     
605     groups: {},
606     
607      /**
608     * register a CheckBox Group
609     * @param {Roo.bootstrap.CheckBox} the CheckBox to add
610     */
611     register : function(checkbox)
612     {
613         if(typeof(this.groups[checkbox.groupId]) == 'undefined'){
614             this.groups[checkbox.groupId] = {};
615         }
616         
617         if(this.groups[checkbox.groupId].hasOwnProperty(checkbox.name)){
618             return;
619         }
620         
621         this.groups[checkbox.groupId][checkbox.name] = checkbox;
622         
623     },
624     /**
625     * fetch a CheckBox Group based on the group ID
626     * @param {string} the group ID
627     * @returns {Roo.bootstrap.CheckBox} the CheckBox group
628     */
629     get: function(groupId) {
630         if (typeof(this.groups[groupId]) == 'undefined') {
631             return false;
632         }
633         
634         return this.groups[groupId] ;
635     }
636     
637     
638 });