On my page, I have multiple text boxes and need at least one of those boxes to always have focus. Is there a js event listener I can call that will detect when nothing on the page has focus, so I can give it focus?
If you want to know if an element from a list of tags is focused :
function hasFocus(selector) {
return Array
.from(document.querySelectorAll(selector))
.some(function(el){
return el === document.activeElement
});
}
// usage
console.log(hasFocus('input, select, textarea'))
You can also attach a focusout handler to the document which checks the focusable elements every time a focusout event bubbles up. Then force focus on an element other than the source of the blur event, if none have it.
Edited per comment.
Please check out my solution on this link: https://codesandbox.io/s/nostalgic-lovelace-f9hei
When you load the page, the first input get focus. Everytime you click out. A random input get focused.
blur event will not bubble up by default. So make it bubble up by changing usecapture to true.
const inputs = document.querySelectorAll('input')
document.querySelector('input').focus()
document.addEventListener('blur', (e) => {
console.log(e)
if (e.isTrusted) {
const random = Math.round(Math.random() * (inputs.length-1));
console.log(random)
Array.from(inputs)[random].focus()
}
},true)
Related
I have a "parent div" containing a child box input type=number. When user clicks outside of input box I use blur or focusout event of parent div to use input values at some other place.
I also need to use $('inputbox').trigger('focus') at some place, which fires "parent div"'s blur event unwantedly and runs code on that event.
Please give a solution to stop this parent blur event on child's focus OR give a way to find whether focus is made by trigger('focus') on child element or by user clicking outside of parent div.
I need to fire parent Blur only when user clicks outside of it & not when focus is triggered through code.
with jquery you can make custom events very easily , something like:
$('inputbox').trigger('special-focus');
then you can wait for this event just like any other event:
$('div').on('special-focus' , function(){ ... } );
this will prevent your events from interfering with the built in ones.
I guess if you don't want to use that suggestion then do this in your click handler or your focus handler of the child
.on('focus' , function(e){
e.stopPropagation();
e.preventDefault();
/// the rest of your code ...
});
this will stop the propagation of events to parent elements
This worked perfect for me:
if (e.relatedTarget === null) ...
What worked for me was checking the relatedTarget property of the eventObject object in the handler function.
$("#parentDiv").focusout(function (eventObject) {
if (eventObject.relatedTarget.id === "childInputId")
/// childInput is getting focus
else
/// childInput is not getting focus
});
.on('blur',...) of parent fires before .on('focus' ,...) of child.
Anyways for a parent div containing child input box
we can use $('input').trigger('special-focus');
and then
$("#form" ).on('special-focus', '.parentdiv' , function(event) {
$("#form" ).off('blur', '.parentdiv');
$(event.target).focus();
$("#form" ).on('blur', '.parentdiv' , showValuesOnBlur);
});
Now blur of parent will not fire on focus of child.This worked for me. i.e. off & on the blur event of parent inside special-focus.
Thanks Scott Selby :)
I have added change event on the input field so that whenever user enters the text into it, so other task should happen, it works but when i click outside the input field.I don't know whether it is default behavior or i am doing some thing wrong. I tried using keyup and keydown events and it works as expect.
Please suggest.
Here is my code:
$("#mobile-number").on('change',function(){
// some other code
});
The change event fires when an elements value changes.
For select boxes, checkboxes, and radio buttons, the event is fired immediately when the user makes a selection with the mouse, but for the other element types the event is deferred until the element loses focus.
In other words, on an input, the change event fires when the element loses focus, not when you type, and that is the default behaviour.
That's why there are key events as well, and on modern browsers you can catch most changes to an input with the input event
$("#mobile-number").on('input',function(){ ...
Yes, it is the desired behavior.
Change Event
The change event is fired for , , and
elements when a change to the element's value is committed by the
user. Unlike the input event, the change event is not necessarily
fired for each change to an element's value.
Depending on the kind of form element being changed and the way the
user interacts with the element, the change event fires at a different
moment:
When the element is activated (by clicking or using the keyboard) for and ;
When the user commits the change explicitly (e.g. by selecting a value from a 's dropdown with a mouse click, by selecting a
date from a date picker for , by selecting a file
in the file picker for , etc.);
When the element loses focus after its value was changed, but not commited (e.g. after editing the value of or ).
Try using input event:
$(function() {
$("#mobile-number").on('input', function() {
$("#copy").val(this.value);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type='text' id='mobile-number' />
<input type='text' id='copy' readonly/>
Try this:( If i really understand your problem )
jQuery(document).on('change', '#mobile-number', function() {
// some other code
});
for type event:
jQuery(document).on('keyup', '#mobile-number', function() {
// some other code
});
You should provide your selector to the .on function:
$(document).on('change', '#mobile-number', function() {
// some other code
});
Is it possible to get the dom element that was clicked from the blur event.
myTxtBox.blur(function (e) {
var myTxtBoxClass = e.target.className
var getClassOfElementclicked == //get the class of clicked element
});
I think you should use .click(function(){}); to get clicked object. Then you can set it to blur. Right now it is unclear what initiates the blur event in the first place.
If you want to see which object that is currently "blurring" is clicked, you could assign a class to the objects when they blur and assign click event to this class.
blur can be called for more than just clicking away from a control--the user could have tabbed away. If all you're interested in is the target of a click event, then you can register a handler for clicks.
However, if you're more interested in the elements that gain & lose focus in close proximity to one another (they are two separate events, so you can't really consider a blur to have a "newly-focused target" attribute, you can use something like this:
$('input').blur(function (e) {
console.log('lost focus: ', e.target);
});
$('input').focus(function (e) {
console.log('gained focus: ', e.target);
});
http://jsfiddle.net/Palpatim/QUDED/
Also, be sure to see the discussion of blur() in the jQuery documentation: the event doesn't bubble in IE, so depending on your use case, you may wish to use the focusout event instead.
I need to create a part of a form where if you click on a select, a checkbox field should popup and if you click anywhere else again, this field should disappear. I would like to do this with focusing the field after clicking on the select, but for some reason, my checkbox field loses its focus not only when you click anywhere else out of it, but even when you click on a label of a checkbox INSIDE of it. So the problem is that I am focusing an element in which I click on a label and the focused parent element loses its focus for some reason I can not figure out.
The code: http://jsfiddle.net/RELuL/2/
Any helps appreciated!
P.S.:
Just some bonus question :) As you can see, if you click on the select input, my hidden checkbox section is displayed a little late, it is not shown instantly which looks a little bad. Any tips how to optimize this?
EDIT: I use Firefox 13.0.1
When you click on a <label>, the browser focuses the associated input field. So focus leaves the parent and goes to the checkbox (and your blur event handler is called).
Instead of focusing the parent div and relying on it being blurred, attached a click handler to the document:
$(document).click(function() {
multiSelectUpdate();
});
$('.multiselect.container').click(function(event) {
event.stopPropagation(); // prevent click event from reaching document
});
Also, in Webkit clicking on <select> doesn't fire a click event. A workaround is to use the focus event instead.
Demo
Ok two simple changes got this working first change the click listen on the select box to a mousedown listener like so.
$('.multiselector').mousedown(function(event) {
event.preventDefault();
currentMulti = $(this).attr('id');
thisOffset = $(this).offset();
$(this).hide();
$('#' + currentMulti + '-container')
.css('top', thisOffset.top + 'px').show().attr("tabindex", -1).focus();
$(this).addClass('active');
});
this triggers before the box is able to comes up so it never shows.
Secondly the blur listener was believing it lost focus when a child got focus to fix this change to focusout.
$('.multiselect.container').focusout(function() {
multiSelectUpdate();
});
This only fires when the selector loses focus even focus currently on child of selector.
Fixed fiddle
enjoy :)
EDIT
For some reason blur fires multiple times on FF so to work round this use instead of blur mouseleave.
$('.multiselect.container').mouseleave(function() {
multiSelectUpdate();
});
I have a div that acts like a drop-down. So it pops-up when you click a button and it allows you to scroll through this big list. So the div has a vertical scroll bar. The div is supposed to disappear if you click outside of the div, i.e. on blur.
The problem is that when the user clicks on the div's scrollbar, IE wrongly fires the onblur event, whereas Firefox doesn't. I guess Firefox still treats the scrollbar as part of the div, which I think is correct. I just want IE to behave the same way.
I've had a similar problem with a scrollbar in an autocomplete dropdown. Since the dropdown should be hidden when the form element it is attached to loses focus, maintaining focus on the correct element became an issue. When the scrollbar was clicked, only Firefox (10.0) kept focus on the input element. IE (8.0), Opera (11.61), Chrome (17.0) and Safari (5.1) all removed focus from the input, resulting in the dropdown being hidden, and since it was hidden, click events would not fire on the dropdown.
Fortunately, the shift of focus can be easily prevented in most of the problem browsers. This is done by canceling the default browser action:
dropdown.onmousedown = function(event) {
// Do stuff
return false;
}
Adding a return value to the event handler sorted out the problem on all browsers except IE. Doing this cancels the default browser action, in this case the focus shift. Also, using mousedown instead of click meant that the event handler would be executed before the blur event fired on the input element.
This left IE as the only remaining problem (no surprise there). It turns out that there is no way to cancel the focus shift on IE. Fortunately, IE is the only browser that fires a focus event on the dropdown, meaning focus on the input element can be restored with an IE-exclusive event handler:
dropdown.onfocus = function() {
input.focus();
}
This solution for IE is not perfect, but while the focus shift is not cancelable, this is the best you can do. What happens is that the blur event fires on the input, hiding the dropdown, after which focus fires on the now hidden dropdown, which restores focus on the input and triggers showing the dropdown. In my code it also triggers repopulating the dropdown, resulting in a short delay and loss of the selection, but if the user wants to scroll the selection is probably useless anyway, so I deemed this acceptable.
I hope this is helpful, even though my example is slightly different than in the question. From what I gathered, the question was about IE firing a blur event on the dropdown itself, rather than the button that opened it, which makes no sense to me... Like my use of a focus event handler indicates, clicking on a scrollbar should move focus to the element the scrollbar is part of on IE.
Late answer, but I had the same issue and the current answers didn't work for me.
The hover state of the popup element works as expected, so in your blur event you can check to see if your popup element is hovered, and only remove/hide it if it isn't:
$('#element-with-focus').blur(function()
{
if ($('#popup:hover').length === 0)
{
$('#popup').hide()
}
}
You'll need to shift focus back to the original element that has the blur event bound to it. This doesn't interfere with the scrolling:
$('#popup').focus(function(e)
{
$('#element-with-focus').focus();
});
This does not work with IE7 or lower - so just drop support for it...
Example: http://jsfiddle.net/y7AuF/
I'm having a similar problem with IE firing the blur event when you click on a scrollbar. Apparently it only happens n IE7 and below, and IE8 in quirksmode.
Here's something I found via Google
https://prototype.lighthouseapp.com/projects/8887/tickets/248-results-popup-from-ajaxautocompleter-disappear-when-user-clicks-on-scrollbars-in-ie6ie7
Basically you only do the blur if you know the person clicked somewhere on the document other than the currently focused div. It's possible to inversely detect the scrollbar click because document.onclick doesn't fire when you click on the scrollbar.
This is an old question but since it still applies to IE11 here is what I did.
I listen to the mousedown event on the menu and set a flag on this event. When I catch the blur event, if the mousedown flag is on, I set the focus back. Since Edge, FF and Chrome won't fire the blur event but will fire the mouseup event (which IE won't), I reset the mousedown flag on the mouseup for them (on the blur for IE).
mousedown: function (e) {
this.mouseddown = true;
this.$menu.one("mouseup", function(e){
// IE won't fire this, but FF and Chrome will so we reset our flag for them here
this.mouseddown = false;
}.bind(this));
}
blur: function (e) {
if (!this.mouseddown && this.shown) {
this.hide();
this.focused = false;
} else if (this.mouseddown) {
// This is for IE that blurs the input when user clicks on scroll.
// We set the focus back on the input and prevent the lookup to occur again
this.skipShowHintOnFocus = true; // Flag used to avoid repopulating the menu
this.$element.focus();
this.mouseddown = false;
}
},
That way the menu stays visible and user doesn't loose anything.
Use focusout, and focusin (IE specific events)
$(document).bind('focusout', function(){
preventHiding = false;
//trigger blur event
this.$element.trigger('blur');
});
$(document).bind('focusin', function(){
preventHiding = true;
});
$(document).bind('blur', function(){
// Did anyone want us to prevent hiding?
if (this.preventHiding) {
this.preventHiding = false;
return;
}
this.hide();
});
I had the same probleme. Resolved by putting the menu in a wrapping (bigger) div. With the blur applied to the wrapper, it worked!
Perhaps try adding the tabindex attribute set to -1 to the div node.
I don't think this is an IE issue.
It's more a case of how to design your interaction and where to handle which event.
If you have a unique css-class-accessor for the related target, canceling a blur event can be done by checking the classList of the event.relatedTarget for the element you want to allow or disallow to initiate the blur event. See my onBlurHandler from a custom autocomplete dropdown in an ES2015 project of mine (you might need to work around contains() for older JS support):
onBlurHandler(event: FocusEvent) {
if (event.relatedTarget
&& (event.relatedTarget as HTMLElement).classList.contains('folding-select-result-list')) {
// Disallow any blur event from `.folding-select-result-list`
event.preventDefault();
} else if (!event.relatedTarget
|| event.relatedTarget
&& !(event.relatedTarget as HTMLElement).classList.contains('select-item')) {
// If blur event is from outside (not `.select-item`), clear the suggest list
// onClickHandler of `.select-item` will clear suggestList as configured with this.clearAfterSelect
this.clearOptions(this.clearAfterBlur);
}
}
.folding-select-result-list is my suggestions-dropdown having 'empty spots' and 'possibly a scrollbar', where I don't need this blur event.
.select-item has it's own onClickHandler that fires the XHR-request of the selection, and closes the dropdown when another property of the component this.clearAfterSelect is true.