SMMJ_Dev
23 Apr 2010, 5:44 AM
DEMO: http://www.djengineer.com/ExtJSExamples/formpaneleditorexample.html
Now upgraded for ExtJS 4.0 as well: Form Panel Editor Example (ExtJS 4.0) (http://www.djengineer.com/ExtJSExamples/PluginExamples/FormPanelEditor/FormPanelEditor.html)
Good Morning/Afternoon everyone,
I have deleted my previous post with a cell editor and form panel editor combo, for a new Ext.ux.FormPanelEditor that allows you to have a form panel as your editor for the EditableGridPanel. Also, I was having trouble with textareas in the EditableGridPanel not taking up the entire cell row and height all the time. So I put a little extra stuff in the EditableGridPanel as well.
First of all, let's talk about the overrides!
Ext.grid.EditorGridPanel Overrides
Ext.override(Ext.grid.EditorGridPanel,{
onEditComplete:function(ed, value, startValue){
this.editing=false;
this.lastActiveEditor=this.activeEditor;
this.activeEditor=null;
var r=ed.record,field=this.colModel.getDataIndex(ed.col);
value=this.postEditValue(value,startValue,r,field);
if(this.forceValidation===true||String(value)!==String(startValue)){
var e={
grid:this,
record:r,
field:field,
originalValue:startValue,
value:value,
row:ed.row,
column:ed.col,
cancel:false
};
if(this.fireEvent("validateedit",e)!==false&&!e.cancel&&String(value)!==String(startValue)){
if(ed.field.getXType()!="formeditor"){
r.set(field,e.value);
}
delete e.cancel;
this.fireEvent("afteredit",e);
}
}
this.view.focusCell(ed.row,ed.col);
},
startEditing : function(row, col){
this.stopEditing();
if(this.colModel.isCellEditable(col, row)){
this.view.ensureVisible(row, col, true);
var r = this.store.getAt(row),
field = this.colModel.getDataIndex(col),
e = {
grid: this,
record: r,
field: field,
value: r.data[field],
row: row,
column: col,
cancel:false
};
if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
this.editing = true;
var ed=this.colModel.getCellEditor(col,row);
if(!ed){return;}
/**
* Update height and width of the editor
*/
var colWidth=e.grid.getColumnModel().getColumnAt(col).width;
var rowHeight=(ed.field.fillRowHeight)?this.view.getCell(row,col).offsetHeight:"";
if(ed.field.minWidth){colWidth=(colWidth>=ed.field.minWidth)?colWidth:ed.field.minWidth;}
if(ed.field.maxWidth){colWidth=(colWidth<=ed.field.maxWidth)?colWidth:ed.field.maxWidth;}
if(ed.field.minHeight){rowHeight=(rowHeight>=ed.field.minHeight)?rowHeight:ed.field.minHeight;}
if(ed.field.maxHeight){rowHeight=(rowHeight<=ed.field.maxHeight)?rowHeight:ed.field.maxHeight;}
ed.setSize(colWidth,rowHeight);
if(!ed.rendered){
ed.parentEl = this.view.getEditorParent(ed);
ed.on({
scope: this,
render: {
fn: function(c){
c.field.focus(false, true);
},
single: true,
scope: this
},
specialkey: function(field, e){
this.getSelectionModel().onEditorKey(field, e);
},
complete: this.onEditComplete,
canceledit: this.stopEditing.createDelegate(this, [true])
});
}
Ext.apply(ed, {
row : row,
col : col,
record : r
});
this.lastEdit = {
row: row,
col: col
};
this.activeEditor = ed;
// Set the selectSameEditor flag if we are reusing the same editor again and
// need to prevent the editor from firing onBlur on itself.
ed.selectSameEditor = (this.activeEditor == this.lastActiveEditor);
var v = this.preEditValue(r, field);
ed.startEdit(this.view.getCell(row, col).firstChild, Ext.isDefined(v) ? v : '');
if(ed.field.getXType()=="formeditor"){
var scrollerBox=this.view.scroller.getBox();
var editorBox=ed.getEl().getBox();
var scrollTop=this.view.scroller.dom.scrollTop;
if(editorBox.bottom>=(scrollerBox.y+scrollerBox.height)){
this.view.scroller.dom.scrollTop=editorBox.bottom-(scrollerBox.y+scrollerBox.height)+scrollTop;
}
}
// Clear the selectSameEditor flag
(function(){
delete ed.selectSameEditor;
}).defer(50);
}
}
}
});
(On the onEditComplete function, the value in the record was being set incorrectly to how the FormPanelEditor works. On the startEditing function, I have added some code to allow me to have a textarea editor fill up the entire contents of cell. I also added the ability to set minimum and maximum width's and height's on the editors.)
Ext.Editor Overrides
Ext.override(Ext.Editor,{
startEdit:function(el,value){
if(this.editing){this.completeEdit();}
this.boundEl=Ext.get(el);
if(this.field.getXType()=="formeditor"){
var buildValue="";
this.field.items.each(function(item,idx){
buildValue+=(idx==0)?this.record.get(item.dataIndex):this.field.delimiter+this.record.get(item.dataIndex);
},this);
var v=buildValue;
}
else{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();
}
},
onHide:function(){
if(this.editing){
this.completeEdit();
return;
}
this.field.blur();
if(this.field.getXType()!="formeditor"){
if(this.field.collapse){this.field.collapse();}
}
this.el.hide();
if(this.hideEl !== false){
this.boundEl.show();
}
},
clkTarget:function(e){
var clkTarget=false;
var target=Ext.get(e.getTarget());
if(e.getXY()[0]>=this.el.getXY()[0]&&e.getXY()[1]>=this.el.getXY()[1]){
if(e.getXY()[0]<=this.el.getXY()[0]+this.el.getSize().width&&e.getXY()[1]<=this.el.getXY()[1]+this.el.getSize().height){
clkTarget=true;
}
else if(target.hasClass("x-combo-list-item")||target.hasClass("x-combo-list-inner")||target.findParent("a.x-date-date")){clkTarget=true;}
else{clkTarget=false;}
}
else if(target.hasClass("x-combo-list-item")||target.hasClass("x-combo-list-inner")||target.findParent("a.x-date-date")){clkTarget=true;}
else{clkTarget=false;}
if(!clkTarget){
Ext.getBody().un("mousedown",this.clkTarget,this);
this.completeEdit();
return;
}
},
onShow:function(){
if(this.field.getXType()=="formeditor"){this.hasClickTarget=true;Ext.getBody().on("mousedown",this.clkTarget,this);}
this.el.show();
if(this.hideEl !== false){
this.boundEl.hide();
}
if(this.field.getXType()!="formeditor"){this.field.show().focus(false, true);}
else{this.field.items.items[0].focus(false,true);}
this.fireEvent("startedit", this.boundEl, this.startValue);
},
completeEdit:function(remainVisible){
if(!this.editing){return;}
if (this.field.assertValue){this.field.assertValue();}
var v=this.getValue();
if(!this.field.isValid()){
if(this.revertInvalid!==false){this.cancelEdit(remainVisible);}
return;
}
if(String(v)===String(this.startValue)&&this.ignoreNoChange){
this.hideEdit(remainVisible);
return;
}
if(this.fireEvent("beforecomplete",this,v,this.startValue)!==false){
v=this.getValue();
if(this.field.getXType()=="formeditor"){
this.field.items.each(function(item,idx){
this.record.set(item.dataIndex,v.split(this.field.delimiter)[idx]);
},this);
}
else{
if(this.updateEl&&this.boundEl){this.boundEl.update(v);}
}
this.hideEdit(remainVisible);
this.fireEvent("complete",this,v,this.startValue);
}
}
});
(The startEdit function was modified to pre-populate the values in the FormPanelEditor based upon their dataIndex of each field instead of what is in the cell. The onHide function was modified because the FormPanel of the FormPanelEditor was being collapsed and never reshown. I didn't know what the need to even collapse the FormPanel was for the FormPanelEditor, so I left it out for this editor. The onShow function was changed to focus the first field of the FormPanel. There is also an onmousedown event added to the body to check when the FormPanelEditor looses focus. The completeEdit function was changed to correctly update the store with values inside of the FormPanel with their associated dataIndex values.)
Ext.ux.form.FormPanelEditor
/**
* @class Ext.ux.FormPanelEditor
* @extends Ext.form.FormPanel
* Form panel editor
* @author Phillip W. Moore
* @date 04/20/2010
* @version 1.0
*/
Ext.ux.FormPanelEditor=Ext.extend(Ext.form.FormPanel,{
initComponent:function(){
Ext.ux.FormPanelEditor.superclass.initComponent.call(this);
},
initValue:function(){
if(this.value !== undefinded){
this.setValue(this.value);
}else if(!Ext.isEmpty(this.el.dom.value)&&this.el.dom.value!=this.emptyText){
this.setValue(this.el.dom.value);
}
this.originalValue=this.getValue();
},
getValue:function(){
var v=[];
this.items.each(function(item,idx){
if(item.showRawValue){v.push(item.getRawValue());}
else{v.push(item.getValue());}
},this);
return v.join(this.delimiter);
},
getRawValue:function(){
var v=[];
this.items.each(function(item,idx){
v.push(item.getRawValue());
},this);
return v.join(this.delimiter);
},
setValue:function(v){
v=v.split(this.delimiter);
this.items.each(function(item,idx){
item.setValue(v[idx]);
},this);
},
setRawValue:function(v){
v=v.split(this.delimiter);
this.items.each(function(item,idx){
this.setRawValue(v[idx]);
},this);
},
isValid:function(){
var isValid=true;
this.items.each(function(item,idx){
if(!item.isValid()){
isValid=false;
}
},this);
return isValid;
},
isDirty:function(){
if(this.disabled||!this.rendered){return false;}
return String(this.getValue()!==String(this.originalValue));
},
setReadOnly:function(readOnly){
if(this.rendered){
this.items.each(function(item,idx){
item.setReadOnly(readOnly);
},this);
}
},
processValue:function(value){
return value;
},
reset:function(){
this.items.each(function(item,idx){
item.setValue(item.originalValue);
item.clearInvalid();
},this);
}
});
Ext.reg('formeditor',Ext.ux.FormPanelEditor);
The FormPanel was extended to become a FormPanelEditor. I have added functions that are like form fields to change the FormPanel into a type of field to be used as an editor.
If you have any questions or modifications, just let me know.
Here's an example of how to set the editor:
editor:{
xtype:'formeditor',
id:'formpaneleditor',
padding:'5',
defaults:{width:170},
editable:false,
minWidth:170,
defaultType:'textfield',
delimiter:'~#~',
items:[{
name:'category',
id:'category',
hideLabel:true,
dataIndex:'category',
style:'text-align:left;'
},{
xtype:'textfield',
name:'entry',
id:'entry',
hideLabel:true,
dataIndex:'entry',
style:'text-align:left;'
}]
}
Updates
4/26/2010: Fix to the Ext.grid.EditorGridPanel override on the startEditing function. Instead of
var rowHeight=(ed.field.fillRowHeight)?this.view.getCell(row,col).offsetHeight:null;this has been replaced with
var rowHeight=(ed.field.fillRowHeight)?this.view.getCell(row,col).offsetHeight:"";to fix rendering errors in IE.
4/26/2010: Update added to the Ext.editor override on the onShow function. Added new clkTarget function.
4/30/2010: Update to the Ext.grid.EditorGridPanel to the startEditing function. The update will automatically scroll the grid to make sure the FormPanelEditor is in the viewing area when displaying the editor.
5/17/2010: Update to the Ext.editor override on the startEdit function. Changed the delimiter from a "," to a formpaneleditor specified delimiter.
5/17/2010: Update to the Ext.editor override on the clkTarget function. Changed the clkTarget function. The clkTarget function is used to see if we have clicked somewhere on the Ext.ux.FormPanelEditor or not. If we have not clicked on the editor, then changes to the editor are saved and the editor will hide. If we have clicked on the editor, then the editor will remain open. I have added special code to see if the selected target was a combo list item or part of the scrollbar. These items can appear outside the area of the form panel editor when expanded. This issue was found by the testers at our company and by flipthefrog.
5/17/2010: Update to the Ext.editor override on the completeEdit function. Changed the delimiter from a "," to a formpaneleditor specified delimiter.
5/17/2010: Update to the Ext.ux.FormPanelEditor extend on almost all functions. Changed the delimiter from a "," to a formpaneleditor specified delimiter. Also removed escape and unescape calls to prevent odd store value saving.
5/31/2010: Update to Ext.ux.FormPanelEditor on the clkTarget functions. Bug & Solution found by flipthefrog (http://www.extjs.com/forum/member.php?16987-flipthefrog). Added target.findParent('a.x-date-date') to check to see if you are still clicking w/in the FormPanelEditor to avoid the panel editor from closing unexpectedly.
Now upgraded for ExtJS 4.0 as well: Form Panel Editor Example (ExtJS 4.0) (http://www.djengineer.com/ExtJSExamples/PluginExamples/FormPanelEditor/FormPanelEditor.html)
Good Morning/Afternoon everyone,
I have deleted my previous post with a cell editor and form panel editor combo, for a new Ext.ux.FormPanelEditor that allows you to have a form panel as your editor for the EditableGridPanel. Also, I was having trouble with textareas in the EditableGridPanel not taking up the entire cell row and height all the time. So I put a little extra stuff in the EditableGridPanel as well.
First of all, let's talk about the overrides!
Ext.grid.EditorGridPanel Overrides
Ext.override(Ext.grid.EditorGridPanel,{
onEditComplete:function(ed, value, startValue){
this.editing=false;
this.lastActiveEditor=this.activeEditor;
this.activeEditor=null;
var r=ed.record,field=this.colModel.getDataIndex(ed.col);
value=this.postEditValue(value,startValue,r,field);
if(this.forceValidation===true||String(value)!==String(startValue)){
var e={
grid:this,
record:r,
field:field,
originalValue:startValue,
value:value,
row:ed.row,
column:ed.col,
cancel:false
};
if(this.fireEvent("validateedit",e)!==false&&!e.cancel&&String(value)!==String(startValue)){
if(ed.field.getXType()!="formeditor"){
r.set(field,e.value);
}
delete e.cancel;
this.fireEvent("afteredit",e);
}
}
this.view.focusCell(ed.row,ed.col);
},
startEditing : function(row, col){
this.stopEditing();
if(this.colModel.isCellEditable(col, row)){
this.view.ensureVisible(row, col, true);
var r = this.store.getAt(row),
field = this.colModel.getDataIndex(col),
e = {
grid: this,
record: r,
field: field,
value: r.data[field],
row: row,
column: col,
cancel:false
};
if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
this.editing = true;
var ed=this.colModel.getCellEditor(col,row);
if(!ed){return;}
/**
* Update height and width of the editor
*/
var colWidth=e.grid.getColumnModel().getColumnAt(col).width;
var rowHeight=(ed.field.fillRowHeight)?this.view.getCell(row,col).offsetHeight:"";
if(ed.field.minWidth){colWidth=(colWidth>=ed.field.minWidth)?colWidth:ed.field.minWidth;}
if(ed.field.maxWidth){colWidth=(colWidth<=ed.field.maxWidth)?colWidth:ed.field.maxWidth;}
if(ed.field.minHeight){rowHeight=(rowHeight>=ed.field.minHeight)?rowHeight:ed.field.minHeight;}
if(ed.field.maxHeight){rowHeight=(rowHeight<=ed.field.maxHeight)?rowHeight:ed.field.maxHeight;}
ed.setSize(colWidth,rowHeight);
if(!ed.rendered){
ed.parentEl = this.view.getEditorParent(ed);
ed.on({
scope: this,
render: {
fn: function(c){
c.field.focus(false, true);
},
single: true,
scope: this
},
specialkey: function(field, e){
this.getSelectionModel().onEditorKey(field, e);
},
complete: this.onEditComplete,
canceledit: this.stopEditing.createDelegate(this, [true])
});
}
Ext.apply(ed, {
row : row,
col : col,
record : r
});
this.lastEdit = {
row: row,
col: col
};
this.activeEditor = ed;
// Set the selectSameEditor flag if we are reusing the same editor again and
// need to prevent the editor from firing onBlur on itself.
ed.selectSameEditor = (this.activeEditor == this.lastActiveEditor);
var v = this.preEditValue(r, field);
ed.startEdit(this.view.getCell(row, col).firstChild, Ext.isDefined(v) ? v : '');
if(ed.field.getXType()=="formeditor"){
var scrollerBox=this.view.scroller.getBox();
var editorBox=ed.getEl().getBox();
var scrollTop=this.view.scroller.dom.scrollTop;
if(editorBox.bottom>=(scrollerBox.y+scrollerBox.height)){
this.view.scroller.dom.scrollTop=editorBox.bottom-(scrollerBox.y+scrollerBox.height)+scrollTop;
}
}
// Clear the selectSameEditor flag
(function(){
delete ed.selectSameEditor;
}).defer(50);
}
}
}
});
(On the onEditComplete function, the value in the record was being set incorrectly to how the FormPanelEditor works. On the startEditing function, I have added some code to allow me to have a textarea editor fill up the entire contents of cell. I also added the ability to set minimum and maximum width's and height's on the editors.)
Ext.Editor Overrides
Ext.override(Ext.Editor,{
startEdit:function(el,value){
if(this.editing){this.completeEdit();}
this.boundEl=Ext.get(el);
if(this.field.getXType()=="formeditor"){
var buildValue="";
this.field.items.each(function(item,idx){
buildValue+=(idx==0)?this.record.get(item.dataIndex):this.field.delimiter+this.record.get(item.dataIndex);
},this);
var v=buildValue;
}
else{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();
}
},
onHide:function(){
if(this.editing){
this.completeEdit();
return;
}
this.field.blur();
if(this.field.getXType()!="formeditor"){
if(this.field.collapse){this.field.collapse();}
}
this.el.hide();
if(this.hideEl !== false){
this.boundEl.show();
}
},
clkTarget:function(e){
var clkTarget=false;
var target=Ext.get(e.getTarget());
if(e.getXY()[0]>=this.el.getXY()[0]&&e.getXY()[1]>=this.el.getXY()[1]){
if(e.getXY()[0]<=this.el.getXY()[0]+this.el.getSize().width&&e.getXY()[1]<=this.el.getXY()[1]+this.el.getSize().height){
clkTarget=true;
}
else if(target.hasClass("x-combo-list-item")||target.hasClass("x-combo-list-inner")||target.findParent("a.x-date-date")){clkTarget=true;}
else{clkTarget=false;}
}
else if(target.hasClass("x-combo-list-item")||target.hasClass("x-combo-list-inner")||target.findParent("a.x-date-date")){clkTarget=true;}
else{clkTarget=false;}
if(!clkTarget){
Ext.getBody().un("mousedown",this.clkTarget,this);
this.completeEdit();
return;
}
},
onShow:function(){
if(this.field.getXType()=="formeditor"){this.hasClickTarget=true;Ext.getBody().on("mousedown",this.clkTarget,this);}
this.el.show();
if(this.hideEl !== false){
this.boundEl.hide();
}
if(this.field.getXType()!="formeditor"){this.field.show().focus(false, true);}
else{this.field.items.items[0].focus(false,true);}
this.fireEvent("startedit", this.boundEl, this.startValue);
},
completeEdit:function(remainVisible){
if(!this.editing){return;}
if (this.field.assertValue){this.field.assertValue();}
var v=this.getValue();
if(!this.field.isValid()){
if(this.revertInvalid!==false){this.cancelEdit(remainVisible);}
return;
}
if(String(v)===String(this.startValue)&&this.ignoreNoChange){
this.hideEdit(remainVisible);
return;
}
if(this.fireEvent("beforecomplete",this,v,this.startValue)!==false){
v=this.getValue();
if(this.field.getXType()=="formeditor"){
this.field.items.each(function(item,idx){
this.record.set(item.dataIndex,v.split(this.field.delimiter)[idx]);
},this);
}
else{
if(this.updateEl&&this.boundEl){this.boundEl.update(v);}
}
this.hideEdit(remainVisible);
this.fireEvent("complete",this,v,this.startValue);
}
}
});
(The startEdit function was modified to pre-populate the values in the FormPanelEditor based upon their dataIndex of each field instead of what is in the cell. The onHide function was modified because the FormPanel of the FormPanelEditor was being collapsed and never reshown. I didn't know what the need to even collapse the FormPanel was for the FormPanelEditor, so I left it out for this editor. The onShow function was changed to focus the first field of the FormPanel. There is also an onmousedown event added to the body to check when the FormPanelEditor looses focus. The completeEdit function was changed to correctly update the store with values inside of the FormPanel with their associated dataIndex values.)
Ext.ux.form.FormPanelEditor
/**
* @class Ext.ux.FormPanelEditor
* @extends Ext.form.FormPanel
* Form panel editor
* @author Phillip W. Moore
* @date 04/20/2010
* @version 1.0
*/
Ext.ux.FormPanelEditor=Ext.extend(Ext.form.FormPanel,{
initComponent:function(){
Ext.ux.FormPanelEditor.superclass.initComponent.call(this);
},
initValue:function(){
if(this.value !== undefinded){
this.setValue(this.value);
}else if(!Ext.isEmpty(this.el.dom.value)&&this.el.dom.value!=this.emptyText){
this.setValue(this.el.dom.value);
}
this.originalValue=this.getValue();
},
getValue:function(){
var v=[];
this.items.each(function(item,idx){
if(item.showRawValue){v.push(item.getRawValue());}
else{v.push(item.getValue());}
},this);
return v.join(this.delimiter);
},
getRawValue:function(){
var v=[];
this.items.each(function(item,idx){
v.push(item.getRawValue());
},this);
return v.join(this.delimiter);
},
setValue:function(v){
v=v.split(this.delimiter);
this.items.each(function(item,idx){
item.setValue(v[idx]);
},this);
},
setRawValue:function(v){
v=v.split(this.delimiter);
this.items.each(function(item,idx){
this.setRawValue(v[idx]);
},this);
},
isValid:function(){
var isValid=true;
this.items.each(function(item,idx){
if(!item.isValid()){
isValid=false;
}
},this);
return isValid;
},
isDirty:function(){
if(this.disabled||!this.rendered){return false;}
return String(this.getValue()!==String(this.originalValue));
},
setReadOnly:function(readOnly){
if(this.rendered){
this.items.each(function(item,idx){
item.setReadOnly(readOnly);
},this);
}
},
processValue:function(value){
return value;
},
reset:function(){
this.items.each(function(item,idx){
item.setValue(item.originalValue);
item.clearInvalid();
},this);
}
});
Ext.reg('formeditor',Ext.ux.FormPanelEditor);
The FormPanel was extended to become a FormPanelEditor. I have added functions that are like form fields to change the FormPanel into a type of field to be used as an editor.
If you have any questions or modifications, just let me know.
Here's an example of how to set the editor:
editor:{
xtype:'formeditor',
id:'formpaneleditor',
padding:'5',
defaults:{width:170},
editable:false,
minWidth:170,
defaultType:'textfield',
delimiter:'~#~',
items:[{
name:'category',
id:'category',
hideLabel:true,
dataIndex:'category',
style:'text-align:left;'
},{
xtype:'textfield',
name:'entry',
id:'entry',
hideLabel:true,
dataIndex:'entry',
style:'text-align:left;'
}]
}
Updates
4/26/2010: Fix to the Ext.grid.EditorGridPanel override on the startEditing function. Instead of
var rowHeight=(ed.field.fillRowHeight)?this.view.getCell(row,col).offsetHeight:null;this has been replaced with
var rowHeight=(ed.field.fillRowHeight)?this.view.getCell(row,col).offsetHeight:"";to fix rendering errors in IE.
4/26/2010: Update added to the Ext.editor override on the onShow function. Added new clkTarget function.
4/30/2010: Update to the Ext.grid.EditorGridPanel to the startEditing function. The update will automatically scroll the grid to make sure the FormPanelEditor is in the viewing area when displaying the editor.
5/17/2010: Update to the Ext.editor override on the startEdit function. Changed the delimiter from a "," to a formpaneleditor specified delimiter.
5/17/2010: Update to the Ext.editor override on the clkTarget function. Changed the clkTarget function. The clkTarget function is used to see if we have clicked somewhere on the Ext.ux.FormPanelEditor or not. If we have not clicked on the editor, then changes to the editor are saved and the editor will hide. If we have clicked on the editor, then the editor will remain open. I have added special code to see if the selected target was a combo list item or part of the scrollbar. These items can appear outside the area of the form panel editor when expanded. This issue was found by the testers at our company and by flipthefrog.
5/17/2010: Update to the Ext.editor override on the completeEdit function. Changed the delimiter from a "," to a formpaneleditor specified delimiter.
5/17/2010: Update to the Ext.ux.FormPanelEditor extend on almost all functions. Changed the delimiter from a "," to a formpaneleditor specified delimiter. Also removed escape and unescape calls to prevent odd store value saving.
5/31/2010: Update to Ext.ux.FormPanelEditor on the clkTarget functions. Bug & Solution found by flipthefrog (http://www.extjs.com/forum/member.php?16987-flipthefrog). Added target.findParent('a.x-date-date') to check to see if you are still clicking w/in the FormPanelEditor to avoid the panel editor from closing unexpectedly.