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