开发者

Action on blur except when specific element clicked with jQuery

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 clic开发者_如何学Pythonked, 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