$(“:focus”)在Firefox中没有返回<input type =“file”/>的元素

时间:2012-02-15 21:00:53

标签: javascript jquery forms firefox file-upload

如果它是<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')获得结果。
  4. 请参阅jsFiddle demonstration of getting the id of the focused element - 使用Firefox进行测试。

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

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

3 个答案:

答案 0 :(得分:3)

修改:此解决方案已在the problem was first foundEmulateTab处实施。请参阅getFocusedElement()


在编码中断后,我自己找到了一个解决方案 - 但它不是一个非常干净的解决方案。当我第一次写这篇文章时,它基本上是same solution建议的@Neil

在Firefox中尝试the updated jsFiddle version with focus listeners and try-catch logic。它结合了: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')那么干净。欢迎其他答案!

答案 1 :(得分:1)

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

答案 2 :(得分:0)

试试这个 - 在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"/>

编辑 - 我们只能为所有输入[type = file]元素使用一个选择器,而不是每个元素使用一个选择器

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