| Summary: Inline editable form fields with support for Ajax auto-save. |
| Author: Nullity |
| Published: 9/12/2007 |
| Version: 1.3 |
| Ext Version: 1.1 |
| License: Creative Commons Attribution-Share Alike 3.0 |
| Demo Link: View Demo |
| Forum Post: No Forum |
Contents |
InformationA collection of inline editable form fields (TextField, TextArea, ComboBox). The fields initially display as plain text, but when clicked on, they turn into their respective field. If desired, each field can be configured to automatically save the changes when the field is blurred.
Forum PostsInlineTextField
InlineTextArea
InlineComboBox
UsageInlineTextField:
new Ext.form.InlineTextField({ autoSave: { // set to enable ajax auto-save url: 'ajax.php', method: 'POST', callback: {success: successFn, failure: failureFn}, params: {foo: 'bar'}, scope: this }, saveOnlyOnChange: true, // (default true) only saves data if changed confirmSave: true, // (default false) show Ext.MessageBox on successful save confirmText: 'The data has been successfully saved.', // (this is the default) text to show in Ext.MessageBox fieldLabel: 'InlineTextField', id: 'textfield', value: 'InlineTextField' })
InlineTextArea:
new Ext.form.InlineTextArea({ autoSave: { // set to enable ajax auto-save url: 'ajax.php', method: 'POST', callback: {success: successFn, failure: failureFn}, params: {foo: 'bar'}, scope: this }, saveOnlyOnChange: true, // (default true) only saves data if changed confirmSave: true, // (default false) show Ext.MessageBox on successful save confirmText: 'The data has been successfully saved.', // (this is the default) text to show in Ext.MessageBox fieldLabel: 'InlineTextArea', id: 'textarea', value: 'InlineTextArea' })
InlineComboBox:
new Ext.form.InlineComboBox({ autoSave: { // set to enable ajax auto-save url: 'ajax.php', method: 'POST', callback: {success: successFn, failure: failureFn}, params: {foo: 'bar'}, scope: this }, saveOnlyOnChange: true, // (default true) only saves data if changed confirmSave: true, // (default false) show Ext.MessageBox on successful save confirmText: 'The data has been successfully saved.', // (this is the default) text to show in Ext.MessageBox store: combo_store, fieldLabel: 'InlineComboBox', hiddenName: 'combobox_hid', id: 'combobox', displayField: 'text', valueField: 'value', typeAhead: true, mode: 'local', triggerAction: 'all', emptyText: 'Select one...' })
SourceCSS:
.x-form-inline-field, textarea.x-form-inline-field { background: transparent; border: 1px solid transparent; cursor: pointer; overflow: hidden; } .x-form-inline-field-disabled { color: #000000; cursor: default; opacity: 1.0; -moz-opacity: 1.0; filter: alpha(opacity=100); }
InlineTextField:
Ext.form.InlineTextField = function(config) { Ext.form.InlineTextField.superclass.constructor.call(this, config); this.on('specialkey', function(f, e) { if (e.getKey() == e.ESC) { f.setValue(this.startValue); f.blur(); } }, this); }; Ext.extend(Ext.form.InlineTextField, Ext.form.TextField, { inlineClass: 'x-form-inline-field', disabledClass: 'x-form-inline-field-disabled', saveOnlyOnChange: true, confirmSave: false, confirmText: 'The data has been successfully saved.', doSave : function() { var cfg = this.autoSave; this.params = (this.name || this.id) + '=' + this.getValue(); if (typeof cfg == 'object') { this.method = cfg.method || 'POST'; this.callback = (!cfg.callback) ? {success: Ext.emptyFn, failure: Ext.emptyFn} : {success: cfg.callback.success || cfg.callback, failure: cfg.callback.failure || Ext.emptyFn}; this.scope = cfg.scope || this.callback; if (this.confirmSave === true) { var success = function() { Ext.MessageBox.alert('Success', this.confirmText); }.createDelegate(this); this.callback.success = success.createSequence(this.callback.success); } var p = (cfg.params) ? cfg.params : ''; if (p) { if (typeof p == 'object') { this.params += '&' + Ext.urlEncode(p); } else if (typeof p == 'string' && p.length) { this.params += '&' + p; } } this.url = (this.method == 'POST') ? cfg.url : cfg.url + '?' + this.params; } else if (typeof cfg == 'string') { this.method = 'POST'; this.url = (this.method == 'POST') ? cfg : cfg + '?' + this.params; } Ext.Ajax.request({ url: this.url, method: this.method, success: this.callback.success, failure: this.callback.failure, params: this.params, scope: this.scope }); }, reset : function() { Ext.form.TextField.superclass.reset.call(this); if (this.value) { this.setRawValue(this.value); } else if (this.emptyText && this.getRawValue().length < 1) { this.setRawValue(this.emptyText); this.el.addClass(this.emptyClass); } } }); Ext.override(Ext.form.InlineTextField, { onRender : Ext.form.TextField.prototype.onRender.createSequence(function() { this.el.addClass(this.inlineClass); if (this.editable === false) { this.disabled = true; } }), onFocus : Ext.form.TextField.prototype.onFocus.createSequence(function() { if (this.editable !== false) { this.el.removeClass(this.inlineClass); } }), onBlur : Ext.form.TextField.prototype.onBlur.createSequence(function() { if (this.isValid() && !this.el.hasClass(this.inlineClass)) { this.el.addClass(this.inlineClass); if (this.autoSave && (this.saveOnlyOnChange === false || this.getValue() != this.startValue)) { this.doSave(); } } }) });
InlineTextarea:
Ext.form.InlineTextArea = function(config) { Ext.form.InlineTextArea.superclass.constructor.call(this, config); this.on('specialkey', function(f, e) { if (e.getKey() == e.ESC) { f.setValue(this.startValue); f.blur(); } }, this); }; Ext.extend(Ext.form.InlineTextArea, Ext.form.TextArea, { inlineClass: 'x-form-inline-field', disabledClass: 'x-form-inline-field-disabled', saveOnlyOnChange: true, confirmSave: false, confirmText: 'The data has been successfully saved.', doSave : function() { var cfg = this.autoSave; this.params = (this.name || this.id) + '=' + this.getValue(); if (typeof cfg == 'object') { this.method = cfg.method || 'POST'; this.callback = (!cfg.callback) ? {success: Ext.emptyFn, failure: Ext.emptyFn} : {success: cfg.callback.success || cfg.callback, failure: cfg.callback.failure || Ext.emptyFn}; this.scope = cfg.scope || this.callback; if (this.confirmSave === true) { var success = function() { Ext.MessageBox.alert('Success', this.confirmText); }.createDelegate(this); this.callback.success = success.createSequence(this.callback.success); } var p = (cfg.params) ? cfg.params : ''; if (p) { if (typeof p == 'object') { this.params += '&' + Ext.urlEncode(p); } else if (typeof p == 'string' && p.length) { this.params += '&' + p; } } this.url = (this.method == 'POST') ? cfg.url : cfg.url + '?' + this.params; } else if (typeof cfg == 'string') { this.method = 'POST'; this.url = (this.method == 'POST') ? cfg : cfg + '?' + this.params; } Ext.Ajax.request({ url: this.url, method: this.method, success: this.callback.success, failure: this.callback.failure, params: this.params, scope: this.scope }); }, reset : function() { Ext.form.TextField.superclass.reset.call(this); if (this.value) { this.setRawValue(this.value); } else if (this.emptyText && this.getRawValue().length < 1) { this.setRawValue(this.emptyText); this.el.addClass(this.emptyClass); } } }); Ext.override(Ext.form.InlineTextArea, { onRender : Ext.form.TextArea.prototype.onRender.createSequence(function() { this.el.addClass(this.inlineClass); if (this.editable === false) { this.disabled = true; } }), onFocus : Ext.form.TextArea.prototype.onFocus.createSequence(function() { if (this.editable !== false) { this.el.removeClass(this.inlineClass); } }), onBlur : Ext.form.TextArea.prototype.onBlur.createSequence(function() { if (this.isValid() && !this.el.hasClass(this.inlineClass)) { this.el.addClass(this.inlineClass); if (this.autoSave && (this.saveOnlyOnChange === false || this.getValue() != this.startValue)) { this.doSave(); } } }) });
InlineComboBox:
Ext.form.InlineComboBox = function(config) { Ext.form.InlineComboBox.superclass.constructor.call(this, config); }; Ext.extend(Ext.form.InlineComboBox, Ext.form.ComboBox, { inlineClass: 'x-form-inline-field', disabledClass: 'x-form-inline-field-disabled', saveOnlyOnChange: true, confirmSave: false, confirmText: 'The data has been successfully saved.', doSave : function() { var cfg = this.autoSave; this.params = (this.name || this.id) + '=' + this.getRawValue(); if (this.hiddenName) { this.params += '&' + this.hiddenName + '=' + this.hiddenField.value; } if (typeof cfg == 'object') { this.method = cfg.method || 'POST'; this.callback = (!cfg.callback) ? {success: Ext.emptyFn, failure: Ext.emptyFn} : {success: cfg.callback.success || cfg.callback, failure: cfg.callback.failure || Ext.emptyFn}; this.scope = cfg.scope || this.callback; if (this.confirmSave === true) { var success = function() { Ext.MessageBox.alert('Success', this.confirmText); }.createDelegate(this); this.callback.success = success.createSequence(this.callback.success); } var p = (cfg.params) ? cfg.params : ''; if (p) { if (typeof p == 'object') { this.params += '&' + Ext.urlEncode(p); } else if (typeof p == 'string' && p.length) { this.params += '&' + p; } } this.url = (this.method == 'POST') ? cfg.url : cfg.url + '?' + this.params; } else if (typeof cfg == 'string') { this.method = 'POST'; this.url = (this.method == 'POST') ? cfg : cfg + '?' + this.params; } Ext.Ajax.request({ url: this.url, method: this.method, success: this.callback.success, failure: this.callback.failure, params: this.params, scope: this.scope }); } }); Ext.override(Ext.form.InlineComboBox, { onRender : Ext.form.ComboBox.prototype.onRender.createSequence(function() { this.lastValue = ''; this.lastRawValue = ''; this.el.addClass(this.inlineClass); this.trigger.setDisplayed(false); }), onFocus : Ext.form.ComboBox.prototype.onFocus.createSequence(function() { this.el.removeClass(this.inlineClass); this.trigger.setDisplayed(true); }), triggerBlur : Ext.form.ComboBox.prototype.triggerBlur.createSequence(function() { if (this.isValid() && !this.el.hasClass(this.inlineClass)) { this.el.addClass(this.inlineClass); this.trigger.setDisplayed(false); if (!this.store.getAt(this.view.getSelectedIndexes()[0]) || !this.getRawValue()) { this.selectedIndex = -1; if (this.hiddenField) { this.hiddenField.value = ''; } this.value = ''; } if (this.autoSave && (this.saveOnlyOnChange === false || this.getValue() != this.lastValue || this.getRawValue() != this.lastRawValue)) { this.doSave(); } this.lastValue = this.getValue(); this.lastRawValue = this.getRawValue(); } }) });
TODO