PDA

View Full Version : Ext.ux.FieldReadOnlyPlugin (plugin)



mabello
9 Jul 2008, 8:57 AM
Goal of the plugin:

Make a field (combobox, triggerfield, textarea, textfield etc) readonly dinamically using the readonly attribute of the underlying dom element instead of using the disable method provided.
Basically, using disable method of a field results in modifying the look and feel of the component and with IE6 using a disableClass attribute to make the look and feel of the component look like a readonly field does not work (the color of the text is still gray).
Described behaviour is here:
http://extjs.com/forum/showthread.php?p=175972

For further information, please check out the following threads:

http://extjs.com/forum/showthread.php?t=40711
http://extjs.com/forum/showthread.php?t=40640
http://extjs.com/forum/showthread.php?p=180524

While in this case I have created a plugin, I would say that it'd better be an extension of the base class field.

To fix the problem, this is the "hack" I came up with:


Ext.namespace('Ext.ux');
//Utility class
if(!Ext.ux.Utility)
Ext.ux.Utility = {

isNullOrUndefined: function(obj) {
return (typeof obj == 'undefined' || obj == null );
},
isFunction: function(f){
return typeof f == 'function';
}

};

Ext.ux.FieldReadOnlyPlugin = function(){

this.init = function(f){
f.setReadOnly = function(value){
if(f.readOnly)//if readonly is set in the Ext way, like in cfg object, do not take any action.
return;
f._readOnly = value;
if(f.rendered){
if(Ext.ux.Utility.isNullOrUndefined(f.editable) || f.editable === true){
var el = f.getEl();
el.dom.setAttribute('readOnly', value);
el.dom.readOnly = value;
}
}
else {
f.readOnly = value;
}
};

if(Ext.ux.Utility.isFunction(f.expand))
f.expand = f.expand.createInterceptor(function(){
return !f._readOnly;
});
if(Ext.ux.Utility.isFunction(f.onTriggerClick))
f.onTriggerClick = f.onTriggerClick.createInterceptor(function(){
return !f._readOnly;
});
if(Ext.ux.Utility.isFunction(f.onClick))
f.onClick = f.onClick.createInterceptor(function(){
if(f._readOnly){
this.el.dom.checked = f.checked;
}
return !f._readOnly;
});
if(Ext.ux.Utility.isFunction(f.setValue) && f instanceof Ext.form.Checkbox)
f.setValue = f.setValue.createInterceptor(function(){
return !f._readOnly;
});
}
}

Use it:


var savePassword = new Ext.form.Checkbox({

xtype:'checkbox',

plugins: [new Ext.ux.FieldReadOnlyPlugin()],

...

});

savePassword .setReadOnly(true);


I hope this helps.

slarti42uk
15 Aug 2008, 7:24 AM
Hi mabello,

Your plugin has really helped me out with getting runtime switching of forms to readonly.=D>

The only problem I'm having still is with radio buttons. I have a set of four Ext.radio's all with the same name so the browser handles the selection of only one. The problem is that in readonly mode, if I select one that is not checked, it clears the one that was but doesn't set the new one either, so you end up with no radio selected.

Can you see any way to add to the existing code to allow for radio buttons?

Cheers
Steve

mabello
25 Aug 2008, 9:17 AM
Dear Steve,
Sorry for my very late answer, I was on holiday without a laptop!
I will look at it when I find some spare time, you are just right, I have not tried with radio buttons..
Thanks for pointing out the problem

carl23934
10 Sep 2008, 11:26 AM
I just wanted to thank you for creating this. It took me a bit to get it setup because I was missing the Ext.ux.Utility portion. I found this in another thread first, and that thread did not contain that part! I will add links to this thread in that thread.

Anyway, it works great, and I greatly appreciate your effort!

mabello
10 Sep 2008, 1:26 PM
Dear Carl23934,
You are very welcome!
Thanks for your kind comment, I'm happy that this plugin is useful also for you.

fangzhouxing
23 Sep 2008, 6:44 PM
mabello,thank you so much! Your plugin is very useful and I am used it in my current project!

My question: Why this plugin not have effect when i only set config item readOnly to true?

mabello
24 Sep 2008, 12:20 AM
Dear fangzhouxing,
I really appreciated your comment!
The reason is that if you set readOnly: true in the cfg object, my plugin does not take any action (because if i remember right, using readOnly: true directly in the cfg object makes the ui of the component being displayed in the right way).

The line of my code used to follow this behaviour is highlighted(<-----) in the following fragment of code:



