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