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