暂时禁止jQuery事件处理

时间:2009-11-27 15:07:55

标签: jquery jquery-plugins

是否有一种优雅的方式来暂时禁止jQuery事件?我使用这样的代码:

$(element).unbind(event, function1).unbind(event, function2);
// code for which the event is suppressed
$(element).bind(event, function1).bind(event, function2);

但是我发现它有点笨拙并且对许多事件来说不是很容易扩展。为什么我要暂时压制事件?我使用BlockUI插件在Ajax访问期间阻止UI。这是通过BlockUI提出的: $()。ajaxStart($。blockUI).ajaxStop($ .unblockUI)来完成的。

但是,一个Ajax访问是特殊的,所以我需要一个不同的消息。 ajaxStart和ajaxStop事件会干扰消息代码(不显示任何内容):

function message(text, callback) {
  if (text == undefined) {
     $.unblockUI();
     return;
  }

  // $().unbind('ajaxStop', $.unblockUI).unbind('ajaxStart', $.blockUI);
  $("#message_text").html(text);
  $.blockUI({message: $("#message")});
  $("#message_ok").click(function() { 
    // $().bind('ajaxStop', $.unblockUI).bind('ajaxStart', $.blockUI);
    $.unblockUI();
    if (callback != undefined) callback();
  });
}

只有取消注释unbind()和bind()行,它才有效。

6 个答案:

答案 0 :(得分:14)

我意识到这个问题已经过时了,但我在寻找同一个问题的答案时找到了它,并最终找到了一个在事件处理程序的简单应用程序中运行良好的不同解决方案。

