How to determine where focus went? - javascript

This has been asked here before, but several years ago, and there was no cross-platform solution at the time (other than the setTimeout solution, which is really not very handy).
I'd like to do onblur="foo(parm);" and have foo be able to determine which element now has focus.
I'm using regular javascript; no jQuery for this one, please.
Is that possible these days?

You can try something like this:
function whereDidYouGo() {
var all = document.getElementsByTagName('*');
for (var i = 0; i < all.length; i++)
if (all[i] === all[i].ownerDocument.activeElement)
return all[i];
}
EDIT:
function whereDidYouGo() { return document.activeElement; }

In jQuery, at the OP's request:
$(':input').blur(function() {
$focusedElement = $(':input:focus');
//Do stuff with $focusedElement
}

Interesting question. The heart of the matter is - when does the 'focus' event fire, before or after the blur event? If it fires before the blur event, the problem is easy, because you can just store the current focus in a variable that your blur event can access.
However, at least in Chrome 13, it appears the blur event happens before the focus event. One possible solution.
Given the following HTML:
<input id="foo" value='foo' />
<input id="bar" value='bar' />
You can then:
var currentFocus;
var pendingBlur;
var foo = document.getElementById('foo');
foo.addEventListener('focus', function(){
currentFocus = foo;
if(pendingBlur !== undefined){
pendingBlur();
pendingBlur = undefined;
}
});
foo.addEventListener('blur', function(){
pendingBlur = function(){
console.log('new focus:', currentFocus);
};
});
var bar= document.getElementById('bar');
bar.addEventListener('focus', function(){
currentFocus = bar;
if(pendingBlur !== undefined){
pendingBlur();
pendingBlur = undefined;
}
});
bar.addEventListener('blur', function(){
pendingBlur = function(){
console.log('new focus:', currentFocus);
};
});
Basically, I just not the blur callback so it is handy for the focus event to call after we know about which element was focused.
Here is a working example on JSFiddle.
EDIT: This solution suffers from the problem that if you blur on the form by clicking on something other than another form element, the blur event never fires (since we wait for the focus event). The only way around that, that I can conceive, is using a timer to check if pendingBlur is defined, and if so, call it. At which point you don't really need the focus event to call the blur callback anymore...

Year 2020: All major browsers (desktop and mobile) support FocusEvent.relatedTarget.

event.relatedTarget couldn't find the newly-focused element(was div type in my case), but only null gets returned.
After attaching the attribute tabindex="0" on the element, now it works.
<div id="myDiv">myDiv</div>
console.log(e.relatedTarget) // null
<div id="myDiv" tabindex="0"> tabindexed div </div>
console.log(e.relatedTarget) // <div id="myDiv" tabindex="0">
tabindex is an attribute that make elements focusable using tab key on keyboard. I guess it is mainly for web accessibility.
And I guess you won't need to set tabindex attribute as long as to-be focused elements are already accessible by tab key (such as a, select.. and so on)

Related

how to check if the textbox is in focus in Javascript [duplicate]

I would like to find out, in JavaScript, which element currently has focus. I've been looking through the DOM and haven't found what I need, yet. Is there a way to do this, and how?
The reason I was looking for this:
I'm trying to make keys like the arrows and enter navigate through a table of input elements. Tab works now, but enter, and arrows do not by default it seems. I've got the key handling part set up but now I need to figure out how to move the focus over in the event handling functions.
Use document.activeElement, it is supported in all major browsers.
Previously, if you were trying to find out what form field has focus, you could not. To emulate detection within older browsers, add a "focus" event handler to all fields and record the last-focused field in a variable. Add a "blur" handler to clear the variable upon a blur event for the last-focused field.
If you need to remove the activeElement you can use blur; document.activeElement.blur(). It will change the activeElement to body.
Related links:
activeElement Browser Compatibility
jQuery alternative for document.activeElement
As said by JW, you can't find the current focused element, at least in a browser-independent way. But if your app is IE only (some are...), you can find it the following way:
document.activeElement
It looks like IE did not have everything wrong after all, this is part of HTML5 draft and seems to be supported by the latest version of Chrome, Safari and Firefox at least.
If you can use jQuery, it now supports :focus, just make sure you are using version 1.6+.
This statement will get you the currently focused element.
$(":focus")
From: How to select an element that has focus on it with jQuery
document.activeElement is now part of the HTML5 working draft specification, but it might not yet be supported in some non-major/mobile/older browsers. You can fall back to querySelector (if that is supported). It's also worth mentioning that document.activeElement will return document.body if no element is focused — even if the browser window doesn't have focus.
The following code will work around this issue and fall back to querySelector giving a little better support.
var focused = document.activeElement;
if (!focused || focused == document.body)
focused = null;
else if (document.querySelector)
focused = document.querySelector(":focus");
An addition thing to note is the performance difference between these two methods. Querying the document with selectors will always be much slower than accessing the activeElement property. See this jsperf.com test.
By itself, document.activeElement can still return an element if the document isn't focused (and thus nothing in the document is focused!)
You may want that behavior, or it may not matter (e.g. within a keydown event), but if you need to know something is actually focused, you can additionally check document.hasFocus().
The following will give you the focused element if there is one, or else null.
var focused_element = null;
if (
document.hasFocus() &&
document.activeElement !== document.body &&
document.activeElement !== document.documentElement
) {
focused_element = document.activeElement;
}
To check whether a specific element has focus, it's simpler:
var input_focused = document.activeElement === input && document.hasFocus();
To check whether anything is focused, it's more complex again:
var anything_is_focused = (
document.hasFocus() &&
document.activeElement !== null &&
document.activeElement !== document.body &&
document.activeElement !== document.documentElement
);
Robustness Note: In the code where it the checks against document.body and document.documentElement, this is because some browsers return one of these or null when nothing is focused.
It doesn't account for if the <body> (or maybe <html>) had a tabIndex attribute and thus could actually be focused. If you're writing a library or something and want it to be robust, you should probably handle that somehow.
Here's a (heavy airquotes) "one-liner" version of getting the focused element, which is conceptually more complicated because you have to know about short-circuiting, and y'know, it obviously doesn't fit on one line, assuming you want it to be readable.
I'm not gonna recommend this one. But if you're a 1337 hax0r, idk... it's there.
You could also remove the || null part if you don't mind getting false in some cases. (You could still get null if document.activeElement is null):
var focused_element = (
document.hasFocus() &&
document.activeElement !== document.body &&
document.activeElement !== document.documentElement &&
document.activeElement
) || null;
For checking if a specific element is focused, alternatively you could use events, but this way requires setup (and potentially teardown), and importantly, assumes an initial state:
var input_focused = false;
input.addEventListener("focus", function() {
input_focused = true;
});
input.addEventListener("blur", function() {
input_focused = false;
});
You could fix the initial state assumption by using the non-evented way, but then you might as well just use that instead.
document.activeElement may default to the <body> element if no focusable elements are in focus. Additionally, if an element is focused and the browser window is blurred, activeElement will continue to hold the focused element.
If either of these two behaviors are not desirable, consider a CSS-based approach: document.querySelector( ':focus' ).
I have found the following snippet to be useful when trying to determine which element currently has focus. Copy the following into the console of your browser, and every second it will print out the details of the current element that has focus.
setInterval(function() { console.log(document.querySelector(":focus")); }, 1000);
Feel free to modify the console.log to log out something different to help you pinpoint the exact element if printing out the whole element does not help you pinpoint the element.
I liked the approach used by Joel S, but I also love the simplicity of document.activeElement. I used jQuery and combined the two. Older browsers that don't support document.activeElement will use jQuery.data() to store the value of 'hasFocus'. Newer browsers will use document.activeElement. I assume that document.activeElement will have better performance.
(function($) {
var settings;
$.fn.focusTracker = function(options) {
settings = $.extend({}, $.focusTracker.defaults, options);
if (!document.activeElement) {
this.each(function() {
var $this = $(this).data('hasFocus', false);
$this.focus(function(event) {
$this.data('hasFocus', true);
});
$this.blur(function(event) {
$this.data('hasFocus', false);
});
});
}
return this;
};
$.fn.hasFocus = function() {
if (this.length === 0) { return false; }
if (document.activeElement) {
return this.get(0) === document.activeElement;
}
return this.data('hasFocus');
};
$.focusTracker = {
defaults: {
context: 'body'
},
focusedElement: function(context) {
var focused;
if (!context) { context = settings.context; }
if (document.activeElement) {
if ($(document.activeElement).closest(context).length > 0) {
focused = document.activeElement;
}
} else {
$(':visible:enabled', context).each(function() {
if ($(this).data('hasFocus')) {
focused = this;
return false;
}
});
}
return $(focused);
}
};
})(jQuery);
A little helper that I've used for these purposes in Mootools:
FocusTracker = {
startFocusTracking: function() {
this.store('hasFocus', false);
this.addEvent('focus', function() { this.store('hasFocus', true); });
this.addEvent('blur', function() { this.store('hasFocus', false); });
},
hasFocus: function() {
return this.retrieve('hasFocus');
}
}
Element.implement(FocusTracker);
This way you can check if element has focus with el.hasFocus() provided that startFocusTracking() has been called on the given element.
JQuery does support the :focus pseudo-class as of current. If you are looking for it in the JQuery documentation, check under "Selectors" where it points you to the W3C CSS docs. I've tested with Chrome, FF, and IE 7+. Note that for it to work in IE, <!DOCTYPE... must exist on the html page. Here is an example assuming you've assigned an id to the element that has focus:
$(":focus").each(function() {
alert($(this).attr("id") + " has focus!");
});
If you want to get a object that is instance of Element, you must use document.activeElement, but if you want to get a object that is instance of Text, you must to use document.getSelection().focusNode.
I hope helps.
If you're using jQuery, you can use this to find out if an element is active:
$("input#id").is(":active");
There are potential problems with using document.activeElement. Consider:
<div contentEditable="true">
<div>Some text</div>
<div>Some text</div>
<div>Some text</div>
</div>
If the user focuses on an inner-div, then document.activeElement still references the outer div. You cannot use document.activeElement to determine which of the inner div's has focus.
The following function gets around this, and returns the focused node:
function active_node(){
return window.getSelection().anchorNode;
}
If you would rather get the focused element, use:
function active_element(){
var anchor = window.getSelection().anchorNode;
if(anchor.nodeType == 3){
return anchor.parentNode;
}else if(anchor.nodeType == 1){
return anchor;
}
}
Reading other answers, and trying myself, it seems document.activeElement will give you the element you need in most browsers.
If you have a browser that doesn't support document.activeElement if you have jQuery around, you should be able populate it on all focus events with something very simple like this (untested as I don't have a browser meeting those criteria to hand):
if (typeof document.activeElement === 'undefined') { // Check browser doesn't do it anyway
$('*').live('focus', function () { // Attach to all focus events using .live()
document.activeElement = this; // Set activeElement to the element that has been focussed
});
}
With dojo, you can use dijit.getFocus()
Just putting this here to give the solution I eventually came up with.
I created a property called document.activeInputArea, and used jQuery's HotKeys addon to trap keyboard events for arrow keys, tab and enter, and I created an event handler for clicking into input elements.
Then I adjusted the activeInputArea every time focus changed, so I could use that property to find out where I was.
It's easy to screw this up though, because if you have a bug in the system and focus isn't where you think it is, then its very hard to restore the correct focus.
simple use document.activeElement to find the current active element
use document.activeElement.id
appending .id filters out returning the entire DOM and allows you to work only with identified elements
If you want to test the focused element on the dev tools, I suggest using.
$(":focus")
As document.activeElement will change to body when you click on anything in the dev tool.
To get the previous active element add this.
Example: you click on a button and need the previous active element. Since the button gets the focus once click on it.
document.addEventListener("focusout",ev => {
document.previousActiveElement = ev.target;
});

