X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/c930e9176a5a85509c5b0230e2bff5c22a591432..7a654f8d43fdb43d78b63d90528bed6e86b608cc:/docs/source/Editor.html diff --git a/docs/source/Editor.html b/docs/source/Editor.html index a5282b44..63085843 100644 --- a/docs/source/Editor.html +++ b/docs/source/Editor.html @@ -1,117 +1,214 @@ - - - The source code - - - - -
/** - * @class Ext.Editor +Sencha Documentation Project
/**
+ * @class Ext.Editor
  * @extends Ext.Component
- * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
+ *
+ * <p>
+ * The Editor class is used to provide inline editing for elements on the page. The editor
+ * is backed by a {@link Ext.form.field.Field} that will be displayed to edit the underlying content.
+ * The editor is a floating Component, when the editor is shown it is automatically aligned to
+ * display over the top of the bound element it is editing. The Editor contains several options
+ * for how to handle key presses:
+ * <ul>
+ * <li>{@link #completeOnEnter}</li>
+ * <li>{@link #cancelOnEsc}</li>
+ * <li>{@link #swallowKeys}</li>
+ * </ul>
+ * It also has options for how to use the value once the editor has been activated:
+ * <ul>
+ * <li>{@link #revertInvalid}</li>
+ * <li>{@link #ignoreNoChange}</li>
+ * <li>{@link #updateEl}</li>
+ * </ul>
+ * Sample usage:
+ * </p>
+ * <pre><code>
+var editor = new Ext.Editor({
+    updateEl: true, // update the innerHTML of the bound element when editing completes
+    field: {
+        xtype: 'textfield'
+    }
+});
+var el = Ext.get('my-text'); // The element to 'edit'
+editor.startEdit(el); // The value of the field will be taken as the innerHTML of the element.
+ * </code></pre>
+ * {@img Ext.Editor/Ext.Editor.png Ext.Editor component}
+ *
  * @constructor
  * Create a new Editor
  * @param {Object} config The config object
  * @xtype editor
  */
