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