how to use Jquery :focus selector on input elements in iOS? - javascript

I'm using Jquery 1.7.1 and iPad1 iOS3.
I need to fire a function on scrollstart unless an input element has focus. The function below worked for a long time, but all of a sudden it doesn't (looking aroud I guess because of switching to Jquery 1.7.1)
$(document).on('scroll', function(){
if ( !$("input:focus").length > 0 ) {
self.hideAllPanels();
}
});
Specifically $('input:focus').length = 0, although I can detect the focus event triggering before the scroll event.
I have been fiddling with a workaround using:
if ( !$(document.activeElement).get(0).tagName == "input" ){
....
}
But I'm not sure when the activeElement is changing, because it seems to persist for quite a while even after I'm "leaving" the resprective element.
Question:
Any idea why I can't detect the focus-ed element on iOS? Some hints how I could set this up with activeElement, so on blur, I'm no longer having the input as activeElement are also welcome!
Thanks for help!

$(document).on('scroll', function(){
if (!$("input").is(':focus')) {
self.hideAllPanels();
}
});
This seems to work for me, but it will fire the function multiple times during scroll if an input element does not have focus.

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;
});

Enable and disable jquery knob dynamically

I'm using the excellent jQuery knob plugin. However, I need to dynamically enable/disable the element depending on user input. There is support for having a disabled state on page load which have the effect that no mouse (or touch) events are bound to the canvas element. Does anyone know how to resolve this issue, that is, how to (after page load) bind and unbind these mouse event listeners?
Ideally I would like to do something like this (on a disabled knob)
$('.button').click(function() {
$('.knob').enable();
});
Edit:
I ended up rewriting the source which binds/unbinds the mouse and touch events. The solution is not perfect so I leave the question open if someone perhaps have a better (cleaner) solution.
html
<input class="knobSlider" data-readOnly="true">
<button id="testBtn">clickHere</button>
script
in doc ready,
$(".knobSlider").knob();
$("#testBtn").click(function(){
$(".knobSlider").siblings("canvas").remove();
if($(".knobSlider").attr("data-readOnly")=='true'){
$(".knobSlider").unwrap().removeAttr("data-readOnly readonly").data("kontroled","").data("readonly",false).knob();
}
else{
$(".knobSlider").unwrap().attr("data-readOnly",true).data("kontroled","").data("readonly",true).knob();
}
});
For reference you can use my jsfiddle link > http://jsfiddle.net/EG4QM/ (check this in firefox, because of some external resource load problem in chrome)
If someone doesn't like how the accepted answer destroys and recreates the internal canvas element, then checkout my approach:
https://jsfiddle.net/604kj5g5/1/
Essentially, check the draw() implementation (I also recommend listening on value changes in the draw method instead of the change and release, which work for and click and mousewheel events respectively, which imo is inconvenient).
var $input = $("input");
var knobEnabled = true;
var knobPreviousValue = $input.val();
$input.knob({
draw: function () {
if (knobPreviousValue === $input.val()) {
return;
}
if (!knobEnabled) {
$input.val(knobPreviousValue).trigger("change");
return;
}
knobPreviousValue = $input.val();
console.log($input.val());
},
});
Try this to disable the control.
I'm still trying to find a way to enable it back
$("#btnDisable").click(function(){
$("#knob").off().prev().off();
});

Chrome sets cursor to text while dragging, why?