-Ext.Editor = function(field, config){
-    if(field.field){
-        this.field = Ext.create(field.field, 'textfield');
-        config = Ext.apply({}, field); // copy so we don't disturb original config
-        delete config.field;
-    }else{
-        this.field = field;
-    }
-    Ext.Editor.superclass.constructor.call(this, config);
-};
+Ext.define('Ext.Editor', {
+
+    /* Begin Definitions */
+
+    extend: 'Ext.Component',
 
-Ext.extend(Ext.Editor, Ext.Component, {
-    
/** - * @cfg {Ext.form.Field} field + alias: 'widget.editor', + + requires: ['Ext.layout.component.Editor'], + + /* End Definitions */ + + componentLayout: 'editor', + + /** + * @cfg {Ext.form.field.Field} field * The Field object (or descendant) or config object for field */ -
/** - * @cfg {Boolean} allowBlur + + /** + * @cfg {Boolean} allowBlur * True to {@link #completeEdit complete the editing process} if in edit mode when the - * field is blurred. Defaults to false. + * field is blurred. Defaults to <tt>true</tt>. */ -
/** - * @cfg {Boolean/String} autoSize - * True for the editor to automatically adopt the size of the element being edited, "width" to adopt the width only, - * or "height" to adopt the height only (defaults to false) + allowBlur: true, + + /** + * @cfg {Boolean/Object} autoSize + * True for the editor to automatically adopt the size of the underlying field. Otherwise, an object + * can be passed to indicate where to get each dimension. The available properties are 'boundEl' and + * 'field'. If a dimension is not specified, it will use the underlying height/width specified on + * the editor object. + * Examples: + * <pre><code> +autoSize: true // The editor will be sized to the height/width of the field + +height: 21, +autoSize: { + width: 'boundEl' // The width will be determined by the width of the boundEl, the height from the editor (21) +} + +autoSize: { + width: 'field', // Width from the field + height: 'boundEl' // Height from the boundEl +} + * </pre></code> */ -
/** - * @cfg {Boolean} revertInvalid + + /** + * @cfg {Boolean} revertInvalid * True to automatically revert the field value and cancel the edit when the user completes an edit and the field * validation fails (defaults to true) */ -
/** - * @cfg {Boolean} ignoreNoChange + revertInvalid: true, + + /** + * @cfg {Boolean} ignoreNoChange * True to skip the edit completion process (no save, no events fired) if the user completes an edit and * the value has not changed (defaults to false). Applies only to string values - edits for other data types * will never be ignored. */ -
/** - * @cfg {Boolean} hideEl + + /** + * @cfg {Boolean} hideEl * False to keep the bound element visible while the editor is displayed (defaults to true) */ -
/** - * @cfg {Mixed} value - * The data value of the underlying field (defaults to "") + + /** + * @cfg {Mixed} value + * The data value of the underlying field (defaults to "") */ - value : "", -
/** - * @cfg {String} alignment - * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?"). + value : '', + + /** + * @cfg {String} alignment + * The position to align to (see {@link Ext.core.Element#alignTo} for more details, defaults to "c-c?"). + */ + alignment: 'c-c?', + + /** + * @cfg {Array} offsets + * The offsets to use when aligning (see {@link Ext.core.Element#alignTo} for more details. Defaults to <tt>[0, 0]</tt>. */ - alignment: "c-c?", -
/** - * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop" - * for bottom-right shadow (defaults to "frame") + offsets: [0, 0], + + /** + * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop" + * for bottom-right shadow (defaults to "frame") */ - shadow : "frame", -
/** - * @cfg {Boolean} constrain True to constrain the editor to the viewport + shadow : 'frame', + + /** + * @cfg {Boolean} constrain True to constrain the editor to the viewport */ constrain : false, -
/** - * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true) + + /** + * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true) */ swallowKeys : true, -
/** - * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed (defaults to false) + + /** + * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed. Defaults to <tt>true</tt>. */ - completeOnEnter : false, -
/** - * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed (defaults to false) + completeOnEnter : true, + + /** + * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed. Defaults to <tt>true</tt>. */ - cancelOnEsc : false, -
/** - * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false) + cancelOnEsc : true, + + /** + * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false) */ updateEl : false, - initComponent : function(){ - Ext.Editor.superclass.initComponent.call(this); - this.addEvents( -
/** - * @event beforestartedit + /** + * @cfg {Mixed} parentEl An element to render to. Defaults to the <tt>document.body</tt>. + */ + + // private overrides + hidden: true, + baseCls: Ext.baseCSSPrefix + 'editor', + + initComponent : function() { + var me = this, + field = me.field = Ext.ComponentManager.create(me.field, 'textfield'); + + Ext.apply(field, { + inEditor: true, + msgTarget: field.msgTarget == 'title' ? 'title' : 'qtip' + }); + me.mon(field, { + scope: me, + blur: { + fn: me.onBlur, + // slight delay to avoid race condition with startEdits (e.g. grid view refresh) + delay: 1 + }, + specialkey: me.onSpecialKey + }); + + if (field.grow) { + me.mon(field, 'autosize', me.onAutoSize, me, {delay: 1}); + } + me.floating = { + constrain: me.constrain + }; + + me.callParent(arguments); + + me.addEvents( + /** + * @event beforestartedit * Fires when editing is initiated, but before the value changes. Editing can be canceled by returning * false from the handler of this event. - * @param {Editor} this - * @param {Ext.Element} boundEl The underlying element bound to this editor + * @param {Ext.Editor} this + * @param {Ext.core.Element} boundEl The underlying element bound to this editor * @param {Mixed} value The field value being set */ - "beforestartedit", -
/** - * @event startedit + 'beforestartedit', + /** + * @event startedit * Fires when this editor is displayed - * @param {Ext.Element} boundEl The underlying element bound to this editor + * @param {Ext.Editor} this + * @param {Ext.core.Element} boundEl The underlying element bound to this editor * @param {Mixed} value The starting field value */ - "startedit", -
/** - * @event beforecomplete + 'startedit', + /** + * @event beforecomplete * Fires after a change has been made to the field, but before the change is reflected in the underlying * field. Saving the change to the field can be canceled by returning false from the handler of this event. * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this @@ -120,269 +217,264 @@ Ext.extend(Ext.Editor, Ext.Component, { * @param {Mixed} value The current field value * @param {Mixed} startValue The original field value */ - "beforecomplete", -
/** - * @event complete + 'beforecomplete', + /** + * @event complete * Fires after editing is complete and any changed value has been written to the underlying field. - * @param {Editor} this + * @param {Ext.Editor} this * @param {Mixed} value The current field value * @param {Mixed} startValue The original field value */ - "complete", -
/** - * @event canceledit + 'complete', + /** + * @event canceledit * Fires after editing has been canceled and the editor's value has been reset. - * @param {Editor} this + * @param {Ext.Editor} this * @param {Mixed} value The user-entered field value that was discarded * @param {Mixed} startValue The original field value that was set back into the editor after cancel */ - "canceledit", -
/** - * @event specialkey + 'canceledit', + /** + * @event specialkey * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed. You can check * {@link Ext.EventObject#getKey} to determine which key was pressed. - * @param {Ext.form.Field} this - * @param {Ext.EventObject} e The event object + * @param {Ext.Editor} this + * @param {Ext.form.field.Field} The field attached to this editor + * @param {Ext.EventObject} event The event object */ - "specialkey" + 'specialkey' ); }, // private - onRender : function(ct, position){ - this.el = new Ext.Layer({ - shadow: this.shadow, - cls: "x-editor", - parentEl : ct, - shim : this.shim, - shadowOffset: this.shadowOffset || 4, - id: this.id, - constrain: this.constrain - }); - if(this.zIndex){ - this.el.setZIndex(this.zIndex); - } - this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden"); - if(this.field.msgTarget != 'title'){ - this.field.msgTarget = 'qtip'; - } - this.field.inEditor = true; - this.field.render(this.el); - if(Ext.isGecko){ - this.field.el.dom.setAttribute('autocomplete', 'off'); - } - this.mon(this.field, "specialkey", this.onSpecialKey, this); - if(this.swallowKeys){ - this.field.el.swallowEvent(['keydown','keypress']); - } - this.field.show(); - this.mon(this.field, "blur", this.onBlur, this); - if(this.field.grow){ - this.mon(this.field, "autosize", this.el.sync, this.el, {delay:1}); - } + onAutoSize: function(){ + this.doComponentLayout(); }, // private - onSpecialKey : function(field, e){ - var key = e.getKey(); - if(this.completeOnEnter && key == e.ENTER){ - e.stopEvent(); - this.completeEdit(); - }else if(this.cancelOnEsc && key == e.ESC){ - this.cancelEdit(); - }else{ - this.fireEvent('specialkey', field, e); + onRender : function(ct, position) { + var me = this, + field = me.field; + + me.callParent(arguments); + + field.render(me.el); + //field.hide(); + // Ensure the field doesn't get submitted as part of any form + field.inputEl.dom.name = ''; + if (me.swallowKeys) { + field.inputEl.swallowEvent([ + 'keypress', // *** Opera + 'keydown' // *** all other browsers + ]); } - if(this.field.triggerBlur && (key == e.ENTER || key == e.ESC || key == e.TAB)){ - this.field.triggerBlur(); + }, + + // private + onSpecialKey : function(field, event) { + var me = this, + key = event.getKey(), + complete = me.completeOnEnter && key == event.ENTER, + cancel = me.cancelOnEsc && key == event.ESC; + + if (complete || cancel) { + event.stopEvent(); + // Must defer this slightly to prevent exiting edit mode before the field's own + // key nav can handle the enter key, e.g. selecting an item in a combobox list + Ext.defer(function() { + if (complete) { + me.completeEdit(); + } else { + me.cancelEdit(); + } + if (field.triggerBlur) { + field.triggerBlur(); + } + }, 10); } + + this.fireEvent('specialkey', this, field, event); }, -
/** - * Starts the editing process and shows the editor. + /** + * Starts the editing process and shows the editor. * @param {Mixed} el The element to edit * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults * to the innerHTML of el. */ - startEdit : function(el, value){ - if(this.editing){ - this.completeEdit(); - } - this.boundEl = Ext.get(el); - var v = value !== undefined ? value : this.boundEl.dom.innerHTML; - if(!this.rendered){ - this.render(this.parentEl || document.body); - } - if(this.fireEvent("beforestartedit", this, this.boundEl, v) === false){ - return; - } - this.startValue = v; - this.field.setValue(v); - this.doAutoSize(); - this.el.alignTo(this.boundEl, this.alignment); - this.editing = true; - this.show(); - }, + startEdit : function(el, value) { + var me = this, + field = me.field; - // private - doAutoSize : function(){ - if(this.autoSize){ - var sz = this.boundEl.getSize(); - switch(this.autoSize){ - case "width": - this.setSize(sz.width, ""); - break; - case "height": - this.setSize("", sz.height); - break; - default: - this.setSize(sz.width, sz.height); - } + me.completeEdit(); + me.boundEl = Ext.get(el); + value = Ext.isDefined(value) ? value : me.boundEl.dom.innerHTML; + + if (!me.rendered) { + me.render(me.parentEl || document.body); } - }, -
/** - * Sets the height and width of this editor. - * @param {Number} width The new width - * @param {Number} height The new height - */ - setSize : function(w, h){ - delete this.field.lastSize; - this.field.setSize(w, h); - if(this.el){ - if(Ext.isGecko2 || Ext.isOpera){ - // prevent layer scrollbars - this.el.setSize(w, h); + if (me.fireEvent('beforestartedit', me, me.boundEl, value) !== false) { + me.startValue = value; + me.show(); + field.reset(); + field.setValue(value); + me.realign(true); + field.focus(false, 10); + if (field.autoSize) { + field.autoSize(); } - this.el.sync(); + me.editing = true; } }, -
/** - * Realigns the editor to the bound field based on the current alignment config value. + /** + * Realigns the editor to the bound field based on the current alignment config value. + * @param {Boolean} autoSize (optional) True to size the field to the dimensions of the bound element. */ - realign : function(){ - this.el.alignTo(this.boundEl, this.alignment); + realign : function(autoSize) { + var me = this; + if (autoSize === true) { + me.doComponentLayout(); + } + me.alignTo(me.boundEl, me.alignment, me.offsets); }, -
/** - * Ends the editing process, persists the changed value to the underlying field, and hides the editor. + /** + * Ends the editing process, persists the changed value to the underlying field, and hides the editor. * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false) */ - completeEdit : function(remainVisible){ - if(!this.editing){ + completeEdit : function(remainVisible) { + var me = this, + field = me.field, + value; + + if (!me.editing) { return; } - var v = this.getValue(); - if(!this.field.isValid()){ - if(this.revertInvalid !== false){ - this.cancelEdit(remainVisible); + + // Assert combo values first + if (field.assertValue) { + field.assertValue(); + } + + value = me.getValue(); + if (!field.isValid()) { + if (me.revertInvalid !== false) { + me.cancelEdit(remainVisible); } return; } - if(String(v) === String(this.startValue) && this.ignoreNoChange){ - this.hideEdit(remainVisible); + + if (String(value) === String(me.startValue) && me.ignoreNoChange) { + me.hideEdit(remainVisible); return; } - if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){ - v = this.getValue(); - if(this.updateEl && this.boundEl){ - this.boundEl.update(v); + + if (me.fireEvent('beforecomplete', me, value, me.startValue) !== false) { + // Grab the value again, may have changed in beforecomplete + value = me.getValue(); + if (me.updateEl && me.boundEl) { + me.boundEl.update(value); } - this.hideEdit(remainVisible); - this.fireEvent("complete", this, v, this.startValue); + me.hideEdit(remainVisible); + me.fireEvent('complete', me, value, me.startValue); } }, // private - onShow : function(){ - this.el.show(); - if(this.hideEl !== false){ - this.boundEl.hide(); - } - this.field.show(); - if(Ext.isIE && !this.fixIEFocus){ // IE has problems with focusing the first time - this.fixIEFocus = true; - this.deferredFocus.defer(50, this); - }else{ - this.field.focus(); - } - this.fireEvent("startedit", this.boundEl, this.startValue); - }, + onShow : function() { + var me = this; - deferredFocus : function(){ - if(this.editing){ - this.field.focus(); + me.callParent(arguments); + if (me.hideEl !== false) { + me.boundEl.hide(); } + me.fireEvent("startedit", me.boundEl, me.startValue); }, -
/** - * Cancels the editing process and hides the editor without persisting any changes. The field value will be + /** + * Cancels the editing process and hides the editor without persisting any changes. The field value will be * reverted to the original starting value. * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after * cancel (defaults to false) */ - cancelEdit : function(remainVisible){ - if(this.editing){ - var v = this.getValue(); - this.setValue(this.startValue); - this.hideEdit(remainVisible); - this.fireEvent("canceledit", this, v, this.startValue); + cancelEdit : function(remainVisible) { + var me = this, + startValue = me.startValue, + value; + + if (me.editing) { + value = me.getValue(); + me.setValue(startValue); + me.hideEdit(remainVisible); + me.fireEvent('canceledit', me, value, startValue); } }, - + // private - hideEdit: function(remainVisible){ - if(remainVisible !== true){ + hideEdit: function(remainVisible) { + if (remainVisible !== true) { this.editing = false; this.hide(); } }, // private - onBlur : function(){ - if(this.allowBlur !== true && this.editing){ - this.completeEdit(); + onBlur : function() { + var me = this; + + // selectSameEditor flag allows the same editor to be started without onBlur firing on itself + if(me.allowBlur === true && me.editing && me.selectSameEditor !== true) { + me.completeEdit(); } }, // private - onHide : function(){ - if(this.editing){ - this.completeEdit(); + onHide : function() { + var me = this, + field = me.field; + + if (me.editing) { + me.completeEdit(); return; } - this.field.blur(); - if(this.field.collapse){ - this.field.collapse(); + field.blur(); + if (field.collapse) { + field.collapse(); } - this.el.hide(); - if(this.hideEl !== false){ - this.boundEl.show(); + + //field.hide(); + if (me.hideEl !== false) { + me.boundEl.show(); } + me.callParent(arguments); }, -
/** - * Sets the data value of the editor + /** + * Sets the data value of the editor * @param {Mixed} value Any valid value supported by the underlying field */ - setValue : function(v){ - this.field.setValue(v); + setValue : function(value) { + this.field.setValue(value); }, -
/** - * Gets the data value of the editor + /** + * Gets the data value of the editor * @return {Mixed} The data value */ - getValue : function(){ + getValue : function() { return this.field.getValue(); }, - beforeDestroy : function(){ - Ext.destroy(this.field); - this.field = null; + beforeDestroy : function() { + var me = this; + + Ext.destroy(me.field); + delete me.field; + delete me.parentEl; + delete me.boundEl; + + me.callParent(arguments); } -}); -Ext.reg('editor', Ext.Editor);
- - \ No newline at end of file +});
\ No newline at end of file