2009-11-27 119 views
18

有没有一种优雅的方式来暂时禁止jQuery事件?我用这样的代码:暂时禁止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(); 
    }); 
} 

只有当我去掉拆散()和绑定()线,它是工作。

回答

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'); 
    } 
} 

简单地增加一个类你的“元素的同时,从事件的代码被解雇,可以防止进一步的代码作为另一个点击事件的结果执行。因此,虽然实际上并未阻止任何其他点击事件,但您正在阻止运行生成的代码。简单粗暴,忽视了重重鼓吹使用绑定和解除绑定,但工程。

+0

你的意思是,防止从运行结果代码? – nalply 2012-05-23 15:25:59

+0

为什么是*编辑答案*,是不是我说的?我全都被事件处理人员和所有他们做的事情所困扰,我误用了这个词。 – Eric 2012-05-23 15:30:52

+0

没问题,你编辑了答案。欢迎来到Stackoverflow。 – nalply 2012-05-24 05:30:54

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; 
} 
+1

这是一个众所周知的成语。如果事件处理程序以某种方式触发自己的事件并因此被递归调用,导致无限循环,导致浏览器无响应,这是必要的。 但这不是我的问题。我没有不必要的递归。我的问题是其他事件处理程序干扰我的代码,所以我需要暂时禁止事件处理。其他事件处理程序的代码位于BlockUI本身中,所以不,我无法修改它。 – nalply 2009-11-27 17:30:06

1

所以是阻止页面的想法,引发多个Ajax请求(链接或其他),然后解锁页面?

如果是这样的话(和我理解正确的问题),那么你可以使用块计数器?

例如 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事件可以在不同的时间完成之间发生的这种方法。如果你把所有东西都包装在命名空间中,你也可以避免使用全局变量来乱扔垃圾。

+1

是的,我首先使用了块计数器。但$().ajaxStart($ .blockUI).ajaxStop($。unblockUI)是整洁的 - 它为你做了阻塞和解锁,但会干扰它在message()中发生在我身上。 请让我们坚持原来的问题:如何暂时抑制事件处理。也许是暂停/恢复机制。 – nalply 2009-11-27 18:37:31

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> 
+0

哇!你写了一个小的jQuery插件!所以你认为在jQuery中通常暂停/恢复(或称为冻结/解冻)事件处理并不容易。 – nalply 2009-11-27 21:48:33

+0

回顾了jQuery库,我发现最好使这个插件。必须尝试找出你是否有用 – 2009-11-28 11:25:54

+0

如何冻结和解冻工作?顺便说一下,你知道CopyEvents jQuery插件吗? http://plugins.jquery.com/project/copyEvents – nalply 2009-11-30 20:28:23

5

我真的很喜欢安德烈的方式解决这个问题,但现在看来,因为他想出了代码,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); 
     }); 
    }; 

我还没有两个事件测试了这个超越的元素,但它为我工作得很好。希望这可以帮助某人。

+0

我删除了命名空间检查,我使用jQuery的每个方法遍历事件,并重构表达式以使用新的jQuery事件模型。如果您比较代码,您会看到不同之处,它们非常明显。 – 2012-11-06 10:42:24

+0

谢谢。我太懒了差异。 – nalply 2012-11-06 14:50:45

1

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

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 

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

+0

我喜欢这种方法,并认为这是一个很好的方法 – abzarak 2015-09-27 13:08:58