My application has many drag and drop features. While dragging I want the cursor to change to some grab cursor. Internet Explorer and Firefox work fine for this, but Chrome always changes the cursor to the text cursor.
None of these solutions worked for me because it's too much code.
I use a custom jQuery implementation to do the drag, and adding this line in the mousedown handler did the trick for me in Chrome.
e.originalEvent.preventDefault();
Try turning off text selection event.
document.onselectstart = function(){ return false; }
This will disable any text selection on the page and it seems that browser starts to show custom cursors.
But remember that text selection will not work at all, so it's the best to do it only while dragging, and turn it on again just after that. Just attach function that doesn't return false:
document.onselectstart = function(){ return true; }
If you want to prevent the browser from selecting text within an element and showing the select cursor, you can do the following:
element.addEventListener("mousedown", function(e) { e.preventDefault(); }, false);
Pitfall
You cannot put the
document.onselectstart = function(){ return false; };
into your "mousedown" handler because onselectstart has already been triggered.
Solution
Thus, to have it working, you need to do it before the mousedown event. I did it in the mouseover event, since as soon as the mouse enters my element, I want it to be draggable, not selectable. Then you can put the
document.onselectstart = null;
call into the mouseout event. However, there's a catch. While dragging, the mouseover/mouseout event might be called. To counter that, in your dragging/mousedown event, set a flag_dragging to true and set it to false when dragging stops (mouseup). The mouseout function can check that flag before setting
document.onselectstart = null;
Example
I know you are not using any library, but here's a jQuery code sample that might help others.
var flag_dragging = false;//counter Chrome dragging/text selection issue
$(".dragme").mouseover(function(){
document.onselectstart = function(){ return false; };
}).mouseout(function(){
if(!flag_dragging){
document.onselectstart = null;
}
});
//make them draggable
$(".dragme").draggable({
start: function(event, ui){
flag_dragging = true;
}, stop: function(event, ui){
flag_dragging = false;
}
});
I solved a same issue by making the Elements not selectable, and adding an active pseudo class on the draged elements:
* {
-webkit-user-select: none;
}
.your-class:active {
cursor: crosshair;
}
I was facing almost same problem. I want cursor inside my DIV element and all its child to be the default, the CSS tips here helped in IE, FF and Opera, but not for Google Chrome. Here is what I have done in parent DIV:
<div ... onselectstart="return false;" ... > ... </div>
Now it is working fine. Hope this help.
I have a similar issue using jQuery UI draggable and sortable (ver. 1.8.1), and it's quite specific, so I assume that you are using same library.
Problem is caused by a bug in jQuery UI (actually a fix for other Safari bug).
I just raised the issue in jQuery UI http://dev.jqueryui.com/ticket/5678 so I guess you will need to wait till it's fixed.
I've found a workaround for this, but it's quite hard-core, so you only use it if you really know what is going on ;)
if ($.browser.safari) {
$.ui.mouse.prototype.__mouseDown = $.ui.mouse.prototype._mouseDown;
$.ui.mouse.prototype._mouseDown = function(event){
event.preventDefault();
return $.ui.mouse.prototype.__mouseDown.apply(this, arguments);
}
}
It simply switches off the fix that's in jQuery UI code, so basically it may break something.
Just use this line inside your mousedown event
arguments[0].preventDefault();
You can also disable text selection by CSS adding this class to your draggable element
.nonselectable {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

Internet Explorer and <select> tag problem

I am having the following problem under Internet Explorer 7/8:
I have a popup that gets activated when user mouseover a link. The popup is a simple <div> that contains some data. Inside this <div> tag there is a <select> tag with some <option>s. I have attached mouseover/mouseout events to the <div>, so that this popup will stay open while cursor is over it. The problem comes when you click on the <select> and then move the cursor over any of the <option>s. This triggers the mouseout event of the <div> tag and respectively closes it.
How can I prevent the closing of the popup in IE ?
You should be able to detect if the situation is the one you want just with the values off the event. It is a little convoluted but it seems to work.
In the event handler of your outer div, do something like this:
<div onmouseover="if (isReal()) { toggle(); }"
onmouseout="if (isReal()) { toggle(); }">
</div>
Then implement the isReal method:
function isReal() {
var evt = window.event;
if (!evt) {
return true;
}
var el;
if (evt.type === "mouseout") {
el = evt.toElement;
} else if (evt.type === "mouseover") {
el = evt.fromElement;
}
if (!el) {
return false;
}
while (el) {
if (el === evt.srcElement) {
return false;
}
el = el.parentNode;
}
return true;
}
Basically the isReal method just detects if the event was coming from within the div. If so, then it returns false which avoids calling the hide toggle.
My suggestion would be to set another flag while the select box has focus. Do not close the div while the flag is set.
How about re-showing the div when the mouse is over the <options>s through mouseover events of <options>s.
Edit: execution order of mouseover of option and mouseout of div might cause problems though.
In the mouseout event for the div add a timeout to the div element that will hide the div in 200 milliseconds or so.
Then in the mouseover event for the div/select and the click event of the select clear the timeout stored in the div element.
This gives a very slight delay before hiding the div that allows the mouseover or click events to clear the timeout before it is executed. It's not pretty but it should work.
instead of using mouseout as the event to close the div, use mouseleave, then the event will only be triggered when the pointer leaves the boundary of the div, not when it moves onto other elements within it
you could try adding another mouseover event specifically for the options list.
Well, the reason for this behavior is because the mouseover/out events bubble, which effectively means that whenever you mouseover any of the elements inside the popup, the popup receives the event also.
You can read more here about these events, and here about event bubbling.
You have 3 possible solutions here:
Change the events to onmouseenter/leave. You've mentioned that this didn't help, which just sounds plain odd, since these aren't supposed to bubble.
Check srcElement in relation to from/toElement in the event.
An improved version of McKAMEY's check would be:
function isReal() {
var evt = window.event;
if (!evt) {
return true;
}
var el;
if (evt.type === "mouseout") {
el = evt.toElement;
} else if (evt.type === "mouseover") {
el = evt.fromElement;
}
if (!el) {
return false;
}
// this will also return true if el == evt.srcElement
return evt.srcElement.contains(el);
}
Does the same thing, just shorter.
3 . Another option would be to create a transparent, invisible div just under your popup that covers the area that the select box drops down into. I'm assuming that it's dropping outside the actual area of the popup.
Hope this helps!
have you tried hover instead of mouseover/out effects?
$(".myDiv").hover(function(){
$(this).show();
}, function {
$(this).hide();
});
What about something like this:
<div id="trigger">
Hover over me!
</div>
<div class="container">
<select>
<option>Blah</option>
<option>Blah</option>
</select>
</div>
$("#trigger").mouseover(function(){
$('.container).show();
});
$(".container").mouseleave(function(){
$(this).hide();
});
The basic idea is that you show the container element when you hover over the trigger then when you leave the container you hide the container. You'd need to position the container so it clipped the trigger element, otherwise it would hide straight away.
Why have mouseover / mouseout on the <div>? Why not just show the <div> on the mouse over, then set <body onmouseover="hidedivs();"> I don't know if this would work, but if the <div> is on top of the body, then the <div> should stay visible.
Many people posting solutions/examples do not seem to realize one thing: onmouseout event on <div> fires before onmouseover event on <select>.
When <div> loses focus (onmouseout) do not close it immediately, but after say, 500 milliseconds. If during this time <select> gets focus (mouseover) do not close <div> at all (clearTimeout).
Also, try to play with event propagation/bubling.
Given that selects in IE are a pain, especially when it comes to the whole layering issue where a select appears above a div even though it shouldn't, can I point you in the direction of YUI's Menu button controls. They look really nice, are easy to implement and won't cause this issue
Here is a link: http://developer.yahoo.com/yui/examples/button/btn_example07.html
You should use event.stopPropagation() while in <select>, or cancelBubble() in <select> element itself.

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;
});

Categories

Resources