PDA

View Full Version : new Ext.form field type - InlineTextField



Nullity
12 Jun 2007, 11:28 AM
I created a new form field type called InlineTextField. On render, the field shows as plain text. When the text is clicked on, it changes to a regular TextField (basically like an EditorGrid), and then changes back to plain text when the field is blurred. This is much easier and faster than using an Ext.Editor, which I'm not even sure can be used in a form anyway.

Here is the code:


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();
}
}
})
});

... and here is the needed CSS:


.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);
}

It includes a couple new config options. The first is 'autoSave', which when set and the field is blurred, it does and ajax call to immediately save the changes. The 'autoSave' option accepts either a string containing the url for the ajax call, or an object, like so:


autoSave: '/path/ajax.php'
or
autoSave: {url: '/path/ajax.php', method: 'POST', callback: some_function, scope: this}


There is also a 'saveOnlyOnChange' option which should be pretty self-explanatory. When true (default), the field only auto-saves the data on blur if it was changed. So, when false, the data is always saved, whether changed or not.


UPDATE 1: I added code suggested by schmidetzki which cancels the edit if the ESC key is pressed.


UPDATE 2 (9/10/2007): Updated code to version 1.2. Added new options: 'confirmSave' and 'confirmText'. The first, 'confirmSave' is a boolean which when true, will display a MessageBox containing the text set by 'confirmText' (optional) when the changes are saved successfully. Also, the 'autoSave' object now supports a 'scope' setting.


UPDATE 3 (9/11/2007): Updated code for version 1.3. Changed the way 'confirmSave' was handled to fix a bug. Refactored some code to be cleaner.

galdaka
12 Jun 2007, 1:03 PM
any example or screenshot?

JorisA
12 Jun 2007, 1:47 PM
demo: http://ext.designism.nl/examples/textfield/inlinetextfield.html

Nullity
13 Jun 2007, 5:13 AM
Thank you for supplying a demo, JorisA. Sorry, I don't have a public web site to set up my own, and I didn't post a screenshot because I was short on time. I have attached a screenshot now though (to the first post).

JorisA
15 Jun 2007, 4:46 PM
Hmmm I think a InlineForm would be awesome:

Add a config var editMode (or something) to the Form class:
'default' = Show input elements for all fields
'single' = Only show input element for focussed field

And lockedMode:
'default' = All fields are editable
'locked' = Fields are readonly

I think this can be achieved by extending the Form class, and making some small changes to the Field one (since all inputs are extended by it)

If you've got big forms like contact details it makes them nice to view and print without the need for a separate edit form. (just add a small unlock/edit icon in the form header). This also doesn't confuse users viewing the form without editing rights.

Maybe I'm talking poo because I'm pretty tired. I will read this tomorrow and hope it still looks like a good idea.

schmidetzki
17 Jun 2007, 7:51 AM
I implemented a similar function but yours is much nicer!
I would however prefere to cancel edit if the user presses ESC and to call "save" when the user presses ENTER.

Updated: Anyway - here is my version:


BI.util.editDivText=function (el, callback){
var dh = Ext.DomHelper;
var span = dh.insertBefore(el, {tag:"span"})
var f = new Ext.form.TextField({
originalElement: el,
callback: callback,
restore: function(){
span.parentNode.removeChild(span);
//info.parentNode.removeChild(info);
},
width: Ext.get(el).getWidth(),
qtip: "ESC to cancel edit",
value: el.innerHTML
});
el.style.display="none";
f.render(span);
f.on("specialkey", function(field, ev){
if(ev.getKey() == ev.ENTER){
ev.preventDefault();
field.el.dom.blur();
}
if(ev.getKey() == ev.ESC){
field.reset();
field.el.dom.blur();
}
})
f.on("change", function(field){
field.originalElement.innerHTML = field.getValue();
field.callback(field.getValue())
});
f.on("blur", function(field){
field.restore();
field.originalElement.style.display="block";
field.destroy();
});
f.focus(true);
}

z1nkum
22 Jun 2007, 6:38 AM
Thanks a lot!

Is it possible to do subj?
I mean plain text that transform to TextArea on click.
I think it's must looks like googles notebook fields.

Nullity
22 Jun 2007, 7:25 AM
schmidetzki, that's a great idea using ESC to cancel the edit. I hope you don't mind, I edited my code in the first post to add this functionality.


Thanks a lot!

Is it possible to do subj?
I mean plain text that transform to TextArea on click.
I think it's must looks like googles notebook fields.
I just posted InlineTextArea. :)

http://extjs.com/forum/showthread.php?t=8118

z1nkum
23 Jun 2007, 7:46 AM
Thanks a lot for you!!

