Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / form / field / Checkbox.js
index 2f8611b..68ad1af 100644 (file)
+/*
+
+This file is part of Ext JS 4
+
+Copyright (c) 2011 Sencha Inc
+
+Contact:  http://www.sencha.com/contact
+
+GNU General Public License Usage
+This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
+
+If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
+
+*/
 /**
- * @class Ext.form.field.Checkbox
- * @extends Ext.form.field.Base
-
-Single checkbox field. Can be used as a direct replacement for traditional checkbox fields. Also serves as a
-parent class for {@link Ext.form.field.Radio radio buttons}.
-
-__Labeling:__ In addition to the {@link Ext.form.Labelable standard field labeling options}, checkboxes
-may be given an optional {@link #boxLabel} which will be displayed immediately after checkbox. Also see
-{@link Ext.form.CheckboxGroup} for a convenient method of grouping related checkboxes.
-
-__Values:__
-The main value of a checkbox is a boolean, indicating whether or not the checkbox is checked.
-The following values will check the checkbox:
-* `true`
-* `'true'`
-* `'1'`
-* `'on'`
-
-Any other value will uncheck the checkbox.
-
-In addition to the main boolean value, you may also specify a separate {@link #inputValue}. This will be
-sent as the parameter value when the form is {@link Ext.form.Basic#submit submitted}. You will want to set
-this value if you have multiple checkboxes with the same {@link #name}. If not specified, the value `on`
-will be used.
-{@img Ext.form.Checkbox/Ext.form.Checkbox.png Ext.form.Checkbox Checkbox component}
-__Example usage:__
-
-    Ext.create('Ext.form.Panel', {
-        bodyPadding: 10,
-        width      : 300,
-        title      : 'Pizza Order',
-        items: [
-            {
-                xtype      : 'fieldcontainer',
-                fieldLabel : 'Toppings',
-                defaultType: 'checkboxfield',
-                items: [
-                    {
-                        boxLabel  : 'Anchovies',
-                        name      : 'topping',
-                        inputValue: '1',
-                        id        : 'checkbox1'
-                    }, {
-                        boxLabel  : 'Artichoke Hearts',
-                        name      : 'topping',
-                        inputValue: '2',
-                        checked   : true,
-                        id        : 'checkbox2'
-                    }, {
-                        boxLabel  : 'Bacon',
-                        name      : 'topping',
-                        inputValue: '3',
-                        id        : 'checkbox3'
-                    }
-                ]
-            }
-        ],
-        bbar: [
-            {
-                text: 'Select Bacon',
-                handler: function() {
-                    var checkbox = Ext.getCmp('checkbox3');
-                    checkbox.setValue(true);
-                }
-            },
-            '-',
-            {
-                text: 'Select All',
-                handler: function() {
-                    var checkbox1 = Ext.getCmp('checkbox1'),
-                        checkbox2 = Ext.getCmp('checkbox2'),
-                        checkbox3 = Ext.getCmp('checkbox3');
-    
-                    checkbox1.setValue(true);
-                    checkbox2.setValue(true);
-                    checkbox3.setValue(true);
-                }
-            },
-            {
-                text: 'Deselect All',
-                handler: function() {
-                    var checkbox1 = Ext.getCmp('checkbox1'),
-                        checkbox2 = Ext.getCmp('checkbox2'),
-                        checkbox3 = Ext.getCmp('checkbox3');
-    
-                    checkbox1.setValue(false);
-                    checkbox2.setValue(false);
-                    checkbox3.setValue(false);
-                }
-            }
-        ],
-        renderTo: Ext.getBody()
-    });
-
- * @constructor
- * Creates a new Checkbox
- * @param {Object} config Configuration options
- * @xtype checkboxfield
  * @docauthor Robert Dougan <rob@sencha.com>
- * @markdown
+ *
+ * Single checkbox field. Can be used as a direct replacement for traditional checkbox fields. Also serves as a
+ * parent class for {@link Ext.form.field.Radio radio buttons}.
+ *
+ * # Labeling
+ *
+ * In addition to the {@link Ext.form.Labelable standard field labeling options}, checkboxes
+ * may be given an optional {@link #boxLabel} which will be displayed immediately after checkbox. Also see
+ * {@link Ext.form.CheckboxGroup} for a convenient method of grouping related checkboxes.
+ *
+ * # Values
+ *
+ * The main value of a checkbox is a boolean, indicating whether or not the checkbox is checked.
+ * The following values will check the checkbox:
+ *
+ * - `true`
+ * - `'true'`
+ * - `'1'`
+ * - `'on'`
+ *
+ * Any other value will uncheck the checkbox.
+ *
+ * In addition to the main boolean value, you may also specify a separate {@link #inputValue}. This will be
+ * sent as the parameter value when the form is {@link Ext.form.Basic#submit submitted}. You will want to set
+ * this value if you have multiple checkboxes with the same {@link #name}. If not specified, the value `on`
+ * will be used.
+ *
+ * # Example usage
+ *
+ *     @example
+ *     Ext.create('Ext.form.Panel', {
+ *         bodyPadding: 10,
+ *         width: 300,
+ *         title: 'Pizza Order',
+ *         items: [
+ *             {
+ *                 xtype: 'fieldcontainer',
+ *                 fieldLabel: 'Toppings',
+ *                 defaultType: 'checkboxfield',
+ *                 items: [
+ *                     {
+ *                         boxLabel  : 'Anchovies',
+ *                         name      : 'topping',
+ *                         inputValue: '1',
+ *                         id        : 'checkbox1'
+ *                     }, {
+ *                         boxLabel  : 'Artichoke Hearts',
+ *                         name      : 'topping',
+ *                         inputValue: '2',
+ *                         checked   : true,
+ *                         id        : 'checkbox2'
+ *                     }, {
+ *                         boxLabel  : 'Bacon',
+ *                         name      : 'topping',
+ *                         inputValue: '3',
+ *                         id        : 'checkbox3'
+ *                     }
+ *                 ]
+ *             }
+ *         ],
+ *         bbar: [
+ *             {
+ *                 text: 'Select Bacon',
+ *                 handler: function() {
+ *                     Ext.getCmp('checkbox3').setValue(true);
+ *                 }
+ *             },
+ *             '-',
+ *             {
+ *                 text: 'Select All',
+ *                 handler: function() {
+ *                     Ext.getCmp('checkbox1').setValue(true);
+ *                     Ext.getCmp('checkbox2').setValue(true);
+ *                     Ext.getCmp('checkbox3').setValue(true);
+ *                 }
+ *             },
+ *             {
+ *                 text: 'Deselect All',
+ *                 handler: function() {
+ *                     Ext.getCmp('checkbox1').setValue(false);
+ *                     Ext.getCmp('checkbox2').setValue(false);
+ *                     Ext.getCmp('checkbox3').setValue(false);
+ *                 }
+ *             }
+ *         ],
+ *         renderTo: Ext.getBody()
+ *     });
  */
 Ext.define('Ext.form.field.Checkbox', {
     extend: 'Ext.form.field.Base',
@@ -106,9 +108,10 @@ Ext.define('Ext.form.field.Checkbox', {
     alternateClassName: 'Ext.form.Checkbox',
     requires: ['Ext.XTemplate', 'Ext.form.CheckboxManager'],
 
+    // note: {id} here is really {inputId}, but {cmpId} is available
     fieldSubTpl: [
         '<tpl if="boxLabel && boxLabelAlign == \'before\'">',
-            '<label class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
+            '<label id="{cmpId}-boxLabelEl" class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
         '</tpl>',
         // Creates not an actual checkbox, but a button which is given aria role="checkbox" and
         // styled with a custom checkbox image. This allows greater control and consistency in
@@ -117,7 +120,7 @@ Ext.define('Ext.form.field.Checkbox', {
             '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
             'class="{fieldCls} {typeCls}" autocomplete="off" hidefocus="true" />',
         '<tpl if="boxLabel && boxLabelAlign == \'after\'">',
-            '<label class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
+            '<label id="{cmpId}-boxLabelEl" class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
         '</tpl>',
         {
             disableFormats: true,
@@ -128,72 +131,79 @@ Ext.define('Ext.form.field.Checkbox', {
     isCheckbox: true,
 
     /**
-     * @cfg {String} focusCls The CSS class to use when the checkbox receives focus
-     * (defaults to <tt>'x-form-cb-focus'</tt>)
+     * @cfg {String} [focusCls='x-form-cb-focus']
+     * The CSS class to use when the checkbox receives focus
      */
     focusCls: Ext.baseCSSPrefix + 'form-cb-focus',
 
     /**
-     * @cfg {String} fieldCls The default CSS class for the checkbox (defaults to <tt>'x-form-field'</tt>)
+     * @cfg {String} [fieldCls='x-form-field']
+     * The default CSS class for the checkbox
      */
 
     /**
-     * @cfg {String} fieldBodyCls
+     * @cfg {String} [fieldBodyCls='x-form-cb-wrap']
      * An extra CSS class to be applied to the body content element in addition to {@link #fieldBodyCls}.
-     * Defaults to 'x-form-cb-wrap.
+     * .
      */
     fieldBodyCls: Ext.baseCSSPrefix + 'form-cb-wrap',
 
     /**
-     * @cfg {Boolean} checked <tt>true</tt> if the checkbox should render initially checked (defaults to <tt>false</tt>)
+     * @cfg {Boolean} checked
+     * true if the checkbox should render initially checked
      */
     checked: false,
 
     /**
-     * @cfg {String} checkedCls The CSS class added to the component's main element when it is in the checked state.
+     * @cfg {String} [checkedCls='x-form-cb-checked']
+     * The CSS class added to the component's main element when it is in the checked state.
      */
     checkedCls: Ext.baseCSSPrefix + 'form-cb-checked',
 
     /**
-     * @cfg {String} boxLabel An optional text label that will appear next to the checkbox. Whether it appears before
-     * or after the checkbox is determined by the {@link #boxLabelAlign} config (defaults to after).
+     * @cfg {String} boxLabel
+     * An optional text label that will appear next to the checkbox. Whether it appears before or after the checkbox is
+     * determined by the {@link #boxLabelAlign} config.
      */
 
     /**
-     * @cfg {String} boxLabelCls The CSS class to be applied to the {@link #boxLabel} element
+     * @cfg {String} [boxLabelCls='x-form-cb-label']
+     * The CSS class to be applied to the {@link #boxLabel} element
      */
     boxLabelCls: Ext.baseCSSPrefix + 'form-cb-label',
 
     /**
-     * @cfg {String} boxLabelAlign The position relative to the checkbox where the {@link #boxLabel} should
-     * appear. Recognized values are <tt>'before'</tt> and <tt>'after'</tt>. Defaults to <tt>'after'</tt>.
+     * @cfg {String} boxLabelAlign
+     * The position relative to the checkbox where the {@link #boxLabel} should appear. Recognized values are 'before'
+     * and 'after'.
      */
     boxLabelAlign: 'after',
 
     /**
-     * @cfg {String} inputValue The value that should go into the generated input element's value attribute and
-     * should be used as the parameter value when submitting as part of a form. Defaults to <tt>"on"</tt>.
+     * @cfg {String} inputValue
+     * The value that should go into the generated input element's value attribute and should be used as the parameter
+     * value when submitting as part of a form.
      */
     inputValue: 'on',
 
     /**
-     * @cfg {String} uncheckedValue If configured, this will be submitted as the checkbox's value during form
-     * submit if the checkbox is unchecked. By default this is undefined, which results in nothing being
-     * submitted for the checkbox field when the form is submitted (the default behavior of HTML checkboxes).
+     * @cfg {String} uncheckedValue
+     * If configured, this will be submitted as the checkbox's value during form submit if the checkbox is unchecked. By
+     * default this is undefined, which results in nothing being submitted for the checkbox field when the form is
+     * submitted (the default behavior of HTML checkboxes).
      */
 
     /**
-     * @cfg {Function} handler A function called when the {@link #checked} value changes (can be used instead of
-     * handling the {@link #change change event}). The handler is passed the following parameters:
-     * <div class="mdetail-params"><ul>
-     * <li><b>checkbox</b> : Ext.form.field.Checkbox<div class="sub-desc">The Checkbox being toggled.</div></li>
-     * <li><b>checked</b> : Boolean<div class="sub-desc">The new checked state of the checkbox.</div></li>
-     * </ul></div>
+     * @cfg {Function} handler
+     * A function called when the {@link #checked} value changes (can be used instead of handling the {@link #change
+     * change event}).
+     * @cfg {Ext.form.field.Checkbox} handler.checkbox The Checkbox being toggled.
+     * @cfg {Boolean} handler.checked The new checked state of the checkbox.
      */
 
     /**
-     * @cfg {Object} scope An object to use as the scope ('this' reference) of the {@link #handler} function
-     * (defaults to this Checkbox).
+     * @cfg {Object} scope
+     * An object to use as the scope ('this' reference) of the {@link #handler} function (defaults to this Checkbox).
      */
 
     // private overrides
@@ -214,11 +224,9 @@ Ext.define('Ext.form.field.Checkbox', {
             checked = !!me.checked;
 
         /**
-         * The original value of the field as configured in the {@link #checked} configuration, or
-         * as loaded by the last form load operation if the form's {@link Ext.form.Basic#trackResetOnLoad trackResetOnLoad}
-         * setting is <code>true</code>.
-         * @type Mixed
-         * @property originalValue
+         * @property {Object} originalValue
+         * The original value of the field as configured in the {@link #checked} configuration, or as loaded by the last
+         * form load operation if the form's {@link Ext.form.Basic#trackResetOnLoad trackResetOnLoad} setting is `true`.
          */
         me.originalValue = me.lastValue = checked;
 
@@ -229,15 +237,14 @@ Ext.define('Ext.form.field.Checkbox', {
     // private
     onRender : function(ct, position) {
         var me = this;
-        Ext.applyIf(me.renderSelectors, {
-            /**
-             * @property boxLabelEl
-             * @type Ext.core.Element
-             * A reference to the label element created for the {@link #boxLabel}. Only present if the
-             * component has been rendered and has a boxLabel configured.
-             */
-            boxLabelEl: 'label.' + me.boxLabelCls
-        });
+
+        /**
+         * @property {Ext.Element} boxLabelEl
+         * A reference to the label element created for the {@link #boxLabel}. Only present if the component has been
+         * rendered and has a boxLabel configured.
+         */
+        me.addChildEls('boxLabelEl');
+
         Ext.applyIf(me.subTplData, {
             boxLabel: me.boxLabel,
             boxLabelCls: me.boxLabelCls,
@@ -281,20 +288,19 @@ Ext.define('Ext.form.field.Checkbox', {
 
     /**
      * Returns the submit value for the checkbox which can be used when submitting forms.
-     * @return {Boolean/null} True if checked; otherwise either the {@link #uncheckedValue} or null.
+     * @return {Boolean/Object} True if checked; otherwise either the {@link #uncheckedValue} or null.
      */
     getSubmitValue: function() {
-        return this.checked ? this.inputValue : (this.uncheckedValue || null);
-    },
-
-    getModelData: function() {
-        return this.getSubmitData();
+        var unchecked = this.uncheckedValue,
+            uncheckedVal = Ext.isDefined(unchecked) ? unchecked : null;
+        return this.checked ? this.inputValue : uncheckedVal;
     },
 
     /**
      * Sets the checked state of the checkbox.
-     * @param {Boolean/String} value The following values will check the checkbox:
-     * <code>true, 'true', '1', or 'on'</code>, as well as a String that matches the {@link #inputValue}.
+     *
+     * @param {Boolean/String/Number} value The following values will check the checkbox:
+     * `true, 'true', '1', 1, or 'on'`, as well as a String that matches the {@link #inputValue}.
      * Any other value will uncheck the checkbox.
      * @return {Boolean} the new checked state of the checkbox
      */
@@ -302,8 +308,8 @@ Ext.define('Ext.form.field.Checkbox', {
         var me = this,
             inputEl = me.inputEl,
             inputValue = me.inputValue,
-            checked = (value === true || value === 'true' || value === '1' ||
-                      ((Ext.isString(value) && inputValue) ? value == inputValue : me.onRe.test(value)));
+            checked = (value === true || value === 'true' || value === '1' || value === 1 ||
+                (((Ext.isString(value) || Ext.isNumber(value)) && inputValue) ? value == inputValue : me.onRe.test(value)));
 
         if (inputEl) {
             inputEl.dom.setAttribute('aria-checked', checked);
@@ -316,9 +322,8 @@ Ext.define('Ext.form.field.Checkbox', {
 
     /**
      * Sets the checked state of the checkbox, and invokes change detection.
-     * @param {Boolean/String} checked The following values will check the checkbox:
-     * <code>true, 'true', '1', or 'on'</code>, as well as a String that matches the {@link #inputValue}.
-     * Any other value will uncheck the checkbox.
+     * @param {Boolean/String} checked The following values will check the checkbox: `true, 'true', '1', or 'on'`, as
+     * well as a String that matches the {@link #inputValue}. Any other value will uncheck the checkbox.
      * @return {Ext.form.field.Checkbox} this
      */
     setValue: function(checked) {
@@ -359,6 +364,12 @@ Ext.define('Ext.form.field.Checkbox', {
         me.callParent(arguments);
     },
 
+    // inherit docs
+    beforeDestroy: function(){
+        this.callParent();
+        this.getManager().removeAtKey(this.id);
+    },
+
     // inherit docs
     getManager: function() {
         return Ext.form.CheckboxManager;
@@ -384,11 +395,8 @@ Ext.define('Ext.form.field.Checkbox', {
         me.readOnly = readOnly;
     },
 
-    /**
-     * @protected Calculate and return the natural width of the bodyEl. It's possible that the initial
-     * rendering will cause the boxLabel to wrap and give us a bad width, so we must prevent wrapping
-     * while measuring.
-     */
+    // Calculates and returns the natural width of the bodyEl. It's possible that the initial rendering will
+    // cause the boxLabel to wrap and give us a bad width, so we must prevent wrapping while measuring.
     getBodyNaturalWidth: function() {
         var me = this,
             bodyEl = me.bodyEl,
@@ -401,3 +409,4 @@ Ext.define('Ext.form.field.Checkbox', {
     }
 
 });
+