Notice This is a beta feature offered by Google. Also this is automatic translation, which means the results are often inacurate and/or hilarious. Enjoy.

ARCHIVES / RSS
Blog

Delayed observer for jQuery

h3  ~  14 Sep 2007, 20:50  –  post a comment

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..

post a comment Comments

no comments :|

Copyrighted stuff .. u know.