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