Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / form / Labelable.js
index a892395..54ddc4b 100644 (file)
@@ -1,45 +1,57 @@
-/**
- * @class Ext.form.Labelable
+/*
+
+This file is part of Ext JS 4
 
-A mixin which allows a component to be configured and decorated with a label and/or error message as is
-common for form fields. This is used by e.g. {@link Ext.form.field.Base} and {@link Ext.form.FieldContainer}
-to let them be managed by the Field layout.
+Copyright (c) 2011 Sencha Inc
 
-**NOTE**: This mixin is mainly for internal library use and most users should not need to use it directly. It
-is more likely you will want to use one of the component classes that import this mixin, such as
-{@link Ext.form.field.Base} or {@link Ext.form.FieldContainer}.
+Contact:  http://www.sencha.com/contact
 
-Use of this mixin does not make a component a field in the logical sense, meaning it does not provide any
-logic or state related to values or validation; that is handled by the related {@link Ext.form.field.Field}
-mixin. These two mixins may be used separately (for example {@link Ext.form.FieldContainer} is Labelable but not a
-Field), or in combination (for example {@link Ext.form.field.Base} implements both and has logic for connecting the
-two.)
+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.
 
-Component classes which use this mixin should use the Field layout
-or a derivation thereof to properly size and position the label and message according to the component config.
-They must also call the {@link #initLabelable} method during component initialization to ensure the mixin gets
-set up correctly.
+If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
 
- * @markdown
+*/
+/**
+ * A mixin which allows a component to be configured and decorated with a label and/or error message as is
+ * common for form fields. This is used by e.g. Ext.form.field.Base and Ext.form.FieldContainer
+ * to let them be managed by the Field layout.
+ *
+ * NOTE: This mixin is mainly for internal library use and most users should not need to use it directly. It
+ * is more likely you will want to use one of the component classes that import this mixin, such as
+ * Ext.form.field.Base or Ext.form.FieldContainer.
+ *
+ * Use of this mixin does not make a component a field in the logical sense, meaning it does not provide any
+ * logic or state related to values or validation; that is handled by the related Ext.form.field.Field
+ * mixin. These two mixins may be used separately (for example Ext.form.FieldContainer is Labelable but not a
+ * Field), or in combination (for example Ext.form.field.Base implements both and has logic for connecting the
+ * two.)
+ *
+ * Component classes which use this mixin should use the Field layout
+ * or a derivation thereof to properly size and position the label and message according to the component config.
+ * They must also call the {@link #initLabelable} method during component initialization to ensure the mixin gets
+ * set up correctly.
+ *
  * @docauthor Jason Johnston <jason@sencha.com>
  */
 Ext.define("Ext.form.Labelable", {
     requires: ['Ext.XTemplate'],
 
     /**
-     * @cfg {Array/String/Ext.XTemplate} labelableRenderTpl
+     * @cfg {String/String[]/Ext.XTemplate} labelableRenderTpl
      * The rendering template for the field decorations. Component classes using this mixin should include
      * logic to use this as their {@link Ext.AbstractComponent#renderTpl renderTpl}, and implement the
      * {@link #getSubTplMarkup} method to generate the field body content.
      */
     labelableRenderTpl: [
         '<tpl if="!hideLabel && !(!fieldLabel && hideEmptyLabel)">',
-            '<label<tpl if="inputId"> for="{inputId}"</tpl> class="{labelCls}"<tpl if="labelStyle"> style="{labelStyle}"</tpl>>',
+            '<label id="{id}-labelEl"<tpl if="inputId"> for="{inputId}"</tpl> class="{labelCls}"',
+                '<tpl if="labelStyle"> style="{labelStyle}"</tpl>>',
                 '<tpl if="fieldLabel">{fieldLabel}{labelSeparator}</tpl>',
             '</label>',
         '</tpl>',
-        '<div class="{baseBodyCls} {fieldBodyCls}"<tpl if="inputId"> id="{baseBodyCls}-{inputId}"</tpl> role="presentation">{subTplMarkup}</div>',
-        '<div class="{errorMsgCls}" style="display:none"></div>',
+        '<div class="{baseBodyCls} {fieldBodyCls}" id="{id}-bodyEl" role="presentation">{subTplMarkup}</div>',
+        '<div id="{id}-errorEl" class="{errorMsgCls}" style="display:none"></div>',
         '<div class="{clearCls}" role="presentation"><!-- --></div>',
         {
             compiled: true,
@@ -66,47 +78,55 @@ Ext.define("Ext.form.Labelable", {
     isFieldLabelable: true,
 
     /**
-     * @cfg {String} formItemCls
+     * @cfg {String} [formItemCls='x-form-item']
      * A CSS class to be applied to the outermost element to denote that it is participating in the form
-     * field layout. Defaults to 'x-form-item'.
+     * field layout.
      */
     formItemCls: Ext.baseCSSPrefix + 'form-item',
 
     /**
-     * @cfg {String} labelCls
-     * The CSS class to be applied to the label element. Defaults to 'x-form-item-label'.
+     * @cfg {String} [labelCls='x-form-item-label']
+     * The CSS class to be applied to the label element.
+     * This (single) CSS class is used to formulate the renderSelector and drives the field
+     * layout where it is concatenated with a hyphen ('-') and {@link #labelAlign}. To add
+     * additional classes, use {@link #labelClsExtra}.
      */
     labelCls: Ext.baseCSSPrefix + 'form-item-label',
 
     /**
-     * @cfg {String} errorMsgCls
-     * The CSS class to be applied to the error message element. Defaults to 'x-form-error-msg'.
+     * @cfg {String} labelClsExtra
+     * An optional string of one or more additional CSS classes to add to the label element.
+     * Defaults to empty.
+     */
+
+    /**
+     * @cfg {String} [errorMsgCls='x-form-error-msg']
+     * The CSS class to be applied to the error message element.
      */
     errorMsgCls: Ext.baseCSSPrefix + 'form-error-msg',
 
     /**
-     * @cfg {String} baseBodyCls
-     * The CSS class to be applied to the body content element. Defaults to 'x-form-item-body'.
+     * @cfg {String} [baseBodyCls='x-form-item-body']
+     * The CSS class to be applied to the body content element.
      */
     baseBodyCls: Ext.baseCSSPrefix + 'form-item-body',
 
     /**
      * @cfg {String} fieldBodyCls
      * An extra CSS class to be applied to the body content element in addition to {@link #fieldBodyCls}.
-     * Defaults to empty.
      */
     fieldBodyCls: '',
 
     /**
-     * @cfg {String} clearCls
+     * @cfg {String} [clearCls='x-clear']
      * The CSS class to be applied to the special clearing div rendered directly after the field
-     * contents wrapper to provide field clearing (defaults to <tt>'x-clear'</tt>).
+     * contents wrapper to provide field clearing.
      */
     clearCls: Ext.baseCSSPrefix + 'clear',
 
     /**
-     * @cfg {String} invalidCls
-     * The CSS class to use when marking the component invalid (defaults to 'x-form-invalid')
+     * @cfg {String} [invalidCls='x-form-invalid']
+     * The CSS class to use when marking the component invalid.
      */
     invalidCls : Ext.baseCSSPrefix + 'form-invalid',
 
@@ -114,7 +134,7 @@ Ext.define("Ext.form.Labelable", {
      * @cfg {String} fieldLabel
      * The label for the field. It gets appended with the {@link #labelSeparator}, and its position
      * and sizing is determined by the {@link #labelAlign}, {@link #labelWidth}, and {@link #labelPad}
-     * configs. Defaults to undefined.
+     * configs.
      */
     fieldLabel: undefined,
 
@@ -134,13 +154,13 @@ Ext.define("Ext.form.Labelable", {
     /**
      * @cfg {Number} labelWidth
      * The width of the {@link #fieldLabel} in pixels. Only applicable if the {@link #labelAlign} is set
-     * to "left" or "right". Defaults to <tt>100</tt>.
+     * to "left" or "right".
      */
     labelWidth: 100,
 
     /**
      * @cfg {Number} labelPad
-     * The amount of space in pixels between the {@link #fieldLabel} and the input field. Defaults to <tt>5</tt>.
+     * The amount of space in pixels between the {@link #fieldLabel} and the input field.
      */
     labelPad : 5,
 
@@ -152,14 +172,13 @@ Ext.define("Ext.form.Labelable", {
 
     /**
      * @cfg {String} labelStyle
-     * <p>A CSS style specification string to apply directly to this field's label. Defaults to undefined.</p>
+     * A CSS style specification string to apply directly to this field's label.
      */
 
     /**
      * @cfg {Boolean} hideLabel
-     * <p>Set to <tt>true</tt> to completely hide the label element ({@link #fieldLabel} and {@link #labelSeparator}).
-     * Defaults to <tt>false</tt>.</p>
-     * <p>Also see {@link #hideEmptyLabel}, which controls whether space will be reserved for an empty fieldLabel.</p>
+     * Set to true to completely hide the label element ({@link #fieldLabel} and {@link #labelSeparator}).
+     * Also see {@link #hideEmptyLabel}, which controls whether space will be reserved for an empty fieldLabel.
      */
     hideLabel: false,
 
@@ -168,7 +187,7 @@ Ext.define("Ext.form.Labelable", {
      * <p>When set to <tt>true</tt>, the label element ({@link #fieldLabel} and {@link #labelSeparator}) will be
      * automatically hidden if the {@link #fieldLabel} is empty. Setting this to <tt>false</tt> will cause the empty
      * label element to be rendered and space to be reserved for it; this is useful if you want a field without a label
-     * to line up with other labeled fields in the same form. Defaults to <tt>true</tt>.</p>
+     * to line up with other labeled fields in the same form.</p>
      * <p>If you wish to unconditionall hide the label even if a non-empty fieldLabel is configured, then set
      * the {@link #hideLabel} config to <tt>true</tt>.</p>
      */
@@ -177,14 +196,13 @@ Ext.define("Ext.form.Labelable", {
     /**
      * @cfg {Boolean} preventMark
      * <tt>true</tt> to disable displaying any {@link #setActiveError error message} set on this object.
-     * Defaults to <tt>false</tt>.
      */
     preventMark: false,
 
     /**
      * @cfg {Boolean} autoFitErrors
      * Whether to adjust the component's body area to make room for 'side' or 'under'
-     * {@link #msgTarget error messages}. Defaults to <tt>true</tt>.
+     * {@link #msgTarget error messages}.
      */
     autoFitErrors: true,
 
@@ -206,7 +224,7 @@ Ext.define("Ext.form.Labelable", {
     /**
      * @cfg {String} activeError
      * If specified, then the component will be displayed with this value as its active error when
-     * first rendered. Defaults to undefined. Use {@link #setActiveError} or {@link #unsetActiveError} to
+     * first rendered. Use {@link #setActiveError} or {@link #unsetActiveError} to
      * change it after component creation.
      */
 
@@ -246,6 +264,8 @@ Ext.define("Ext.form.Labelable", {
     getLabelableRenderData: function() {
         var me = this,
             labelAlign = me.labelAlign,
+            labelCls = me.labelCls,
+            labelClsExtra = me.labelClsExtra,
             labelPad = me.labelPad,
             labelStyle;
 
@@ -265,47 +285,41 @@ Ext.define("Ext.form.Labelable", {
             {
                 inputId: me.getInputId(),
                 fieldLabel: me.getFieldLabel(),
+                labelCls: labelClsExtra ? labelCls + ' ' + labelClsExtra : labelCls,
                 labelStyle: labelStyle + (me.labelStyle || ''),
                 subTplMarkup: me.getSubTplMarkup()
             },
             me,
-            'hideLabel,hideEmptyLabel,labelCls,fieldBodyCls,baseBodyCls,errorMsgCls,clearCls,labelSeparator',
+            'hideLabel,hideEmptyLabel,fieldBodyCls,baseBodyCls,errorMsgCls,clearCls,labelSeparator',
             true
         );
     },
 
-    /**
-     * @protected
-     * Returns the additional {@link Ext.AbstractComponent#renderSelectors} for selecting the field
-     * decoration elements from the rendered {@link #labelableRenderTpl}. Component classes using this mixin should
-     * be sure and merge this method's result into the component's {@link Ext.AbstractComponent#renderSelectors}
-     * before rendering.
-     */
-    getLabelableSelectors: function() {
-        return {
+    onLabelableRender: function () {
+        this.addChildEls(
             /**
              * @property labelEl
-             * @type Ext.core.Element
+             * @type Ext.Element
              * The label Element for this component. Only available after the component has been rendered.
              */
-            labelEl: 'label.' + this.labelCls,
+            'labelEl',
 
             /**
              * @property bodyEl
-             * @type Ext.core.Element
+             * @type Ext.Element
              * The div Element wrapping the component's contents. Only available after the component has been rendered.
              */
-            bodyEl: '.' + this.baseBodyCls,
+            'bodyEl',
 
             /**
              * @property errorEl
-             * @type Ext.core.Element
+             * @type Ext.Element
              * The div Element that will contain the component's error message(s). Note that depending on the
              * configured {@link #msgTarget}, this element may be hidden in favor of some other form of
              * presentation, but will always be present in the DOM for use by assistive technologies.
              */
-            errorEl: '.' + this.errorMsgCls
-        };
+            'errorEl'
+        );
     },
 
     /**
@@ -349,6 +363,11 @@ Ext.define("Ext.form.Labelable", {
      * Sets the active error message to the given string. This replaces the entire error message
      * contents with the given string. Also see {@link #setActiveErrors} which accepts an Array of
      * messages and formats them according to the {@link #activeErrorsTpl}.
+     *
+     * Note that this only updates the error message element's text and attributes, you'll have
+     * to call doComponentLayout to actually update the field's layout to match. If the field extends
+     * {@link Ext.form.field.Base} you should call {@link Ext.form.field.Base#markInvalid markInvalid} instead.
+     *
      * @param {String} msg The error message
      */
     setActiveError: function(msg) {
@@ -360,7 +379,7 @@ Ext.define("Ext.form.Labelable", {
     /**
      * Gets an Array of any active error messages currently applied to the field. This does not trigger
      * validation on its own, it merely returns any messages that the component may already hold.
-     * @return {Array} The active error messages on the component; if there are no errors, an empty Array is returned.
+     * @return {String[]} The active error messages on the component; if there are no errors, an empty Array is returned.
      */
     getActiveErrors: function() {
         return this.activeErrors || [];
@@ -370,7 +389,12 @@ Ext.define("Ext.form.Labelable", {
      * Set the active error message to an Array of error messages. The messages are formatted into
      * a single message string using the {@link #activeErrorsTpl}. Also see {@link #setActiveError}
      * which allows setting the entire error contents with a single string.
-     * @param {Array} errors The error messages
+     *
+     * Note that this only updates the error message element's text and attributes, you'll have
+     * to call doComponentLayout to actually update the field's layout to match. If the field extends
+     * {@link Ext.form.field.Base} you should call {@link Ext.form.field.Base#markInvalid markInvalid} instead.
+     *
+     * @param {String[]} errors The error messages
      */
     setActiveErrors: function(errors) {
         this.activeErrors = errors;
@@ -379,7 +403,11 @@ Ext.define("Ext.form.Labelable", {
     },
 
     /**
-     * Clears the active error.
+     * Clears the active error message(s).
+     *
+     * Note that this only clears the error message element's text and attributes, you'll have
+     * to call doComponentLayout to actually update the field's layout to match. If the field extends
+     * {@link Ext.form.field.Base} you should call {@link Ext.form.field.Base#clearInvalid clearInvalid} instead.
      */
     unsetActiveError: function() {
         delete this.activeError;
@@ -439,3 +467,4 @@ Ext.define("Ext.form.Labelable", {
     }
 
 });
+