3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
4 <title>The source code</title>
5 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
6 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8 <body onload="prettyPrint();">
9 <pre class="prettyprint lang-js">/*!
10 * Ext JS Library 3.3.1
11 * Copyright(c) 2006-2010 Sencha Inc.
12 * licensing@sencha.com
13 * http://www.sencha.com/license
15 Ext.ns('Ext.ux.grid');
18 * @class Ext.ux.grid.RowEditor
20 * Plugin (ptype = 'roweditor') that adds the ability to rapidly edit full rows in a grid.
21 * A validation mode may be enabled which uses AnchorTips to notify the user of all
22 * validation errors at once.
26 Ext.ux.grid.RowEditor = Ext.extend(Ext.Panel, {
30 cls: 'x-small-editor',
31 buttonAlign: 'center',
32 baseCls: 'x-row-editor',
33 elements: 'header,footer,body',
43 commitChangesText: 'You need to commit or cancel your changes',
50 initComponent: function(){
51 Ext.ux.grid.RowEditor.superclass.initComponent.call(this);
53 <div id="event-Ext.ux.grid.RowEditor-beforeedit"></div>/**
55 * Fired before the row editor is activated.
56 * If the listener returns <tt>false</tt> the editor will not be activated.
57 * @param {Ext.ux.grid.RowEditor} roweditor This object
58 * @param {Number} rowIndex The rowIndex of the row just edited
61 <div id="event-Ext.ux.grid.RowEditor-canceledit"></div>/**
63 * Fired when the editor is cancelled.
64 * @param {Ext.ux.grid.RowEditor} roweditor This object
65 * @param {Boolean} forced True if the cancel button is pressed, false is the editor was invalid.
68 <div id="event-Ext.ux.grid.RowEditor-validateedit"></div>/**
70 * Fired after a row is edited and passes validation.
71 * If the listener returns <tt>false</tt> changes to the record will not be set.
72 * @param {Ext.ux.grid.RowEditor} roweditor This object
73 * @param {Object} changes Object with changes made to the record.
74 * @param {Ext.data.Record} r The Record that was edited.
75 * @param {Number} rowIndex The rowIndex of the row just edited
78 <div id="event-Ext.ux.grid.RowEditor-afteredit"></div>/**
80 * Fired after a row is edited and passes validation. This event is fired
81 * after the store's update event is fired with this edit.
82 * @param {Ext.ux.grid.RowEditor} roweditor This object
83 * @param {Object} changes Object with changes made to the record.
84 * @param {Ext.data.Record} r The Record that was edited.
85 * @param {Number} rowIndex The rowIndex of the row just edited
94 if(this.clicksToEdit === 2){
95 grid.on('rowdblclick', this.onRowDblClick, this);
97 grid.on('rowclick', this.onRowClick, this);
99 grid.on('rowdblclick', this.onRowDblClick, this);
103 // stopEditing without saving when a record is removed from Store.
104 grid.getStore().on('remove', function() {
105 this.stopEditing(false);
110 keydown: this.onGridKey,
111 columnresize: this.verifyLayout,
112 columnmove: this.refreshFields,
113 reconfigure: this.refreshFields,
114 beforedestroy : this.beforedestroy,
115 destroy : this.destroy,
118 fn: this.positionButtons
121 grid.getColumnModel().on('hiddenchange', this.verifyLayout, this, {delay:1});
122 grid.getView().on('refresh', this.stopEditing.createDelegate(this, []));
125 beforedestroy: function() {
126 this.stopMonitoring();
127 this.grid.getStore().un('remove', this.onStoreRemove, this);
128 this.stopEditing(false);
129 Ext.destroy(this.btns, this.tooltip);
132 refreshFields: function(){
139 this.items.each(function(f){
140 if(String(this.values[f.id]) !== String(f.getValue())){
148 startEditing: function(rowIndex, doFocus){
149 if(this.editing && this.isDirty()){
150 this.showTooltip(this.commitChangesText);
153 if(Ext.isObject(rowIndex)){
154 rowIndex = this.grid.getStore().indexOf(rowIndex);
156 if(this.fireEvent('beforeedit', this, rowIndex) !== false){
158 var g = this.grid, view = g.getView(),
159 row = view.getRow(rowIndex),
160 record = g.store.getAt(rowIndex);
162 this.record = record;
163 this.rowIndex = rowIndex;
166 this.render(view.getEditorParent());
168 var w = Ext.fly(row).getWidth();
170 if(!this.initialized){
173 var cm = g.getColumnModel(), fields = this.items.items, f, val;
174 for(var i = 0, len = cm.getColumnCount(); i < len; i++){
175 val = this.preEditValue(record, cm.getDataIndex(i));
178 this.values[f.id] = Ext.isEmpty(val) ? '' : val;
180 this.verifyLayout(true);
181 if(!this.isVisible()){
182 this.setPagePosition(Ext.fly(row).getXY());
184 this.el.setXY(Ext.fly(row).getXY(), {duration:0.15});
186 if(!this.isVisible()){
187 this.show().doLayout();
189 if(doFocus !== false){
190 this.doFocus.defer(this.focusDelay, this);
195 stopEditing : function(saveChanges){
196 this.editing = false;
197 if(!this.isVisible()){
200 if(saveChanges === false || !this.isValid()){
202 this.fireEvent('canceledit', this, saveChanges === false);
208 cm = this.grid.colModel,
209 fields = this.items.items;
210 for(var i = 0, len = cm.getColumnCount(); i < len; i++){
212 var dindex = cm.getDataIndex(i);
213 if(!Ext.isEmpty(dindex)){
214 var oldValue = r.data[dindex],
215 value = this.postEditValue(fields[i].getValue(), oldValue, r, dindex);
216 if(String(oldValue) !== String(value)){
217 changes[dindex] = value;
223 if(hasChange && this.fireEvent('validateedit', this, changes, r, this.rowIndex) !== false){
225 Ext.iterate(changes, function(name, value){
229 this.fireEvent('afteredit', this, changes, r, this.rowIndex);
234 verifyLayout: function(force){
235 if(this.el && (this.isVisible() || force === true)){
236 var row = this.grid.getView().getRow(this.rowIndex);
237 this.setSize(Ext.fly(row).getWidth(), Ext.isIE ? Ext.fly(row).getHeight() + 9 : undefined);
238 var cm = this.grid.colModel, fields = this.items.items;
239 for(var i = 0, len = cm.getColumnCount(); i < len; i++){
243 adjust += 3; // outer padding
248 fields[i].setWidth(cm.getColumnWidth(i) - adjust);
254 this.positionButtons();
258 slideHide : function(){
262 initFields: function(){
263 var cm = this.grid.getColumnModel(), pm = Ext.layout.ContainerLayout.prototype.parseMargins;
264 this.removeAll(false);
265 for(var i = 0, len = cm.getColumnCount(); i < len; i++){
266 var c = cm.getColumnAt(i),
269 ed = c.displayEditor || new Ext.form.DisplayField();
272 ed.margins = pm('0 1 2 1');
273 } else if(i == len - 1){
274 ed.margins = pm('0 0 2 1');
277 ed.margins = pm('0 0 2 0');
280 ed.margins = pm('0 1 2 0');
283 ed.setWidth(cm.getColumnWidth(i));
285 if(ed.ownerCt !== this){
286 ed.on('focus', this.ensureVisible, this);
287 ed.on('specialkey', this.onKey, this);
291 this.initialized = true;
294 onKey: function(f, e){
295 if(e.getKey() === e.ENTER){
296 this.stopEditing(true);
301 onGridKey: function(e){
302 if(e.getKey() === e.ENTER && !this.isVisible()){
303 var r = this.grid.getSelectionModel().getSelected();
305 var index = this.grid.store.indexOf(r);
306 this.startEditing(index);
312 ensureVisible: function(editor){
313 if(this.isVisible()){
314 this.grid.getView().ensureVisible(this.rowIndex, this.grid.colModel.getIndexById(editor.column.id), true);
318 onRowClick: function(g, rowIndex, e){
319 if(this.clicksToEdit == 'auto'){
320 var li = this.lastClickIndex;
321 this.lastClickIndex = rowIndex;
322 if(li != rowIndex && !this.isVisible()){
326 this.startEditing(rowIndex, false);
327 this.doFocus.defer(this.focusDelay, this, [e.getPoint()]);
330 onRowDblClick: function(g, rowIndex, e){
331 this.startEditing(rowIndex, false);
332 this.doFocus.defer(this.focusDelay, this, [e.getPoint()]);
335 onRender: function(){
336 Ext.ux.grid.RowEditor.superclass.onRender.apply(this, arguments);
337 this.el.swallowEvent(['keydown', 'keyup', 'keypress']);
338 this.btns = new Ext.Panel({
343 width: (this.minButtonWidth * 2) + (this.frameWidth * 2) + (this.buttonPad * 4), // width must be specified for IE
349 width: this.minButtonWidth,
350 handler: this.stopEditing.createDelegate(this, [true])
353 text: this.cancelText,
354 width: this.minButtonWidth,
355 handler: this.stopEditing.createDelegate(this, [false])
358 this.btns.render(this.bwrap);
361 afterRender: function(){
362 Ext.ux.grid.RowEditor.superclass.afterRender.apply(this, arguments);
363 this.positionButtons();
364 if(this.monitorValid){
365 this.startMonitoring();
370 if(this.monitorValid){
371 this.startMonitoring();
373 Ext.ux.grid.RowEditor.superclass.onShow.apply(this, arguments);
377 Ext.ux.grid.RowEditor.superclass.onHide.apply(this, arguments);
378 this.stopMonitoring();
379 this.grid.getView().focusRow(this.rowIndex);
382 positionButtons: function(){
385 h = this.el.dom.clientHeight,
387 scroll = view.scroller.dom.scrollLeft,
388 bw = this.btns.getWidth(),
389 width = Math.min(g.getWidth(), g.getColumnModel().getTotalWidth());
391 this.btns.el.shift({left: (width/2)-(bw/2)+scroll, top: h - 2, stopFx: true, duration:0.2});
396 preEditValue : function(r, field){
397 var value = r.data[field];
398 return this.autoEncode && typeof value === 'string' ? Ext.util.Format.htmlDecode(value) : value;
402 postEditValue : function(value, originalValue, r, field){
403 return this.autoEncode && typeof value == 'string' ? Ext.util.Format.htmlEncode(value) : value;
406 doFocus: function(pt){
407 if(this.isVisible()){
409 cm = this.grid.getColumnModel(),
412 index = this.getTargetColumnIndex(pt);
414 for(var i = index||0, len = cm.getColumnCount(); i < len; i++){
415 c = cm.getColumnAt(i);
416 if(!c.hidden && c.getEditor()){
417 c.getEditor().focus();
424 getTargetColumnIndex: function(pt){
425 var grid = this.grid,
428 cms = grid.colModel.config,
431 for(var len = cms.length, c; c = cms[i]; i++){
433 if(Ext.fly(v.getHeaderCell(i)).getRegion().right >= x){
442 startMonitoring : function(){
443 if(!this.bound && this.monitorValid){
446 run : this.bindHandler,
447 interval : this.monitorPoll || 200,
453 stopMonitoring : function(){
462 this.items.each(function(f){
463 if(!f.isValid(true)){
472 bindHandler : function(){
474 return false; // stops binding
476 var valid = this.isValid();
477 if(!valid && this.errorSummary){
478 this.showTooltip(this.getErrorText().join(''));
480 this.btns.saveBtn.setDisabled(!valid);
481 this.fireEvent('validation', this, valid);
484 lastVisibleColumn : function() {
485 var i = this.items.getCount() - 1,
488 c = this.items.items[i];
495 showTooltip: function(msg){
496 var t = this.tooltip;
498 t = this.tooltip = new Ext.ToolTip({
502 title: this.errorText,
505 anchorToTarget: true,
509 var v = this.grid.getView(),
510 top = parseInt(this.el.dom.style.top, 10),
511 scroll = v.scroller.dom.scrollTop,
512 h = this.el.getHeight();
514 if(top + h >= scroll){
515 t.initTarget(this.lastVisibleColumn().getEl());
523 }else if(t.rendered){
528 getErrorText: function(){
530 this.items.each(function(f){
531 if(!f.isValid(true)){
532 data.push('<li>', f.getActiveError(), '</li>');
539 Ext.preg('roweditor', Ext.ux.grid.RowEditor);