silkcom
silkcom

Reputation: 502

javascript/jquery How to cancel .on when a class is present

I have several places throughout my code where I use .on to attach events (usually to delegate the events). We're changing around how we're doing a few things, and we're now wanting to add a .disabled class to the elements that we want to be disabled. I'd like to block all the events on disabled items without having to refactor each location, I'm wondering if it's possible.

Example code: I've added this to the top of my script

$('body').on('click', '.disabled', function(event){
    console.log("blocked");
    event.stopImmediatePropagation();
    // event.preventDefault();
    // event.stopPropogation();
     return false;
});

And an example of my normal events:

$('.ActionsContainer').on('click', '.Link', functions.ClickAction);

Problem is that even with the return false and all the others it still runs both the "blocked" and functions.ClickAction

Is there anyway around refactoring every one? I mean I can change that line below to:

$('.ActionsContainer').on('click', '.Link:not(.disabled)', functions.ClickAction);

but that's really annoying, and feels brittle.

Upvotes: 1

Views: 132

Answers (2)

Erik  Reppen
Erik Reppen

Reputation: 4635

Assuming every .Link has that container and you're handling all events at that container, this is the most straightforward way:

$('.disabled').click( function(e){ e.stopPropagation(); } );

stopProp prevents that event from ever bubbling up to the action containers.

Upvotes: 0

David Atchley
David Atchley

Reputation: 1204

It's not too hard. You'll need to take advantage of jQuery's special events and basically override calls to any of the original event handlers setup in the existing code. jQuery's special events hooks let you override a number of features of the event system. jQuery essentially sets up it's own handler on an element the first time a listener is attached, and then adds the callback for the listener to its queue. As other listeners get attached to the element later, their callbacks get added to this queue as well.

Using the 'events.special.click' hook, we can add a function that gets called prior to any callbacks on that element's event queue which lets us intercept the call and check for, as you mentioned, that the element has a 'disabled' class and if so, stop the original callback from executing; or if it doesn't have the class, allow the original callback to execute normally.

I've put together a jsFiddle to show how it works. See if that solves your issue. The code for the override using special events is embedded below the link:

http://jsfiddle.net/datchley/bthcv/

// ADDED TO OVERRIDE CLICKS ON 'DISABLED' ELEMENTS
(function($) {
    $.event.special.click = {
        add: function(handle) {
            // Save original handler
            var orig_handlefn = handle.handler,
                $el = $(this);

            // Reassign our new handler to intercept here       
            handle.handler = function(ev) {
                if ($el.hasClass('disabled')) {
                    // Don't allow clicks on disabled elements
                    $('.output').html('<b>Warning</b> You clicked a disabled element!');
                    ev.preventDefault();
                }
                else {
                    return orig_handlefn.apply(this, arguments);
                }
            };
        }
    };
})(jQuery);

Upvotes: 2

Related Questions