There are two elements in play:
$('#myInput') // an input field for search
$('#myList') // a list to display search results
I want to hide the list when the input no longer has focus, like so:
$('#myInput').blur(function() {
$('#myList').hide();
});
This works great, except when a list item is clicked, because the blur event fires and hides the list before the click is registered. The goal is for the list to stay visible when any part of the list is clicked, even though this will cause the input to blur.
How can I do this? Thanks!
You can accomplish this by keeping a global variable, and setTimouts, to wait a delay of 200ms and then check if one of the 2 elements have focus.
var keepFocus = false;
function hideList(){
if(!keepFocus){
$('#myList').hide();
}
}
$('#myInput').blur(function() {
keepFocus = false;
window.setTimeout(hideList, 200);
}).focus(function(){
keepFocus = true;
});
$('#myList').blur(function() {
keepFocus = false;
window.setTimeout(hideList, 200);
}).focus(function(){
keepFocus = true;
});
I've faced with the exact same problem, so this is how I solved it.
I came up with the fact that blur() fires earlier than click().
So I've tried to change click() to mousedown() and found out that mousedown() fires before blur().
And to imitate click() you'll have to fire mousedown() and then mouseup()
So in your case I would do something like this:
var click_in_process = false; // global
$('#myList').mousedown(function() {
click_in_process = true;
});
$('#myList').mouseup(function() {
click_in_process = false;
$('#myInput').focus();
// a code of $('#myList') clicking event
});
$('#myInput').blur(function() {
if(!click_in_process) {
$('#myList').hide();
// a code of what you want to happen after you really left $('#myInput')
}
});
Demo / example: http://jsfiddle.net/bbrh4/
Hope it helps!
You need to be able to say "do this blur() unless the list gains focus at the same time".
This question says how to detect if an element has focus: Using jQuery to test if an input has focus
Then all you need to do is:
$("#myInput").blur(function () {
if (!$("#myList").is(":focus")) {
$("#myList").hide();
}
});
Pigalev Pavel's answer above works great.
However, If you want an even simplier solution, you can just "prevent default" in the "mousedown" of an element to prevent the blur event from taking place. (since preventing default actually means that in the end, the input never looses focus in the first place!)
Of course, this is only if you're alright with preventing default in the div. It does have some side-effects, like the text is no longer selectable. As long as that's not an issue, this will work.
I suppose if you hold the mouse down over the div, move the mouse outside of the div, and then release the mouse, it also doesn't fire the "blur" event. But in my case, I wasn't too worried about that either, since the click started in the target div.
$("input").focus(function(){
$(this).val("");
});
$("input").blur(function(){
$(this).val("blur event fired!");
});
$("div").mousedown(function(e){
e.preventDefault();
})
div{
height: 200px;
width: 200px;
background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input>
<div>
Click here to prevent blur event!
</div>
The best way to do this is to attach an event handler to the body element, then another handler to the list that stops event propagation:
$(body).click(function () {
$("#myList").hide();
});
$("#myList").click(function (e) {
e.stopImmediatePropagation();
});
This listens for a click outside of #myInput and hides #myList. At the same time, the second function listens for a click on #myList and if it occurs, it prevents the hide() from firing.
Related
I have an input that when clicked shows a bootstrap 4 dropdown BUT I need it to open when a user tabs to it as well for ADA accessibility.
If I use a focus event that uses $('#input-name).dropdown('toggle') it works fine, but when the input is clicked focus fires first which opens the dropdown and then the click event closes it.
I have tried e.preventDefault(); e.stopPropagation(); but neither help solve this issue.
events: {
focus #healthPlanMenu": "openDropDown"
}
openDropDown: function (e) {
if ($('#healthPlanMenu').find('.dropdown-menu:no(.show)')){
$("#healthPlanMenu.dropdown-toggle").dropdown('toggle');
}//fails
$("#healthPlanMenu.dropdown-toggle").dropdown('toggle');//fails
$( "#healthPlanMenu" ).click();//fails
}
So ideally you'd probably solve this by having the focus event set the dropdown's state to open, that way if it gets "reopened" by the click event, no problem. However, as far as I can tell there is only a toggle option with the jQuery API; seems unnecessarily limiting...
Given that, we can know if a click is coming after our focus event by using mousedown. So a somewhat hacky way to solve this problem is to disable our focus event if we know a click is coming.
(function() {
var disable = false;
$('#healthPlanMenu.dropdown-toggle')
.on('mousedown touchstart', function() {
disable = true;
})
.on('focus', function() {
if (!disable) {
$(this).dropdown('toggle');
}
})
.on('mouseup touchend',function() {
disable = false;
})
})()
I don't know if the touchstart and touchend are necessary as most browsers probably fire mouse events on touch as well. But better safe than sorry.
I'm using the following solution to prevent loss of focus of the #content textarea when the user has clicked on a .box element:
// Detect latest element clicked
$(document).mousedown(function(e) {
lastElClicked = $(e.target);
});
// Prevent loss of focus for textarea when clicking on tools
$("#content").on("blur", function(event) {
if (lastElClicked.attr('class') == 'box'){
event.preventDefault();
this.focus();
return false;
}
});
In a few words, on mouse down save the target element that has been clicked. On the blur of the #content textarea check if that last element clicked was a .box. If it was then prevent default, refocus the #content textarea and return false.
My solution works perfect under Chrome but I still loose focus under Safari and Firefox. How can I make this work cross browser?
EDIT:
The problem with the solutions offered is that the element actually looses focus and is refocused after. In Chrome with the code above I never actually loose fucus, which means selected text stays selected.
EDITED:
try this:
// Detect latest element clicked
$(document).mousedown(function(e) {
window.lastElClicked = $(e.target);
});
// Prevent loss of focus for textarea when clicking on tools
$("#content").on("blur", function(event) {
if (window.lastElClicked.attr('class') == 'box'){
event.preventDefault();
var that=this;
setTimeout(function(){
$(that).trigger('focus');
},200);
window.lastElClicked="";
return false;
}
});
Also this is a nice article on this bug which appears to be on Safari's part: http://bugs.jquery.com/ticket/7768
Alternatively you could try this one:
$('.box').click(function(event){
event.preventDefault();
$('input').each(function(){
$(this).trigger('blur');
});
setTimeout(function(){
$('#content').trigger('focus');
},200);
});
finally I have to mention that it still loses the focus on the highlighted text which seems to me as an impossible task to achieve in this case!
fiddle is here: http://jsfiddle.net/44zAy/11/
Everything is working as I want however, if you click inside the first input and then go to click inside the second, the first one closes and same if you click the x button.
What I need is for it to stay open even if i click inside another and only close if I blur out of it and not by doing a focus on another input. is that possible?
CODE:
var inputWdith = '185px';
var inputWdithReturn = '68px';
jQuery('.resize-close').hide();
jQuery(".resize-input").on('focus', function() {
jQuery(this).animate({
width: inputWdith
},400);
jQuery(this).promise().done(function(){
jQuery(this).next('.resize-close').show();
});
}).bind('blur', function() {
jQuery(this).animate({
width: inputWdithReturn
},500);
jQuery(this).next('.resize-close').hide();
});
jQuery('.resize-close').click(function(){
jQuery(this).prev('.resize-input').animate({
width: inputWdithReturn
},500);;
});
For a quick fix of your current code, use the event.relatedTarget: http://jsfiddle.net/QKVL9/
The problem is that when you click into the second input, the 'blur' event is fired for the first input. So the quick fix is to check whether there is event.relatedTarget != null. If there is a relatedTarget, then stop execution of the 'blur' event for the first input.
But I recommend a complete refactor of this code :)
I want to set up an onBlur event for an input element that validates the value and, if invalid, "cancels" the blur and refocusses(or focus never loss) the current input.
i have this peace of code already
document.getElementById('my_input_id1').onblur = function() {
var self = this;
setTimeout(function() { self.focus(); }, 10);
}
Suppose my next focused element is'my_input_id2' which also has an "onblur" event.as focus is already moved to 'my_input_id2'.When i set focus back to 'my_input_id1' the second elment 'my_input_id2' "onblur event is fried.I want to cancel onblur event of second element.i have many other element with "onlur" for Validation.
Can i stop elemnt not to lost focus?
Is there another function that can do it without lost focus??
Should i use some other function that does not lose focus??
Is there another way to get out of this problem??
Many many thanks in advance.
Try it
$('#my_input_id1').on('blur',function(){
if(SOME CONDITION){
setTimeout(function(){
$('#my_input_id1').focus();
},100);
return false;
}
});
This is quite straight forward to do with JavaScript:
document.getElementById('id1').onblur = function(e) {
if(this.value.length == 0) {
this.focus();
e.preventDefault();
return false;
}
}
Essentially just refocusing the element based on a criteria, of course this can be anything you want it to be.
and here is the fiddle: http://jsfiddle.net/m4cZ2/1/
Anyone know how to prevent an HTML checkbox from getting focus when clicked? I still want it to change state, just not get focus.
You can prevent the focus by using preventDefault() in a mousedown handler:
$('input[type=checkbox]').mousedown(function (event) {
// Toggle checkstate logic
event.preventDefault(); // this would stop mousedown from continuing and would not focus
});
In pure JavaScript:
checkbox.onmousedown = function (event) {
// Toggle checkstate logic
event.preventDefault(); // this would stop mousedown from continuing and would not focus
}
Give this CSS:
input {outline: 0;}
But be aware that when you move control using Tab key, it won't be possible to identify which control are you in currently.
Update #1
Use this JavaScript:
$('input[type=checkbox]').click(function () {
this.blur();
});