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