jquery rebind() disable events for a specific time, then rebind them
Asked Answered
N

2

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');
});
Nurserymaid answered 5/12, 2012 at 18:11 Comment(2)
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.Fowliang
Check out [this][1] post, where ".on()" solves the problem! [1]: #13941091Nurserymaid
N
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 !!

Nurserymaid answered 6/12, 2012 at 8:23 Comment(0)
I
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.

Inconsequent answered 5/12, 2012 at 18:15 Comment(16)
oh i tried this, but it doesn't work if $('a') has other js-code on the click eventNurserymaid
I updated my answer to prevent the event to propagate, is it better?Inconsequent
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.Fowliang
Wouldn't it be the other way? Run the latest event handler added first?Inconsequent
Oh yes you are right I tested it and it does not work as I expected. SorryInconsequent
@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.Fowliang
@Fowliang what do you mean with 'one if-statement'Nurserymaid
I updated my answer to reflect what Yoshi was saying and how to work around thatInconsequent
@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.Fowliang
@Fowliang & 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 !?Nurserymaid
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 nothingInconsequent
I hardly dare to ask.. but do you have a code example? .. i really don't get this :(Nurserymaid
thx. but this variable has to be global then. available everywhere..?Nurserymaid
Either global or you add specific functions to set this variable and check if it is blocked?Inconsequent
regarding to the second solution: Could it be that .data('events') isn't compatible with new jquery versions?Nurserymaid
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 maintainInconsequent
N
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 !!

Nurserymaid answered 6/12, 2012 at 8:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.