【问题标题】:How to intercept jQuery Dialog ESC key event?如何拦截jQuery Dialog ESC键事件?
【发布时间】:2012-05-05 23:12:06
【问题描述】:

我有一个模态 jQuery 对话框和另一个在对话框后面接受 ESC 键事件的元素。当 jQuery 对话框启动时,我不希望这个 ESC 键事件传播。现在发生的情况是,当我点击 ESC 时,它会关闭对话框并触发背景元素上的 ESC 事件处理程序。

当一个 jQuery 对话框被关闭时,我如何吃掉 ESC 键事件?

【问题讨论】:

    标签: jquery jquery-ui jquery-ui-dialog


    【解决方案1】:

    在内部,jQuery UI 的对话框的closeOnEscape 选项是通过将keydown 侦听器附加到文档本身来实现的。因此,一旦 keydown 事件一直冒泡到顶层,对话框就会关闭。

    因此,如果您想继续使用转义键关闭对话框,并且希望阻止转义键传播到父节点,您需要自己实现 closeOnEscape 功能以及使用事件对象上的stopPropagation 方法(参见MDN article on event.stopPropagation)。

    (function() {
      var dialog = $('whatever-selector-you-need')
        .dialog()
        .on('keydown', function(evt) {
            if (evt.keyCode === $.ui.keyCode.ESCAPE) {
                dialog.dialog('close');
            }                
            evt.stopPropagation();
        });
    }());
    

    它的作用是监听对话框中发生的所有 keydown 事件。如果按下的键是转义键,您将照常关闭对话框,并且无论 evt.stopPropagation 调用如何,都会阻止 keydown 冒泡到父节点。

    我在这里有一个活生生的例子 - http://jsfiddle.net/ud9KL/2/

    【讨论】:

    • 这不起作用,我在 keydown 函数内的 jsfiddle 中添加了一个简单的警报,它永远不会被调用:(
    • 不幸的是 closeOnEscape 对我不起作用。但是这个绑定成功了。
    • 如果对话框上没有“输入”元素,或者焦点离开该元素并在实际对话框上,这将不起作用。您需要将keydown绑定到上面的元素与父元素,因此您需要将“.on('keydown'”位更改为“.parent().on('keydown'”
    • ^^ @RobDonovan 评论的是真的..如果没有输入或焦点没有输入,它不会抓住关键。但是,如果您将 keydown 处理程序放在对话框父级上,那么一切都很好。另外,我发现,你必须明确设置对话框closeOnEscape: false,否则对话框仍然会安装自己的处理程序并导致问题。
    【解决方案2】:

    你需要 closeOnEscape...

    示例代码:

    $(function() {
    $("#popup").dialog({
    height: 200,
    width: 400,
    resizable: false,
    autoOpen: true,
    modal: true,
    closeOnEscape: false
    });
    });
    

    现场观看:http://jsfiddle.net/vutdV/

    【讨论】:

    • 他并没有说他希望对话框在逃逸时不关闭,他说他不希望在对话框打开时侦听逃逸的其他元素忽略它。您的方式将删除通过按 Escape 关闭对话框的功能。
    • 你确实有一点。我编辑了样式标签,所以仍然有一个“关闭”链接可用。 jsfiddle.net/vutdV/1 仍然不是最终的解决方案。
    【解决方案3】:

    你可以使用下面的

        $(document).keyup(function (e) {
            if (e.keyCode == 27) {
    
                $('#YourDialogID').dialog('close')  
            }
        });
    

    【讨论】:

      【解决方案4】:

      您需要修改对话框后面的元素的代码,以查看对话框是否已打开并且是否按下了转义键并忽略这种情况。

      【讨论】:

      • 感谢您的回答。但问题是,当我按 ESC 时,事件首先进入对话框并关闭对话框。只有这样它才会进入我的背景元素,此时它会发现对话框不存在并接受 ESC 事件。
      • 当对话框打开时从背景元素中移除监听器,然后在对话框关闭后重新附加它呢?
      • 我想这会奏效,但这不会有点 hacky 吗?会有一种不那么老套的方法吗?
      【解决方案5】:

      因此,如果模态窗口在 ui 对话框顶部打开,则 ESC 必须只关闭模态窗口并使 ui 对话框保持打开状态。我不想为对话框禁用 closeOnEscape,如果另一个模态在它上面打开,只需抑制它。

      我对 jquery-ui-1.12.1 中的 $(document).on("keydown", ...) 或 $dialog.on("keydown", ...) 不满意。我调用小部件方法 _off 和 _on 来删除原始 keydown 事件并将其替换为我自己的拦截事件,在该事件中我可以什么都不做或运行原始处理程序代码。

      可能有一种更优雅的方式来调用原始 keydown 事件而不复制代码,但我还没有想出来。

      我在使用 $dialog.dialog(...) 创建 PatchCloseOnEscape($dialog) 之后调用它。

      /**
       * Tedium required to prevent the jQuery-UI dialog closing when we hit the ESC key to close
       * a modal window opened from the dialog while the dialog is still open.
       */
      private static PatchCloseOnEscape($dialog: JQuery): void
      {
          // Get dialog widget
          let dialog = $dialog.data("ui-dialog");
      
          // Remove original keydown event
          dialog._off(dialog.uiDialog, "keydown");
      
          // Add our new keydown event
          dialog._on(dialog.uiDialog, {
              keydown: function (event)
              {
                  // Only close on escape if a modal window is not showing.
                  if (<check if modal window is open> == true)
                  {
                      return;
                  }
      
                  ////////////////////////////////////////////////////////////////////////////////
                  // Copied from original keydown event in jquery-ui-1.12.1.js line 12278 - 12305
      
                  if (this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
                      event.keyCode === (<any>$).ui.keyCode.ESCAPE)
                  {
                      event.preventDefault();
      
                      this.close(event);
      
                      return;
                  }
      
                  // Prevent tabbing out of dialogs
                  if (event.keyCode !== (<any>$).ui.keyCode.TAB || event.isDefaultPrevented())
                  {
                      return;
                  }
                  var tabbables = this.uiDialog.find(":tabbable"),
                      first = tabbables.filter(":first"),
                      last = tabbables.filter(":last");
      
                  if ((event.target === last[0] || event.target === this.uiDialog[0]) &&
                      !event.shiftKey)
                  {
                      this._delay(function ()
                      {
                          first.trigger("focus");
                      });
                      event.preventDefault();
                  } else if ((event.target === first[0] ||
                      event.target === this.uiDialog[0]) && event.shiftKey)
                  {
                      this._delay(function ()
                      {
                          last.trigger("focus");
                      });
                      event.preventDefault();
                  }
      
                  ////////////////////////////////////////////////////////////////////////////////
              }
          });
      }
      

      【讨论】:

        猜你喜欢
        • 2015-11-05
        • 1970-01-01
        • 1970-01-01
        • 2011-10-25
        • 1970-01-01
        • 2011-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多