2 * Ext JS Library 2.2.1
\r
3 * Copyright(c) 2006-2009, Ext JS, LLC.
\r
4 * licensing@extjs.com
\r
6 * http://extjs.com/license
\r
11 * @extends Ext.Component
\r
12 * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
\r
14 * Create a new Editor
\r
15 * @param {Ext.form.Field} field The Field object (or descendant)
\r
16 * @param {Object} config The config object
\r
18 Ext.Editor = function(field, config){
\r
20 Ext.Editor.superclass.constructor.call(this, config);
\r
23 Ext.extend(Ext.Editor, Ext.Component, {
\r
25 * @cfg {Boolean/String} autoSize
\r
26 * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only,
\r
27 * or "height" to adopt the height only (defaults to false)
\r
30 * @cfg {Boolean} revertInvalid
\r
31 * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
\r
32 * validation fails (defaults to true)
\r
35 * @cfg {Boolean} ignoreNoChange
\r
36 * True to skip the edit completion process (no save, no events fired) if the user completes an edit and
\r
37 * the value has not changed (defaults to false). Applies only to string values - edits for other data types
\r
38 * will never be ignored.
\r
41 * @cfg {Boolean} hideEl
\r
42 * False to keep the bound element visible while the editor is displayed (defaults to true)
\r
45 * @cfg {Mixed} value
\r
46 * The data value of the underlying field (defaults to "")
\r
50 * @cfg {String} alignment
\r
51 * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?").
\r
55 * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
\r
56 * for bottom-right shadow (defaults to "frame")
\r
60 * @cfg {Boolean} constrain True to constrain the editor to the viewport
\r
64 * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true)
\r
68 * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed (defaults to false)
\r
70 completeOnEnter : false,
\r
72 * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed (defaults to false)
\r
74 cancelOnEsc : false,
\r
76 * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
\r
80 initComponent : function(){
\r
81 Ext.Editor.superclass.initComponent.call(this);
\r
84 * @event beforestartedit
\r
85 * Fires when editing is initiated, but before the value changes. Editing can be canceled by returning
\r
86 * false from the handler of this event.
\r
87 * @param {Editor} this
\r
88 * @param {Ext.Element} boundEl The underlying element bound to this editor
\r
89 * @param {Mixed} value The field value being set
\r
94 * Fires when this editor is displayed
\r
95 * @param {Ext.Element} boundEl The underlying element bound to this editor
\r
96 * @param {Mixed} value The starting field value
\r
100 * @event beforecomplete
\r
101 * Fires after a change has been made to the field, but before the change is reflected in the underlying
\r
102 * field. Saving the change to the field can be canceled by returning false from the handler of this event.
\r
103 * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
\r
104 * event will not fire since no edit actually occurred.
\r
105 * @param {Editor} this
\r
106 * @param {Mixed} value The current field value
\r
107 * @param {Mixed} startValue The original field value
\r
112 * Fires after editing is complete and any changed value has been written to the underlying field.
\r
113 * @param {Editor} this
\r
114 * @param {Mixed} value The current field value
\r
115 * @param {Mixed} startValue The original field value
\r
119 * @event canceledit
\r
120 * Fires after editing has been canceled and the editor's value has been reset.
\r
121 * @param {Editor} this
\r
122 * @param {Mixed} value The user-entered field value that was discarded
\r
123 * @param {Mixed} startValue The original field value that was set back into the editor after cancel
\r
127 * @event specialkey
\r
128 * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed. You can check
\r
129 * {@link Ext.EventObject#getKey} to determine which key was pressed.
\r
130 * @param {Ext.form.Field} this
\r
131 * @param {Ext.EventObject} e The event object
\r
138 onRender : function(ct, position){
\r
139 this.el = new Ext.Layer({
\r
140 shadow: this.shadow,
\r
146 constrain: this.constrain
\r
148 this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
\r
149 if(this.field.msgTarget != 'title'){
\r
150 this.field.msgTarget = 'qtip';
\r
152 this.field.inEditor = true;
\r
153 this.field.render(this.el);
\r
155 this.field.el.dom.setAttribute('autocomplete', 'off');
\r
157 this.field.on("specialkey", this.onSpecialKey, this);
\r
158 if(this.swallowKeys){
\r
159 this.field.el.swallowEvent(['keydown','keypress']);
\r
162 this.field.on("blur", this.onBlur, this);
\r
163 if(this.field.grow){
\r
164 this.field.on("autosize", this.el.sync, this.el, {delay:1});
\r
169 onSpecialKey : function(field, e){
\r
170 var key = e.getKey();
\r
171 if(this.completeOnEnter && key == e.ENTER){
\r
173 this.completeEdit();
\r
174 }else if(this.cancelOnEsc && key == e.ESC){
\r
177 this.fireEvent('specialkey', field, e);
\r
179 if(this.field.triggerBlur && (key == e.ENTER || key == e.ESC || key == e.TAB)){
\r
180 this.field.triggerBlur();
\r
185 * Starts the editing process and shows the editor.
\r
186 * @param {Mixed} el The element to edit
\r
187 * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
\r
188 * to the innerHTML of el.
\r
190 startEdit : function(el, value){
\r
192 this.completeEdit();
\r
194 this.boundEl = Ext.get(el);
\r
195 var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
\r
196 if(!this.rendered){
\r
197 this.render(this.parentEl || document.body);
\r
199 if(this.fireEvent("beforestartedit", this, this.boundEl, v) === false){
\r
202 this.startValue = v;
\r
203 this.field.setValue(v);
\r
205 this.el.alignTo(this.boundEl, this.alignment);
\r
206 this.editing = true;
\r
211 doAutoSize : function(){
\r
213 var sz = this.boundEl.getSize();
\r
214 switch(this.autoSize){
\r
216 this.setSize(sz.width, "");
\r
219 this.setSize("", sz.height);
\r
222 this.setSize(sz.width, sz.height);
\r
228 * Sets the height and width of this editor.
\r
229 * @param {Number} width The new width
\r
230 * @param {Number} height The new height
\r
232 setSize : function(w, h){
\r
233 delete this.field.lastSize;
\r
234 this.field.setSize(w, h);
\r
236 if(Ext.isGecko2 || Ext.isOpera){
\r
237 // prevent layer scrollbars
\r
238 this.el.setSize(w, h);
\r
245 * Realigns the editor to the bound field based on the current alignment config value.
\r
247 realign : function(){
\r
248 this.el.alignTo(this.boundEl, this.alignment);
\r
252 * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
\r
253 * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
\r
255 completeEdit : function(remainVisible){
\r
259 var v = this.getValue();
\r
260 if(this.revertInvalid !== false && !this.field.isValid()){
\r
261 v = this.startValue;
\r
262 this.cancelEdit(true);
\r
264 if(String(v) === String(this.startValue) && this.ignoreNoChange){
\r
265 this.editing = false;
\r
269 if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
\r
270 this.editing = false;
\r
271 if(this.updateEl && this.boundEl){
\r
272 this.boundEl.update(v);
\r
274 if(remainVisible !== true){
\r
277 this.fireEvent("complete", this, v, this.startValue);
\r
282 onShow : function(){
\r
284 if(this.hideEl !== false){
\r
285 this.boundEl.hide();
\r
288 if(Ext.isIE && !this.fixIEFocus){ // IE has problems with focusing the first time
\r
289 this.fixIEFocus = true;
\r
290 this.deferredFocus.defer(50, this);
\r
292 this.field.focus();
\r
294 this.fireEvent("startedit", this.boundEl, this.startValue);
\r
297 deferredFocus : function(){
\r
299 this.field.focus();
\r
304 * Cancels the editing process and hides the editor without persisting any changes. The field value will be
\r
305 * reverted to the original starting value.
\r
306 * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
\r
307 * cancel (defaults to false)
\r
309 cancelEdit : function(remainVisible){
\r
311 var v = this.getValue();
\r
312 this.setValue(this.startValue);
\r
313 if(remainVisible !== true){
\r
316 this.fireEvent("canceledit", this, v, this.startValue);
\r
321 onBlur : function(){
\r
322 if(this.allowBlur !== true && this.editing){
\r
323 this.completeEdit();
\r
328 onHide : function(){
\r
330 this.completeEdit();
\r
334 if(this.field.collapse){
\r
335 this.field.collapse();
\r
338 if(this.hideEl !== false){
\r
339 this.boundEl.show();
\r
344 * Sets the data value of the editor
\r
345 * @param {Mixed} value Any valid value supported by the underlying field
\r
347 setValue : function(v){
\r
348 this.field.setValue(v);
\r
352 * Gets the data value of the editor
\r
353 * @return {Mixed} The data value
\r
355 getValue : function(){
\r
356 return this.field.getValue();
\r
359 beforeDestroy : function(){
\r
360 Ext.destroy(this.field);
\r
364 Ext.reg('editor', Ext.Editor);