Search code examples
javascriptprototypejsdom-events

Disabling click event handlers


I am trying to basically disable the click event on a <div> temporarily.

I have tried the following (preview):

$('hello').observe('click', function (e) {
    e.stop();
});

$('hello').observe('click', function (e) {
    alert('click not stopped!');
});

However, when #hello is clicked, the alert box still appears. I do not want the second attached handler to be called, and I do not want to change the second handler.

I will also accept a solution such as:

$('hello').observe('click', function (e) {
    alert('click not stopped!');
});

$('hello').disableEvent('click');

// Now, handler won't be called

$('hello').observe('click', function (e) {
    alert('click not stopped (2)!');
});

// New handler won't be called, either

$('hello').enableEvent('click');

// Now, handler will be called

I am using the Prototype.js framework. This doesn't seem to be a browser-specific issue.


Solution

  • As I said in comments to roosteronacid's answer, I wrote an extension to Event.observe. Works in most browsers, but not IE.

    // XXX HACK XXX
    (function () {
        var handlerCache = $A([ ]);
    
        function findHandler(either) {
            var pair = handlerCache.find(function (pair) {
                return $A(pair).member(either);
            });
    
            return pair && pair[0];
        }
    
        function addHandler(handler) {
            function newHandler(e) {
                if (!e.halted) {
                    handler.apply(this, arguments);
                }
            }
    
            handlerCache.push([ handler, newHandler ]);
    
            return newHandler;
        }
    
        Event.observe = Event.observe.extended(function ($super, element, eventName, handler) {
            handler = findHandler(handler) || addHandler(handler);
    
            $super(element, eventName, handler);
        });
    
        Event.stopObserving = Event.stopObserving.extended(function ($super, element, eventName, handler) {
            handler = findHandler(handler) || handler;
    
            $super(element, eventName, handler);
        });
    
        Element.addMethods({
            observe: Event.observe
        });
    
        Event.prototype.halt = function () {
            this.halted = true;
        };
    }());
    

    Note: Function.prototype.extended is a custom function which puts the original Event.observe in as $super.