Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / docs / source / Editor.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="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../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-Editor'>/**
19 </span> * @class Ext.Editor
20  * @extends Ext.Component
21  *
22  * &lt;p&gt;
23  * The Editor class is used to provide inline editing for elements on the page. The editor
24  * is backed by a {@link Ext.form.field.Field} that will be displayed to edit the underlying content.
25  * The editor is a floating Component, when the editor is shown it is automatically aligned to
26  * display over the top of the bound element it is editing. The Editor contains several options
27  * for how to handle key presses:
28  * &lt;ul&gt;
29  * &lt;li&gt;{@link #completeOnEnter}&lt;/li&gt;
30  * &lt;li&gt;{@link #cancelOnEsc}&lt;/li&gt;
31  * &lt;li&gt;{@link #swallowKeys}&lt;/li&gt;
32  * &lt;/ul&gt;
33  * It also has options for how to use the value once the editor has been activated:
34  * &lt;ul&gt;
35  * &lt;li&gt;{@link #revertInvalid}&lt;/li&gt;
36  * &lt;li&gt;{@link #ignoreNoChange}&lt;/li&gt;
37  * &lt;li&gt;{@link #updateEl}&lt;/li&gt;
38  * &lt;/ul&gt;
39  * Sample usage:
40  * &lt;/p&gt;
41  * &lt;pre&gt;&lt;code&gt;
42 var editor = new Ext.Editor({
43     updateEl: true, // update the innerHTML of the bound element when editing completes
44     field: {
45         xtype: 'textfield'
46     }
47 });
48 var el = Ext.get('my-text'); // The element to 'edit'
49 editor.startEdit(el); // The value of the field will be taken as the innerHTML of the element.
50  * &lt;/code&gt;&lt;/pre&gt;
51  * {@img Ext.Editor/Ext.Editor.png Ext.Editor component}
52  *
53  */
54 Ext.define('Ext.Editor', {
55
56     /* Begin Definitions */
57
58     extend: 'Ext.Component',
59
60     alias: 'widget.editor',
61
62     requires: ['Ext.layout.component.Editor'],
63
64     /* End Definitions */
65
66    componentLayout: 'editor',
67
68 <span id='Ext-Editor-cfg-field'>    /**
69 </span>    * @cfg {Ext.form.field.Field} field
70     * The Field object (or descendant) or config object for field
71     */
72
73 <span id='Ext-Editor-cfg-allowBlur'>    /**
74 </span>     * @cfg {Boolean} allowBlur
75      * True to {@link #completeEdit complete the editing process} if in edit mode when the
76      * field is blurred. Defaults to &lt;tt&gt;true&lt;/tt&gt;.
77      */
78     allowBlur: true,
79
80 <span id='Ext-Editor-cfg-autoSize'>    /**
81 </span>     * @cfg {Boolean/Object} autoSize
82      * True for the editor to automatically adopt the size of the underlying field. Otherwise, an object
83      * can be passed to indicate where to get each dimension. The available properties are 'boundEl' and
84      * 'field'. If a dimension is not specified, it will use the underlying height/width specified on
85      * the editor object.
86      * Examples:
87      * &lt;pre&gt;&lt;code&gt;
88 autoSize: true // The editor will be sized to the height/width of the field
89
90 height: 21,
91 autoSize: {
92     width: 'boundEl' // The width will be determined by the width of the boundEl, the height from the editor (21)
93 }
94
95 autoSize: {
96     width: 'field', // Width from the field
97     height: 'boundEl' // Height from the boundEl
98 }
99      * &lt;/pre&gt;&lt;/code&gt;
100      */
101
102 <span id='Ext-Editor-cfg-revertInvalid'>    /**
103 </span>     * @cfg {Boolean} revertInvalid
104      * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
105      * validation fails (defaults to true)
106      */
107     revertInvalid: true,
108
109 <span id='Ext-Editor-cfg-ignoreNoChange'>    /**
110 </span>     * @cfg {Boolean} ignoreNoChange
111      * True to skip the edit completion process (no save, no events fired) if the user completes an edit and
112      * the value has not changed (defaults to false).  Applies only to string values - edits for other data types
113      * will never be ignored.
114      */
115
116 <span id='Ext-Editor-cfg-hideEl'>    /**
117 </span>     * @cfg {Boolean} hideEl
118      * False to keep the bound element visible while the editor is displayed (defaults to true)
119      */
120
121 <span id='Ext-Editor-cfg-value'>    /**
122 </span>     * @cfg {Mixed} value
123      * The data value of the underlying field (defaults to &quot;&quot;)
124      */
125     value : '',
126
127 <span id='Ext-Editor-cfg-alignment'>    /**
128 </span>     * @cfg {String} alignment
129      * The position to align to (see {@link Ext.core.Element#alignTo} for more details, defaults to &quot;c-c?&quot;).
130      */
131     alignment: 'c-c?',
132
133 <span id='Ext-Editor-cfg-offsets'>    /**
134 </span>     * @cfg {Array} offsets
135      * The offsets to use when aligning (see {@link Ext.core.Element#alignTo} for more details. Defaults to &lt;tt&gt;[0, 0]&lt;/tt&gt;.
136      */
137     offsets: [0, 0],
138
139 <span id='Ext-Editor-cfg-shadow'>    /**
140 </span>     * @cfg {Boolean/String} shadow &quot;sides&quot; for sides/bottom only, &quot;frame&quot; for 4-way shadow, and &quot;drop&quot;
141      * for bottom-right shadow (defaults to &quot;frame&quot;)
142      */
143     shadow : 'frame',
144
145 <span id='Ext-Editor-cfg-constrain'>    /**
146 </span>     * @cfg {Boolean} constrain True to constrain the editor to the viewport
147      */
148     constrain : false,
149
150 <span id='Ext-Editor-cfg-swallowKeys'>    /**
151 </span>     * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true)
152      */
153     swallowKeys : true,
154
155 <span id='Ext-Editor-cfg-completeOnEnter'>    /**
156 </span>     * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed. Defaults to &lt;tt&gt;true&lt;/tt&gt;.
157      */
158     completeOnEnter : true,
159
160 <span id='Ext-Editor-cfg-cancelOnEsc'>    /**
161 </span>     * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed. Defaults to &lt;tt&gt;true&lt;/tt&gt;.
162      */
163     cancelOnEsc : true,
164
165 <span id='Ext-Editor-cfg-updateEl'>    /**
166 </span>     * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
167      */
168     updateEl : false,
169
170 <span id='Ext-Editor-cfg-parentEl'>    /**
171 </span>     * @cfg {Mixed} parentEl An element to render to. Defaults to the &lt;tt&gt;document.body&lt;/tt&gt;.
172      */
173
174     // private overrides
175     hidden: true,
176     baseCls: Ext.baseCSSPrefix + 'editor',
177
178     initComponent : function() {
179         var me = this,
180             field = me.field = Ext.ComponentManager.create(me.field, 'textfield');
181
182         Ext.apply(field, {
183             inEditor: true,
184             msgTarget: field.msgTarget == 'title' ? 'title' :  'qtip'
185         });
186         me.mon(field, {
187             scope: me,
188             blur: {
189                 fn: me.onBlur,
190                 // slight delay to avoid race condition with startEdits (e.g. grid view refresh)
191                 delay: 1
192             },
193             specialkey: me.onSpecialKey
194         });
195
196         if (field.grow) {
197             me.mon(field, 'autosize', me.onAutoSize,  me, {delay: 1});
198         }
199         me.floating = {
200             constrain: me.constrain
201         };
202
203         me.callParent(arguments);
204
205         me.addEvents(
206 <span id='Ext-Editor-event-beforestartedit'>            /**
207 </span>             * @event beforestartedit
208              * Fires when editing is initiated, but before the value changes.  Editing can be canceled by returning
209              * false from the handler of this event.
210              * @param {Ext.Editor} this
211              * @param {Ext.core.Element} boundEl The underlying element bound to this editor
212              * @param {Mixed} value The field value being set
213              */
214             'beforestartedit',
215 <span id='Ext-Editor-event-startedit'>            /**
216 </span>             * @event startedit
217              * Fires when this editor is displayed
218              * @param {Ext.Editor} this
219              * @param {Ext.core.Element} boundEl The underlying element bound to this editor
220              * @param {Mixed} value The starting field value
221              */
222             'startedit',
223 <span id='Ext-Editor-event-beforecomplete'>            /**
224 </span>             * @event beforecomplete
225              * Fires after a change has been made to the field, but before the change is reflected in the underlying
226              * field.  Saving the change to the field can be canceled by returning false from the handler of this event.
227              * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
228              * event will not fire since no edit actually occurred.
229              * @param {Editor} this
230              * @param {Mixed} value The current field value
231              * @param {Mixed} startValue The original field value
232              */
233             'beforecomplete',
234 <span id='Ext-Editor-event-complete'>            /**
235 </span>             * @event complete
236              * Fires after editing is complete and any changed value has been written to the underlying field.
237              * @param {Ext.Editor} this
238              * @param {Mixed} value The current field value
239              * @param {Mixed} startValue The original field value
240              */
241             'complete',
242 <span id='Ext-Editor-event-canceledit'>            /**
243 </span>             * @event canceledit
244              * Fires after editing has been canceled and the editor's value has been reset.
245              * @param {Ext.Editor} this
246              * @param {Mixed} value The user-entered field value that was discarded
247              * @param {Mixed} startValue The original field value that was set back into the editor after cancel
248              */
249             'canceledit',
250 <span id='Ext-Editor-event-specialkey'>            /**
251 </span>             * @event specialkey
252              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
253              * {@link Ext.EventObject#getKey} to determine which key was pressed.
254              * @param {Ext.Editor} this
255              * @param {Ext.form.field.Field} The field attached to this editor
256              * @param {Ext.EventObject} event The event object
257              */
258             'specialkey'
259         );
260     },
261
262     // private
263     onAutoSize: function(){
264         this.doComponentLayout();
265     },
266
267     // private
268     onRender : function(ct, position) {
269         var me = this,
270             field = me.field;
271
272         me.callParent(arguments);
273
274         field.render(me.el);
275         //field.hide();
276         // Ensure the field doesn't get submitted as part of any form
277         field.inputEl.dom.name = '';
278         if (me.swallowKeys) {
279             field.inputEl.swallowEvent([
280                 'keypress', // *** Opera
281                 'keydown'   // *** all other browsers
282             ]);
283         }
284     },
285
286     // private
287     onSpecialKey : function(field, event) {
288         var me = this,
289             key = event.getKey(),
290             complete = me.completeOnEnter &amp;&amp; key == event.ENTER,
291             cancel = me.cancelOnEsc &amp;&amp; key == event.ESC;
292
293         if (complete || cancel) {
294             event.stopEvent();
295             // Must defer this slightly to prevent exiting edit mode before the field's own
296             // key nav can handle the enter key, e.g. selecting an item in a combobox list
297             Ext.defer(function() {
298                 if (complete) {
299                     me.completeEdit();
300                 } else {
301                     me.cancelEdit();
302                 }
303                 if (field.triggerBlur) {
304                     field.triggerBlur();
305                 }
306             }, 10);
307         }
308
309         this.fireEvent('specialkey', this, field, event);
310     },
311
312 <span id='Ext-Editor-method-startEdit'>    /**
313 </span>     * Starts the editing process and shows the editor.
314      * @param {Mixed} el The element to edit
315      * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
316       * to the innerHTML of el.
317      */
318     startEdit : function(el, value) {
319         var me = this,
320             field = me.field;
321
322         me.completeEdit();
323         me.boundEl = Ext.get(el);
324         value = Ext.isDefined(value) ? value : me.boundEl.dom.innerHTML;
325
326         if (!me.rendered) {
327             me.render(me.parentEl || document.body);
328         }
329
330         if (me.fireEvent('beforestartedit', me, me.boundEl, value) !== false) {
331             me.startValue = value;
332             me.show();
333             field.reset();
334             field.setValue(value);
335             me.realign(true);
336             field.focus(false, 10);
337             if (field.autoSize) {
338                 field.autoSize();
339             }
340             me.editing = true;
341         }
342     },
343
344 <span id='Ext-Editor-method-realign'>    /**
345 </span>     * Realigns the editor to the bound field based on the current alignment config value.
346      * @param {Boolean} autoSize (optional) True to size the field to the dimensions of the bound element.
347      */
348     realign : function(autoSize) {
349         var me = this;
350         if (autoSize === true) {
351             me.doComponentLayout();
352         }
353         me.alignTo(me.boundEl, me.alignment, me.offsets);
354     },
355
356 <span id='Ext-Editor-method-completeEdit'>    /**
357 </span>     * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
358      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
359      */
360     completeEdit : function(remainVisible) {
361         var me = this,
362             field = me.field,
363             value;
364
365         if (!me.editing) {
366             return;
367         }
368
369         // Assert combo values first
370         if (field.assertValue) {
371             field.assertValue();
372         }
373
374         value = me.getValue();
375         if (!field.isValid()) {
376             if (me.revertInvalid !== false) {
377                 me.cancelEdit(remainVisible);
378             }
379             return;
380         }
381
382         if (String(value) === String(me.startValue) &amp;&amp; me.ignoreNoChange) {
383             me.hideEdit(remainVisible);
384             return;
385         }
386
387         if (me.fireEvent('beforecomplete', me, value, me.startValue) !== false) {
388             // Grab the value again, may have changed in beforecomplete
389             value = me.getValue();
390             if (me.updateEl &amp;&amp; me.boundEl) {
391                 me.boundEl.update(value);
392             }
393             me.hideEdit(remainVisible);
394             me.fireEvent('complete', me, value, me.startValue);
395         }
396     },
397
398     // private
399     onShow : function() {
400         var me = this;
401
402         me.callParent(arguments);
403         if (me.hideEl !== false) {
404             me.boundEl.hide();
405         }
406         me.fireEvent(&quot;startedit&quot;, me.boundEl, me.startValue);
407     },
408
409 <span id='Ext-Editor-method-cancelEdit'>    /**
410 </span>     * Cancels the editing process and hides the editor without persisting any changes.  The field value will be
411      * reverted to the original starting value.
412      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
413      * cancel (defaults to false)
414      */
415     cancelEdit : function(remainVisible) {
416         var me = this,
417             startValue = me.startValue,
418             value;
419
420         if (me.editing) {
421             value = me.getValue();
422             me.setValue(startValue);
423             me.hideEdit(remainVisible);
424             me.fireEvent('canceledit', me, value, startValue);
425         }
426     },
427
428     // private
429     hideEdit: function(remainVisible) {
430         if (remainVisible !== true) {
431             this.editing = false;
432             this.hide();
433         }
434     },
435
436     // private
437     onBlur : function() {
438         var me = this;
439
440         // selectSameEditor flag allows the same editor to be started without onBlur firing on itself
441         if(me.allowBlur === true &amp;&amp; me.editing &amp;&amp; me.selectSameEditor !== true) {
442             me.completeEdit();
443         }
444     },
445
446     // private
447     onHide : function() {
448         var me = this,
449             field = me.field;
450
451         if (me.editing) {
452             me.completeEdit();
453             return;
454         }
455         field.blur();
456         if (field.collapse) {
457             field.collapse();
458         }
459
460         //field.hide();
461         if (me.hideEl !== false) {
462             me.boundEl.show();
463         }
464         me.callParent(arguments);
465     },
466
467 <span id='Ext-Editor-method-setValue'>    /**
468 </span>     * Sets the data value of the editor
469      * @param {Mixed} value Any valid value supported by the underlying field
470      */
471     setValue : function(value) {
472         this.field.setValue(value);
473     },
474
475 <span id='Ext-Editor-method-getValue'>    /**
476 </span>     * Gets the data value of the editor
477      * @return {Mixed} The data value
478      */
479     getValue : function() {
480         return this.field.getValue();
481     },
482
483     beforeDestroy : function() {
484         var me = this;
485
486         Ext.destroy(me.field);
487         delete me.field;
488         delete me.parentEl;
489         delete me.boundEl;
490
491         me.callParent(arguments);
492     }
493 });</pre>
494 </body>
495 </html>