Upgrade to ExtJS 3.0.3 - Released 10/11/2009
[extjs.git] / docs / source / TriggerField.html
1 <html>
2 <head>
3   <title>The source code</title>
4     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
5     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
6 </head>
7 <body  onload="prettyPrint();">
8     <pre class="prettyprint lang-js">/*!
9  * Ext JS Library 3.0.3
10  * Copyright(c) 2006-2009 Ext JS, LLC
11  * licensing@extjs.com
12  * http://www.extjs.com/license
13  */
14 <div id="cls-Ext.form.TriggerField"></div>/**\r
15  * @class Ext.form.TriggerField\r
16  * @extends Ext.form.TextField\r
17  * Provides a convenient wrapper for TextFields that adds a clickable trigger button (looks like a combobox by default).\r
18  * The trigger has no default action, so you must assign a function to implement the trigger click handler by\r
19  * overriding {@link #onTriggerClick}. You can create a TriggerField directly, as it renders exactly like a combobox\r
20  * for which you can provide a custom implementation.  For example:\r
21  * <pre><code>\r
22 var trigger = new Ext.form.TriggerField();\r
23 trigger.onTriggerClick = myTriggerFn;\r
24 trigger.applyToMarkup('my-field');\r
25 </code></pre>\r
26  *\r
27  * However, in general you will most likely want to use TriggerField as the base class for a reusable component.\r
28  * {@link Ext.form.DateField} and {@link Ext.form.ComboBox} are perfect examples of this.\r
29  * \r
30  * @constructor\r
31  * Create a new TriggerField.\r
32  * @param {Object} config Configuration options (valid {@Ext.form.TextField} config options will also be applied\r
33  * to the base TextField)\r
34  * @xtype trigger\r
35  */\r
36 Ext.form.TriggerField = Ext.extend(Ext.form.TextField,  {\r
37     <div id="cfg-Ext.form.TriggerField-triggerClass"></div>/**\r
38      * @cfg {String} triggerClass\r
39      * An additional CSS class used to style the trigger button.  The trigger will always get the\r
40      * class <tt>'x-form-trigger'</tt> by default and <tt>triggerClass</tt> will be <b>appended</b> if specified.\r
41      */\r
42     <div id="cfg-Ext.form.TriggerField-triggerConfig"></div>/**\r
43      * @cfg {Mixed} triggerConfig\r
44      * <p>A {@link Ext.DomHelper DomHelper} config object specifying the structure of the\r
45      * trigger element for this Field. (Optional).</p>\r
46      * <p>Specify this when you need a customized element to act as the trigger button for a TriggerField.</p>\r
47      * <p>Note that when using this option, it is the developer's responsibility to ensure correct sizing, positioning\r
48      * and appearance of the trigger.  Defaults to:</p>\r
49      * <pre><code>{tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass}</code></pre>\r
50      */\r
51     <div id="cfg-Ext.form.TriggerField-autoCreate"></div>/**\r
52      * @cfg {String/Object} autoCreate <p>A {@link Ext.DomHelper DomHelper} element spec, or true for a default\r
53      * element spec. Used to create the {@link Ext.Component#getEl Element} which will encapsulate this Component.\r
54      * See <tt>{@link Ext.Component#autoEl autoEl}</tt> for details.  Defaults to:</p>\r
55      * <pre><code>{tag: "input", type: "text", size: "16", autocomplete: "off"}</code></pre>\r
56      */\r
57     defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},\r
58     <div id="cfg-Ext.form.TriggerField-hideTrigger"></div>/**\r
59      * @cfg {Boolean} hideTrigger <tt>true</tt> to hide the trigger element and display only the base\r
60      * text field (defaults to <tt>false</tt>)\r
61      */\r
62     hideTrigger:false,\r
63     <div id="cfg-Ext.form.TriggerField-editable"></div>/**\r
64      * @cfg {Boolean} editable <tt>false</tt> to prevent the user from typing text directly into the field,\r
65      * the field will only respond to a click on the trigger to set the value. (defaults to <tt>true</tt>)\r
66      */\r
67     editable: true,\r
68     <div id="cfg-Ext.form.TriggerField-wrapFocusClass"></div>/**\r
69      * @cfg {String} wrapFocusClass The class added to the to the wrap of the trigger element. Defaults to\r
70      * <tt>x-trigger-wrap-focus</tt>.\r
71      */\r
72     wrapFocusClass: 'x-trigger-wrap-focus',\r
73     <div id="method-Ext.form.TriggerField-autoSize"></div>/**\r
74      * @hide \r
75      * @method autoSize\r
76      */\r
77     autoSize: Ext.emptyFn,\r
78     // private\r
79     monitorTab : true,\r
80     // private\r
81     deferHeight : true,\r
82     // private\r
83     mimicing : false,\r
84     \r
85     actionMode: 'wrap',\r
86     \r
87     defaultTriggerWidth: 17,\r
88 \r
89     // private\r
90     onResize : function(w, h){\r
91         Ext.form.TriggerField.superclass.onResize.call(this, w, h);\r
92         var tw = this.getTriggerWidth();\r
93         if(Ext.isNumber(w)){\r
94             this.el.setWidth(w - tw);\r
95         }\r
96         this.wrap.setWidth(this.el.getWidth() + tw);\r
97     },\r
98     \r
99     getTriggerWidth: function(){\r
100         var tw = this.trigger.getWidth();\r
101         if(!this.hideTrigger && tw === 0){\r
102             tw = this.defaultTriggerWidth;\r
103         }\r
104         return tw;\r
105     },\r
106 \r
107     // private\r
108     alignErrorIcon : function(){\r
109         if(this.wrap){\r
110             this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);\r
111         }\r
112     },\r
113 \r
114     // private\r
115     onRender : function(ct, position){\r
116         this.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();\r
117         Ext.form.TriggerField.superclass.onRender.call(this, ct, position);\r
118 \r
119         this.wrap = this.el.wrap({cls: 'x-form-field-wrap x-form-field-trigger-wrap'});\r
120         this.trigger = this.wrap.createChild(this.triggerConfig ||\r
121                 {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass});\r
122         if(this.hideTrigger){\r
123             this.trigger.setDisplayed(false);\r
124         }\r
125         this.initTrigger();\r
126         if(!this.width){\r
127             this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());\r
128         }\r
129         if(!this.editable){\r
130             this.editable = true;\r
131             this.setEditable(false);\r
132         }\r
133         this.resizeEl = this.positionEl = this.wrap;\r
134     },\r
135 \r
136     afterRender : function(){\r
137         Ext.form.TriggerField.superclass.afterRender.call(this);\r
138     },\r
139 \r
140     // private\r
141     initTrigger : function(){\r
142         this.mon(this.trigger, 'click', this.onTriggerClick, this, {preventDefault:true});\r
143         this.trigger.addClassOnOver('x-form-trigger-over');\r
144         this.trigger.addClassOnClick('x-form-trigger-click');\r
145     },\r
146 \r
147     // private\r
148     onDestroy : function(){\r
149         Ext.destroy(this.trigger, this.wrap);\r
150         if (this.mimicing){\r
151             this.doc.un('mousedown', this.mimicBlur, this);\r
152         }\r
153         Ext.form.TriggerField.superclass.onDestroy.call(this);\r
154     },\r
155 \r
156     // private\r
157     onFocus : function(){\r
158         Ext.form.TriggerField.superclass.onFocus.call(this);\r
159         if(!this.mimicing){\r
160             this.wrap.addClass(this.wrapFocusClass);\r
161             this.mimicing = true;\r
162             this.doc.on('mousedown', this.mimicBlur, this, {delay: 10});\r
163             if(this.monitorTab){\r
164                 this.on('specialkey', this.checkTab, this);\r
165             }\r
166         }\r
167     },\r
168 \r
169     // private\r
170     checkTab : function(me, e){\r
171         if(e.getKey() == e.TAB){\r
172             this.triggerBlur();\r
173         }\r
174     },\r
175 \r
176     // private\r
177     onBlur : Ext.emptyFn,\r
178 \r
179     // private\r
180     mimicBlur : function(e){\r
181         if(!this.isDestroyed && !this.wrap.contains(e.target) && this.validateBlur(e)){\r
182             this.triggerBlur();\r
183         }\r
184     },\r
185 \r
186     // private\r
187     triggerBlur : function(){\r
188         this.mimicing = false;\r
189         this.doc.un('mousedown', this.mimicBlur, this);\r
190         if(this.monitorTab && this.el){\r
191             this.un('specialkey', this.checkTab, this);\r
192         }\r
193         Ext.form.TriggerField.superclass.onBlur.call(this);\r
194         if(this.wrap){\r
195             this.wrap.removeClass(this.wrapFocusClass);\r
196         }\r
197     },\r
198 \r
199     beforeBlur : Ext.emptyFn, \r
200     \r
201     <div id="method-Ext.form.TriggerField-setEditable"></div>/**\r
202      * Allow or prevent the user from directly editing the field text.  If false is passed,\r
203      * the user will only be able to modify the field using the trigger.  This method\r
204      * is the runtime equivalent of setting the 'editable' config option at config time.\r
205      * @param {Boolean} value True to allow the user to directly edit the field text\r
206      */\r
207     setEditable : function(value){\r
208         if(value == this.editable){\r
209             return;\r
210         }\r
211         this.editable = value;\r
212         if(!value){\r
213             this.el.addClass('x-trigger-noedit').on('click', this.onTriggerClick, this).dom.setAttribute('readOnly', true);\r
214         }else{\r
215             this.el.removeClass('x-trigger-noedit').un('click', this.onTriggerClick,  this).dom.removeAttribute('readOnly');\r
216         }\r
217     },\r
218 \r
219     // private\r
220     // This should be overriden by any subclass that needs to check whether or not the field can be blurred.\r
221     validateBlur : function(e){\r
222         return true;\r
223     },\r
224 \r
225     <div id="method-Ext.form.TriggerField-onTriggerClick"></div>/**\r
226      * The function that should handle the trigger's click event.  This method does nothing by default\r
227      * until overridden by an implementing function.  See Ext.form.ComboBox and Ext.form.DateField for\r
228      * sample implementations.\r
229      * @method\r
230      * @param {EventObject} e\r
231      */\r
232     onTriggerClick : Ext.emptyFn\r
233 \r
234     <div id="cfg-Ext.form.TriggerField-grow"></div>/**\r
235      * @cfg {Boolean} grow @hide\r
236      */\r
237     <div id="cfg-Ext.form.TriggerField-growMin"></div>/**\r
238      * @cfg {Number} growMin @hide\r
239      */\r
240     <div id="cfg-Ext.form.TriggerField-growMax"></div>/**\r
241      * @cfg {Number} growMax @hide\r
242      */\r
243 });\r
244 \r
245 <div id="cls-Ext.form.TwinTriggerField"></div>/**\r
246  * @class Ext.form.TwinTriggerField\r
247  * @extends Ext.form.TriggerField\r
248  * TwinTriggerField is not a public class to be used directly.  It is meant as an abstract base class\r
249  * to be extended by an implementing class.  For an example of implementing this class, see the custom\r
250  * SearchField implementation here:\r
251  * <a href="http://extjs.com/deploy/ext/examples/form/custom.html">http://extjs.com/deploy/ext/examples/form/custom.html</a>\r
252  */\r
253 Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {\r
254     <div id="cfg-Ext.form.TwinTriggerField-triggerConfig"></div>/**\r
255      * @cfg {Mixed} triggerConfig\r
256      * <p>A {@link Ext.DomHelper DomHelper} config object specifying the structure of the trigger elements\r
257      * for this Field. (Optional).</p>\r
258      * <p>Specify this when you need a customized element to contain the two trigger elements for this Field.\r
259      * Each trigger element must be marked by the CSS class <tt>x-form-trigger</tt> (also see\r
260      * <tt>{@link #trigger1Class}</tt> and <tt>{@link #trigger2Class}</tt>).</p>\r
261      * <p>Note that when using this option, it is the developer's responsibility to ensure correct sizing,\r
262      * positioning and appearance of the triggers.</p>\r
263      */\r
264     <div id="cfg-Ext.form.TwinTriggerField-trigger1Class"></div>/**\r
265      * @cfg {String} trigger1Class\r
266      * An additional CSS class used to style the trigger button.  The trigger will always get the\r
267      * class <tt>'x-form-trigger'</tt> by default and <tt>triggerClass</tt> will be <b>appended</b> if specified.\r
268      */\r
269     <div id="cfg-Ext.form.TwinTriggerField-trigger2Class"></div>/**\r
270      * @cfg {String} trigger2Class\r
271      * An additional CSS class used to style the trigger button.  The trigger will always get the\r
272      * class <tt>'x-form-trigger'</tt> by default and <tt>triggerClass</tt> will be <b>appended</b> if specified.\r
273      */\r
274 \r
275     initComponent : function(){\r
276         Ext.form.TwinTriggerField.superclass.initComponent.call(this);\r
277 \r
278         this.triggerConfig = {\r
279             tag:'span', cls:'x-form-twin-triggers', cn:[\r
280             {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},\r
281             {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class}\r
282         ]};\r
283     },\r
284 \r
285     getTrigger : function(index){\r
286         return this.triggers[index];\r
287     },\r
288 \r
289     initTrigger : function(){\r
290         var ts = this.trigger.select('.x-form-trigger', true);\r
291         var triggerField = this;\r
292         ts.each(function(t, all, index){\r
293             var triggerIndex = 'Trigger'+(index+1);\r
294             t.hide = function(){\r
295                 var w = triggerField.wrap.getWidth();\r
296                 this.dom.style.display = 'none';\r
297                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());\r
298                 this['hidden' + triggerIndex] = true;\r
299             };\r
300             t.show = function(){\r
301                 var w = triggerField.wrap.getWidth();\r
302                 this.dom.style.display = '';\r
303                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());\r
304                 this['hidden' + triggerIndex] = false;\r
305             };\r
306             \r
307             if(this['hide'+triggerIndex]){\r
308                 t.dom.style.display = 'none';\r
309                 this['hidden' + triggerIndex] = true;\r
310             }\r
311             this.mon(t, 'click', this['on'+triggerIndex+'Click'], this, {preventDefault:true});\r
312             t.addClassOnOver('x-form-trigger-over');\r
313             t.addClassOnClick('x-form-trigger-click');\r
314         }, this);\r
315         this.triggers = ts.elements;\r
316     },\r
317     \r
318     getTriggerWidth: function(){\r
319         var tw = 0;\r
320         Ext.each(this.triggers, function(t, index){\r
321             var triggerIndex = 'Trigger' + (index + 1),\r
322                 w = t.getWidth();\r
323             if(w === 0 && !this['hidden' + triggerIndex]){\r
324                 tw += this.defaultTriggerWidth;\r
325             }else{\r
326                 tw += w;\r
327             }\r
328         }, this);\r
329         return tw;\r
330     },\r
331     \r
332     // private\r
333     onDestroy : function() {\r
334         Ext.destroy(this.triggers);\r
335         Ext.form.TwinTriggerField.superclass.onDestroy.call(this);\r
336     },\r
337 \r
338     <div id="method-Ext.form.TwinTriggerField-onTrigger1Click"></div>/**\r
339      * The function that should handle the trigger's click event.  This method does nothing by default\r
340      * until overridden by an implementing function. See {@link Ext.form.TriggerField#onTriggerClick}\r
341      * for additional information.  \r
342      * @method\r
343      * @param {EventObject} e\r
344      */\r
345     onTrigger1Click : Ext.emptyFn,\r
346     <div id="method-Ext.form.TwinTriggerField-onTrigger2Click"></div>/**\r
347      * The function that should handle the trigger's click event.  This method does nothing by default\r
348      * until overridden by an implementing function. See {@link Ext.form.TriggerField#onTriggerClick}\r
349      * for additional information.  \r
350      * @method\r
351      * @param {EventObject} e\r
352      */\r
353     onTrigger2Click : Ext.emptyFn\r
354 });\r
355 Ext.reg('trigger', Ext.form.TriggerField);</pre>
356 </body>
357 </html>