All the solutions I've found with Google were kludges along the lines of “scan all the elements and test each one to see whether it has focus”. It's much better to use the capture phase of the DOM event model and track the focus and blur events with the document object:
function _dom_trackActiveElement(evt) {
if (evt && evt.target) {
document.activeElement =
evt.target == document ? null : evt.target;
}
}
function _dom_trackActiveElementLost(evt) {
document.activeElement = null; }
if (document.addEventListener) {
document.addEventListener("focus",_dom_trackActiveElement,true);
document.addEventListener("blur",_dom_trackActiveElementLost,true);
}
This implementation is slightly over-pessimistic; if the browser window loses focus, the activeElement is set to null (as the input control loses focus as well). If your application needs the activeElement value even when the browser window doesn't have the focus, you could remove the blur event listener.
4 comments:
thanks for your post - that was quite helpful. i implemented a variation of this specifically to track keyboard based focus change and to retrigger the blur event in a way that is similar to how they are produced in firefox and in IE.
if ($.browser.safari && document.addEventListener)
{
function fixupActiveElement(e)
{
if (e.type == "keyup")
{
document.activeElement = null;
return;
}
if (!e.target || !$(e.target).is(":input"))
{
return;
}
var oldActiveElement = document.activeElement;
document.activeElement = e.target;
if (e.type == "focus" && oldActiveElement && oldActiveElement != document.activeElement )
{
// retrigger blur with document.activeElement set to the right thing
$(oldActiveElement).trigger("blur");
}
};
// this is the order in which events will fire if we shift focus using a tab
document.addEventListener("keydown", fixupActiveElement, true);
document.addEventListener("focus", fixupActiveElement, true);
document.addEventListener("keyup", fixupActiveElement, true);
}
The above uses jQuery (http://jquery.com/) to abbreviate document.getElementById with $('#' + id || element) and $.browser
...just for clarity
But, 'document.activeElement' is read-only. (https://developer.mozilla.org/en/DOM/document.activeElement)
"document.activeElement =
evt.target == document ? null : evt.target;"
throws error.
Yeah, the trick only works with those browser versions that don't support native activeElement, so you should try/catch the code that sets it.
Post a Comment