X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/ee06f37b0f6f6d94cd05a6ffae556660f7c4a2bc..c930e9176a5a85509c5b0230e2bff5c22a591432:/docs/source/RowEditor.html diff --git a/docs/source/RowEditor.html b/docs/source/RowEditor.html new file mode 100644 index 00000000..3a47def5 --- /dev/null +++ b/docs/source/RowEditor.html @@ -0,0 +1,525 @@ + + + The source code + + + + +
Ext.ns('Ext.ux.grid');
+
+
/** + * @class Ext.ux.grid.RowEditor + * @extends Ext.Panel + * Plugin (ptype = 'roweditor') that adds the ability to rapidly edit full rows in a grid. + * A validation mode may be enabled which uses AnchorTips to notify the user of all + * validation errors at once. + * + * @ptype roweditor + */ +Ext.ux.grid.RowEditor = Ext.extend(Ext.Panel, { + floating: true, + shadow: false, + layout: 'hbox', + cls: 'x-small-editor', + buttonAlign: 'center', + baseCls: 'x-row-editor', + elements: 'header,footer,body', + frameWidth: 5, + buttonPad: 3, + clicksToEdit: 'auto', + monitorValid: true, + focusDelay: 250, + errorSummary: true, + + defaults: { + normalWidth: true + }, + + initComponent: function(){ + Ext.ux.grid.RowEditor.superclass.initComponent.call(this); + this.addEvents( +
/** + * @event beforeedit + * Fired before the row editor is activated. + * If the listener returns false the editor will not be activated. + * @param {Ext.ux.grid.RowEditor} roweditor This object + * @param {Number} rowIndex The rowIndex of the row just edited + */ + 'beforeedit', +
/** + * @event validateedit + * Fired after a row is edited and passes validation. + * If the listener returns false changes to the record will not be set. + * @param {Ext.ux.grid.RowEditor} roweditor This object + * @param {Object} changes Object with changes made to the record. + * @param {Ext.data.Record} r The Record that was edited. + * @param {Number} rowIndex The rowIndex of the row just edited + */ + 'validateedit', +
/** + * @event afteredit + * Fired after a row is edited and passes validation. This event is fired + * after the store's update event is fired with this edit. + * @param {Ext.ux.grid.RowEditor} roweditor This object + * @param {Object} changes Object with changes made to the record. + * @param {Ext.data.Record} r The Record that was edited. + * @param {Number} rowIndex The rowIndex of the row just edited + */ + 'afteredit' + ); + }, + + init: function(grid){ + this.grid = grid; + this.ownerCt = grid; + if(this.clicksToEdit === 2){ + grid.on('rowdblclick', this.onRowDblClick, this); + }else{ + grid.on('rowclick', this.onRowClick, this); + if(Ext.isIE){ + grid.on('rowdblclick', this.onRowDblClick, this); + } + } + + // stopEditing without saving when a record is removed from Store. + grid.getStore().on('remove', function() { + this.stopEditing(false); + },this); + + grid.on({ + scope: this, + keydown: this.onGridKey, + columnresize: this.verifyLayout, + columnmove: this.refreshFields, + reconfigure: this.refreshFields, + destroy : this.destroy, + bodyscroll: { + buffer: 250, + fn: this.positionButtons + } + }); + grid.getColumnModel().on('hiddenchange', this.verifyLayout, this, {delay:1}); + grid.getView().on('refresh', this.stopEditing.createDelegate(this, [])); + }, + + refreshFields: function(){ + this.initFields(); + this.verifyLayout(); + }, + + isDirty: function(){ + var dirty; + this.items.each(function(f){ + if(String(this.values[f.id]) !== String(f.getValue())){ + dirty = true; + return false; + } + }, this); + return dirty; + }, + + startEditing: function(rowIndex, doFocus){ + if(this.editing && this.isDirty()){ + this.showTooltip('You need to commit or cancel your changes'); + return; + } + this.editing = true; + if(typeof rowIndex == 'object'){ + rowIndex = this.grid.getStore().indexOf(rowIndex); + } + if(this.fireEvent('beforeedit', this, rowIndex) !== false){ + var g = this.grid, view = g.getView(); + var row = view.getRow(rowIndex); + var record = g.store.getAt(rowIndex); + this.record = record; + this.rowIndex = rowIndex; + this.values = {}; + if(!this.rendered){ + this.render(view.getEditorParent()); + } + var w = Ext.fly(row).getWidth(); + this.setSize(w); + if(!this.initialized){ + this.initFields(); + } + var cm = g.getColumnModel(), fields = this.items.items, f, val; + for(var i = 0, len = cm.getColumnCount(); i < len; i++){ + val = this.preEditValue(record, cm.getDataIndex(i)); + f = fields[i]; + f.setValue(val); + this.values[f.id] = val || ''; + } + this.verifyLayout(true); + if(!this.isVisible()){ + this.setPagePosition(Ext.fly(row).getXY()); + } else{ + this.el.setXY(Ext.fly(row).getXY(), {duration:0.15}); + } + if(!this.isVisible()){ + this.show().doLayout(); + } + if(doFocus !== false){ + this.doFocus.defer(this.focusDelay, this); + } + } + }, + + stopEditing : function(saveChanges){ + this.editing = false; + if(!this.isVisible()){ + return; + } + if(saveChanges === false || !this.isValid()){ + this.hide(); + return; + } + var changes = {}, r = this.record, hasChange = false; + var cm = this.grid.colModel, fields = this.items.items; + for(var i = 0, len = cm.getColumnCount(); i < len; i++){ + if(!cm.isHidden(i)){ + var dindex = cm.getDataIndex(i); + if(!Ext.isEmpty(dindex)){ + var oldValue = r.data[dindex]; + var value = this.postEditValue(fields[i].getValue(), oldValue, r, dindex); + if(String(oldValue) !== String(value)){ + changes[dindex] = value; + hasChange = true; + } + } + } + } + if(hasChange && this.fireEvent('validateedit', this, changes, r, this.rowIndex) !== false){ + r.beginEdit(); + for(var k in changes){ + if(changes.hasOwnProperty(k)){ + r.set(k, changes[k]); + } + } + r.endEdit(); + this.fireEvent('afteredit', this, changes, r, this.rowIndex); + } + this.hide(); + }, + + verifyLayout: function(force){ + if(this.el && (this.isVisible() || force === true)){ + var row = this.grid.getView().getRow(this.rowIndex); + this.setSize(Ext.fly(row).getWidth(), Ext.isIE ? Ext.fly(row).getHeight() + (Ext.isBorderBox ? 9 : 0) : undefined); + var cm = this.grid.colModel, fields = this.items.items; + for(var i = 0, len = cm.getColumnCount(); i < len; i++){ + if(!cm.isHidden(i)){ + var adjust = 0; + if(i === 0){ + adjust += 0; // outer padding + } + if(i === (len - 1)){ + adjust += 3; // outer padding + } else{ + adjust += 1; + } + fields[i].show(); + fields[i].setWidth(cm.getColumnWidth(i) - adjust); + } else{ + fields[i].hide(); + } + } + this.doLayout(); + this.positionButtons(); + } + }, + + slideHide : function(){ + this.hide(); + }, + + initFields: function(){ + var cm = this.grid.getColumnModel(), pm = Ext.layout.ContainerLayout.prototype.parseMargins; + this.removeAll(false); + for(var i = 0, len = cm.getColumnCount(); i < len; i++){ + var c = cm.getColumnAt(i); + var ed = c.getEditor(); + if(!ed){ + ed = c.displayEditor || new Ext.form.DisplayField(); + } + if(i == 0){ + ed.margins = pm('0 1 2 1'); + } else if(i == len - 1){ + ed.margins = pm('0 0 2 1'); + } else{ + ed.margins = pm('0 1 2'); + } + ed.setWidth(cm.getColumnWidth(i)); + ed.column = c; + if(ed.ownerCt !== this){ + ed.on('focus', this.ensureVisible, this); + ed.on('specialkey', this.onKey, this); + } + this.insert(i, ed); + } + this.initialized = true; + }, + + onKey: function(f, e){ + if(e.getKey() === e.ENTER){ + this.stopEditing(true); + e.stopPropagation(); + } + }, + + onGridKey: function(e){ + if(e.getKey() === e.ENTER && !this.isVisible()){ + var r = this.grid.getSelectionModel().getSelected(); + if(r){ + var index = this.grid.store.indexOf(r); + this.startEditing(index); + e.stopPropagation(); + } + } + }, + + ensureVisible: function(editor){ + if(this.isVisible()){ + this.grid.getView().ensureVisible(this.rowIndex, this.grid.colModel.getIndexById(editor.column.id), true); + } + }, + + onRowClick: function(g, rowIndex, e){ + if(this.clicksToEdit == 'auto'){ + var li = this.lastClickIndex; + this.lastClickIndex = rowIndex; + if(li != rowIndex && !this.isVisible()){ + return; + } + } + this.startEditing(rowIndex, false); + this.doFocus.defer(this.focusDelay, this, [e.getPoint()]); + }, + + onRowDblClick: function(g, rowIndex, e){ + this.startEditing(rowIndex, false); + this.doFocus.defer(this.focusDelay, this, [e.getPoint()]); + }, + + onRender: function(){ + Ext.ux.grid.RowEditor.superclass.onRender.apply(this, arguments); + this.el.swallowEvent(['keydown', 'keyup', 'keypress']); + this.btns = new Ext.Panel({ + baseCls: 'x-plain', + cls: 'x-btns', + elements:'body', + layout: 'table', + width: (this.minButtonWidth * 2) + (this.frameWidth * 2) + (this.buttonPad * 4), // width must be specified for IE + items: [{ + ref: 'saveBtn', + itemId: 'saveBtn', + xtype: 'button', + text: this.saveText || 'Save', + width: this.minButtonWidth, + handler: this.stopEditing.createDelegate(this, [true]) + }, { + xtype: 'button', + text: this.cancelText || 'Cancel', + width: this.minButtonWidth, + handler: this.stopEditing.createDelegate(this, [false]) + }] + }); + this.btns.render(this.bwrap); + }, + + afterRender: function(){ + Ext.ux.grid.RowEditor.superclass.afterRender.apply(this, arguments); + this.positionButtons(); + if(this.monitorValid){ + this.startMonitoring(); + } + }, + + onShow: function(){ + if(this.monitorValid){ + this.startMonitoring(); + } + Ext.ux.grid.RowEditor.superclass.onShow.apply(this, arguments); + }, + + onHide: function(){ + Ext.ux.grid.RowEditor.superclass.onHide.apply(this, arguments); + this.stopMonitoring(); + this.grid.getView().focusRow(this.rowIndex); + }, + + positionButtons: function(){ + if(this.btns){ + var h = this.el.dom.clientHeight; + var view = this.grid.getView(); + var scroll = view.scroller.dom.scrollLeft; + var width = view.mainBody.getWidth(); + var bw = this.btns.getWidth(); + this.btns.el.shift({left: (width/2)-(bw/2)+scroll, top: h - 2, stopFx: true, duration:0.2}); + } + }, + + // private + preEditValue : function(r, field){ + var value = r.data[field]; + return this.autoEncode && typeof value === 'string' ? Ext.util.Format.htmlDecode(value) : value; + }, + + // private + postEditValue : function(value, originalValue, r, field){ + return this.autoEncode && typeof value == 'string' ? Ext.util.Format.htmlEncode(value) : value; + }, + + doFocus: function(pt){ + if(this.isVisible()){ + var index = 0; + if(pt){ + index = this.getTargetColumnIndex(pt); + } + var cm = this.grid.getColumnModel(); + for(var i = index||0, len = cm.getColumnCount(); i < len; i++){ + var c = cm.getColumnAt(i); + if(!c.hidden && c.getEditor()){ + c.getEditor().focus(); + break; + } + } + } + }, + + getTargetColumnIndex: function(pt){ + var grid = this.grid, v = grid.view; + var x = pt.left; + var cms = grid.colModel.config; + var i = 0, match = false; + for(var len = cms.length, c; c = cms[i]; i++){ + if(!c.hidden){ + if(Ext.fly(v.getHeaderCell(i)).getRegion().right >= x){ + match = i; + break; + } + } + } + return match; + }, + + startMonitoring : function(){ + if(!this.bound && this.monitorValid){ + this.bound = true; + Ext.TaskMgr.start({ + run : this.bindHandler, + interval : this.monitorPoll || 200, + scope: this + }); + } + }, + + stopMonitoring : function(){ + this.bound = false; + if(this.tooltip){ + this.tooltip.hide(); + } + }, + + isValid: function(){ + var valid = true; + this.items.each(function(f){ + if(!f.isValid(true)){ + valid = false; + return false; + } + }); + return valid; + }, + + // private + bindHandler : function(){ + if(!this.bound){ + return false; // stops binding + } + var valid = this.isValid(); + if(!valid && this.errorSummary){ + this.showTooltip(this.getErrorText().join('')); + } + this.btns.saveBtn.setDisabled(!valid); + this.fireEvent('validation', this, valid); + }, + + showTooltip: function(msg){ + var t = this.tooltip; + if(!t){ + t = this.tooltip = new Ext.ToolTip({ + maxWidth: 600, + cls: 'errorTip', + width: 300, + title: 'Errors', + autoHide: false, + anchor: 'left', + anchorToTarget: true, + mouseOffset: [40,0] + }); + } + t.initTarget(this.items.last().getEl()); + if(!t.rendered){ + t.show(); + t.hide(); + } + t.body.update(msg); + t.doAutoWidth(); + t.show(); + }, + + getErrorText: function(){ + var data = [''); + return data; + } +}); +Ext.preg('roweditor', Ext.ux.grid.RowEditor); + +Ext.override(Ext.form.Field, { + markInvalid : function(msg){ + if(!this.rendered || this.preventMark){ // not rendered + return; + } + msg = msg || this.invalidText; + + var mt = this.getMessageHandler(); + if(mt){ + mt.mark(this, msg); + }else if(this.msgTarget){ + this.el.addClass(this.invalidClass); + var t = Ext.getDom(this.msgTarget); + if(t){ + t.innerHTML = msg; + t.style.display = this.msgDisplay; + } + } + this.activeError = msg; + this.fireEvent('invalid', this, msg); + } +}); + +Ext.override(Ext.ToolTip, { + doAutoWidth : function(){ + var bw = this.body.getTextWidth(); + if(this.title){ + bw = Math.max(bw, this.header.child('span').getTextWidth(this.title)); + } + bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr") + 20; + this.setWidth(bw.constrain(this.minWidth, this.maxWidth)); + + // IE7 repaint bug on initial show + if(Ext.isIE7 && !this.repainted){ + this.el.repaint(); + this.repainted = true; + } + } +}); +
+ + \ No newline at end of file