将事件重定向到内部元素

时间:2016-11-14 14:39:29

标签: javascript jquery

我有一个特殊的场景,我需要在更高级别捕获关键事件,并将它们重定向到更低级别。我尝试编写这样的代码,但实际上似乎jQuery愚蠢地使用完全相同的事件对象,因此target不会更改,因此Maximum callstack size exceeded ...

$("#outer").on("keydown", function(evt) {
  if (evt.target !== $("#inner")[0] && !$.contains($("#inner")[0], evt.target)) {
    $("#inner").trigger(evt);
  }
});

使用示例标记

<div id="#outer">
  <div id="#inner">
  </div>
</div>

将事件重定向到另一个元素的正确方法是什么?我当然可以手动&#34; hack&#34; target,但是安全吗?

我正在使用插件,该插件根据屏幕大小动态显示菜单作为弹出窗口或模式。如果我有一个模态,我需要这个键重定向。消费者不应该知道它是弹出窗口还是模态。我正在使用bootstrap的模态插件,它会因为焦点锁定事件而捕获关键事件&#34;所以我能让它变得透明的唯一方法就是我将这些事件重定向到我的真实的菜单。

3 个答案:

答案 0 :(得分:0)

您可以将事件处理程序附加到外部,并指定用于匹配事件的选择器:

$('#outer').on('keydown', '#inner', event => {
  /* this is executed when #inner is clicked */
});

如果你真的想使用触发器,可以将它放在setTimeout:

$('#outer').on('keydown', event => {
  if (yourCondition) {
    setTimeout(() => $('#inner').trigger(event), 0);
  }
});

答案 1 :(得分:0)

事件会冒出来,你是对的,这是同一个事件。这不是一个jQuery的东西,但实际上只是javascript的工作原理。您可能希望在子元素上设置侦听器,并使用preventDefault();

$("#outer").on("keydown", doSomeThing);

$("#inner").on("keydown", doSomeThingElse);

function doSomeThing(e) {
}

function doSomeThingElse(e) {
   e.preventDefault();
}

这将允许您将听众分成不同的功能。

答案 2 :(得分:0)

谢谢大家的回答和评论。你们中的一些人建议阻止在#inner div传播事件。我需要避免这种情况,我需要一种方法,任何外部消费者都会看到这个事件,就像#inner元素为真实触发一样。

与此同时,我深入研究了jQuery源代码,并在trigger中找到了这一行。

if ( !event.target ) {
    event.target = elem;
}

因此,当jQuery初始化要触发的事件时,如果尚未指定target,则仅将该元素指定给target。确定他们有一些很好的理由来解释这种行为,这是我现在看不到的。

所以我能想到的最好的东西就是这样的功能。

function redirectEvent(currentTarget, evt, newTarget) {
  if (currentTarget !== newTarget && !$.contains(currentTarget, newTarget)) {
    evt = $.Event(evt.type, evt);
    delete evt.target;
    $(newTarget).trigger(evt);
  }
}

就第一次测试而言,我看不出任何副作用或缺点。