While switching a quite big project from Prototyle to jQuery, I realized that there isn't any method in jQuery core that accomplish the same task as the Prototype's delayed observer.
I absolutely needed it and I couldn't find anything in their somewhat half baked plugin repository.
To tell the truth I found something, it's called typeWatch. Its description says that it does pretty much what I needed, but it didn't work.. Naively I though to myself, well I'm gonna fix it ! The first obstacle I've met was that the whole script was compressed to one line .. great. Then after spending 5 minutes re-indenting code I realized that the code was horrific. I wish I could re-indent it mentally and forget that I've seen such a thing.
So yesterday I spent half the night trying to implement it. After 3 gallons of coffee, I've came to this tortured solution:
/* jQuery delayed observer (c) 2007 - Maxime Haineault (max@centdessin.com) */ jQuery.fn.extend({ delayedObserver:function(delay, callback){ $this = $(this); if (typeof window.delayedObserverStack == 'undefined') { window.delayedObserverStack = []; } if (typeof window.delayedObserverCallback == 'undefined') { window.delayedObserverCallback = function(stackPos) { observed = window.delayedObserverStack[stackPos]; if (observed.timer) clearTimeout(observed.timer); observed.timer = setTimeout(function(){ observed.timer = null; observed.callback(observed.obj.val(), observed.obj); }, observed.delay * 1000); observed.oldVal = observed.obj.val(); } } window.delayedObserverStack.push({ obj: $this, timer: null, delay: delay, oldVal: $this.val(), callback: callback }); stackPos = window.delayedObserverStack.length-1; $this.keyup(function() { observed = window.delayedObserverStack[stackPos]; if (observed.obj.val() == observed.obj.oldVal) return; else window.delayedObserverCallback(stackPos); }); } });
It was particularly hard because I couldn't use closures as they are used in Prototype, I had to use some dirty tricks, like adding two global variables to the window object. But I managed to keep the name space clean !
There is still one catch22, the observed element can be observed more than once. I wish I could prevent this, but the only way I found involved requiring the element to have an id attribute.
On the other hand I'm not sure that I should prevent it..
no comments :|