$(“:焦点”)不返回<输入类型=“;文件“/>在Firefox中

$(":focus") returns no element for <input type="file" /> in Firefox

本文关键字:类型 文件 gt Firefox 输入 lt 焦点 返回      更新时间:2023-09-26

如果当前焦点/活动元素是<input type="file" />,那么在Firefox中,我似乎无法将其作为jQuery对象。它适用于其他输入类型(文本、密码、提交等)和其他元素类型(<select><textarea>等)。

HTML

<input type="file" />

Javascript

// Cannot find input type file elements with :focus,
// $focused.length is always 0 in Firefox (tested using FF 10.0.1)
var $focusedTest1 = $(':focus');
// This line throws for Firefox (tested using FF 10.0.1)
// Permission denied to access property 'nodeType'
// @ http://code.jquery.com/jquery-1.7.1.js:108
// in jQuery.fn.init, below "Handle $(DOMElement)"
var $focusedTest2 = $(document.activeElement);

复制步骤

  1. 使用Firefox
  2. 聚焦文件框:
    • 按tab键直到够到为止
    • 或者点击它
  3. 在聚焦文件框的同时,尝试从$(':focus')获得结果

请参阅jsFiddle演示获取关注元素的id,并使用Firefox进行测试。

是否有人可以将焦点/活动元素作为适用于<input type="file" />的jQuery对象的解决方案

该解决方案需要完全通用,因为该功能是插件的一部分。我将无法控制脚本运行的页面。

编辑:此解决方案已在EmulateTab中首次发现问题的地方实现。请参见getFocusedElement()。


在中断编码后,我自己找到了一个解决方案,但这不是一个非常干净的解决方案。这与@Neil在我第一次写这篇文章时提出的解决方案基本相同。

尝试使用焦点侦听器更新jsFiddle版本,并在Firefox中尝试catch逻辑。它结合了:focusdocument.activeElement和文档级别的焦点侦听器,用于跟踪最后一个"已知"的焦点元素。

查找聚焦元素的函数

// Comined function to get the focused element trying as long as possible.
// Extra work done trying to avoid problems with security features around
// <input type="file" /> in Firefox (tested using 10.0.1).
function getFocused() {
    // Try the well-known, recommended method first.
    var $focused = $(':focus');
    if ($focused.size() === 0) {
        try {
            // Fall back to a fast method that might fail.
            // Known to fail for Firefox (tested using 10.0.1) with
            // Permission denied to access property 'nodeType'.
            $focused = $(document.activeElement)
        }
        catch (error1) {
                warnToConsole("Could not use document.activeElement", document.activeElement, error1);
            if (lastFocusedElement !== null) {
                try {
                    // As a last resort, use the last known focused element.
                    // Has not been tested enough to be sure it works as expected.
                    $focused = $(lastFocusedElement);
                } catch (error3) {
                    warnToConsole("Could not use lastFocusedElement ", lastFocusedElement, error3);
                }
            }
        }
    }
    return $focused;
}

集中听众

// Keep a reference to the last focused element, use as a last resort.
var lastFocusedElement = null;
function focusInElement(event) {
    lastFocusedElement = event.target;
}
function focusOutElement(event) {
    lastFocusedElement = null;
}
// Start listeners.
$(function() {
    // Start listeners that keep track of the last focused element.
    $(document).on("focusin", focusInElement);
    $(document).on("focusout", focusOutElement);
});

我不太喜欢这个解决方案,因为它远没有一行$(':focus')那么干净。欢迎其他答案!

我能想到的唯一方法是在窗口级别添加一个捕获焦点侦听器,在该侦听器中用事件目标更新全局变量。(在Firefox中,文件输入中焦点事件的事件目标是文件输入本身,即使document.activeElement返回"匿名"按钮。)

试试这个-在Firefox 10.0.1 中测试

$(document).ready(function () {
        var crtFocus;
        $("#id1").focus(function () {
            crtFocus = $(this);
        });
        $("#id2").focus(function () {
            crtFocus = $(this);
        });
        $("#id3").focus(function () {
            crtFocus = $(this);
        });
        $("#click").click(function () {
            // $(crtFocus) contains the currently focused element
            //alert($(crtFocus));
        });
    });

...

<input type="file" id="id1" />
<input type="file" id="id2" />
<input type="file" id="id3" />    
<input type="button" id="click"/>

EDIT-我们只能为所有输入[类型=文件]元素使用一个选择器,而不是每个元素使用一个选择符

$(':input[type=file]').focus(function () {
            crtFocus = $(this);
        });