PDA

View Full Version : Disable a button from being double clicked



bhaidaya
16 Mar 2010, 8:31 AM
I wrote a simple plugin to disable a button from being double clicked. the time difference is set at 400 which should likely be tweaked if you run into trouble.

used like this:


buttons: [{
text: 'Next',
plugins: [Ext.ux.DisableDoubleClick],
handler: function(){}
}]


based off of a conversation about enabling separate behavior for double clicks here:
http://www.extjs.com/forum/showthread.php?t=2278



Ext.ux.DisableDoubleClick = (function(){

return {

init: function(f){

f.lastClick = 0;

f.onClick = f.onClick.createInterceptor(this.onClick);
},

onClick: function(){
if (!this.disabled) {
var time = new Date().getTime();
if (time - this.lastClick < 400) {
this.lastClick = 0;
return false;//was recently pushed
}
else {
this.lastClick = time;
return true;
}
}

}
};
})();


Am I missing something? is there another way to do this?

tof
17 Mar 2010, 12:58 AM
My solution :



buttons: [{
text: 'Next',
handler: function(){},
listeners : { click : function(b) {b.setDisabled(true); b.setDisabled.defer(2000, b, [false]);} }
}]



Or, much nicer, like a plugin :


var disabler = function(delay) {
return function(b) {
b.setDisabled(true);
b.setDisabled.defer(delay, b, [false]);
}
};

buttons: [{
text: 'Next',
handler: function(){},
listeners : { click : disabler(400) }
}]


You can put the "disabler" function in a global ux tool lib, for exemple, if you used this often.

bhaidaya
17 Mar 2010, 7:03 AM
Have you tested that?

When i tried to simply disable the button it seemed to fail half the time.. maybe the timing of disabling wasn't quick enough..

trying your solution now...

bhaidaya
17 Mar 2010, 7:22 AM
Your solution works as well and I actually like it better because it doesn't store a value in memory.

I recall now that when I was using .disable() it was in the handler and that was probably the difference in timing.

I think i will leave it as an Ext Plugin for Modularity and Name Space..

so...


Ext.ux.DisableDoubleClick = (function(){
return {
init: function(f){
f.on({
click: {
fn: function(b){
b.setDisabled(true);
b.setDisabled.defer(2000, b, [false]);
}
}
});
}
};
})();

and used like...

buttons: [{
text: 'Next',
plugins: [Ext.ux.DisableDoubleClick],
handler: function(){}
}]

thanks for your input tof..

tof
17 Mar 2010, 7:25 AM
You're welcome :)

A plugin is good.

But IMHO, you should set the delay as a config option for your plugin.

bhaidaya
17 Mar 2010, 7:31 AM
Still not working... I'll test and reply.

Once i put it into this plugin form it does'nt work..

bhaidaya
17 Mar 2010, 7:46 AM
OK here is what i tried...


Ext.ux.DisableDoubleClick2 = function(delay){
delay = delay || 2000;

return {
init: function(f){
f.on({
click: {
fn: function(b){
b.setDisabled(true);
b.setDisabled.defer(delay, b, [false]);
//Ext.ux.NotificationAlert('click');
}
}
});
}
};
};


to be used like this

plugins: [new Ext.ux.DisableDoubleClick2(2000)]

but it does not work. The listener actually only fires with the correct timing 1 in 10. Which leads me to believing that in this case the first solution fits the bill better. A listener is passive whereas the first solution intercepts the action.

I'm back to the first option... thoughts?

I'm curious to know if you are using the code you shared in any live environment.

tof
17 Mar 2010, 7:56 AM
No, i juste put this code to help you, and for fun and curiosity.

I didn't want you to loose time on this, thought; I'm sorry if I did.

The goal was to prevent overloading the onClick method (I don't like overloading methods), working with events is always better.

But, indeed, because of the race conditions, I think you should put the setDisabled(true); in the onClick overloading.

tof
17 Mar 2010, 8:01 AM
After trying again, I don't have any problems with the {listeners : { click.... method.

I suspect that listeners are managed before the Button "onclick" events initialisation; which is not the case in a plugin.

bhaidaya
17 Mar 2010, 11:32 AM
No, i juste put this code to help you, and for fun and curiosity.

I didn't want you to loose time on this, thought; I'm sorry if I did.


Not a waste at all, all in good fun.

Odd though that when you use f.on({click}) in the plugin init() it doesn't work but when you use the listener directly it does. Must be timing issue...

I wonder if an Ext support rep will read this (or care)