Reputation: 25127
I can't seem to get the currently focused/active element as a jQuery object in Firefox, if it is an <input type="file" />
. It works on other input types (text, password, submit, others) and on other element types (<select>
, <textarea>
, others).
<input type="file" />
// 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);
$(':focus')
.See jsFiddle demonstration of getting the id of the focused element - test it with Firefox.
Does anyone have a solution for getting the focused/active element as a jQuery object that works for <input type="file" />
?
The solution needs to be fully generic as the functionality is part of a plugin. I will not have control over the page the script will run on.
Upvotes: 3
Views: 3722
Reputation: 25127
Edit: This solution has been implemented where the problem was first found, in EmulateTab. See getFocusedElement().
Found a solution myself, after a break from coding - but it is not a very clean solution. It is basically the same solution suggested by @Neil while I first wrote this post.
Try the updated jsFiddle version with focus listeners and try-catch logic in Firefox. It combines :focus
, document.activeElement
and document level focus listeners that keep track of the last "known" focused element.
// 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);
});
I don't like this solution very much, as it is far from as clean as just a one-line $(':focus')
. Other answers are welcome!
Upvotes: 3
Reputation: 144
Try this - tested in 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 - we can use only one selector for all input[type=file] elements instead of one selector per element
$(':input[type=file]').focus(function () {
crtFocus = $(this);
});
Upvotes: 0
Reputation: 55402
The only way I can think of is to add a capturing focus listener at the window level in which you update a global variable with the event target. (In Firefox, the event target for a focus event in a file input is the file input itself even though document.activeElement returns the "anonymous" button.)
Upvotes: 1