How should I fire Javascript blur event after click event that causes the blur?

对着背影说爱祢 提交于 2019-11-30 00:03:38

We had a similar problem at work. what we figured out in the end was that the mousedown event will fire before the blur event allowing you to set the content before the validation or even cancel the validation process completely using a flag.

check this fiddle I made using your example- http://jsfiddle.net/dL3K3/31/

$(function(){
    var flag = true;
    $('input').blur(function(){
        if(!$(this).val() && flag){
            alert("Grrr, It's empty");
        }
    });

    $('button').mousedown(function(){
        flag = false;
    });    
    $('button').mouseup(function(){
        flag = true;
        $('input').val('content').focus();
    });

});

-Edit-

As @mclin Suggested, using the mousedown event and preventDefault will prevent blur behavior. And you can just leave the original click event intact -

http://jsfiddle.net/dL3K3/364/

$(function(){
    $('input').blur(function(){
        if(!$(this).val()){
            alert("Grrr, It's empty");
        }
    });

    $('button').mousedown(function(e){
        e.preventDefault();
    });    
    $('button').click(function(){
        $('input').val('content');
    });

});

This solution might be a bit cleaner and better for most cases just note that if you use it you'll preventDefault and blur of any other element the focus is currently on but for most use cases that shouldn't be an issue.

I have a better solution than Yoni Jah's: call preventDefault on the button's mousedown event. The onBlur never happens so you're free to do whatever in the click event.

This is better because it doesn't change the click behavior by making things happen on mouse down instead of mouse up, which can be unexpected.

Vardhini

This might also help:

Set a timer that delays the blur event action before it fires the button click event.

// Namespace for timer var setTimer = { timer: null }

    $('input,select').blur(function () {
        setTimer.timer = setTimeout(function () {
           functionCall();
        }, 1000);
    });

    $('input,select').focus(function () {
        setTimer.timer = setTimeout(function () {
            functionCall();
        }, 1000);
    });

    $("#btn").click(function () {
        clearTimeout(setTimer.timer);
        functionCall();
    });

Separate the input validation logic to it's own function which is called both by the blur event automatically and then by the click event after you've modified the value in the input box. True your validation logic would be called twice, but I'm not seeing a way around that without making a lot more changes.

Example using jQuery:

$('input').blur(function() {
    validate(this);
});

$('submit').click(function() {
   //modify the input element
   validate(inputElement);
});

var validate = function(obj) {
   // validate the object
}

Sometimes it is useful to get a child object on mouseup, but the parent wants to hide its children on blur. We can cancel the hiding of the children elements, then wait until our mouseup occurs, then force the blur to occur when we are ready

js

var cancelHide = false;

$('.my-input').blur(function() {
    if (!cancelHide) {
        $('.my-item').hide();
    }
});

$('.my-input').click(function() {
    $('.my-item').show();
});

$('.my-item').mousedown(function() {
    cancelHide = true;
});

$('.my-item').mouseup(function() {
    var text = $(this).text();
    alert(text);
    cancelHide = false;
    $('.my-input').blur();
});

html

<input type="text" class="my-input"/>
<div class="my-item">Hello</div>
<div class="my-item">Lovely</div>
<div class="my-item">World</div>

css

.my-item {
    display:none;
}

https://jsfiddle.net/tic84/on421rxg/

Clicking the list items will only alert on mouseup, despite the parent trying to hide them on blur

The trick is not to use blur and click events, because they are always performed in order of blur first, click second. Instead you should check when the element having focus has changed, because that happens only after the click.

I think I have an elegant solution for this one:

var alreadyValidated = 'true';

setInterval(function(){
    if(document.activeElement.id != 'validation-field-id'){
        if(alreadyValidated=='false'){
            alreadyValidated = 'true';
            validate(document.activeElement);       
        }
    }
    else {
        alreadyValidated = 'false';
    }
}, 200);

These days all modern browsers support document.activeElement.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!