this.init = function(f){
f.setReadOnly = function(value){
if(f.readOnly)//<---------HERE if readonly is set in the Ext way, like in cfg object, do not take any action.
return;

I hope this helps

wwwtd
13 Oct 2008, 11:29 PM
hihi

mabello
14 Oct 2008, 12:04 AM
Hello there.

My first post contains also the Ext.ux.Utility stuff at the beginning of the thread.



Ext.namespace('Ext.ux');
//Utility class
if(!Ext.ux.Utility)
Ext.ux.Utility = {

isNullOrUndefined: function(obj) {
return (typeof obj == 'undefined' || obj == null );
},
isFunction: function(f){
return typeof f == 'function';
}

};

wwwtd
15 Oct 2008, 5:55 PM
Hello there.

My first post contains also the Ext.ux.Utility stuff at the beginning of the thread.



Ext.namespace('Ext.ux');
//Utility class
if(!Ext.ux.Utility)
Ext.ux.Utility = {

isNullOrUndefined: function(obj) {
return (typeof obj == 'undefined' || obj == null );
},
isFunction: function(f){
return typeof f == 'function';
}

};

Thank you ,I read the program again .and find out the code above. Thanks~

carl23934
14 Aug 2009, 10:20 AM
I noticed this doesn't work with Chrome 2.0 for textareas. Very strange!!

Here is a complete demo page.
This works with IE, Firefox, Chrome 1.0, but not chrome 2.0


<script type="text/javascript" src="/ext-2.2/source/core/Ext.js"></script>
<script type="text/javascript" src="/ext-2.2/source/adapter/ext-base.js"></script>
<script type="text/javascript" src="/ext-2.2/ext-all-debug.js"></script>

<script type="text/javascript" src="/inc/js/readOnly.js"></script>
<script type="text/javascript">

Ext.BLANK_IMAGE_URL = '/inc/img/s.gif';

Ext.onReady(function(){

viewport = new Ext.Viewport({
layout:'border',
frame: true,
items: [
{
region:'center'
,items:[
{
xtype:'textarea',
width:470,
height:75,
plugins: [new Ext.ux.FieldReadOnlyPlugin()]
},{
xtype:'button',
text:'Toggle Read Only',
handler:function(){
if(textarea._readOnly){
textarea.setReadOnly(false);
}else{
textarea.setReadOnly(true);
}
}
}]
}]
});

viewport.render('body');

textarea = viewport.items.items[0].items.items[0];

textarea.setReadOnly(true);
});

</script>

mabello
24 Aug 2009, 4:58 AM
I don't have Chrome 2.0 installed, but if I will have a look and check how come it does not work hopefully.
Anyway, thanks for the feedback, it's really appreciated!
Cheers

Mathias Weisheit
17 Feb 2010, 1:33 AM
I've added this lines:

if (value==true){
el.addClass("x-item-disabled");
} else {
el.removeClass("x-item-disabled");
}
under el.dom.readOnly = value;

The hole function:

Ext.ux.FieldReadOnlyPlugin = function(){

this.init = function(f){
f.setReadOnly = function(value){
if(f.readOnly)//if readonly is set in the Ext way, like in cfg object, do not take any action.
return;
f._readOnly = value;
if(f.rendered){
if(Ext.ux.Utility.isNullOrUndefined(f.editable) || f.editable === true){
var el = f.getEl();
el.dom.setAttribute('readOnly', value);
el.dom.readOnly = value;
if (value==true){
el.addClass("x-item-disabled");
} else {
el.removeClass("x-item-disabled");
}
}
}
else {
f.readOnly = value;
}
};

if(Ext.ux.Utility.isFunction(f.expand))
f.expand = f.expand.createInterceptor(function(){
return !f._readOnly;
});
if(Ext.ux.Utility.isFunction(f.onTriggerClick))
f.onTriggerClick = f.onTriggerClick.createInterceptor(function(){
return !f._readOnly;
});
if(Ext.ux.Utility.isFunction(f.onClick))
f.onClick = f.onClick.createInterceptor(function(){
if(f._readOnly){
this.el.dom.checked = f.checked;
}
return !f._readOnly;
});
if(Ext.ux.Utility.isFunction(f.setValue) && f instanceof Ext.form.Checkbox)
f.setValue = f.setValue.createInterceptor(function(){
return !f._readOnly;
});
}
}

Mathias Weisheit
17 Feb 2010, 1:35 AM
I want to extend your plugin for sliders. But it doesn't work:

if(Ext.ux.Utility.isFunction(f.drag))
f.expand = f.expand.createInterceptor(function(){
return !f._readOnly;
});

Can you help me?

mabello
19 Feb 2010, 1:27 AM
For the slider I think you can use enable() and disabled() directly, so you may want to extend the plugin to do that...
I haven't tried in IE6 though.
Hope this helps a little

pbodnar
4 Aug 2010, 1:01 AM
Hi slarti42uk (http://www.sencha.com/forum/member.php?28575-slarti42uk),

I have run into the same problem with radio buttons. The previously-checked button gets unchecked because of a standard behaviour of browsers. Here is the onClick interceptor which works for me (apply it when this instanceof Ext.form.Radio; you must of course change the code a bit if you are using the above plugin code):


if (this.readOnly) {
// restore the state of ALL buttons - the state before the click occurred
var els = this.getCheckEl().select('input[name=' + this.el.dom.name + ']');
els.each(function(el) {
el.dom.checked = Ext.getCmp(el.dom.id).checked;
}, this);
}
return !this.readOnly;

Note: The code above uses the Radio's getCheckEl() private function - which I think is in in the framework since version 3.

pramodkhare
19 May 2011, 6:18 AM
In case of textField, triggerfield or combobox,

You can achieve functionality of above plugin with single line,

I have not tested it in case of Radiogroup/radio button..but for above mentioned components ...

You can write...

Ext.getDom(<ID_of_YOUR_Field>).readOnly = true;

and when you want to make it enable ...

Ext.getDom(<ID_of_YOUR_Field>).readOnly = false;