1

After click on a button my script loads new content. As long as it is loading I don't want a list of elements to be clickable.

IS there any way to unbind the click-event of those elements, load the content and then "rebind" the events correctly?

What I want to prevent is a if-statement inside every click-function/element.

Here is what i've tried:

$(load_button).click(function(){
    $('a').each(function(){
        var dis_e = $(this).data('events');
        $(this).data('disabled-events', dis_e);
    }).unbind('click');

    $(some_content).load(function(){
        $('a').each(function(){
            var dis_e = $(this).data('disabled-events');
            $(this).removeData('disabled-events');
            $(this).bind('click', dis_e);
        });
    });
});

UPDATE:

it should also prevent the elements from (in this case) alerting 'click':

$('a').click(function(){
   alert('click');
});
John Doe Smith
  • 1,623
  • 4
  • 24
  • 39
  • You could add an extra layer, absolute positioned with an opacity of 1% above the non-clickable area. To the eye it will probably not be visible, yet prevent any other event. – Yoshi Dec 05 '12 at 18:32
  • Check out [this][1] post, where ".on()" solves the problem! [1]: http://stackoverflow.com/questions/13940591/how-to-bind-unbind-and-rebind-click-events-in-jquery – John Doe Smith Dec 18 '12 at 20:09

2 Answers2

2

You can temporarily bind a new click event with a specific namespace for your elements that will prevent the click event to propagate and when your content is loaded you unbind your event.

$("a").bind("click.disabled", function(e) {
    e.stopImmediatePropagation();
    return false;
});

And later on:

$("a").unbind("click.disabled");

EDIT: As pointed out by Yoshi, this expects your click event handler to be attached to the element before your custom events. So I can see two ways around this:

  1. Either you always bind this event handler to each of your elements when you create them so that they are always called before your custom click event handler. And you only do stopImmediatePropagation() and return false when you are loading your data.
  2. Or you check this other question so that your new event handler is first in the list.

If you chose the first method, your event would be something like this :

var clicDisabled = false;
$("a").bind("click.disabled", function(e) {
    if (true == clicDisabled) {
        e.stopImmediatePropagation();
        return false;
    }
});

and then when loading your content you set the variable clicDisabledto true temporarily.

Community
  • 1
  • 1
koopajah
  • 23,792
  • 9
  • 78
  • 104
  • oh i tried this, but it doesn't work if $('a') has other js-code on the click event – John Doe Smith Dec 05 '12 at 18:25
  • I updated my answer to prevent the event to propagate, is it better? – koopajah Dec 05 '12 at 18:27
  • 1
    jquery will run the callbacks in the same order as they are attached, so any event callback bound prior to this would still be executed. – Yoshi Dec 05 '12 at 18:29
  • Wouldn't it be the other way? Run the latest event handler added first? – koopajah Dec 05 '12 at 18:29
  • Oh yes you are right I tested it and it does not work as I expected. Sorry – koopajah Dec 05 '12 at 18:31
  • @JohnDoeSmith yes, if you can attach it first, you could prevent other event callbacks from being executed. This way you would only need one if-statement. – Yoshi Dec 05 '12 at 18:33
  • @Yoshi what do you mean with 'one if-statement' – John Doe Smith Dec 05 '12 at 18:34
  • I updated my answer to reflect what Yoshi was saying and how to work around that – koopajah Dec 05 '12 at 18:36
  • 2
    @JohnDoeSmith In that one callback, bound before every other, only prevent the event from propagating if a certain condition is met. E.g. your content currently being loaded. – Yoshi Dec 05 '12 at 18:36
  • @Yoshi & koopajah : if I do it the first way (bind it manually), then it does only work the first time.. after unbinding .. i cannot rebind it !? – John Doe Smith Dec 05 '12 at 18:42
  • 1
    You don't unbind if you do the first way. The event handler always stays here. You need to have a variable telling you if the click is currently blocked or not. If it is, you return false and stopImmediatePropagation() else your do nothing – koopajah Dec 05 '12 at 18:43
  • I hardly dare to ask.. but do you have a code example? .. i really don't get this :( – John Doe Smith Dec 05 '12 at 18:46
  • thx. but this variable has to be global then. available everywhere..? – John Doe Smith Dec 05 '12 at 18:47
  • 1
    Either global or you add specific functions to set this variable and check if it is blocked? – koopajah Dec 05 '12 at 18:48
  • regarding to the second solution: Could it be that `.data('events')` isn't compatible with new jquery versions? – John Doe Smith Dec 05 '12 at 18:49
  • 1
    I did not try it so I can't say for sure, it was just an idea on how to avoid this but I guess the first method is really better to maintain – koopajah Dec 05 '12 at 18:51
1

Based on your answers i wrote the following plugin:

(function($){
    $.fn.rebind = function(){
        var init = 'init-rebind';
        return this.each(function() {
            var is_init = $(this).data(init);
            if (!is_init){
                $(this).data(init, true);
                $(this).bind('click.rebind mouseenter.rebind mouseleave.rebind', function(e){
                    if ($(this).hasClass('disabled')){
                        e.stopImmediatePropagation();
                        e.preventDefault();
                    }
                });
            }
        });
    };
})(jQuery);

Instead of using a global variable i decided to add/remove the class 'disabled' in order to also have control within css.

check out the demo!

THX to all!


UPDATE: Check this out !!

Community
  • 1
  • 1
John Doe Smith
  • 1,623
  • 4
  • 24
  • 39