X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/0494b8d9b9bb03ab6c22b34dae81261e3cd7e3e6..HEAD:/docs/source/Editor.html?ds=sidebyside diff --git a/docs/source/Editor.html b/docs/source/Editor.html index 7abd20a3..6c2f4aee 100644 --- a/docs/source/Editor.html +++ b/docs/source/Editor.html @@ -1,412 +1,505 @@ +
- +/*! - * Ext JS Library 3.3.1 - * Copyright(c) 2006-2010 Sencha Inc. - * licensing@sencha.com - * http://www.sencha.com/license - */ -/** - * @class Ext.Editor + +- \ No newline at end of file +/** + * @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. - * @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; + * + * <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' } - Ext.Editor.superclass.constructor.call(this, config); -}; +}); +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} + * + */ +Ext.define('Ext.Editor', { + + /* Begin Definitions */ + + extend: 'Ext.Component', + + alias: 'widget.editor', + + requires: ['Ext.layout.component.Editor'], + + /* End Definitions */ -Ext.extend(Ext.Editor, Ext.Component, { - /** - * @cfg {Ext.form.Field} field + 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 true. + * field is blurred. */ allowBlur: true, - /** - * @cfg {Boolean/String} autoSize - * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only, - * or "height" to adopt the height only, "none" to always use the field dimensions. (defaults to false) + + /** + * @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) + * validation fails */ - /** - * @cfg {Boolean} ignoreNoChange + revertInvalid: true, + + /** + * @cfg {Boolean} [ignoreNoChange=false] * 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 + * the value has not changed. Applies only to string values - edits for other data types * will never be ignored. */ - /** - * @cfg {Boolean} hideEl - * False to keep the bound element visible while the editor is displayed (defaults to true) + + /** + * @cfg {Boolean} [hideEl=true] + * False to keep the bound element visible while the editor is displayed */ - /** - * @cfg {Mixed} value - * The data value of the underlying field (defaults to "") + + /** + * @cfg {Object} value + * The data value of the underlying field */ - 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.Element#alignTo} for more details). */ - alignment: "c-c?", - /** - * @cfg {Array} offsets - * The offsets to use when aligning (see {@link Ext.Element#alignTo} for more details. Defaults to [0, 0]. + alignment: 'c-c?', + + /** + * @cfg {Number[]} offsets + * The offsets to use when aligning (see {@link Ext.Element#alignTo} for more details. */ 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") + + /** + * @cfg {Boolean/String} shadow + * "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop" for bottom-right shadow. */ - 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 */ swallowKeys : true, - /** - * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed. Defaults to true. + + /** + * @cfg {Boolean} completeOnEnter + * True to complete the edit when the enter key is pressed. */ completeOnEnter : true, - /** - * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed. Defaults to true. + + /** + * @cfg {Boolean} cancelOnEsc + * True to cancel the edit when the escape key is pressed. */ cancelOnEsc : true, - /** - * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false) + + /** + * @cfg {Boolean} updateEl + * True to update the innerHTML of the bound element when the update completes */ updateEl : false, - initComponent : function(){ - Ext.Editor.superclass.initComponent.call(this); - this.addEvents( - /** - * @event beforestartedit + /** + * @cfg {String/HTMLElement/Ext.Element} 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.Editor} this * @param {Ext.Element} boundEl The underlying element bound to this editor - * @param {Mixed} value The field value being set + * @param {Object} value The field value being set */ - "beforestartedit", - /** - * @event startedit + 'beforestartedit', + + /** + * @event startedit * Fires when this editor is displayed + * @param {Ext.Editor} this * @param {Ext.Element} boundEl The underlying element bound to this editor - * @param {Mixed} value The starting field value + * @param {Object} 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 * event will not fire since no edit actually occurred. - * @param {Editor} this - * @param {Mixed} value The current field value - * @param {Mixed} startValue The original field value + * @param {Ext.Editor} this + * @param {Object} value The current field value + * @param {Object} 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 {Mixed} value The current field value - * @param {Mixed} startValue The original field value + * @param {Ext.Editor} this + * @param {Object} value The current field value + * @param {Object} 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 {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 + * @param {Ext.Editor} this + * @param {Object} value The user-entered field value that was discarded + * @param {Object} 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.mon(this.field, { - scope: this, - blur: this.onBlur, - specialkey: this.onSpecialKey - }); - if(this.field.grow){ - this.mon(this.field, "autosize", this.el.sync, this.el, {delay:1}); - } - this.field.render(this.el).show(); - this.field.getEl().dom.name = ''; - if(this.swallowKeys){ - this.field.el.swallowEvent([ - 'keypress', // *** Opera - 'keydown' // *** all other browsers - ]); - } + onAutoSize: function(){ + this.doComponentLayout(); }, // private - onSpecialKey : function(field, e){ - var key = e.getKey(), - complete = this.completeOnEnter && key == e.ENTER, - cancel = this.cancelOnEsc && key == e.ESC; - if(complete || cancel){ - e.stopEvent(); - if(complete){ - this.completeEdit(); - }else{ - this.cancelEdit(); - } - if(field.triggerBlur){ - field.triggerBlur(); + onRender : function(ct, position) { + var me = this, + field = me.field, + inputEl = field.inputEl; + + me.callParent(arguments); + + field.render(me.el); + //field.hide(); + // Ensure the field doesn't get submitted as part of any form + if (inputEl) { + inputEl.dom.name = ''; + if (me.swallowKeys) { + inputEl.swallowEvent([ + 'keypress', // *** Opera + 'keydown' // *** all other browsers + ]); } } - this.fireEvent('specialkey', field, e); }, - /** - * Starts the editing process and shows the editor. - * @param {Mixed} el The element to edit + // 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. + * @param {String/HTMLElement/Ext.Element} 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){ - this.startValue = v; - this.field.reset(); - this.field.setValue(v); - this.realign(true); - 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(), - fs = this.field.getSize(); - - switch(this.autoSize){ - case "width": - this.setSize(sz.width, fs.height); - break; - case "height": - this.setSize(fs.width, sz.height); - break; - case "none": - this.setSize(fs.width, fs.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){ - // IE7 in strict mode doesn't size properly. - if(Ext.isGecko2 || Ext.isOpera || (Ext.isIE7 && Ext.isStrict)){ - // 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(autoSize){ - if(autoSize === true){ - this.doAutoSize(); + realign : function(autoSize) { + var me = this; + if (autoSize === true) { + me.doComponentLayout(); } - this.el.alignTo(this.boundEl, this.alignment, this.offsets); + me.alignTo(me.boundEl, me.alignment, me.offsets); }, - /** - * 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) + /** + * Ends the editing process, persists the changed value to the underlying field, and hides the editor. + * @param {Boolean} [remainVisible=false] Override the default behavior and keep the editor visible after edit */ - completeEdit : function(remainVisible){ - if(!this.editing){ + completeEdit : function(remainVisible) { + var me = this, + field = me.field, + value; + + if (!me.editing) { return; } + // Assert combo values first - if (this.field.assertValue) { - this.field.assertValue(); + if (field.assertValue) { + field.assertValue(); } - var v = this.getValue(); - if(!this.field.isValid()){ - if(this.revertInvalid !== false){ - this.cancelEdit(remainVisible); + + 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(); + onShow : function() { + var me = this; + + me.callParent(arguments); + if (me.hideEl !== false) { + me.boundEl.hide(); } - this.field.show().focus(false, true); - this.fireEvent("startedit", this.boundEl, this.startValue); + 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) + * @param {Boolean} [remainVisible=false] Override the default behavior and keep the editor visible after cancel */ - 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(){ + onBlur : function() { + var me = this; + // selectSameEditor flag allows the same editor to be started without onBlur firing on itself - if(this.allowBlur === true && this.editing && this.selectSameEditor !== true){ - this.completeEdit(); + 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 - * @param {Mixed} value Any valid value supported by the underlying field + /** + * Sets the data value of the editor + * @param {Object} 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 - * @return {Mixed} The data value + /** + * Gets the data value of the editor + * @return {Object} The data value */ - getValue : function(){ + getValue : function() { return this.field.getValue(); }, - beforeDestroy : function(){ - Ext.destroyMembers(this, 'field'); + beforeDestroy : function() { + var me = this; - delete this.parentEl; - delete this.boundEl; + Ext.destroy(me.field); + delete me.field; + delete me.parentEl; + delete me.boundEl; + + me.callParent(arguments); } -}); -Ext.reg('editor', Ext.Editor); -+});