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