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.inputType == 'radio' ? this.inputValue : ((!this.checked) ? this.valueOff : this.inputValue),
70             cls : 'roo-' + this.inputType, //'form-box',
71             placeholder : this.placeholder || ''
72             
73         };
74         
75         if (this.weight) { // Validity check?
76             cfg.cls += " " + this.inputType + "-" + this.weight;
77         }
78         
79         if (this.disabled) {
80             input.disabled=true;
81         }
82         
83         if(this.checked){
84             input.checked = this.checked;
85         }
86         
87         if (this.name) {
88             input.name = this.name;
89         }
90         
91         if (this.size) {
92             input.cls += ' input-' + this.size;
93         }
94         
95         var settings=this;
96         
97         ['xs','sm','md','lg'].map(function(size){
98             if (settings[size]) {
99                 cfg.cls += ' col-' + size + '-' + settings[size];
100             }
101         });
102         
103         var inputblock = input;
104          
105         if (this.before || this.after) {
106             
107             inputblock = {
108                 cls : 'input-group',
109                 cn :  [] 
110             };
111             
112             if (this.before) {
113                 inputblock.cn.push({
114                     tag :'span',
115                     cls : 'input-group-addon',
116                     html : this.before
117                 });
118             }
119             
120             inputblock.cn.push(input);
121             
122             if (this.after) {
123                 inputblock.cn.push({
124                     tag :'span',
125                     cls : 'input-group-addon',
126                     html : this.after
127                 });
128             }
129             
130         }
131         
132         if (align ==='left' && this.fieldLabel.length) {
133                 Roo.log("left and has label");
134                 cfg.cn = [
135                     
136                     {
137                         tag: 'label',
138                         'for' :  id,
139                         cls : 'control-label col-md-' + this.labelWidth,
140                         html : this.fieldLabel
141                         
142                     },
143                     {
144                         cls : "col-md-" + (12 - this.labelWidth), 
145                         cn: [
146                             inputblock
147                         ]
148                     }
149                     
150                 ];
151         } else if ( this.fieldLabel.length) {
152                 Roo.log(" label");
153                 cfg.cn = [
154                    
155                     {
156                         tag: this.boxLabel ? 'span' : 'label',
157                         'for': id,
158                         cls: 'control-label box-input-label',
159                         //cls : 'input-group-addon',
160                         html : this.fieldLabel
161                         
162                     },
163                     
164                     inputblock
165                     
166                 ];
167
168         } else {
169             
170                 Roo.log(" no label && no align");
171                 cfg.cn = [  inputblock ] ;
172                 
173                 
174         }
175         if(this.boxLabel){
176              var boxLabelCfg = {
177                 tag: 'label',
178                 //'for': id, // box label is handled by onclick - so no for...
179                 cls: 'box-label',
180                 html: this.boxLabel
181             };
182             
183             if(this.tooltip){
184                 boxLabelCfg.tooltip = this.tooltip;
185             }
186              
187             cfg.cn.push(boxLabelCfg);
188         }
189         
190         
191        
192         return cfg;
193         
194     },
195     
196     /**
197      * return the real input element.
198      */
199     inputEl: function ()
200     {
201         return this.el.select('input.roo-' + this.inputType,true).first();
202     },
203     
204     labelEl: function()
205     {
206         return this.el.select('label.control-label',true).first();
207     },
208     /* depricated... */
209     
210     label: function()
211     {
212         return this.labelEl();
213     },
214     
215     initEvents : function()
216     {
217 //        Roo.bootstrap.CheckBox.superclass.initEvents.call(this);
218         
219         this.inputEl().on('click', this.onClick,  this);
220         
221         if (this.boxLabel) { 
222             this.el.select('label.box-label',true).first().on('click', this.onClick,  this);
223         }
224         
225         this.startValue = this.getValue();
226         
227         if(this.groupId){
228             Roo.bootstrap.CheckBox.register(this);
229         }
230     },
231     
232     onClick : function()
233     {   
234         this.setChecked(!this.checked);
235     },
236     
237     setChecked : function(state,suppressEvent)
238     {
239         this.startValue = this.getValue();
240         
241         if(this.inputType == 'radio'){
242             
243             Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
244                 e.dom.checked = false;
245             });
246             
247             this.inputEl().dom.checked = true;
248             
249             this.inputEl().dom.value = this.inputValue;
250             
251             if(suppressEvent !== true){
252                 this.fireEvent('check', this, true);
253             }
254             
255             this.validate();
256             
257             return;
258         }
259         
260         this.checked = state;
261         
262         this.inputEl().dom.checked = state;
263         
264         this.inputEl().dom.value = state ? this.inputValue : this.valueOff;
265         
266         if(suppressEvent !== true){
267             this.fireEvent('check', this, state);
268         }
269         
270         this.validate();
271     },
272     
273     getValue : function()
274     {
275         if(this.inputType == 'radio'){
276             return this.getGroupValue();
277         }
278         
279         return this.inputEl().getValue();
280         
281     },
282     
283     getGroupValue : function()
284     {
285         if(typeof(this.el.up('form').child('input[name='+this.name+']:checked', true)) == 'undefined'){
286             return '';
287         }
288         
289         return this.el.up('form').child('input[name='+this.name+']:checked', true).value;
290     },
291     
292     setValue : function(v,suppressEvent)
293     {
294         if(this.inputType == 'radio'){
295             this.setGroupValue(v, suppressEvent);
296             return;
297         }
298         
299         this.setChecked(((typeof(v) == 'undefined') ? this.checked : (String(v) === String(this.inputValue))), suppressEvent);
300         
301         this.validate();
302     },
303     
304     setGroupValue : function(v, suppressEvent)
305     {
306         this.startValue = this.getValue();
307         
308         Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
309             e.dom.checked = false;
310             
311             if(e.dom.value == v){
312                 e.dom.checked = true;
313             }
314         });
315         
316         if(suppressEvent !== true){
317             this.fireEvent('check', this, true);
318         }
319
320         this.validate();
321         
322         return;
323     },
324     
325     validate : function()
326     {
327         if(
328                 this.disabled || 
329                 (this.inputType == 'radio' && this.validateRadio()) ||
330                 (this.inputType == 'checkbox' && this.validateCheckbox())
331         ){
332             this.markValid();
333             return true;
334         }
335         
336         this.markInvalid();
337         return false;
338     },
339     
340     validateRadio : function()
341     {
342         var valid = false;
343         
344         Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
345             if(!e.dom.checked){
346                 return;
347             }
348             
349             valid = true;
350             
351             return false;
352         });
353         
354         return valid;
355     },
356     
357     validateCheckbox : function()
358     {
359         if(!this.groupId){
360             return (this.getValue() == this.inputValue || this.allowBlank) ? true : false;
361         }
362         
363         var group = Roo.bootstrap.CheckBox.get(this.groupId);
364         
365         if(!group){
366             return false;
367         }
368         
369         var r = false;
370         
371         for(var i in group){
372             if(r){
373                 break;
374             }
375             
376             r = (group[i].getValue() == group[i].inputValue) ? true : false;
377         }
378         
379         return r;
380     },
381     
382     /**
383      * Mark this field as valid
384      */
385     markValid : function()
386     {
387         if(this.allowBlank){
388             return;
389         }
390         
391         var _this = this;
392         
393         this.fireEvent('valid', this);
394         
395         var label = Roo.bootstrap.FieldLabel.get(this.name + '-group');
396         
397         if(label){
398             Roo.log('label mark valid???');
399             Roo.log(label);
400 //            label.markInvalid();
401         }
402         
403         if(this.inputType == 'radio'){
404             Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
405                 e.findParent('.form-group', false, true).removeClass([_this.invalidClass, _this.validClass]);
406                 e.findParent('.form-group', false, true).addClass(_this.validClass);
407             });
408             
409             return;
410         }
411         
412         if(!this.groupId){
413             this.el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
414             this.el.findParent('.form-group', false, true).addClass(this.validClass);
415             return;
416         }
417         
418         var group = Roo.bootstrap.CheckBox.get(this.groupId);
419             
420         if(!group){
421             return;
422         }
423         
424         for(var i in group){
425             group[i].el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
426             group[i].el.findParent('.form-group', false, true).addClass(this.validClass);
427         }
428     },
429     
430      /**
431      * Mark this field as invalid
432      * @param {String} msg The validation message
433      */
434     markInvalid : function(msg)
435     {
436         if(this.allowBlank){
437             return;
438         }
439         
440         var _this = this;
441         
442         this.fireEvent('invalid', this, msg);
443         
444         var label = Roo.bootstrap.FieldLabel.get(this.name + '-group');
445         
446         if(label){
447             Roo.log('label mark invalid???');
448             label.markInvalid();
449         }
450         
451         if(this.inputType == 'radio'){
452             Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
453                 e.findParent('.form-group', false, true).removeClass([_this.invalidClass, _this.validClass]);
454                 e.findParent('.form-group', false, true).addClass(_this.invalidClass);
455             });
456             
457             return;
458         }
459         
460         if(!this.groupId){
461             this.el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
462             this.el.findParent('.form-group', false, true).addClass(this.invalidClass);
463             return;
464         }
465         
466         var group = Roo.bootstrap.CheckBox.get(this.groupId);
467             
468         if(!group){
469             return;
470         }
471         
472         for(var i in group){
473             group[i].el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
474             group[i].el.findParent('.form-group', false, true).addClass(this.invalidClass);
475         }
476         
477     }
478     
479 });
480
481 Roo.apply(Roo.bootstrap.CheckBox, {
482     
483     groups: {},
484     
485      /**
486     * register a CheckBox Group
487     * @param {Roo.bootstrap.CheckBox} the CheckBox to add
488     */
489     register : function(checkbox)
490     {
491         if(typeof(this.groups[checkbox.groupId]) == 'undefined'){
492             this.groups[checkbox.groupId] = {};
493         }
494         
495         if(this.groups[checkbox.groupId].hasOwnProperty(checkbox.name)){
496             return;
497         }
498         
499         this.groups[checkbox.groupId][checkbox.name] = checkbox;
500         
501     },
502     /**
503     * fetch a CheckBox Group based on the group ID
504     * @param {string} the group ID
505     * @returns {Roo.bootstrap.CheckBox} the CheckBox group
506     */
507     get: function(groupId) {
508         if (typeof(this.groups[groupId]) == 'undefined') {
509             return false;
510         }
511         
512         return this.groups[groupId] ;
513     }
514     
515     
516 });