【问题标题】:jQuery UI Focus StealingjQuery UI 焦点窃取
【发布时间】:2013-03-27 17:33:45
【问题描述】:

每当我在下面的“插入超链接”文本输入中键入内容时,所有单词都会在其后面指向textarea。确定和取消按钮工作正常,但我无法专注于文本输入。

我们使用的是 jQuery UI 1.10.1。它与以前版本的 jQuery 1.8.x 配合得很好。

我检查了 jQuery 背后的代码,它在打开模态对话框时调用了以下方法:

_focusTabbable: function () {
    // Set focus to the first match:
    // 1. First element inside the dialog matching [autofocus]
    // 2. Tabbable element inside the content element
    // 3. Tabbable element inside the buttonpane
    // 4. The close button
    // 5. The dialog itself
    var hasFocus = this.element.find("[autofocus]");
    if (!hasFocus.length) {
        hasFocus = this.element.find(":tabbable");
    }
    if (!hasFocus.length) {
        hasFocus = this.uiDialogButtonPane.find(":tabbable");
    }
    if (!hasFocus.length) {
        hasFocus = this.uiDialogTitlebarClose.filter(":tabbable");
    }
    if (!hasFocus.length) {
        hasFocus = this.uiDialog;
    }
    hasFocus.eq(0).focus();
},

_keepFocus: function (event) {
    function checkFocus() {
        var activeElement = this.document[0].activeElement,
            isActive = this.uiDialog[0] === activeElement ||
                $.contains(this.uiDialog[0], activeElement);
        if (!isActive) {
            this._focusTabbable();
        }
    }
    event.preventDefault();
    checkFocus.call(this);
    // support: IE
    // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
    // so we check again later
    this._delay(checkFocus);
},

取自这里:http://code.jquery.com/ui/1.10.1/jquery-ui.js

【问题讨论】:

  • 有趣...我在带有垂直内容滚动条的对话框中遇到了类似的锚标签问题。如果我向下滚动并单击对话框中的任意位置,焦点将滚动回对话框中最顶部的锚标记。我已将其追溯到您引用的代码,但我不喜欢注释掉该代码......我也不应该......而且我觉得解除绑定很脏。
  • 这是 jQuery UI 中的一个错误:bugs.jqueryui.com/ticket/9101。应该会在下个版本修复。
  • 该错误已在 jQuery UI 1.11.0 中修复。那是我正在运行的版本,但我仍然观察到这个问题。

标签: jquery jquery-ui modal-dialog


【解决方案1】:

我发现的第二个答案是,在以下代码中,jQuery 将文档绑定到对话框。因此,当我单击所需按钮的 onclick 事件(或您正在处理的任何事件)时取消绑定:

 if (window.jQuery && window.jQuery.ui.dialog) {
   $(document).unbind("focusin.dialog");
 }

这是 jQuery UI 将 _focusTabble() 方法绑定到文档的 focusin.dialog 事件的地方。

if ( !$.ui.dialog.overlayInstances ) {
            // Prevent use of anchors and inputs.
            // We use a delay in case the overlay is created from an
            // event that we're going to be cancelling. (#2804)
            this._delay(function() {
                // Handle .dialog().dialog("close") (#4065)
                if ( $.ui.dialog.overlayInstances ) {
                    this.document.bind( "focusin.dialog", function( event ) {
                        if ( !$( event.target ).closest(".ui-dialog").length &&
                                // TODO: Remove hack when datepicker implements
                                // the .ui-front logic (#8989)
                                !$( event.target ).closest(".ui-datepicker").length ) {
                            event.preventDefault();
                            $(".ui-dialog:visible:last .ui-dialog-content")
                                .data("ui-dialog")._focusTabbable();
                        }
                    });
                }
            });
        }

【讨论】:

  • 这对我来说效果很好。在打开 JavaScript SpellChecker 之前,我执行了您在顶部发布的那一小段代码……现在焦点正常工作。在 jquery 对话框窃取焦点之前。但是,我只是想知道如果删除这个 jQuery 放置的事件处理程序,我们是否会导致某些事情中断!
  • 应该在 jQuery UI 1.11.0 中修复:bugs.jqueryui.com/ticket/9101
【解决方案2】:

我为解决这个问题所做的就是注释掉这个$(".ui-dialog:visible:last .ui-dialog-content").data("ui-dialog")._focusTabbable();

您可以在下面找到完整的代码:

    if ( !$.ui.dialog.overlayInstances ) {
        // Prevent use of anchors and inputs.
        // We use a delay in case the overlay is created from an
        // event that we're going to be cancelling. (#2804)
        this._delay(function() {
            // Handle .dialog().dialog("close") (#4065)
            if ( $.ui.dialog.overlayInstances ) {
                this.document.bind( "focusin.dialog", function( event ) {
                    if ( !$( event.target ).closest(".ui-dialog").length &&
                            // TODO: Remove hack when datepicker implements
                            // the .ui-front logic (#8989)
                            !$( event.target ).closest(".ui-datepicker").length ) {
                        event.preventDefault();
                        //$(".ui-dialog:visible:last .ui-dialog-content")
                            //.data("ui-dialog")._focusTabbable();
                    }
                });
            }
        });
    }

【讨论】:

    【解决方案3】:

    另一种停止阻止 jquery 对话框焦点的方法

    $.widget("ui.dialog", $.ui.dialog, {
        _allowInteraction: function (event) {
            return !!$(event.target).closest(".input-container").length || this._super(event);
        }
    });
    

    .input-container 是容器,其中包含应获得焦点的控件。

    【讨论】:

      【解决方案4】:

      那是因为 jquery 阻止了对话框子之外的焦点,jquery 有这个你可以阅读的方法,它会将你想要允许焦点的其他元素列入白名单。

      "_allowInteraction(event)返回:布尔模态对话框不允许 用户与对话框后面的元素进行交互。这可以是 对于不是对话框子元素的元素有问题,但 绝对定位似乎它们是。这 _allowInteraction() 方法确定是否应允许用户与给定的目标元素进行交互;因此,它可以是 用于将不是对话框子元素的元素列入白名单,但您 希望用户能够使用。”

      https://api.jqueryui.com/dialog/#method-_allowInteraction

      所以我要对具有类 .other-popups 的某些项目禁用此“块焦点”的方法是在代码中添加这一行

      $.widget( "ui.dialog", $.ui.dialog, {
          _allowInteraction: function( event ) {
              return !!$( event.target ).closest( ".other-popups" ).length || this._super( event );
          }
      });
      

      或者完全禁用

       $.widget( "ui.dialog", $.ui.dialog, {
              _allowInteraction: function( event ) {
                  return true ;
              }
          });
      

      【讨论】:

        【解决方案5】:

        我有一个类似的问题,我需要将焦点放在我的对话框的内容中(对于 WCAG)。单独使用 focus() 失败了,所以我的最终解决方案是在我添加的对话框实例化中:

        focus: function(event, ui) {
                            setTimeout(function(){ 
                                $('#element').blur().focus().css({'color': '#000', 'text-decoration' : 'none', 'cursor' : 'default'});
                            }, 500);
                        }
        

        我使用超时来确保兼容性。 *注意,我将“#element”设置为锚标记(交互式元素),以便获得焦点。这就是样式的原因。

        这段代码应该也可以添加到jQuery Dialog的“打开”功能中。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-04-13
          • 1970-01-01
          • 1970-01-01
          • 2011-11-04
          • 1970-01-01
          • 1970-01-01
          • 2013-06-21
          • 1970-01-01
          相关资源
          最近更新 更多