jon.whitcraft
24 Jun 2007, 1:21 PM
This would a great add to the Wiki under the User Extensions:

http://extjs.com/learn/Ext_Extensions

JorisA
24 Jun 2007, 1:55 PM
Will do: http://www.extjs.com/learn/Extension:Inline_Form

Nullity
26 Jun 2007, 5:51 AM
Will do: http://www.extjs.com/learn/Extension:Inline_Form

I've been looking into this for part of my morning, and I'm not sure there's going to be a real easy way to do it. Adding and expanding the necessary methods in the base Field class is easy enough, but then some of the other classes like TextField, TextArea, and ComboBox override some of those. So, I'd have to override them a second time with the inline stuff.

So If you can think of a better way, I'd love to hear it; I like this idea too.

mjlecomte
7 Jul 2007, 7:52 PM
I'm very new to ext so please excuse me. The sample text editing is excellent. I like that it supports tabbing to get to the next editable text area as well.
Not knowing exactly what is going on with the request to Escape or having to hit enter to save I would hope that could be made an optional argument for the user to decide. For me, I like the Escape feature to cancel the edit, but instead of Enter to accept I would have preferred "tab". Which leads to my inquiry if this example has or can be incorporated into an editable grid.
I saw that ext has a nice grid, and that's it's being expanded for ext 2.0. It would be nice if that grid coupled this editing feature such that you could tab through the grid and edit 'grids'. This would almost be like working with Excel.
I'm not sure how difficult it would be, but would be nice to configure the tabbing order (whether the next tab goes horizontally in the grid row or vertically in the grid column).

justCharlie
17 Jul 2007, 4:02 PM
I'm very new to JS and Ext, this may be a very n00bish questions, but could anyone give an example how to use this InlineTextField.


-charlie

sintax.era
3 Sep 2007, 6:15 PM
is there any way to add more parameters to the ajax send?
for example, id like to send the contact ID of the field im updating...

sintax.era
3 Sep 2007, 6:18 PM
oh ok I just figured it out after trying something i thought id already tried :)

contactDisplayFirstName = new Ext.form.InlineTextField({
autoSave: {url:'test.html',table:'contact',id:100,params:{another:'param'}},
id: 'firstname',
fieldLabel:'First Name'
});

posts :
firstname sintax
another param

sintax.era
4 Sep 2007, 8:16 PM
ive been trying to get a callback function to work for the last day...
has anyone succeeded in making it go? or am I just still stupid :P

Nullity
5 Sep 2007, 5:19 AM
ive been trying to get a callback function to work for the last day...
has anyone succeeded in making it go? or am I just still stupid :P

It worked for me in testing. Please post the relevant parts of your code.

sintax.era
5 Sep 2007, 10:53 AM
AutoSaveCallBack:function(){
console.log('test');
}
,
DisplayForm:function(){
console.log('->ContactDisplay.DisplayForm<-');
rec = PMS.dsContact.getById(cid);

contactDisplayFirstName = new Ext.form.InlineTextField({
autoSave: {
url:'php/update.php' (http://extjs.com/forum/'php/update.php'),
callback:PMS.ContactDisplay.AutoSaveCallBack,
id:cid,params:{
id:cid,
table:'contact'
}},
id: 'firstname',
fieldLabel:'First Name',
value:rec.get('firstname')
});
form.column({width:'280'},contactDisplayFirstName);
form.render('ContactDisplayFormId');
}

Nullity
10 Sep 2007, 7:26 AM
First post updated to version 1.2 (along with details). sintax.era, this may fix the callback issues you were having.

jon.whitcraft
12 Sep 2007, 5:29 AM
Can you please move this to the wiki so that it's with all the other user extensions?

http://extjs.com/learn/Ext_Extensions (http://extjs.com/forum/../learn/Ext_Extensions)

Grimsk
12 Sep 2007, 5:34 AM
good job=D>

Nullity
12 Sep 2007, 8:25 AM
Can you please move this to the wiki so that it's with all the other user extensions?

http://extjs.com/learn/Ext_Extensions (http://extjs.com/forum/../learn/Ext_Extensions)

I have added all of my Inline Form Fields to the Extensions wiki.

http://extjs.com/learn/Extension:InlineFormFields


good job=D>

Thank you :)

LALING
1 Nov 2007, 7:02 PM
GREAT EXTENSION!

nexneo
25 Jan 2008, 10:30 AM
Is it possible to use with Ext 2.0?

mayurid
28 Jul 2010, 5:56 AM
i am new to extjs,

should i put the souce code in one file and include it or just use the source code with my main code.i tried both its not working