Upgrade to ExtJS 4.0.1 - Released 05/18/2011
[extjs.git] / docs / source / Editing.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">
19 <span id='Ext-grid-plugin-Editing'>/**
20 </span> * @class Ext.grid.plugin.Editing
21
22 This class provides an abstract grid editing plugin on selected {@link Ext.grid.column.Column columns}.
23 The editable columns are specified by providing an {@link Ext.grid.column.Column#editor editor}
24 in the {@link Ext.grid.column.Column column configuration}.
25
26 *Note:* This class should not be used directly. See {@link Ext.grid.plugin.CellEditing} and
27 {@link Ext.grid.plugin.RowEditing}.
28
29  * @markdown
30  */
31 Ext.define('Ext.grid.plugin.Editing', {
32     alias: 'editing.editing',
33
34     requires: [
35         'Ext.grid.column.Column',
36         'Ext.util.KeyNav'
37     ],
38
39     mixins: {
40         observable: 'Ext.util.Observable'
41     },
42
43 <span id='Ext-grid-plugin-Editing-cfg-clicksToEdit'>    /**
44 </span>     * @cfg {Number} clicksToEdit
45      * The number of clicks on a grid required to display the editor (defaults to 2).
46      */
47     clicksToEdit: 2,
48
49     // private
50     defaultFieldXType: 'textfield',
51
52     // cell, row, form
53     editStyle: '',
54
55     constructor: function(config) {
56         var me = this;
57         Ext.apply(me, config);
58
59         me.addEvents(
60             // Doc'ed in separate editing plugins
61             'beforeedit',
62
63             // Doc'ed in separate editing plugins
64             'edit',
65
66             // Doc'ed in separate editing plugins
67             'validateedit'
68         );
69         me.mixins.observable.constructor.call(me);
70         // TODO: Deprecated, remove in 5.0
71         me.relayEvents(me, ['afteredit'], 'after');
72     },
73
74     // private
75     init: function(grid) {
76         var me = this;
77
78         me.grid = grid;
79         me.view = grid.view;
80         me.initEvents();
81         me.initFieldAccessors(me.view.getGridColumns());
82
83         grid.relayEvents(me, ['beforeedit', 'edit', 'validateedit']);
84         // Marks the grid as editable, so that the SelectionModel
85         // can make appropriate decisions during navigation
86         grid.isEditable = true;
87         grid.editingPlugin = grid.view.editingPlugin = me;
88     },
89
90 <span id='Ext-grid-plugin-Editing-method-destroy'>    /**
91 </span>     * @private
92      * AbstractComponent calls destroy on all its plugins at destroy time.
93      */
94     destroy: function() {
95         var me = this,
96             grid = me.grid,
97             headerCt = grid.headerCt,
98             events = grid.events;
99
100         Ext.destroy(me.keyNav);
101         me.removeFieldAccessors(grid.getView().getGridColumns());
102
103         // Clear all listeners from all our events, clear all managed listeners we added to other Observables
104         me.clearListeners();
105
106         delete me.grid.editingPlugin;
107         delete me.grid.view.editingPlugin;
108         delete me.grid;
109         delete me.view;
110         delete me.editor;
111         delete me.keyNav;
112     },
113
114     // private
115     getEditStyle: function() {
116         return this.editStyle;
117     },
118
119     // private
120     initFieldAccessors: function(column) {
121         var me = this;
122
123         if (Ext.isArray(column)) {
124             Ext.Array.forEach(column, me.initFieldAccessors, me);
125             return;
126         }
127
128         // Augment the Header class to have a getEditor and setEditor method
129         // Important: Only if the header does not have its own implementation.
130         Ext.applyIf(column, {
131             getEditor: function(record, defaultField) {
132                 return me.getColumnField(this, defaultField);
133             },
134
135             setEditor: function(field) {
136                 me.setColumnField(this, field);
137             }
138         });
139     },
140
141     // private
142     removeFieldAccessors: function(column) {
143         var me = this;
144
145         if (Ext.isArray(column)) {
146             Ext.Array.forEach(column, me.removeFieldAccessors, me);
147             return;
148         }
149
150         delete column.getEditor;
151         delete column.setEditor;
152     },
153
154     // private
155     // remaps to the public API of Ext.grid.column.Column.getEditor
156     getColumnField: function(columnHeader, defaultField) {
157         var field = columnHeader.field;
158
159         if (!field &amp;&amp; columnHeader.editor) {
160             field = columnHeader.editor;
161             delete columnHeader.editor;
162         }
163
164         if (!field &amp;&amp; defaultField) {
165             field = defaultField;
166         }
167
168         if (field) {
169             if (Ext.isString(field)) {
170                 field = { xtype: field };
171             }
172             if (Ext.isObject(field) &amp;&amp; !field.isFormField) {
173                 field = Ext.ComponentManager.create(field, this.defaultFieldXType);
174                 columnHeader.field = field;
175             }
176
177             Ext.apply(field, {
178                 name: columnHeader.dataIndex
179             });
180
181             return field;
182         }
183     },
184
185     // private
186     // remaps to the public API of Ext.grid.column.Column.setEditor
187     setColumnField: function(column, field) {
188         if (Ext.isObject(field) &amp;&amp; !field.isFormField) {
189             field = Ext.ComponentManager.create(field, this.defaultFieldXType);
190         }
191         column.field = field;
192     },
193
194     // private
195     initEvents: function() {
196         var me = this;
197         me.initEditTriggers();
198         me.initCancelTriggers();
199     },
200
201     // @abstract
202     initCancelTriggers: Ext.emptyFn,
203
204     // private
205     initEditTriggers: function() {
206         var me = this,
207             view = me.view,
208             clickEvent = me.clicksToEdit === 1 ? 'click' : 'dblclick';
209
210         // Start editing
211         me.mon(view, 'cell' + clickEvent, me.startEditByClick, me);
212         view.on('render', function() {
213             me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
214                 enter: me.onEnterKey,
215                 esc: me.onEscKey,
216                 scope: me
217             });
218         }, me, { single: true });
219     },
220
221     // private
222     onEnterKey: function(e) {
223         var me = this,
224             grid = me.grid,
225             selModel = grid.getSelectionModel(),
226             record,
227             columnHeader = grid.headerCt.getHeaderAtIndex(0);
228
229         // Calculate editing start position from SelectionModel
230         // CellSelectionModel
231         if (selModel.getCurrentPosition) {
232             pos = selModel.getCurrentPosition();
233             record = grid.store.getAt(pos.row);
234             columnHeader = grid.headerCt.getHeaderAtIndex(pos.column);
235         }
236         // RowSelectionModel
237         else {
238             record = selModel.getLastSelected();
239         }
240         me.startEdit(record, columnHeader);
241     },
242
243     // private
244     onEscKey: function(e) {
245         this.cancelEdit();
246     },
247
248     // private
249     startEditByClick: function(view, cell, colIdx, record, row, rowIdx, e) {
250         this.startEdit(record, view.getHeaderAtIndex(colIdx));
251     },
252
253 <span id='Ext-grid-plugin-Editing-property-beforeEdit'>    /**
254 </span>     * @private
255      * @abstract. Template method called before editing begins.
256      * @param {Object} context The current editing context
257      * @return {Boolean} Return false to cancel the editing process
258      */
259     beforeEdit: Ext.emptyFn,
260
261 <span id='Ext-grid-plugin-Editing-method-startEdit'>    /**
262 </span>     * Start editing the specified record, using the specified Column definition to define which field is being edited.
263      * @param {Model} record The Store data record which backs the row to be edited.
264      * @param {Model} columnHeader The Column object defining the column to be edited.
265      */
266     startEdit: function(record, columnHeader) {
267         var me = this,
268             context = me.getEditingContext(record, columnHeader);
269
270         if (me.beforeEdit(context) === false || me.fireEvent('beforeedit', context) === false || context.cancel) {
271             return false;
272         }
273
274         me.context = context;
275         me.editing = true;
276     },
277
278 <span id='Ext-grid-plugin-Editing-method-getEditingContext'>    /**
279 </span>     * @private Collects all information necessary for any subclasses to perform their editing functions.
280      * @param record
281      * @param columnHeader
282      * @returns {Object} The editing context based upon the passed record and column
283      */
284     getEditingContext: function(record, columnHeader) {
285         var me = this,
286             grid = me.grid,
287             store = grid.store,
288             rowIdx,
289             colIdx,
290             view = grid.getView(),
291             value;
292
293         // If they'd passed numeric row, column indices, look them up.
294         if (Ext.isNumber(record)) {
295             rowIdx = record;
296             record = store.getAt(rowIdx);
297         } else {
298             rowIdx = store.indexOf(record);
299         }
300         if (Ext.isNumber(columnHeader)) {
301             colIdx = columnHeader;
302             columnHeader = grid.headerCt.getHeaderAtIndex(colIdx);
303         } else {
304             colIdx = columnHeader.getIndex();
305         }
306
307         value = record.get(columnHeader.dataIndex);
308         return {
309             grid: grid,
310             record: record,
311             field: columnHeader.dataIndex,
312             value: value,
313             row: view.getNode(rowIdx),
314             column: columnHeader,
315             rowIdx: rowIdx,
316             colIdx: colIdx
317         };
318     },
319
320 <span id='Ext-grid-plugin-Editing-method-cancelEdit'>    /**
321 </span>     * Cancel any active edit that is in progress.
322      */
323     cancelEdit: function() {
324         this.editing = false;
325     },
326
327 <span id='Ext-grid-plugin-Editing-method-completeEdit'>    /**
328 </span>     * Complete the edit if there is an active edit in progress.
329      */
330     completeEdit: function() {
331         var me = this;
332
333         if (me.editing &amp;&amp; me.validateEdit()) {
334             me.fireEvent('edit', me.context);
335         }
336
337         delete me.context;
338         me.editing = false;
339     },
340
341     // @abstract
342     validateEdit: function() {
343         var me = this,
344             context = me.context;
345
346         return me.fireEvent('validateedit', me, context) !== false &amp;&amp; !context.cancel;
347     }
348 });</pre>
349 </body>
350 </html>