Call onclick attribute programatically and talk to the event parameter

I have read the other post relating to this matter. Unfortunately it has not resolved my problem. I am happy to use jQuery, so I am looking for the cleanest solution.
I have radio buttons defined as follow:
a = 5;
input.value = "myButton";
input.onclick = (function (a) {
return function (e) {
changeSelectedRadio(e.srcElement, a);
};
})(a);
I need to be able to execute this when user click on the radio button (this works fine), and programatically.
I have tried:
$("input[type='radio'][value='myButton']").triggerHandler("click");
$("input[type='radio'][value='myButton']").click();
Both produce the same result: e (the event parameter) does not exist.
$("input[type='radio'][value='myButton']").onclick();
Does not work
Changing the input.onclick to input.click also did not work. When the use click, the function does not get triggered.
Thanks
If you're using jquery already, might as well build the inputs that way:
var input = $('<input value="something">').click(function(){
var elem = $(this); // the element clicked, as a jquery obj
alert(elem.attr('id');
});
$('body').append(input);
$('input').trigger('click');
Adjust the selectors as needed, and you'll need to actually append the elements to the DOM, but it'll work.
try this:
$("input[type='radio'][value='myButton']").bind( "click", function() {
alert( "clicked" );
});
What is passed to the function is a jQuery event, not a native event. You can use the target element to get at the source that was clicked on or use this to reference the properties of the object directly. See fiddle at http://jsfiddle.net/YQh3Q/
<p><input id="foo1" name="foo" type="radio" value="0" checked="checked"> Foo1</p>
<p><input id="foo2" name="foo" type="radio" value="1"> Foo2</p>
(function ($) {
var input = document.getElementById("foo2");
var a = 5;
input.value = "myButton";
input.onclick = (function (a) {
return function (e) {
alert(e.target + '|' + this.id);
};
})(a);
$("input[type='radio'][value='myButton']").each(function() {
$(this).trigger("click");
});
})(jQuery);
Alternatively (and probably better) you can use a pure jQuery solution
$(function() {
var a = 5;
$('input#foo2').on('click', function() {
changeSelectedRadio(this, a);
})
.val('myButton');
$("input[type='radio'][value='myButton']").trigger('click');
});
Its best to use addEventListener() you can add all types of events. example: "click", "mousemove", "mouseover", "mouseout", "resize" and many more. the false at the end is to stop the event from traversing up the dom. If you want parent dom objects to also receive the event just change it to true. also this example requires no javascript libraries. This is just plain old javascript and will work in every browser with nothing extra needed.
Also addEventListener() is better than onClick() as you can add an unlimited number of event listeners to a dom element. If you have an onClick() on an element and then set another onClick() on the same element you have overwritten the first onClick(). Using addEventListener() if i want multiple click events to trigger when i click on an element i can do it with no problem.
If you want data about the element that is triggering the event you can pass the event to the function. You will see in my example function(e) e is the event and you can use e or this to target the element that is being triggered. Using e or this i can also get more data about the triggered event. for example if the event was a mousemove or mouseclick i can get the x and y position of the mouse at the time of the event.
<!DOCTYPE html>
<html>
<head>
<title>exampe</title>
</head>
<body>
<a id="test" href="">test</a>
<script>
document.getElementById("test").addEventListener("click",function(e){
alert('hello world');
alert('my element '+e);
alert('my element '+this);
},false);
</script>
</body>
</html>
if you want to have addEventListener call a function just change the 2nd value to the function name like this.
document.getElementById("test").addEventListener("click",f1,false);
this will execute the function
function f1(){ ... }
When you want to remove an event listener just call target.removeEventListener(type, listener[, useCapture]). Very simple and easy to manage.

Retrieving previously focused element

I would like to find out, in Javascript, which previous element had focus as opposed to the current focus. I've been looking through the DOM and haven't found what I need, yet. Is there a way to do this any help would be much appreciated
Each time an element is focused, you'd have to store which one it was. Then when another element is focused, you could retrieve the variable for the previous focused element.
So basically, your single focus handler would do 2 things:
Check if previousFocus is defined. If it is, retrieve it.
Set previousFocus to the currently focused element.
Here is a quick demo with jQuery (you can use raw JS too... just fewer lines w jQuery, so it's easier to understand imo):
// create an anonymous function that we call immediately
// this will hold our previous focus variable, so we don't
// clutter the global scope
(function() {
// the variable to hold the previously focused element
var prevFocus;
// our single focus event handler
$("input").focus(function() {
// let's check if the previous focus has already been defined
if (typeof prevFocus !== "undefined") {
// we do something with the previously focused element
$("#prev").html(prevFocus.val());
}
// AFTER we check upon the previously focused element
// we (re)define the previously focused element
// for use in the next focus event
prevFocus = $(this);
});
})();
working jsFiddle
Just found this question while solving the exact same problem and realised it was so old the jQuery world has moved on a bit :)
This should provide a more effective version of Peter Ajtais code, as it will use only a single delegated event handler (not one per input element).
// prime with empty jQuery object
window.prevFocus = $();
// Catch any bubbling focusin events (focus does not bubble)
$(document).on('focusin', ':input', function () {
// Test: Show the previous value/text so we know it works!
$("#prev").html(prevFocus.val() || prevFocus.text());
// Save the previously clicked value for later
window.prevFocus = $(this);
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/EzPfK/80/
Notes:
Uses $() to create an empty jQuery object (allows it to be used immediately).
As this one uses the jQuery :input selector it works with select & button elements as well as inputs.
It does not need a DOM ready handler as document is always present.
As the previously focused control is required "elsehere" is is simply stored on window for global use, so it does not need an IIFE function wrapper.
Well depending on what else your page is doing, it could be tricky, but for starters you could have a "blur" event handler attached to the <body> element that just stashes the event target.
To me this seems a slight improvement on Gone Coding's answer:
window.currFocus = document;
// Catch focusin
$(window).on( 'focusin', function () {
window.prevFocus = window.currFocus;
console.log( '£ prevFocus set to:');
console.log( window.currFocus );
window.currFocus = document.activeElement;
});
... there's no stipulation in the question that we're talking exclusively about INPUTs here: it says "previous elements". The above code would also include recording focus of things like BUTTONs, or anything capable of getting focus.
document.getElementById('message-text-area').addEventListener('focus',
event => console.log('FOCUS!')
);
event.relatedTarget has all the data about the previously focused element.
See also https://developer.mozilla.org/en-US/docs/Web/API/Event/Comparison_of_Event_Targets
Here is a slightly different approach which watches both focusin and focusout, in this case to prevent focus to a class of inputs:
<input type="text" name="xyz" value="abc" readonly class="nofocus">
<script>
$(function() {
var leaving = $(document);
$(document).on('focusout', function(e) {
leaving = e.target;
});
$( '.nofocus' ).on('focusin', function(e) {
leaving.focus();
});
$( '.nofocus' ).attr('tabIndex', -1);
});
</script>
Setting tabIndex prevents keyboard users from "getting stuck".

How do I find out which DOM element has the focus?

I would like to find out, in JavaScript, which element currently has focus. I've been looking through the DOM and haven't found what I need, yet. Is there a way to do this, and how?
The reason I was looking for this:
I'm trying to make keys like the arrows and enter navigate through a table of input elements. Tab works now, but enter, and arrows do not by default it seems. I've got the key handling part set up but now I need to figure out how to move the focus over in the event handling functions.
Use document.activeElement, it is supported in all major browsers.
Previously, if you were trying to find out what form field has focus, you could not. To emulate detection within older browsers, add a "focus" event handler to all fields and record the last-focused field in a variable. Add a "blur" handler to clear the variable upon a blur event for the last-focused field.
If you need to remove the activeElement you can use blur; document.activeElement.blur(). It will change the activeElement to body.
Related links:
activeElement Browser Compatibility
jQuery alternative for document.activeElement
As said by JW, you can't find the current focused element, at least in a browser-independent way. But if your app is IE only (some are...), you can find it the following way:
document.activeElement
It looks like IE did not have everything wrong after all, this is part of HTML5 draft and seems to be supported by the latest version of Chrome, Safari and Firefox at least.
If you can use jQuery, it now supports :focus, just make sure you are using version 1.6+.
This statement will get you the currently focused element.
$(":focus")
From: How to select an element that has focus on it with jQuery
document.activeElement is now part of the HTML5 working draft specification, but it might not yet be supported in some non-major/mobile/older browsers. You can fall back to querySelector (if that is supported). It's also worth mentioning that document.activeElement will return document.body if no element is focused — even if the browser window doesn't have focus.
The following code will work around this issue and fall back to querySelector giving a little better support.
var focused = document.activeElement;
if (!focused || focused == document.body)
focused = null;
else if (document.querySelector)
focused = document.querySelector(":focus");
An addition thing to note is the performance difference between these two methods. Querying the document with selectors will always be much slower than accessing the activeElement property. See this jsperf.com test.
By itself, document.activeElement can still return an element if the document isn't focused (and thus nothing in the document is focused!)
You may want that behavior, or it may not matter (e.g. within a keydown event), but if you need to know something is actually focused, you can additionally check document.hasFocus().
The following will give you the focused element if there is one, or else null.
var focused_element = null;
if (
document.hasFocus() &&
document.activeElement !== document.body &&
document.activeElement !== document.documentElement
) {
focused_element = document.activeElement;
}
To check whether a specific element has focus, it's simpler:
var input_focused = document.activeElement === input && document.hasFocus();
To check whether anything is focused, it's more complex again:
var anything_is_focused = (
document.hasFocus() &&
document.activeElement !== null &&
document.activeElement !== document.body &&
document.activeElement !== document.documentElement
);
Robustness Note: In the code where it the checks against document.body and document.documentElement, this is because some browsers return one of these or null when nothing is focused.
It doesn't account for if the <body> (or maybe <html>) had a tabIndex attribute and thus could actually be focused. If you're writing a library or something and want it to be robust, you should probably handle that somehow.
Here's a (heavy airquotes) "one-liner" version of getting the focused element, which is conceptually more complicated because you have to know about short-circuiting, and y'know, it obviously doesn't fit on one line, assuming you want it to be readable.
I'm not gonna recommend this one. But if you're a 1337 hax0r, idk... it's there.
You could also remove the || null part if you don't mind getting false in some cases. (You could still get null if document.activeElement is null):
var focused_element = (
document.hasFocus() &&
document.activeElement !== document.body &&
document.activeElement !== document.documentElement &&
document.activeElement
) || null;
For checking if a specific element is focused, alternatively you could use events, but this way requires setup (and potentially teardown), and importantly, assumes an initial state:
var input_focused = false;
input.addEventListener("focus", function() {
input_focused = true;
});
input.addEventListener("blur", function() {
input_focused = false;
});
You could fix the initial state assumption by using the non-evented way, but then you might as well just use that instead.
document.activeElement may default to the <body> element if no focusable elements are in focus. Additionally, if an element is focused and the browser window is blurred, activeElement will continue to hold the focused element.
If either of these two behaviors are not desirable, consider a CSS-based approach: document.querySelector( ':focus' ).
I have found the following snippet to be useful when trying to determine which element currently has focus. Copy the following into the console of your browser, and every second it will print out the details of the current element that has focus.
setInterval(function() { console.log(document.querySelector(":focus")); }, 1000);
Feel free to modify the console.log to log out something different to help you pinpoint the exact element if printing out the whole element does not help you pinpoint the element.
I liked the approach used by Joel S, but I also love the simplicity of document.activeElement. I used jQuery and combined the two. Older browsers that don't support document.activeElement will use jQuery.data() to store the value of 'hasFocus'. Newer browsers will use document.activeElement. I assume that document.activeElement will have better performance.
(function($) {
var settings;
$.fn.focusTracker = function(options) {
settings = $.extend({}, $.focusTracker.defaults, options);
if (!document.activeElement) {
this.each(function() {
var $this = $(this).data('hasFocus', false);
$this.focus(function(event) {
$this.data('hasFocus', true);
});
$this.blur(function(event) {
$this.data('hasFocus', false);
});
});
}
return this;
};
$.fn.hasFocus = function() {
if (this.length === 0) { return false; }
if (document.activeElement) {
return this.get(0) === document.activeElement;
}
return this.data('hasFocus');
};
$.focusTracker = {
defaults: {
context: 'body'
},
focusedElement: function(context) {
var focused;
if (!context) { context = settings.context; }
if (document.activeElement) {
if ($(document.activeElement).closest(context).length > 0) {
focused = document.activeElement;
}
} else {
$(':visible:enabled', context).each(function() {
if ($(this).data('hasFocus')) {
focused = this;
return false;
}
});
}
return $(focused);
}
};
})(jQuery);
A little helper that I've used for these purposes in Mootools:
FocusTracker = {
startFocusTracking: function() {
this.store('hasFocus', false);
this.addEvent('focus', function() { this.store('hasFocus', true); });
this.addEvent('blur', function() { this.store('hasFocus', false); });
},
hasFocus: function() {
return this.retrieve('hasFocus');
}
}
Element.implement(FocusTracker);
This way you can check if element has focus with el.hasFocus() provided that startFocusTracking() has been called on the given element.
JQuery does support the :focus pseudo-class as of current. If you are looking for it in the JQuery documentation, check under "Selectors" where it points you to the W3C CSS docs. I've tested with Chrome, FF, and IE 7+. Note that for it to work in IE, <!DOCTYPE... must exist on the html page. Here is an example assuming you've assigned an id to the element that has focus:
$(":focus").each(function() {
alert($(this).attr("id") + " has focus!");
});
If you want to get a object that is instance of Element, you must use document.activeElement, but if you want to get a object that is instance of Text, you must to use document.getSelection().focusNode.
I hope helps.
If you're using jQuery, you can use this to find out if an element is active:
$("input#id").is(":active");
There are potential problems with using document.activeElement. Consider:
<div contentEditable="true">
<div>Some text</div>
<div>Some text</div>
<div>Some text</div>
</div>
If the user focuses on an inner-div, then document.activeElement still references the outer div. You cannot use document.activeElement to determine which of the inner div's has focus.
The following function gets around this, and returns the focused node:
function active_node(){
return window.getSelection().anchorNode;
}
If you would rather get the focused element, use:
function active_element(){
var anchor = window.getSelection().anchorNode;
if(anchor.nodeType == 3){
return anchor.parentNode;
}else if(anchor.nodeType == 1){
return anchor;
}
}
Reading other answers, and trying myself, it seems document.activeElement will give you the element you need in most browsers.
If you have a browser that doesn't support document.activeElement if you have jQuery around, you should be able populate it on all focus events with something very simple like this (untested as I don't have a browser meeting those criteria to hand):
if (typeof document.activeElement === 'undefined') { // Check browser doesn't do it anyway
$('*').live('focus', function () { // Attach to all focus events using .live()
document.activeElement = this; // Set activeElement to the element that has been focussed
});
}
With dojo, you can use dijit.getFocus()
Just putting this here to give the solution I eventually came up with.
I created a property called document.activeInputArea, and used jQuery's HotKeys addon to trap keyboard events for arrow keys, tab and enter, and I created an event handler for clicking into input elements.
Then I adjusted the activeInputArea every time focus changed, so I could use that property to find out where I was.
It's easy to screw this up though, because if you have a bug in the system and focus isn't where you think it is, then its very hard to restore the correct focus.
simple use document.activeElement to find the current active element
use document.activeElement.id
appending .id filters out returning the entire DOM and allows you to work only with identified elements
If you want to test the focused element on the dev tools, I suggest using.
$(":focus")
As document.activeElement will change to body when you click on anything in the dev tool.
To get the previous active element add this.
Example: you click on a button and need the previous active element. Since the button gets the focus once click on it.
document.addEventListener("focusout",ev => {
document.previousActiveElement = ev.target;
});

When a 'blur' event occurs, how can I find out which element focus went *to*?

Suppose I attach an blur function to an HTML input box like this:
<input id="myInput" onblur="function() { ... }"></input>
Is there a way to get the ID of the element which caused the blur event to fire (the element which was clicked) inside the function? How?
For example, suppose I have a span like this:
<span id="mySpan">Hello World</span>
If I click the span right after the input element has focus, the input element will lose its focus. How does the function know that it was mySpan that was clicked?
PS: If the onclick event of the span would occur before the onblur event of the input element my problem would be solved, because I could set some status value indicating a specific element had been clicked.
PPS: The background of this problem is that I want to trigger an AJAX autocompleter control externally (from a clickable element) to show its suggestions, without the suggestions disappearing immediately because of the blur event on the input element. So I want to check in the blur function if one specific element has been clicked, and if so, ignore the blur event.
2015 answer: according to UI Events, you can use the relatedTarget property of the event:
Used to identify a secondary EventTarget related to a Focus
event, depending on the type of event.
For blur events,
relatedTarget: event target receiving focus.
Example:
function blurListener(event) {
event.target.className = 'blurred';
if(event.relatedTarget)
event.relatedTarget.className = 'focused';
}
[].forEach.call(document.querySelectorAll('input'), function(el) {
el.addEventListener('blur', blurListener, false);
});
.blurred { background: orange }
.focused { background: lime }
<p>Blurred elements will become orange.</p>
<p>Focused elements should become lime.</p>
<input /><input /><input />
Note Firefox won't support relatedTarget until version 48 (bug 962251, MDN).
Hmm... In Firefox, you can use explicitOriginalTarget to pull the element that was clicked on. I expected toElement to do the same for IE, but it does not appear to work... However, you can pull the newly-focused element from the document:
function showBlur(ev)
{
var target = ev.explicitOriginalTarget||document.activeElement;
document.getElementById("focused").value =
target ? target.id||target.tagName||target : '';
}
...
<button id="btn1" onblur="showBlur(event)">Button 1</button>
<button id="btn2" onblur="showBlur(event)">Button 2</button>
<button id="btn3" onblur="showBlur(event)">Button 3</button>
<input id="focused" type="text" disabled="disabled" />
Caveat: This technique does not work for focus changes caused by tabbing through fields with the keyboard, and does not work at all in Chrome or Safari. The big problem with using activeElement (except in IE) is that it is not consistently updated until after the blur event has been processed, and may have no valid value at all during processing! This can be mitigated with a variation on the technique Michiel ended up using:
function showBlur(ev)
{
// Use timeout to delay examination of activeElement until after blur/focus
// events have been processed.
setTimeout(function()
{
var target = document.activeElement;
document.getElementById("focused").value =
target ? target.id||target.tagName||target : '';
}, 1);
}
This should work in most modern browsers (tested in Chrome, IE, and Firefox), with the caveat that Chrome does not set focus on buttons that are clicked (vs. tabbed to).
I solved it eventually with a timeout on the onblur event (thanks to the advice of a friend who is not StackOverflow):
<input id="myInput" onblur="setTimeout(function() {alert(clickSrc);},200);"></input>
<span onclick="clickSrc='mySpan';" id="mySpan">Hello World</span>
Works both in FF and IE.
It's possible to use mousedown event of document instead of blur:
$(document).mousedown(function(){
if ($(event.target).attr("id") == "mySpan") {
// some process
}
});
The instance of type FocusEvent has the relatedTarget property, however, up to version 47 of the FF, specifically, this attribute returns null, from 48 it already works.
You can see more here.
Works in Google Chrome v66.x, Mozilla v59.x and Microsoft Edge... Solution with jQuery.
I test in Internet Explorer 9 and not supported.
$("#YourElement").blur(function(e){
var InputTarget = $(e.relatedTarget).attr("id"); // GET ID Element
console.log(InputTarget);
if(target == "YourId") { // If you want validate or make a action to specfic element
... // your code
}
});
Comment your test in others internet explorer versions.
I am also trying to make Autocompleter ignore blurring if a specific element clicked and have a working solution, but for only Firefox due to explicitOriginalTarget
Autocompleter.Base.prototype.onBlur = Autocompleter.Base.prototype.onBlur.wrap(
function(origfunc, ev) {
if ($(this.options.ignoreBlurEventElement)) {
var newTargetElement = (ev.explicitOriginalTarget.nodeType == 3 ? ev.explicitOriginalTarget.parentNode : ev.explicitOriginalTarget);
if (!newTargetElement.descendantOf($(this.options.ignoreBlurEventElement))) {
return origfunc(ev);
}
}
}
);
This code wraps default onBlur method of Autocompleter and checks if ignoreBlurEventElement parameters is set. if it is set, it checks everytime to see if clicked element is ignoreBlurEventElement or not. If it is, Autocompleter does not cal onBlur, else it calls onBlur. The only problem with this is that it only works in Firefox because explicitOriginalTarget property is Mozilla specific . Now I am trying to find a different way than using explicitOriginalTarget. The solution you have mentioned requires you to add onclick behaviour manually to the element. If I can't manage to solve explicitOriginalTarget issue, I guess I will follow your solution.
Can you reverse what you're checking and when? That is if you remeber what was blurred last:
<input id="myInput" onblur="lastBlurred=this;"></input>
and then in the onClick for your span, call function() with both objects:
<span id="mySpan" onClick="function(lastBlurred, this);">Hello World</span>
Your function could then decide whether or not to trigger the Ajax.AutoCompleter control. The function has the clicked object and the blurred object. The onBlur has already happened so it won't make the suggestions disappear.
Use something like this:
var myVar = null;
And then inside your function:
myVar = fldID;
And then:
setTimeout(setFocus,1000)
And then:
function setFocus(){ document.getElementById(fldID).focus(); }
Final code:
<html>
<head>
<script type="text/javascript">
function somefunction(){
var myVar = null;
myVar = document.getElementById('myInput');
if(myVar.value=='')
setTimeout(setFocusOnJobTitle,1000);
else
myVar.value='Success';
}
function setFocusOnJobTitle(){
document.getElementById('myInput').focus();
}
</script>
</head>
<body>
<label id="jobTitleId" for="myInput">Job Title</label>
<input id="myInput" onblur="somefunction();"></input>
</body>
</html>
i think it's not possibe,
with IE you can try to use window.event.toElement, but it dosn't work with firefox!
You can fix IE with :
event.currentTarget.firstChild.ownerDocument.activeElement
It looks like "explicitOriginalTarget" for FF.
Antoine And J
As noted in this answer, you can check the value of document.activeElement. document is a global variable, so you don't have to do any magic to use it in your onBlur handler:
function myOnBlur(e) {
if(document.activeElement ===
document.getElementById('elementToCheckForFocus')) {
// Focus went where we expected!
// ...
}
}
document.activeElement could be a parent node (for example body node because it is in a temporary phase switching from a target to another), so it is not usable for your scope
ev.explicitOriginalTarget is not always valued
So the best way is to use onclick on body event for understanding indirectly your node(event.target) is on blur
Edit:
A hacky way to do it would be to create a variable that keeps track of focus for every element you care about. So, if you care that 'myInput' lost focus, set a variable to it on focus.
<script type="text/javascript">
var lastFocusedElement;
</script>
<input id="myInput" onFocus="lastFocusedElement=this;" />
Original Answer:
You can pass 'this' to the function.
<input id="myInput" onblur="function(this){
var theId = this.id; // will be 'myInput'
}" />
I suggest using global variables blurfrom and blurto. Then, configure all elements you care about to assign their position in the DOM to the variable blurfrom when they lose focus. Additionally, configure them so that gaining focus sets the variable blurto to their position in the DOM. Then, you could use another function altogether to analyze the blurfrom and blurto data.
keep in mind, that the solution with explicitOriginalTarget does not work for text-input-to-text-input jumps.
try to replace buttons with the following text-inputs and you will see the difference:
<input id="btn1" onblur="showBlur(event)" value="text1">
<input id="btn2" onblur="showBlur(event)" value="text2">
<input id="btn3" onblur="showBlur(event)" value="text3">
I've been playing with this same feature and found out that FF, IE, Chrome and Opera have the ability to provide the source element of an event. I haven't tested Safari but my guess is it might have something similar.
$('#Form').keyup(function (e) {
var ctrl = null;
if (e.originalEvent.explicitOriginalTarget) { // FF
ctrl = e.originalEvent.explicitOriginalTarget;
}
else if (e.originalEvent.srcElement) { // IE, Chrome and Opera
ctrl = e.originalEvent.srcElement;
}
//...
});
I do not like using timeout when coding javascript so I would do it the opposite way of Michiel Borkent. (Did not try the code behind but you should get the idea).
<input id="myInput" onblur="blured = this.id;"></input>
<span onfocus = "sortOfCallback(this.id)" id="mySpan">Hello World</span>
In the head something like that
<head>
<script type="text/javascript">
function sortOfCallback(id){
bluredElement = document.getElementById(blured);
// Do whatever you want on the blured element with the id of the focus element
}
</script>
</head>
I wrote an alternative solution how to make any element focusable and "blurable".
It's based on making an element as contentEditable and hiding visually it and disabling edit mode itself:
el.addEventListener("keydown", function(e) {
e.preventDefault();
e.stopPropagation();
});
el.addEventListener("blur", cbBlur);
el.contentEditable = true;
DEMO
Note: Tested in Chrome, Firefox, and Safari (OS X). Not sure about IE.
Related: I was searching for a solution for VueJs, so for those who interested/curious how to implement such functionality using Vue Focusable directive, please take a look.
I see only hacks in the answers, but there's actually a builtin solution very easy to use :
Basically you can capture the focus element like this:
const focusedElement = document.activeElement
https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/activeElement
This way:
<script type="text/javascript">
function yourFunction(element) {
alert(element);
}
</script>
<input id="myinput" onblur="yourFunction(this)">
Or if you attach the listener via JavaScript (jQuery in this example):
var input = $('#myinput').blur(function() {
alert(this);
});
Edit: sorry. I misread the question.
I think its easily possible via jquery by passing the reference of the field causing the onblur event in "this".
For e.g.
<input type="text" id="text1" onblur="showMessageOnOnblur(this)">
function showMessageOnOnblur(field){
alert($(field).attr("id"));
}
Thanks
Monika
You could make it like this:
<script type="text/javascript">
function myFunction(thisElement)
{
document.getElementByName(thisElement)[0];
}
</script>
<input type="text" name="txtInput1" onBlur="myFunction(this.name)"/>

Categories

Resources