[76] | 1 | /*! |
---|
| 2 | * Ext JS Library 3.4.0 |
---|
| 3 | * Copyright(c) 2006-2011 Sencha Inc. |
---|
| 4 | * licensing@sencha.com |
---|
| 5 | * http://www.sencha.com/license |
---|
| 6 | */ |
---|
| 7 | /** |
---|
| 8 | * @class Ext.grid.CellSelectionModel |
---|
| 9 | * @extends Ext.grid.AbstractSelectionModel |
---|
| 10 | * This class provides the basic implementation for <i>single</i> <b>cell</b> selection in a grid. |
---|
| 11 | * The object stored as the selection contains the following properties: |
---|
| 12 | * <div class="mdetail-params"><ul> |
---|
| 13 | * <li><b>cell</b> : see {@link #getSelectedCell} |
---|
| 14 | * <li><b>record</b> : Ext.data.record The {@link Ext.data.Record Record} |
---|
| 15 | * which provides the data for the row containing the selection</li> |
---|
| 16 | * </ul></div> |
---|
| 17 | * @constructor |
---|
| 18 | * @param {Object} config The object containing the configuration of this model. |
---|
| 19 | */ |
---|
| 20 | Ext.grid.CellSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel, { |
---|
| 21 | |
---|
| 22 | constructor : function(config){ |
---|
| 23 | Ext.apply(this, config); |
---|
| 24 | |
---|
| 25 | this.selection = null; |
---|
| 26 | |
---|
| 27 | this.addEvents( |
---|
| 28 | /** |
---|
| 29 | * @event beforecellselect |
---|
| 30 | * Fires before a cell is selected, return false to cancel the selection. |
---|
| 31 | * @param {SelectionModel} this |
---|
| 32 | * @param {Number} rowIndex The selected row index |
---|
| 33 | * @param {Number} colIndex The selected cell index |
---|
| 34 | */ |
---|
| 35 | "beforecellselect", |
---|
| 36 | /** |
---|
| 37 | * @event cellselect |
---|
| 38 | * Fires when a cell is selected. |
---|
| 39 | * @param {SelectionModel} this |
---|
| 40 | * @param {Number} rowIndex The selected row index |
---|
| 41 | * @param {Number} colIndex The selected cell index |
---|
| 42 | */ |
---|
| 43 | "cellselect", |
---|
| 44 | /** |
---|
| 45 | * @event selectionchange |
---|
| 46 | * Fires when the active selection changes. |
---|
| 47 | * @param {SelectionModel} this |
---|
| 48 | * @param {Object} selection null for no selection or an object with two properties |
---|
| 49 | * <div class="mdetail-params"><ul> |
---|
| 50 | * <li><b>cell</b> : see {@link #getSelectedCell} |
---|
| 51 | * <li><b>record</b> : Ext.data.record<p class="sub-desc">The {@link Ext.data.Record Record} |
---|
| 52 | * which provides the data for the row containing the selection</p></li> |
---|
| 53 | * </ul></div> |
---|
| 54 | */ |
---|
| 55 | "selectionchange" |
---|
| 56 | ); |
---|
| 57 | |
---|
| 58 | Ext.grid.CellSelectionModel.superclass.constructor.call(this); |
---|
| 59 | }, |
---|
| 60 | |
---|
| 61 | /** @ignore */ |
---|
| 62 | initEvents : function(){ |
---|
| 63 | this.grid.on('cellmousedown', this.handleMouseDown, this); |
---|
| 64 | this.grid.on(Ext.EventManager.getKeyEvent(), this.handleKeyDown, this); |
---|
| 65 | this.grid.getView().on({ |
---|
| 66 | scope: this, |
---|
| 67 | refresh: this.onViewChange, |
---|
| 68 | rowupdated: this.onRowUpdated, |
---|
| 69 | beforerowremoved: this.clearSelections, |
---|
| 70 | beforerowsinserted: this.clearSelections |
---|
| 71 | }); |
---|
| 72 | if(this.grid.isEditor){ |
---|
| 73 | this.grid.on('beforeedit', this.beforeEdit, this); |
---|
| 74 | } |
---|
| 75 | }, |
---|
| 76 | |
---|
| 77 | //private |
---|
| 78 | beforeEdit : function(e){ |
---|
| 79 | this.select(e.row, e.column, false, true, e.record); |
---|
| 80 | }, |
---|
| 81 | |
---|
| 82 | //private |
---|
| 83 | onRowUpdated : function(v, index, r){ |
---|
| 84 | if(this.selection && this.selection.record == r){ |
---|
| 85 | v.onCellSelect(index, this.selection.cell[1]); |
---|
| 86 | } |
---|
| 87 | }, |
---|
| 88 | |
---|
| 89 | //private |
---|
| 90 | onViewChange : function(){ |
---|
| 91 | this.clearSelections(true); |
---|
| 92 | }, |
---|
| 93 | |
---|
| 94 | /** |
---|
| 95 | * Returns an array containing the row and column indexes of the currently selected cell |
---|
| 96 | * (e.g., [0, 0]), or null if none selected. The array has elements: |
---|
| 97 | * <div class="mdetail-params"><ul> |
---|
| 98 | * <li><b>rowIndex</b> : Number<p class="sub-desc">The index of the selected row</p></li> |
---|
| 99 | * <li><b>cellIndex</b> : Number<p class="sub-desc">The index of the selected cell. |
---|
| 100 | * Due to possible column reordering, the cellIndex should <b>not</b> be used as an |
---|
| 101 | * index into the Record's data. Instead, use the cellIndex to determine the <i>name</i> |
---|
| 102 | * of the selected cell and use the field name to retrieve the data value from the record:<pre><code> |
---|
| 103 | // get name |
---|
| 104 | var fieldName = grid.getColumnModel().getDataIndex(cellIndex); |
---|
| 105 | // get data value based on name |
---|
| 106 | var data = record.get(fieldName); |
---|
| 107 | * </code></pre></p></li> |
---|
| 108 | * </ul></div> |
---|
| 109 | * @return {Array} An array containing the row and column indexes of the selected cell, or null if none selected. |
---|
| 110 | */ |
---|
| 111 | getSelectedCell : function(){ |
---|
| 112 | return this.selection ? this.selection.cell : null; |
---|
| 113 | }, |
---|
| 114 | |
---|
| 115 | /** |
---|
| 116 | * If anything is selected, clears all selections and fires the selectionchange event. |
---|
| 117 | * @param {Boolean} preventNotify <tt>true</tt> to prevent the gridview from |
---|
| 118 | * being notified about the change. |
---|
| 119 | */ |
---|
| 120 | clearSelections : function(preventNotify){ |
---|
| 121 | var s = this.selection; |
---|
| 122 | if(s){ |
---|
| 123 | if(preventNotify !== true){ |
---|
| 124 | this.grid.view.onCellDeselect(s.cell[0], s.cell[1]); |
---|
| 125 | } |
---|
| 126 | this.selection = null; |
---|
| 127 | this.fireEvent("selectionchange", this, null); |
---|
| 128 | } |
---|
| 129 | }, |
---|
| 130 | |
---|
| 131 | /** |
---|
| 132 | * Returns <tt>true</tt> if there is a selection. |
---|
| 133 | * @return {Boolean} |
---|
| 134 | */ |
---|
| 135 | hasSelection : function(){ |
---|
| 136 | return this.selection ? true : false; |
---|
| 137 | }, |
---|
| 138 | |
---|
| 139 | /** @ignore */ |
---|
| 140 | handleMouseDown : function(g, row, cell, e){ |
---|
| 141 | if(e.button !== 0 || this.isLocked()){ |
---|
| 142 | return; |
---|
| 143 | } |
---|
| 144 | this.select(row, cell); |
---|
| 145 | }, |
---|
| 146 | |
---|
| 147 | /** |
---|
| 148 | * Selects a cell. Before selecting a cell, fires the |
---|
| 149 | * {@link #beforecellselect} event. If this check is satisfied the cell |
---|
| 150 | * will be selected and followed up by firing the {@link #cellselect} and |
---|
| 151 | * {@link #selectionchange} events. |
---|
| 152 | * @param {Number} rowIndex The index of the row to select |
---|
| 153 | * @param {Number} colIndex The index of the column to select |
---|
| 154 | * @param {Boolean} preventViewNotify (optional) Specify <tt>true</tt> to |
---|
| 155 | * prevent notifying the view (disables updating the selected appearance) |
---|
| 156 | * @param {Boolean} preventFocus (optional) Whether to prevent the cell at |
---|
| 157 | * the specified rowIndex / colIndex from being focused. |
---|
| 158 | * @param {Ext.data.Record} r (optional) The record to select |
---|
| 159 | */ |
---|
| 160 | select : function(rowIndex, colIndex, preventViewNotify, preventFocus, /*internal*/ r){ |
---|
| 161 | if(this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false){ |
---|
| 162 | this.clearSelections(); |
---|
| 163 | r = r || this.grid.store.getAt(rowIndex); |
---|
| 164 | this.selection = { |
---|
| 165 | record : r, |
---|
| 166 | cell : [rowIndex, colIndex] |
---|
| 167 | }; |
---|
| 168 | if(!preventViewNotify){ |
---|
| 169 | var v = this.grid.getView(); |
---|
| 170 | v.onCellSelect(rowIndex, colIndex); |
---|
| 171 | if(preventFocus !== true){ |
---|
| 172 | v.focusCell(rowIndex, colIndex); |
---|
| 173 | } |
---|
| 174 | } |
---|
| 175 | this.fireEvent("cellselect", this, rowIndex, colIndex); |
---|
| 176 | this.fireEvent("selectionchange", this, this.selection); |
---|
| 177 | } |
---|
| 178 | }, |
---|
| 179 | |
---|
| 180 | //private |
---|
| 181 | isSelectable : function(rowIndex, colIndex, cm){ |
---|
| 182 | return !cm.isHidden(colIndex); |
---|
| 183 | }, |
---|
| 184 | |
---|
| 185 | // private |
---|
| 186 | onEditorKey: function(field, e){ |
---|
| 187 | if(e.getKey() == e.TAB){ |
---|
| 188 | this.handleKeyDown(e); |
---|
| 189 | } |
---|
| 190 | }, |
---|
| 191 | |
---|
| 192 | /** @ignore */ |
---|
| 193 | handleKeyDown : function(e){ |
---|
| 194 | if(!e.isNavKeyPress()){ |
---|
| 195 | return; |
---|
| 196 | } |
---|
| 197 | |
---|
| 198 | var k = e.getKey(), |
---|
| 199 | g = this.grid, |
---|
| 200 | s = this.selection, |
---|
| 201 | sm = this, |
---|
| 202 | walk = function(row, col, step){ |
---|
| 203 | return g.walkCells( |
---|
| 204 | row, |
---|
| 205 | col, |
---|
| 206 | step, |
---|
| 207 | g.isEditor && g.editing ? sm.acceptsNav : sm.isSelectable, // *** handle tabbing while editorgrid is in edit mode |
---|
| 208 | sm |
---|
| 209 | ); |
---|
| 210 | }, |
---|
| 211 | cell, newCell, r, c, ae; |
---|
| 212 | |
---|
| 213 | switch(k){ |
---|
| 214 | case e.ESC: |
---|
| 215 | case e.PAGE_UP: |
---|
| 216 | case e.PAGE_DOWN: |
---|
| 217 | // do nothing |
---|
| 218 | break; |
---|
| 219 | default: |
---|
| 220 | // *** call e.stopEvent() only for non ESC, PAGE UP/DOWN KEYS |
---|
| 221 | e.stopEvent(); |
---|
| 222 | break; |
---|
| 223 | } |
---|
| 224 | |
---|
| 225 | if(!s){ |
---|
| 226 | cell = walk(0, 0, 1); // *** use private walk() function defined above |
---|
| 227 | if(cell){ |
---|
| 228 | this.select(cell[0], cell[1]); |
---|
| 229 | } |
---|
| 230 | return; |
---|
| 231 | } |
---|
| 232 | |
---|
| 233 | cell = s.cell; // currently selected cell |
---|
| 234 | r = cell[0]; // current row |
---|
| 235 | c = cell[1]; // current column |
---|
| 236 | |
---|
| 237 | switch(k){ |
---|
| 238 | case e.TAB: |
---|
| 239 | if(e.shiftKey){ |
---|
| 240 | newCell = walk(r, c - 1, -1); |
---|
| 241 | }else{ |
---|
| 242 | newCell = walk(r, c + 1, 1); |
---|
| 243 | } |
---|
| 244 | break; |
---|
| 245 | case e.DOWN: |
---|
| 246 | newCell = walk(r + 1, c, 1); |
---|
| 247 | break; |
---|
| 248 | case e.UP: |
---|
| 249 | newCell = walk(r - 1, c, -1); |
---|
| 250 | break; |
---|
| 251 | case e.RIGHT: |
---|
| 252 | newCell = walk(r, c + 1, 1); |
---|
| 253 | break; |
---|
| 254 | case e.LEFT: |
---|
| 255 | newCell = walk(r, c - 1, -1); |
---|
| 256 | break; |
---|
| 257 | case e.ENTER: |
---|
| 258 | if (g.isEditor && !g.editing) { |
---|
| 259 | g.startEditing(r, c); |
---|
| 260 | return; |
---|
| 261 | } |
---|
| 262 | break; |
---|
| 263 | } |
---|
| 264 | |
---|
| 265 | if(newCell){ |
---|
| 266 | // *** reassign r & c variables to newly-selected cell's row and column |
---|
| 267 | r = newCell[0]; |
---|
| 268 | c = newCell[1]; |
---|
| 269 | |
---|
| 270 | this.select(r, c); // *** highlight newly-selected cell and update selection |
---|
| 271 | |
---|
| 272 | if(g.isEditor && g.editing){ // *** handle tabbing while editorgrid is in edit mode |
---|
| 273 | ae = g.activeEditor; |
---|
| 274 | if(ae && ae.field.triggerBlur){ |
---|
| 275 | // *** if activeEditor is a TriggerField, explicitly call its triggerBlur() method |
---|
| 276 | ae.field.triggerBlur(); |
---|
| 277 | } |
---|
| 278 | g.startEditing(r, c); |
---|
| 279 | } |
---|
| 280 | } |
---|
| 281 | }, |
---|
| 282 | |
---|
| 283 | acceptsNav : function(row, col, cm){ |
---|
| 284 | return !cm.isHidden(col) && cm.isCellEditable(col, row); |
---|
| 285 | } |
---|
| 286 | });/** |
---|
| 287 | * @class Ext.grid.EditorGridPanel |
---|
| 288 | * @extends Ext.grid.GridPanel |
---|
| 289 | * <p>This class extends the {@link Ext.grid.GridPanel GridPanel Class} to provide cell editing |
---|
| 290 | * on selected {@link Ext.grid.Column columns}. The editable columns are specified by providing |
---|
| 291 | * an {@link Ext.grid.ColumnModel#editor editor} in the {@link Ext.grid.Column column configuration}.</p> |
---|
| 292 | * <p>Editability of columns may be controlled programatically by inserting an implementation |
---|
| 293 | * of {@link Ext.grid.ColumnModel#isCellEditable isCellEditable} into the |
---|
| 294 | * {@link Ext.grid.ColumnModel ColumnModel}.</p> |
---|
| 295 | * <p>Editing is performed on the value of the <i>field</i> specified by the column's |
---|
| 296 | * <tt>{@link Ext.grid.ColumnModel#dataIndex dataIndex}</tt> in the backing {@link Ext.data.Store Store} |
---|
| 297 | * (so if you are using a {@link Ext.grid.ColumnModel#setRenderer renderer} in order to display |
---|
| 298 | * transformed data, this must be accounted for).</p> |
---|
| 299 | * <p>If a value-to-description mapping is used to render a column, then a {@link Ext.form.Field#ComboBox ComboBox} |
---|
| 300 | * which uses the same {@link Ext.form.Field#valueField value}-to-{@link Ext.form.Field#displayFieldField description} |
---|
| 301 | * mapping would be an appropriate editor.</p> |
---|
| 302 | * If there is a more complex mismatch between the visible data in the grid, and the editable data in |
---|
| 303 | * the {@link Edt.data.Store Store}, then code to transform the data both before and after editing can be |
---|
| 304 | * injected using the {@link #beforeedit} and {@link #afteredit} events. |
---|
| 305 | * @constructor |
---|
| 306 | * @param {Object} config The config object |
---|
| 307 | * @xtype editorgrid |
---|
| 308 | */ |
---|
| 309 | Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, { |
---|
| 310 | /** |
---|
| 311 | * @cfg {Number} clicksToEdit |
---|
| 312 | * <p>The number of clicks on a cell required to display the cell's editor (defaults to 2).</p> |
---|
| 313 | * <p>Setting this option to 'auto' means that mousedown <i>on the selected cell</i> starts |
---|
| 314 | * editing that cell.</p> |
---|
| 315 | */ |
---|
| 316 | clicksToEdit: 2, |
---|
| 317 | |
---|
| 318 | /** |
---|
| 319 | * @cfg {Boolean} forceValidation |
---|
| 320 | * True to force validation even if the value is unmodified (defaults to false) |
---|
| 321 | */ |
---|
| 322 | forceValidation: false, |
---|
| 323 | |
---|
| 324 | // private |
---|
| 325 | isEditor : true, |
---|
| 326 | // private |
---|
| 327 | detectEdit: false, |
---|
| 328 | |
---|
| 329 | /** |
---|
| 330 | * @cfg {Boolean} autoEncode |
---|
| 331 | * True to automatically HTML encode and decode values pre and post edit (defaults to false) |
---|
| 332 | */ |
---|
| 333 | autoEncode : false, |
---|
| 334 | |
---|
| 335 | /** |
---|
| 336 | * @cfg {Boolean} trackMouseOver @hide |
---|
| 337 | */ |
---|
| 338 | // private |
---|
| 339 | trackMouseOver: false, // causes very odd FF errors |
---|
| 340 | |
---|
| 341 | // private |
---|
| 342 | initComponent : function(){ |
---|
| 343 | Ext.grid.EditorGridPanel.superclass.initComponent.call(this); |
---|
| 344 | |
---|
| 345 | if(!this.selModel){ |
---|
| 346 | /** |
---|
| 347 | * @cfg {Object} selModel Any subclass of AbstractSelectionModel that will provide the selection model for |
---|
| 348 | * the grid (defaults to {@link Ext.grid.CellSelectionModel} if not specified). |
---|
| 349 | */ |
---|
| 350 | this.selModel = new Ext.grid.CellSelectionModel(); |
---|
| 351 | } |
---|
| 352 | |
---|
| 353 | this.activeEditor = null; |
---|
| 354 | |
---|
| 355 | this.addEvents( |
---|
| 356 | /** |
---|
| 357 | * @event beforeedit |
---|
| 358 | * Fires before cell editing is triggered. The edit event object has the following properties <br /> |
---|
| 359 | * <ul style="padding:5px;padding-left:16px;"> |
---|
| 360 | * <li>grid - This grid</li> |
---|
| 361 | * <li>record - The record being edited</li> |
---|
| 362 | * <li>field - The field name being edited</li> |
---|
| 363 | * <li>value - The value for the field being edited.</li> |
---|
| 364 | * <li>row - The grid row index</li> |
---|
| 365 | * <li>column - The grid column index</li> |
---|
| 366 | * <li>cancel - Set this to true to cancel the edit or return false from your handler.</li> |
---|
| 367 | * </ul> |
---|
| 368 | * @param {Object} e An edit event (see above for description) |
---|
| 369 | */ |
---|
| 370 | "beforeedit", |
---|
| 371 | /** |
---|
| 372 | * @event afteredit |
---|
| 373 | * Fires after a cell is edited. The edit event object has the following properties <br /> |
---|
| 374 | * <ul style="padding:5px;padding-left:16px;"> |
---|
| 375 | * <li>grid - This grid</li> |
---|
| 376 | * <li>record - The record being edited</li> |
---|
| 377 | * <li>field - The field name being edited</li> |
---|
| 378 | * <li>value - The value being set</li> |
---|
| 379 | * <li>originalValue - The original value for the field, before the edit.</li> |
---|
| 380 | * <li>row - The grid row index</li> |
---|
| 381 | * <li>column - The grid column index</li> |
---|
| 382 | * </ul> |
---|
| 383 | * |
---|
| 384 | * <pre><code> |
---|
| 385 | grid.on('afteredit', afterEdit, this ); |
---|
| 386 | |
---|
| 387 | function afterEdit(e) { |
---|
| 388 | // execute an XHR to send/commit data to the server, in callback do (if successful): |
---|
| 389 | e.record.commit(); |
---|
| 390 | }; |
---|
| 391 | * </code></pre> |
---|
| 392 | * @param {Object} e An edit event (see above for description) |
---|
| 393 | */ |
---|
| 394 | "afteredit", |
---|
| 395 | /** |
---|
| 396 | * @event validateedit |
---|
| 397 | * Fires after a cell is edited, but before the value is set in the record. Return false |
---|
| 398 | * to cancel the change. The edit event object has the following properties <br /> |
---|
| 399 | * <ul style="padding:5px;padding-left:16px;"> |
---|
| 400 | * <li>grid - This grid</li> |
---|
| 401 | * <li>record - The record being edited</li> |
---|
| 402 | * <li>field - The field name being edited</li> |
---|
| 403 | * <li>value - The value being set</li> |
---|
| 404 | * <li>originalValue - The original value for the field, before the edit.</li> |
---|
| 405 | * <li>row - The grid row index</li> |
---|
| 406 | * <li>column - The grid column index</li> |
---|
| 407 | * <li>cancel - Set this to true to cancel the edit or return false from your handler.</li> |
---|
| 408 | * </ul> |
---|
| 409 | * Usage example showing how to remove the red triangle (dirty record indicator) from some |
---|
| 410 | * records (not all). By observing the grid's validateedit event, it can be cancelled if |
---|
| 411 | * the edit occurs on a targeted row (for example) and then setting the field's new value |
---|
| 412 | * in the Record directly: |
---|
| 413 | * <pre><code> |
---|
| 414 | grid.on('validateedit', function(e) { |
---|
| 415 | var myTargetRow = 6; |
---|
| 416 | |
---|
| 417 | if (e.row == myTargetRow) { |
---|
| 418 | e.cancel = true; |
---|
| 419 | e.record.data[e.field] = e.value; |
---|
| 420 | } |
---|
| 421 | }); |
---|
| 422 | * </code></pre> |
---|
| 423 | * @param {Object} e An edit event (see above for description) |
---|
| 424 | */ |
---|
| 425 | "validateedit" |
---|
| 426 | ); |
---|
| 427 | }, |
---|
| 428 | |
---|
| 429 | // private |
---|
| 430 | initEvents : function(){ |
---|
| 431 | Ext.grid.EditorGridPanel.superclass.initEvents.call(this); |
---|
| 432 | |
---|
| 433 | this.getGridEl().on('mousewheel', this.stopEditing.createDelegate(this, [true]), this); |
---|
| 434 | this.on('columnresize', this.stopEditing, this, [true]); |
---|
| 435 | |
---|
| 436 | if(this.clicksToEdit == 1){ |
---|
| 437 | this.on("cellclick", this.onCellDblClick, this); |
---|
| 438 | }else { |
---|
| 439 | var view = this.getView(); |
---|
| 440 | if(this.clicksToEdit == 'auto' && view.mainBody){ |
---|
| 441 | view.mainBody.on('mousedown', this.onAutoEditClick, this); |
---|
| 442 | } |
---|
| 443 | this.on('celldblclick', this.onCellDblClick, this); |
---|
| 444 | } |
---|
| 445 | }, |
---|
| 446 | |
---|
| 447 | onResize : function(){ |
---|
| 448 | Ext.grid.EditorGridPanel.superclass.onResize.apply(this, arguments); |
---|
| 449 | var ae = this.activeEditor; |
---|
| 450 | if(this.editing && ae){ |
---|
| 451 | ae.realign(true); |
---|
| 452 | } |
---|
| 453 | }, |
---|
| 454 | |
---|
| 455 | // private |
---|
| 456 | onCellDblClick : function(g, row, col){ |
---|
| 457 | this.startEditing(row, col); |
---|
| 458 | }, |
---|
| 459 | |
---|
| 460 | // private |
---|
| 461 | onAutoEditClick : function(e, t){ |
---|
| 462 | if(e.button !== 0){ |
---|
| 463 | return; |
---|
| 464 | } |
---|
| 465 | var row = this.view.findRowIndex(t), |
---|
| 466 | col = this.view.findCellIndex(t); |
---|
| 467 | if(row !== false && col !== false){ |
---|
| 468 | this.stopEditing(); |
---|
| 469 | if(this.selModel.getSelectedCell){ // cell sm |
---|
| 470 | var sc = this.selModel.getSelectedCell(); |
---|
| 471 | if(sc && sc[0] === row && sc[1] === col){ |
---|
| 472 | this.startEditing(row, col); |
---|
| 473 | } |
---|
| 474 | }else{ |
---|
| 475 | if(this.selModel.isSelected(row)){ |
---|
| 476 | this.startEditing(row, col); |
---|
| 477 | } |
---|
| 478 | } |
---|
| 479 | } |
---|
| 480 | }, |
---|
| 481 | |
---|
| 482 | // private |
---|
| 483 | onEditComplete : function(ed, value, startValue){ |
---|
| 484 | this.editing = false; |
---|
| 485 | this.lastActiveEditor = this.activeEditor; |
---|
| 486 | this.activeEditor = null; |
---|
| 487 | |
---|
| 488 | var r = ed.record, |
---|
| 489 | field = this.colModel.getDataIndex(ed.col); |
---|
| 490 | value = this.postEditValue(value, startValue, r, field); |
---|
| 491 | if(this.forceValidation === true || String(value) !== String(startValue)){ |
---|
| 492 | var e = { |
---|
| 493 | grid: this, |
---|
| 494 | record: r, |
---|
| 495 | field: field, |
---|
| 496 | originalValue: startValue, |
---|
| 497 | value: value, |
---|
| 498 | row: ed.row, |
---|
| 499 | column: ed.col, |
---|
| 500 | cancel:false |
---|
| 501 | }; |
---|
| 502 | if(this.fireEvent("validateedit", e) !== false && !e.cancel && String(value) !== String(startValue)){ |
---|
| 503 | r.set(field, e.value); |
---|
| 504 | delete e.cancel; |
---|
| 505 | this.fireEvent("afteredit", e); |
---|
| 506 | } |
---|
| 507 | } |
---|
| 508 | this.view.focusCell(ed.row, ed.col); |
---|
| 509 | }, |
---|
| 510 | |
---|
| 511 | /** |
---|
| 512 | * Starts editing the specified for the specified row/column |
---|
| 513 | * @param {Number} rowIndex |
---|
| 514 | * @param {Number} colIndex |
---|
| 515 | */ |
---|
| 516 | startEditing : function(row, col){ |
---|
| 517 | this.stopEditing(); |
---|
| 518 | if(this.colModel.isCellEditable(col, row)){ |
---|
| 519 | this.view.ensureVisible(row, col, true); |
---|
| 520 | var r = this.store.getAt(row), |
---|
| 521 | field = this.colModel.getDataIndex(col), |
---|
| 522 | e = { |
---|
| 523 | grid: this, |
---|
| 524 | record: r, |
---|
| 525 | field: field, |
---|
| 526 | value: r.data[field], |
---|
| 527 | row: row, |
---|
| 528 | column: col, |
---|
| 529 | cancel:false |
---|
| 530 | }; |
---|
| 531 | if(this.fireEvent("beforeedit", e) !== false && !e.cancel){ |
---|
| 532 | this.editing = true; |
---|
| 533 | var ed = this.colModel.getCellEditor(col, row); |
---|
| 534 | if(!ed){ |
---|
| 535 | return; |
---|
| 536 | } |
---|
| 537 | if(!ed.rendered){ |
---|
| 538 | ed.parentEl = this.view.getEditorParent(ed); |
---|
| 539 | ed.on({ |
---|
| 540 | scope: this, |
---|
| 541 | render: { |
---|
| 542 | fn: function(c){ |
---|
| 543 | c.field.focus(false, true); |
---|
| 544 | }, |
---|
| 545 | single: true, |
---|
| 546 | scope: this |
---|
| 547 | }, |
---|
| 548 | specialkey: function(field, e){ |
---|
| 549 | this.getSelectionModel().onEditorKey(field, e); |
---|
| 550 | }, |
---|
| 551 | complete: this.onEditComplete, |
---|
| 552 | canceledit: this.stopEditing.createDelegate(this, [true]) |
---|
| 553 | }); |
---|
| 554 | } |
---|
| 555 | Ext.apply(ed, { |
---|
| 556 | row : row, |
---|
| 557 | col : col, |
---|
| 558 | record : r |
---|
| 559 | }); |
---|
| 560 | this.lastEdit = { |
---|
| 561 | row: row, |
---|
| 562 | col: col |
---|
| 563 | }; |
---|
| 564 | this.activeEditor = ed; |
---|
| 565 | // Set the selectSameEditor flag if we are reusing the same editor again and |
---|
| 566 | // need to prevent the editor from firing onBlur on itself. |
---|
| 567 | ed.selectSameEditor = (this.activeEditor == this.lastActiveEditor); |
---|
| 568 | var v = this.preEditValue(r, field); |
---|
| 569 | ed.startEdit(this.view.getCell(row, col).firstChild, Ext.isDefined(v) ? v : ''); |
---|
| 570 | |
---|
| 571 | // Clear the selectSameEditor flag |
---|
| 572 | (function(){ |
---|
| 573 | delete ed.selectSameEditor; |
---|
| 574 | }).defer(50); |
---|
| 575 | } |
---|
| 576 | } |
---|
| 577 | }, |
---|
| 578 | |
---|
| 579 | // private |
---|
| 580 | preEditValue : function(r, field){ |
---|
| 581 | var value = r.data[field]; |
---|
| 582 | return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlDecode(value) : value; |
---|
| 583 | }, |
---|
| 584 | |
---|
| 585 | // private |
---|
| 586 | postEditValue : function(value, originalValue, r, field){ |
---|
| 587 | return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlEncode(value) : value; |
---|
| 588 | }, |
---|
| 589 | |
---|
| 590 | /** |
---|
| 591 | * Stops any active editing |
---|
| 592 | * @param {Boolean} cancel (optional) True to cancel any changes |
---|
| 593 | */ |
---|
| 594 | stopEditing : function(cancel){ |
---|
| 595 | if(this.editing){ |
---|
| 596 | // Store the lastActiveEditor to check if it is changing |
---|
| 597 | var ae = this.lastActiveEditor = this.activeEditor; |
---|
| 598 | if(ae){ |
---|
| 599 | ae[cancel === true ? 'cancelEdit' : 'completeEdit'](); |
---|
| 600 | this.view.focusCell(ae.row, ae.col); |
---|
| 601 | } |
---|
| 602 | this.activeEditor = null; |
---|
| 603 | } |
---|
| 604 | this.editing = false; |
---|
| 605 | } |
---|
| 606 | }); |
---|
| 607 | Ext.reg('editorgrid', Ext.grid.EditorGridPanel);// private |
---|
| 608 | // This is a support class used internally by the Grid components |
---|
| 609 | Ext.grid.GridEditor = function(field, config){ |
---|
| 610 | Ext.grid.GridEditor.superclass.constructor.call(this, field, config); |
---|
| 611 | field.monitorTab = false; |
---|
| 612 | }; |
---|
| 613 | |
---|
| 614 | Ext.extend(Ext.grid.GridEditor, Ext.Editor, { |
---|
| 615 | alignment: "tl-tl", |
---|
| 616 | autoSize: "width", |
---|
| 617 | hideEl : false, |
---|
| 618 | cls: "x-small-editor x-grid-editor", |
---|
| 619 | shim:false, |
---|
| 620 | shadow:false |
---|
| 621 | }); |
---|