Upgrade to ExtJS 4.0.7 - Released 10/19/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="../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-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.
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
106      */
107     revertInvalid: true,
108
109 <span id='Ext-Editor-cfg-ignoreNoChange'>    /**
110 </span>     * @cfg {Boolean} [ignoreNoChange=false]
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.  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=true]
118      * False to keep the bound element visible while the editor is displayed
119      */
120
121 <span id='Ext-Editor-cfg-value'>    /**
122 </span>     * @cfg {Object} value
123      * The data value of the underlying field
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.Element#alignTo} for more details).
130      */
131     alignment: 'c-c?',
132
133 <span id='Ext-Editor-cfg-offsets'>    /**
134 </span>     * @cfg {Number[]} offsets
135      * The offsets to use when aligning (see {@link Ext.Element#alignTo} for more details.
136      */
137     offsets: [0, 0],
138
139 <span id='Ext-Editor-cfg-shadow'>    /**
140 </span>     * @cfg {Boolean/String} shadow
141      * &quot;sides&quot; for sides/bottom only, &quot;frame&quot; for 4-way shadow, and &quot;drop&quot; for bottom-right shadow.
142      */
143     shadow : 'frame',
144
145 <span id='Ext-Editor-cfg-constrain'>    /**
146 </span>     * @cfg {Boolean} constrain
147      * True to constrain the editor to the viewport
148      */
149     constrain : false,
150
151 <span id='Ext-Editor-cfg-swallowKeys'>    /**
152 </span>     * @cfg {Boolean} swallowKeys
153      * Handle the keydown/keypress events so they don't propagate
154      */
155     swallowKeys : true,
156
157 <span id='Ext-Editor-cfg-completeOnEnter'>    /**
158 </span>     * @cfg {Boolean} completeOnEnter
159      * True to complete the edit when the enter key is pressed.
160      */
161     completeOnEnter : true,
162
163 <span id='Ext-Editor-cfg-cancelOnEsc'>    /**
164 </span>     * @cfg {Boolean} cancelOnEsc
165      * True to cancel the edit when the escape key is pressed.
166      */
167     cancelOnEsc : true,
168
169 <span id='Ext-Editor-cfg-updateEl'>    /**
170 </span>     * @cfg {Boolean} updateEl
171      * True to update the innerHTML of the bound element when the update completes
172      */
173     updateEl : false,
174
175 <span id='Ext-Editor-cfg-parentEl'>    /**
176 </span>     * @cfg {String/HTMLElement/Ext.Element} parentEl
177      * An element to render to. Defaults to the &lt;tt&gt;document.body&lt;/tt&gt;.
178      */
179
180     // private overrides
181     hidden: true,
182     baseCls: Ext.baseCSSPrefix + 'editor',
183
184     initComponent : function() {
185         var me = this,
186             field = me.field = Ext.ComponentManager.create(me.field, 'textfield');
187
188         Ext.apply(field, {
189             inEditor: true,
190             msgTarget: field.msgTarget == 'title' ? 'title' :  'qtip'
191         });
192         me.mon(field, {
193             scope: me,
194             blur: {
195                 fn: me.onBlur,
196                 // slight delay to avoid race condition with startEdits (e.g. grid view refresh)
197                 delay: 1
198             },
199             specialkey: me.onSpecialKey
200         });
201
202         if (field.grow) {
203             me.mon(field, 'autosize', me.onAutoSize,  me, {delay: 1});
204         }
205         me.floating = {
206             constrain: me.constrain
207         };
208
209         me.callParent(arguments);
210
211         me.addEvents(
212 <span id='Ext-Editor-event-beforestartedit'>            /**
213 </span>             * @event beforestartedit
214              * Fires when editing is initiated, but before the value changes.  Editing can be canceled by returning
215              * false from the handler of this event.
216              * @param {Ext.Editor} this
217              * @param {Ext.Element} boundEl The underlying element bound to this editor
218              * @param {Object} value The field value being set
219              */
220             'beforestartedit',
221
222 <span id='Ext-Editor-event-startedit'>            /**
223 </span>             * @event startedit
224              * Fires when this editor is displayed
225              * @param {Ext.Editor} this
226              * @param {Ext.Element} boundEl The underlying element bound to this editor
227              * @param {Object} value The starting field value
228              */
229             'startedit',
230
231 <span id='Ext-Editor-event-beforecomplete'>            /**
232 </span>             * @event beforecomplete
233              * Fires after a change has been made to the field, but before the change is reflected in the underlying
234              * field.  Saving the change to the field can be canceled by returning false from the handler of this event.
235              * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
236              * event will not fire since no edit actually occurred.
237              * @param {Ext.Editor} this
238              * @param {Object} value The current field value
239              * @param {Object} startValue The original field value
240              */
241             'beforecomplete',
242 <span id='Ext-Editor-event-complete'>            /**
243 </span>             * @event complete
244              * Fires after editing is complete and any changed value has been written to the underlying field.
245              * @param {Ext.Editor} this
246              * @param {Object} value The current field value
247              * @param {Object} startValue The original field value
248              */
249             'complete',
250 <span id='Ext-Editor-event-canceledit'>            /**
251 </span>             * @event canceledit
252              * Fires after editing has been canceled and the editor's value has been reset.
253              * @param {Ext.Editor} this
254              * @param {Object} value The user-entered field value that was discarded
255              * @param {Object} startValue The original field value that was set back into the editor after cancel
256              */
257             'canceledit',
258 <span id='Ext-Editor-event-specialkey'>            /**
259 </span>             * @event specialkey
260              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
261              * {@link Ext.EventObject#getKey} to determine which key was pressed.
262              * @param {Ext.Editor} this
263              * @param {Ext.form.field.Field} The field attached to this editor
264              * @param {Ext.EventObject} event The event object
265              */
266             'specialkey'
267         );
268     },
269
270     // private
271     onAutoSize: function(){
272         this.doComponentLayout();
273     },
274
275     // private
276     onRender : function(ct, position) {
277         var me = this,
278             field = me.field,
279             inputEl = field.inputEl;
280
281         me.callParent(arguments);
282
283         field.render(me.el);
284         //field.hide();
285         // Ensure the field doesn't get submitted as part of any form
286         if (inputEl) {
287             inputEl.dom.name = '';
288             if (me.swallowKeys) {
289                 inputEl.swallowEvent([
290                     'keypress', // *** Opera
291                     'keydown'   // *** all other browsers
292                 ]);
293             }
294         }
295     },
296
297     // private
298     onSpecialKey : function(field, event) {
299         var me = this,
300             key = event.getKey(),
301             complete = me.completeOnEnter &amp;&amp; key == event.ENTER,
302             cancel = me.cancelOnEsc &amp;&amp; key == event.ESC;
303
304         if (complete || cancel) {
305             event.stopEvent();
306             // Must defer this slightly to prevent exiting edit mode before the field's own
307             // key nav can handle the enter key, e.g. selecting an item in a combobox list
308             Ext.defer(function() {
309                 if (complete) {
310                     me.completeEdit();
311                 } else {
312                     me.cancelEdit();
313                 }
314                 if (field.triggerBlur) {
315                     field.triggerBlur();
316                 }
317             }, 10);
318         }
319
320         this.fireEvent('specialkey', this, field, event);
321     },
322
323 <span id='Ext-Editor-method-startEdit'>    /**
324 </span>     * Starts the editing process and shows the editor.
325      * @param {String/HTMLElement/Ext.Element} el The element to edit
326      * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
327       * to the innerHTML of el.
328      */
329     startEdit : function(el, value) {
330         var me = this,
331             field = me.field;
332
333         me.completeEdit();
334         me.boundEl = Ext.get(el);
335         value = Ext.isDefined(value) ? value : me.boundEl.dom.innerHTML;
336
337         if (!me.rendered) {
338             me.render(me.parentEl || document.body);
339         }
340
341         if (me.fireEvent('beforestartedit', me, me.boundEl, value) !== false) {
342             me.startValue = value;
343             me.show();
344             field.reset();
345             field.setValue(value);
346             me.realign(true);
347             field.focus(false, 10);
348             if (field.autoSize) {
349                 field.autoSize();
350             }
351             me.editing = true;
352         }
353     },
354
355 <span id='Ext-Editor-method-realign'>    /**
356 </span>     * Realigns the editor to the bound field based on the current alignment config value.
357      * @param {Boolean} autoSize (optional) True to size the field to the dimensions of the bound element.
358      */
359     realign : function(autoSize) {
360         var me = this;
361         if (autoSize === true) {
362             me.doComponentLayout();
363         }
364         me.alignTo(me.boundEl, me.alignment, me.offsets);
365     },
366
367 <span id='Ext-Editor-method-completeEdit'>    /**
368 </span>     * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
369      * @param {Boolean} [remainVisible=false] Override the default behavior and keep the editor visible after edit
370      */
371     completeEdit : function(remainVisible) {
372         var me = this,
373             field = me.field,
374             value;
375
376         if (!me.editing) {
377             return;
378         }
379
380         // Assert combo values first
381         if (field.assertValue) {
382             field.assertValue();
383         }
384
385         value = me.getValue();
386         if (!field.isValid()) {
387             if (me.revertInvalid !== false) {
388                 me.cancelEdit(remainVisible);
389             }
390             return;
391         }
392
393         if (String(value) === String(me.startValue) &amp;&amp; me.ignoreNoChange) {
394             me.hideEdit(remainVisible);
395             return;
396         }
397
398         if (me.fireEvent('beforecomplete', me, value, me.startValue) !== false) {
399             // Grab the value again, may have changed in beforecomplete
400             value = me.getValue();
401             if (me.updateEl &amp;&amp; me.boundEl) {
402                 me.boundEl.update(value);
403             }
404             me.hideEdit(remainVisible);
405             me.fireEvent('complete', me, value, me.startValue);
406         }
407     },
408
409     // private
410     onShow : function() {
411         var me = this;
412
413         me.callParent(arguments);
414         if (me.hideEl !== false) {
415             me.boundEl.hide();
416         }
417         me.fireEvent(&quot;startedit&quot;, me.boundEl, me.startValue);
418     },
419
420 <span id='Ext-Editor-method-cancelEdit'>    /**
421 </span>     * Cancels the editing process and hides the editor without persisting any changes.  The field value will be
422      * reverted to the original starting value.
423      * @param {Boolean} [remainVisible=false] Override the default behavior and keep the editor visible after cancel
424      */
425     cancelEdit : function(remainVisible) {
426         var me = this,
427             startValue = me.startValue,
428             value;
429
430         if (me.editing) {
431             value = me.getValue();
432             me.setValue(startValue);
433             me.hideEdit(remainVisible);
434             me.fireEvent('canceledit', me, value, startValue);
435         }
436     },
437
438     // private
439     hideEdit: function(remainVisible) {
440         if (remainVisible !== true) {
441             this.editing = false;
442             this.hide();
443         }
444     },
445
446     // private
447     onBlur : function() {
448         var me = this;
449
450         // selectSameEditor flag allows the same editor to be started without onBlur firing on itself
451         if(me.allowBlur === true &amp;&amp; me.editing &amp;&amp; me.selectSameEditor !== true) {
452             me.completeEdit();
453         }
454     },
455
456     // private
457     onHide : function() {
458         var me = this,
459             field = me.field;
460
461         if (me.editing) {
462             me.completeEdit();
463             return;
464         }
465         field.blur();
466         if (field.collapse) {
467             field.collapse();
468         }
469
470         //field.hide();
471         if (me.hideEl !== false) {
472             me.boundEl.show();
473         }
474         me.callParent(arguments);
475     },
476
477 <span id='Ext-Editor-method-setValue'>    /**
478 </span>     * Sets the data value of the editor
479      * @param {Object} value Any valid value supported by the underlying field
480      */
481     setValue : function(value) {
482         this.field.setValue(value);
483     },
484
485 <span id='Ext-Editor-method-getValue'>    /**
486 </span>     * Gets the data value of the editor
487      * @return {Object} The data value
488      */
489     getValue : function() {
490         return this.field.getValue();
491     },
492
493     beforeDestroy : function() {
494         var me = this;
495
496         Ext.destroy(me.field);
497         delete me.field;
498         delete me.parentEl;
499         delete me.boundEl;
500
501         me.callParent(arguments);
502     }
503 });</pre>
504 </body>
505 </html>