Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / form / field / Picker.js
index 6a5f7f9..0be3cc9 100644 (file)
@@ -1,19 +1,27 @@
+/*
+
+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.Picker
- * @extends Ext.form.field.Trigger
- * <p>An abstract class for fields that have a single trigger which opens a "picker" popup below
- * the field, e.g. a combobox menu list or a date picker. It provides a base implementation for
- * toggling the picker's visibility when the trigger is clicked, as well as keyboard navigation
- * and some basic events. Sizing and alignment of the picker can be controlled via the {@link #matchFieldWidth}
- * and {@link #pickerAlign}/{@link #pickerOffset} config properties respectively.</p>
- * <p>You would not normally use this class directly, but instead use it as the parent class for
- * a specific picker field implementation. Subclasses must implement the {@link #createPicker} method
- * to create a picker component appropriate for the field.</p>
+ * An abstract class for fields that have a single trigger which opens a "picker" popup below the field, e.g. a combobox
+ * menu list or a date picker. It provides a base implementation for toggling the picker's visibility when the trigger
+ * is clicked, as well as keyboard navigation and some basic events. Sizing and alignment of the picker can be
+ * controlled via the {@link #matchFieldWidth} and {@link #pickerAlign}/{@link #pickerOffset} config properties
+ * respectively.
  *
- * @xtype pickerfield
- * @constructor
- * Create a new picker field
- * @param {Object} config
+ * You would not normally use this class directly, but instead use it as the parent class for a specific picker field
+ * implementation. Subclasses must implement the {@link #createPicker} method to create a picker component appropriate
+ * for the field.
  */
 Ext.define('Ext.form.field.Picker', {
     extend: 'Ext.form.field.Trigger',
@@ -23,42 +31,39 @@ Ext.define('Ext.form.field.Picker', {
 
     /**
      * @cfg {Boolean} matchFieldWidth
-     * Whether the picker dropdown's width should be explicitly set to match the width of the field.
-     * Defaults to <tt>true</tt>.
+     * Whether the picker dropdown's width should be explicitly set to match the width of the field. Defaults to true.
      */
     matchFieldWidth: true,
 
     /**
      * @cfg {String} pickerAlign
-     * The {@link Ext.core.Element#alignTo alignment position} with which to align the picker. Defaults
-     * to <tt>"tl-bl?"</tt>
+     * The {@link Ext.Element#alignTo alignment position} with which to align the picker. Defaults to "tl-bl?"
      */
     pickerAlign: 'tl-bl?',
 
     /**
-     * @cfg {Array} pickerOffset
+     * @cfg {Number[]} pickerOffset
      * An offset [x,y] to use in addition to the {@link #pickerAlign} when positioning the picker.
      * Defaults to undefined.
      */
 
     /**
      * @cfg {String} openCls
-     * A class to be added to the field's {@link #bodyEl} element when the picker is opened. Defaults
-     * to 'x-pickerfield-open'.
+     * A class to be added to the field's {@link #bodyEl} element when the picker is opened.
+     * Defaults to 'x-pickerfield-open'.
      */
     openCls: Ext.baseCSSPrefix + 'pickerfield-open',
 
     /**
-     * @property isExpanded
-     * @type Boolean
+     * @property {Boolean} isExpanded
      * True if the picker is currently expanded, false if not.
      */
 
     /**
-     * @cfg {Boolean} editable <tt>false</tt> to prevent the user from typing text directly into the field;
-     * the field can only have its value set via selecting a value from the picker. In this state, the picker
-     * can also be opened by clicking directly on the input field itself.
-     * (defaults to <tt>true</tt>).
+     * @cfg {Boolean} editable
+     * False to prevent the user from typing text directly into the field; the field can only have its value set via
+     * selecting a value from the picker. In this state, the picker can also be opened by clicking directly on the input
+     * field itself.
      */
     editable: true,
 
@@ -84,7 +89,7 @@ Ext.define('Ext.form.field.Picker', {
              * @event select
              * Fires when a value is selected via the picker.
              * @param {Ext.form.field.Picker} field This field instance
-             * @param {Mixed} value The value that was selected. The exact type of this value is dependent on
+             * @param {Object} value The value that was selected. The exact type of this value is dependent on
              * the individual field and picker implementations.
              */
             'select'
@@ -123,7 +128,7 @@ Ext.define('Ext.form.field.Picker', {
 
 
     /**
-     * Expand this field's picker dropdown.
+     * Expands this field's picker dropdown.
      */
     expand: function() {
         var me = this,
@@ -146,7 +151,7 @@ Ext.define('Ext.form.field.Picker', {
                 mousedown: collapseIf,
                 scope: me
             });
-
+            Ext.EventManager.onWindowResize(me.alignPicker, me);
             me.fireEvent('expand', me);
             me.onExpand();
         }
@@ -155,34 +160,45 @@ Ext.define('Ext.form.field.Picker', {
     onExpand: Ext.emptyFn,
 
     /**
+     * Aligns the picker to the input element
      * @protected
-     * Aligns the picker to the
      */
     alignPicker: function() {
         var me = this,
-            picker, isAbove,
-            aboveSfx = '-above';
+            picker;
 
-        if (this.isExpanded) {
+        if (me.isExpanded) {
             picker = me.getPicker();
             if (me.matchFieldWidth) {
                 // Auto the height (it will be constrained by min and max width) unless there are no records to display.
                 picker.setSize(me.bodyEl.getWidth(), picker.store && picker.store.getCount() ? null : 0);
             }
             if (picker.isFloating()) {
-                picker.alignTo(me.inputEl, me.pickerAlign, me.pickerOffset);
-
-                // add the {openCls}-above class if the picker was aligned above
-                // the field due to hitting the bottom of the viewport
-                isAbove = picker.el.getY() < me.inputEl.getY();
-                me.bodyEl[isAbove ? 'addCls' : 'removeCls'](me.openCls + aboveSfx);
-                picker.el[isAbove ? 'addCls' : 'removeCls'](picker.baseCls + aboveSfx);
+                me.doAlign();
             }
         }
     },
 
     /**
-     * Collapse this field's picker dropdown.
+     * Performs the alignment on the picker using the class defaults
+     * @private
+     */
+    doAlign: function(){
+        var me = this,
+            picker = me.picker,
+            aboveSfx = '-above',
+            isAbove;
+
+        me.picker.alignTo(me.inputEl, me.pickerAlign, me.pickerOffset);
+        // add the {openCls}-above class if the picker was aligned above
+        // the field due to hitting the bottom of the viewport
+        isAbove = picker.el.getY() < me.inputEl.getY();
+        me.bodyEl[isAbove ? 'addCls' : 'removeCls'](me.openCls + aboveSfx);
+        picker[isAbove ? 'addCls' : 'removeCls'](picker.baseCls + aboveSfx);
+    },
+
+    /**
+     * Collapses this field's picker dropdown.
      */
     collapse: function() {
         if (this.isExpanded && !this.isDestroyed) {
@@ -204,7 +220,7 @@ Ext.define('Ext.form.field.Picker', {
             // remove event listeners
             doc.un('mousewheel', collapseIf, me);
             doc.un('mousedown', collapseIf, me);
-
+            Ext.EventManager.removeResizeListener(me.alignPicker, me);
             me.fireEvent('collapse', me);
             me.onCollapse();
         }
@@ -225,7 +241,7 @@ Ext.define('Ext.form.field.Picker', {
     },
 
     /**
-     * Return a reference to the picker component for this field, creating it if necessary by
+     * Returns a reference to the picker component for this field, creating it if necessary by
      * calling {@link #createPicker}.
      * @return {Ext.Component} The picker component
      */
@@ -235,15 +251,16 @@ Ext.define('Ext.form.field.Picker', {
     },
 
     /**
-     * Create and return the component to be used as this field's picker. Must be implemented
-     * by subclasses of Picker.
-     * @return {Ext.Component} The picker component
+     * @method
+     * Creates and returns the component to be used as this field's picker. Must be implemented by subclasses of Picker.
+     * The current field should also be passed as a configuration option to the picker component as the pickerField
+     * property.
      */
     createPicker: Ext.emptyFn,
 
     /**
-     * Handles the trigger click; by default toggles between expanding and collapsing the
-     * picker component.
+     * Handles the trigger click; by default toggles between expanding and collapsing the picker component.
+     * @protected
      */
     onTriggerClick: function() {
         var me = this;
@@ -267,10 +284,18 @@ Ext.define('Ext.form.field.Picker', {
     },
 
     onDestroy : function(){
-        var me = this;
-        Ext.destroy(me.picker, me.keyNav);
+        var me = this,
+            picker = me.picker;
+
+        Ext.EventManager.removeResizeListener(me.alignPicker, me);
+        Ext.destroy(me.keyNav);
+        if (picker) {
+            delete picker.pickerField;
+            picker.destroy();
+        }
         me.callParent();
     }
 
 });
 
+