如何精确找出事件的触发原因?

4

我正在使用一些jQuery函数,例如:

$(window).one('beforeunload', function() {
//my code
});

但我真的想找出是什么触发了这个事件以及如何触发。

我尝试了以下代码:

$(window).one('beforeunload', function(e) {
alert(JSON.stringify(e));
});

但它会引发有关循环结构的异常。肯定还有其他区分和调试的方法。

我将如何应用它?

我想看看是什么触发了这个事件,是链接、提交的表单、Javascript、页面刷新、前进和后退按钮还是其他任何东西,在这种情况下都可以。但是,如果是通过调用打开外部应用程序触发的,我想放弃此事件并返回 null。

外部应用程序启动示例:

<a href="skype:your_skype_name?call" >

有什么想法吗?

已解决

这是我解决的方法。

我先创建了一些脚本链接,以便更好地控制事件:

<a href="javascript:void(0)" id="skype_click_ok"

接下来我创建一个全局变量来存储beforeunload的状态:

var dontunload=0;

然后我手动处理链接,通过设置location.href和更改变量状态:

$('#skype_click_ok').click(function(){
dontunload=1;
location.href='skype:marilynbrusas?call';
});

现在是我的实际beforeunload事件,注意one()也已经改为bind()

$(window).bind('beforeunload', function() {
  if (dontunload==1) dontunload=0;  //if triggered from our skype - do nothing, yet  cancel state for the next call
  else {  //Do the actual code
          // Fade out, before leaving the page.
      $('html#my_html').stop(true,false).css('overflow','hidden').animate({opacity:0},2000);
      // Lock content with invalid image hack
          $('body#my_body').prepend(
        $('<div>').attr({style:'position:fixed;height:100%;width:100%;left:0;top:0;z-index:900100;background-image:url(in-your-face)'})
      );
          // unbind the event
      $(this).unbind('beforeunload');
  }
});

编辑3

事实上,这个问题还没有得到解决。这个技巧无法在IE浏览器中使用,同时也不能触发来自javascript:void(0)链接的事件...


调用外部应用程序?请问您能详细解释一下吗? - guzmanoj
<a href="skype:your_skype_name?call" > - 这会触发 GET 请求,从而触发 before-unload 事件。外部应用程序意味着它具有内部协议,而不是 http:,例如 skype:。因此,它尝试启动 Skype 应用程序而不是在 Web 上打开某个页面。如果是这种情况,我确实想要取消我的事件。 - Anonymous
你能否把“已解决”部分作为答案发布并从你的回答中删除它? - Willi Mentzel
3个回答

3
您可以使用event.target.id选择器来传递触发事件的元素,如下所示:
$(document).ready(function() {
    $("a").click(function(event) {
        alert(event.target.id);
    });
});

请参考jsfiddle。 正如评论者所提到的,这将会提示选择元素的ID,我只是举了一个例子,因为你没有完全说明你想要检索什么?


那么这将获取目标 id - 如果您删除 id 部分,它将获取触发事件的元素 +1。 - wirey00
我知道如何使用event.target获取元素。但是我更想记录事件的所有属性,我想要调试它,有时仅仅通过这种简单的方法是不够的。 - Anonymous

2

使用alert来显示事件等对象是相当无用的。

为什么不尝试将你的事件发送到控制台呢?

function(event) {
    console.log(event);
}

这样,您可以展开事件对象并以树形结构查看它。 编辑:根据您有关事件触发位置的评论:我还没有测试过这一点,但这可能是阻止卸载事件的一种方法。
  • Listen for click events for all a elements
  • Check the element clicked points to an external application (doesn't start with http://)
  • If not, bind an event handler for beforeunload that cancels the event immediately
  • Otherwise unbind the previous handler

    $("a").click(function(event) {
      if(event.target.href.indexOf("http://") != 0) {
        $(window).on("beforeunload.override", function(e) {
          // Stop the 'beforeunload' event.
          return false;
        }
      }
      else {
        $(window).off("beforeunload.override");
      }
    }
    

请注意,此示例使用了称为事件命名空间的东西。通过指定我们要监听beforeunload事件,但我们有自己的命名空间override,我们可以安全地添加和删除事件处理程序,而不会删除所有其他beforeunload事件的侦听器。


那就有问题了。事件始终会提供确切触发事件的信息。如果是由 HTMLDocument 触发的,那么就是这个东西触发的。没有什么神奇的方法可以通过代码回溯找出之前发生了什么。你可能需要开始监听多个事件,例如 $("a").click() - Aesthete
这就是我一直在思考的问题,为我的链接分配一些ID,将href替换为javascript:void(0),然后...然后我不知道...我仍然不知道是什么触发了事件。当然,我可以创建一个全局变量,并在观察到单击skype链接时设置它。但是,我想不出恢复该变量状态的方法,因此,如果用户再次以其他方式触发beforeunload事件,则会再次按预期工作...嗯,也许我应该在每次单击之前调用beforeunload时还原其状态,这是个好主意。 - Anonymous
但出于某种原因它从来没有起作用过...让我更新我的问题。 - Anonymous
我又做了一次编辑。也许你现在可以试着玩一下。 - Aesthete
是的,我最近也听说过。但我仍然不明白为什么不应该使用bind()?(这里是一个Jquery 1.64用户...) - Anonymous
显示剩余4条评论

0

使用 target="_blank" 也可以解决这个问题:

<a href="skype:your_skype_name?call" target="_blank">

这个方案看起来比较丑陋,但在我的情况下,它是唯一一个能完美地在所有浏览器上运行的解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接