Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enable/Disable events of DOM elements with JS / jQuery

I stuck here with a little problem I have put pretty much time in which is pretty bad compared to its functionality.

I have tags in my DOM, and I have been binding several events to them with jQuery..

var a = $('<a>').click(data, function() { ... })

Sometimes I would like to disable some of these elements, which means I add a CSS-Class 'disabled' to it and I'd like to remove all events, so no events are triggered at all anymore. I have created a class here called "Button" to solve that

var button = new Button(a)
button.disable()

I can remove all events from a jQuery object with $.unbind. But I would also like to have the opposite feature

button.enable()

which binds all events with all handlers back to the element OR maybe there is a feature in jQuery that actually nows how to do that?!

My Button Class looks something similar to this:

Button = function(obj) {
  this.element = obj
  this.events = null

  this.enable = function() {
    this.element.removeClass('disabled')
    obj.data('events', this.events)
    return this
  }

  this.disable = function() {
    this.element.addClass('disabled')
    this.events = obj.data('events')
    return this
  }
}

Any ideas? Especially this rebind functionality must be available after disable -> enable

var a = $('<a>').click(data, function() { ... })

I found these sources that did not work for me: http://jquery-howto.blogspot.com/2008/12/how-to-disableenable-element-with.html

http://forum.jquery.com/topic/jquery-temporarily-disabling-events -> I am not setting the events within the button class

Appreciate your help.

like image 540
pabera Avatar asked Nov 23 '11 21:11

pabera


3 Answers

$("a").click(function(event) {
    event.preventDefault(); 
    event.stopPropagation(); 
    return false;
});

Returning false is very important.

Or you could write your own enable and disable functions that do something like:

function enable(element, event, eventHandler) {
    if(element.data()[event].eventHandler && !eventHandler) { //this is pseudo code to check for null and undefined, you should also perform type checking
        element.bind(event, element.data()[event]);

    }
    else (!element.data()[event] && eventHandler) {
        element.bind(event, element.data()[event]);
        element.data({event: eventHandler}); //We save the event handler for future enable() calls
    }
}

function disable(element, event) {
    element.unbind().die();
}

This isn't perfect code, but I'm sure you get the basic idea. Restore the old event handler from the element DOM data when calling enable. The downside is that you will have to use enable() to add any event listener that may need to be disable() d. Otherwise the event handler won't get saved in the DOM data and can't be restored with enable() again. Currently, there's no foolproof way to get a list of all event listeners on an element; this would make the job much easier.

like image 150
Jay Avatar answered Oct 18 '22 04:10

Jay


I would go on this with different approach:

<a id="link1">Test function</a>
<a id="link2">Disable/enable function</a>

<script type="text/javascript">
  $(function() {
      // this needs to be placed before function you want to control with disabled flag
      $("#link1").click(function(event) {
          console.log("Fired event 1");
          if ($(this).hasClass('disabled')) {
              event.stopImmediatePropagation();
          }
      });

      $("#link1").click(function() {
          console.log("Fired event 2");
      });

      $("#link2").click(function() {
          $("#link1").toggleClass("disabled");
      });
  });
</script>

This may not be what you require, since it may effect also other functions binded into this event later. The alternative may be to modify the functions itself to be more like:

$("#link1").click(function(event) {
    console.log("Fired event 1");
    if ($(this).hasClass('disabled')) {
       return;
    }

    // do something here
});

if that is an option.

like image 33
Wojciech Bańcer Avatar answered Oct 18 '22 04:10

Wojciech Bańcer


Instead of adding event handler to each element separately, you should use event delegation. It would make much more manageable structure.

  • http://www.sitepoint.com/javascript-event-delegation-is-easier-than-you-think/
  • http://cherny.com/webdev/70/javascript-event-delegation-and-event-hanlders
  • http://brandonaaron.net/blog/2010/03/4/event-delegation-with-jquery

This why you can just check for class(es) on clicked element , and act accordingly. And you will be able even to re-eanble them , jsut by changing the classes of a tag.

P.S. read the links carefully, so that you can explain it to others later. Event delegation is a very important technique.

like image 2
tereško Avatar answered Oct 18 '22 04:10

tereško