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