Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / Picker.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5   <title>The source code</title>
6   <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8   <style type="text/css">
9     .highlight { display: block; background-color: #ddd; }
10   </style>
11   <script type="text/javascript">
12     function highlight() {
13       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14     }
15   </script>
16 </head>
17 <body onload="prettyPrint(); highlight();">
18   <pre class="prettyprint lang-js"><span id='Ext-form-field-Picker'>/**
19 </span> * An abstract class for fields that have a single trigger which opens a &quot;picker&quot; popup below the field, e.g. a combobox
20  * menu list or a date picker. It provides a base implementation for toggling the picker's visibility when the trigger
21  * is clicked, as well as keyboard navigation and some basic events. Sizing and alignment of the picker can be
22  * controlled via the {@link #matchFieldWidth} and {@link #pickerAlign}/{@link #pickerOffset} config properties
23  * respectively.
24  *
25  * You would not normally use this class directly, but instead use it as the parent class for a specific picker field
26  * implementation. Subclasses must implement the {@link #createPicker} method to create a picker component appropriate
27  * for the field.
28  */
29 Ext.define('Ext.form.field.Picker', {
30     extend: 'Ext.form.field.Trigger',
31     alias: 'widget.pickerfield',
32     alternateClassName: 'Ext.form.Picker',
33     requires: ['Ext.util.KeyNav'],
34
35 <span id='Ext-form-field-Picker-cfg-matchFieldWidth'>    /**
36 </span>     * @cfg {Boolean} matchFieldWidth
37      * Whether the picker dropdown's width should be explicitly set to match the width of the field. Defaults to true.
38      */
39     matchFieldWidth: true,
40
41 <span id='Ext-form-field-Picker-cfg-pickerAlign'>    /**
42 </span>     * @cfg {String} pickerAlign
43      * The {@link Ext.Element#alignTo alignment position} with which to align the picker. Defaults to &quot;tl-bl?&quot;
44      */
45     pickerAlign: 'tl-bl?',
46
47 <span id='Ext-form-field-Picker-cfg-pickerOffset'>    /**
48 </span>     * @cfg {Number[]} pickerOffset
49      * An offset [x,y] to use in addition to the {@link #pickerAlign} when positioning the picker.
50      * Defaults to undefined.
51      */
52
53 <span id='Ext-form-field-Picker-cfg-openCls'>    /**
54 </span>     * @cfg {String} openCls
55      * A class to be added to the field's {@link #bodyEl} element when the picker is opened.
56      * Defaults to 'x-pickerfield-open'.
57      */
58     openCls: Ext.baseCSSPrefix + 'pickerfield-open',
59
60 <span id='Ext-form-field-Picker-property-isExpanded'>    /**
61 </span>     * @property {Boolean} isExpanded
62      * True if the picker is currently expanded, false if not.
63      */
64
65 <span id='Ext-form-field-Picker-cfg-editable'>    /**
66 </span>     * @cfg {Boolean} editable
67      * False to prevent the user from typing text directly into the field; the field can only have its value set via
68      * selecting a value from the picker. In this state, the picker can also be opened by clicking directly on the input
69      * field itself.
70      */
71     editable: true,
72
73
74     initComponent: function() {
75         this.callParent();
76
77         // Custom events
78         this.addEvents(
79 <span id='Ext-form-field-Picker-event-expand'>            /**
80 </span>             * @event expand
81              * Fires when the field's picker is expanded.
82              * @param {Ext.form.field.Picker} field This field instance
83              */
84             'expand',
85 <span id='Ext-form-field-Picker-event-collapse'>            /**
86 </span>             * @event collapse
87              * Fires when the field's picker is collapsed.
88              * @param {Ext.form.field.Picker} field This field instance
89              */
90             'collapse',
91 <span id='Ext-form-field-Picker-event-select'>            /**
92 </span>             * @event select
93              * Fires when a value is selected via the picker.
94              * @param {Ext.form.field.Picker} field This field instance
95              * @param {Object} value The value that was selected. The exact type of this value is dependent on
96              * the individual field and picker implementations.
97              */
98             'select'
99         );
100     },
101
102
103     initEvents: function() {
104         var me = this;
105         me.callParent();
106
107         // Add handlers for keys to expand/collapse the picker
108         me.keyNav = Ext.create('Ext.util.KeyNav', me.inputEl, {
109             down: function() {
110                 if (!me.isExpanded) {
111                     // Don't call expand() directly as there may be additional processing involved before
112                     // expanding, e.g. in the case of a ComboBox query.
113                     me.onTriggerClick();
114                 }
115             },
116             esc: me.collapse,
117             scope: me,
118             forceKeyDown: true
119         });
120
121         // Non-editable allows opening the picker by clicking the field
122         if (!me.editable) {
123             me.mon(me.inputEl, 'click', me.onTriggerClick, me);
124         }
125
126         // Disable native browser autocomplete
127         if (Ext.isGecko) {
128             me.inputEl.dom.setAttribute('autocomplete', 'off');
129         }
130     },
131
132
133 <span id='Ext-form-field-Picker-method-expand'>    /**
134 </span>     * Expands this field's picker dropdown.
135      */
136     expand: function() {
137         var me = this,
138             bodyEl, picker, collapseIf;
139
140         if (me.rendered &amp;&amp; !me.isExpanded &amp;&amp; !me.isDestroyed) {
141             bodyEl = me.bodyEl;
142             picker = me.getPicker();
143             collapseIf = me.collapseIf;
144
145             // show the picker and set isExpanded flag
146             picker.show();
147             me.isExpanded = true;
148             me.alignPicker();
149             bodyEl.addCls(me.openCls);
150
151             // monitor clicking and mousewheel
152             me.mon(Ext.getDoc(), {
153                 mousewheel: collapseIf,
154                 mousedown: collapseIf,
155                 scope: me
156             });
157             Ext.EventManager.onWindowResize(me.alignPicker, me);
158             me.fireEvent('expand', me);
159             me.onExpand();
160         }
161     },
162
163     onExpand: Ext.emptyFn,
164
165 <span id='Ext-form-field-Picker-method-alignPicker'>    /**
166 </span>     * Aligns the picker to the input element
167      * @protected
168      */
169     alignPicker: function() {
170         var me = this,
171             picker;
172
173         if (me.isExpanded) {
174             picker = me.getPicker();
175             if (me.matchFieldWidth) {
176                 // Auto the height (it will be constrained by min and max width) unless there are no records to display.
177                 picker.setSize(me.bodyEl.getWidth(), picker.store &amp;&amp; picker.store.getCount() ? null : 0);
178             }
179             if (picker.isFloating()) {
180                 me.doAlign();
181             }
182         }
183     },
184
185 <span id='Ext-form-field-Picker-method-doAlign'>    /**
186 </span>     * Performs the alignment on the picker using the class defaults
187      * @private
188      */
189     doAlign: function(){
190         var me = this,
191             picker = me.picker,
192             aboveSfx = '-above',
193             isAbove;
194
195         me.picker.alignTo(me.inputEl, me.pickerAlign, me.pickerOffset);
196         // add the {openCls}-above class if the picker was aligned above
197         // the field due to hitting the bottom of the viewport
198         isAbove = picker.el.getY() &lt; me.inputEl.getY();
199         me.bodyEl[isAbove ? 'addCls' : 'removeCls'](me.openCls + aboveSfx);
200         picker[isAbove ? 'addCls' : 'removeCls'](picker.baseCls + aboveSfx);
201     },
202
203 <span id='Ext-form-field-Picker-method-collapse'>    /**
204 </span>     * Collapses this field's picker dropdown.
205      */
206     collapse: function() {
207         if (this.isExpanded &amp;&amp; !this.isDestroyed) {
208             var me = this,
209                 openCls = me.openCls,
210                 picker = me.picker,
211                 doc = Ext.getDoc(),
212                 collapseIf = me.collapseIf,
213                 aboveSfx = '-above';
214
215             // hide the picker and set isExpanded flag
216             picker.hide();
217             me.isExpanded = false;
218
219             // remove the openCls
220             me.bodyEl.removeCls([openCls, openCls + aboveSfx]);
221             picker.el.removeCls(picker.baseCls + aboveSfx);
222
223             // remove event listeners
224             doc.un('mousewheel', collapseIf, me);
225             doc.un('mousedown', collapseIf, me);
226             Ext.EventManager.removeResizeListener(me.alignPicker, me);
227             me.fireEvent('collapse', me);
228             me.onCollapse();
229         }
230     },
231
232     onCollapse: Ext.emptyFn,
233
234
235 <span id='Ext-form-field-Picker-method-collapseIf'>    /**
236 </span>     * @private
237      * Runs on mousewheel and mousedown of doc to check to see if we should collapse the picker
238      */
239     collapseIf: function(e) {
240         var me = this;
241         if (!me.isDestroyed &amp;&amp; !e.within(me.bodyEl, false, true) &amp;&amp; !e.within(me.picker.el, false, true)) {
242             me.collapse();
243         }
244     },
245
246 <span id='Ext-form-field-Picker-method-getPicker'>    /**
247 </span>     * Returns a reference to the picker component for this field, creating it if necessary by
248      * calling {@link #createPicker}.
249      * @return {Ext.Component} The picker component
250      */
251     getPicker: function() {
252         var me = this;
253         return me.picker || (me.picker = me.createPicker());
254     },
255
256 <span id='Ext-form-field-Picker-method-createPicker'>    /**
257 </span>     * @method
258      * Creates and returns the component to be used as this field's picker. Must be implemented by subclasses of Picker.
259      * The current field should also be passed as a configuration option to the picker component as the pickerField
260      * property.
261      */
262     createPicker: Ext.emptyFn,
263
264 <span id='Ext-form-field-Picker-method-onTriggerClick'>    /**
265 </span>     * Handles the trigger click; by default toggles between expanding and collapsing the picker component.
266      * @protected
267      */
268     onTriggerClick: function() {
269         var me = this;
270         if (!me.readOnly &amp;&amp; !me.disabled) {
271             if (me.isExpanded) {
272                 me.collapse();
273             } else {
274                 me.expand();
275             }
276             me.inputEl.focus();
277         }
278     },
279
280     mimicBlur: function(e) {
281         var me = this,
282             picker = me.picker;
283         // ignore mousedown events within the picker element
284         if (!picker || !e.within(picker.el, false, true)) {
285             me.callParent(arguments);
286         }
287     },
288
289     onDestroy : function(){
290         var me = this,
291             picker = me.picker;
292
293         Ext.EventManager.removeResizeListener(me.alignPicker, me);
294         Ext.destroy(me.keyNav);
295         if (picker) {
296             delete picker.pickerField;
297             picker.destroy();
298         }
299         me.callParent();
300     }
301
302 });
303
304 </pre>
305 </body>
306 </html>