$(element).click(function(e) {
  e.preventDefault();

  // Check for fired class
  if ($(this).hasClass('fired') == false) {
     // Add fired class to all instances of element
     $(element).addClass('fired');

     // Do the rest of the function...

     // Remove fired class to 'reactivate' events
     $(element).removeClass('fired');   
  }
}

只需在事件代码触发时向您的'元素添加一个类,就可以防止由于另一个点击事件而执行更多代码。因此,虽然您实际上并未阻止任何其他点击事件,但您仍然无法运行生成的代码。简单粗暴,忽略了对绑定和取消绑定的大量宣传使用,但有效。

答案 1 :(得分:10)

花了我这个脚本,我希望它有用:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 
<script type="text/javascript">
$(function(){

    //ini plugin

    jQuery.event.freezeEvents = function(elem) {

        if (typeof(jQuery._funcFreeze)=="undefined")
            jQuery._funcFreeze = [];

        if (typeof(jQuery._funcNull)=="undefined")
            jQuery._funcNull = function(){ };

        // don't do events on text and comment nodes
        if ( elem.nodeType == 3 || elem.nodeType == 8 )
            return;

        var events = jQuery.data(elem, "events"), ret, index;

        if ( events ) {

            for ( var type in events )
            {
                if ( events[type] ) {

                    var namespaces = type.split(".");
                    type = namespaces.shift();
                    var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");

                    for ( var handle in events[type] )
                        if ( namespace.test(events[type][handle].type) ){
                            if (events[type][handle] != jQuery._funcNull){
                                jQuery._funcFreeze["events_freeze_" + handle] = events[type][handle];
                                events[type][handle] = jQuery._funcNull;
                            }
                        }
                }

            }
        }
    }

    jQuery.event.unFreezeEvents = function(elem) {

        // don't do events on text and comment nodes
        if ( elem.nodeType == 3 || elem.nodeType == 8 )
            return;

        var events = jQuery.data(elem, "events"), ret, index;

        if ( events ) {

            for ( var type in events )
            {
                if ( events[type] ) {

                    var namespaces = type.split(".");
                    type = namespaces.shift();

                    for ( var handle in events[type] )
                        if (events[type][handle]==jQuery._funcNull)
                            events[type][handle] = jQuery._funcFreeze["events_freeze_" + handle];

                }
            }
        }
    }

    jQuery.fn.freezeEvents = function() {

        return this.each(function(){
            jQuery.event.freezeEvents(this);
        });

    };

    jQuery.fn.unFreezeEvents = function() {

        return this.each(function(){
            jQuery.event.unFreezeEvents(this);
        });

    };

    //end plugin

    jQuery("#test1").ajaxStart(function test1(){
        jQuery("#result").append('test1 ajaxStop<br>');
    });

    jQuery("#test1").ajaxStop(function test2(){
        jQuery("#result").append('test1 click<br>');
    });

    jQuery("#test1").bind("click", function test3(){
        jQuery("#result").append('test1 click<br>');
    });

    jQuery("#test2").bind("click", function test5(){
        jQuery("#result").append('test2 click<br>');
    });

    jQuery("#freez").click(function(){
        jQuery("#test1").freezeEvents();
        jQuery("#test2").freezeEvents();
    });

    jQuery("#unfreez").click(function(){
        jQuery("#test1").unFreezeEvents();
        jQuery("#test2").unFreezeEvents();
    });

});
</script>
</head>
<body>
<button id="freez">freez</button>
<button id="unfreez">un freez</button>
<br />
<div id="test1">test1 click mousemove</div>
<div id="test2">test2 click mousemove</div>
<br />
<div id="result"></div>
</body>
</html>

答案 2 :(得分:5)

我真的很喜欢Andres处理这个问题的方法,但看来自从他提出这个代码以来,jQuery事件模型已经改变了,所以在最近的jQuery版本中他的代码不起作用。在这里它是现代化的。在1.8.2中轻轻地测试:

$.event.freezeEvents = function(elem) {

        if (typeof($._funcFreeze)=="undefined") {
            $._funcFreeze = [];
        }

        if (typeof($._funcNull)=="undefined") {
            $._funcNull = function() {};
        }                

        // don't do events on text and comment nodes
        if ( elem.nodeType == 3 || elem.nodeType == 8 ) {
            return;
        }

        var events = $._data(elem, "events");

        if (events) {
            $.each(events, function(type, definition) {
                $.each(definition, function(index, event) {
                    if (event.handler != $._funcNull){
                        $._funcFreeze["events_freeze_" + event.guid] = event.handler;
                        event.handler = $._funcNull;
                    }
                })
            })
        }
    }

    $.event.unFreezeEvents = function(elem) {

        // don't do events on text and comment nodes
        if ( elem.nodeType == 3 || elem.nodeType == 8 )
                return;

        var events = $._data(elem, "events");

        if (events) {
            $.each(events, function(type, definition) {
                $.each(definition, function(index, event) {
                    if (event.handler == $._funcNull){
                        event.handler = $._funcFreeze["events_freeze_" + event.guid];
                    }
                })
            })
        }
    }

    $.fn.freezeEvents = function() {
        return this.each(function(){
            $.event.freezeEvents(this);
        });
    };

    $.fn.unFreezeEvents = function() {
        return this.each(function(){
            $.event.unFreezeEvents(this);
        });
    };

我没有在有两个事件的元素之外测试这个,但它对我来说很好。希望这有助于某人。

答案 3 :(得分:4)

最简单的方法是在绑定方法的开头添加一个检查,以确定该方法是否应该运行。如果没有,只需从方法返回。

var doThing = true;

$("#foo").bind("click", function(e) {
    if(!doThing){return;}
    //do thing
}

function bar(){
    //temp unbind click
    doThing = false;

    //do stuff...

    //rebind click
    doThing = true;
}

答案 4 :(得分:2)

您可以简单地保存和恢复整个事件对象:

var events=$._data(elem, 'events'); // save events
$._data(elem, 'events', {}); // cancel all events
// any code here will not fire events
$._data(elem, 'events', events); // restore events

这对我有用,但可能有未知的副作用......

答案 5 :(得分:1)

阻止页面,触发多个ajax请求(链接或其他)然后取消阻止页面的想法是什么?

如果是这种情况(并且我已正确理解了这个问题)那么您可以使用块计数器吗?

e.g。     var blockcounter = 0;

function block(){
if(blockcounter==0)
 {$.blockUI({message: "Hai", showOverlay:true});}
blockcounter++;
}

function unblock(){
blockcounter--;
if(blockcounter==0)
{$.unblockUI();}
}

然后在你的代码中

function dostuff(){
block();
... do whatever ajax you need
... call unblock() in the success event of your ajax call
}

function dostuff2(){
block();
... do some more ajax - this might take a bit longer to complete though
... call unblock() in the success event
}

dostuff();
dostuff2();

阻止应该只发生一次,你可以自由地在中间做任何事情。

我在网站上成功使用此方法,在阻止和解除阻塞之间发生了多个事件,并且不同的ajax事件可以在不同的时间完成。如果你将整个批量包装在命名空间中,你也可以避免乱丢全局变量的地方。