I am using focusout
and focusin
event on input fields in my application.
My script checks if the input boxes have validation error or not when the focusin
/focuseout
events occur; consequently, relevant error messages get displayed below the input box stating the issue in the user input.
I also have a submit button, and afterwords, when the whole form is filled, I run the validation again on each input box for any errors.
So, I have attached 3 events, 1. focusout 2. focusein events
3. <button> submit button (Click) events
.
Noticed that there when focusout and click
event gets fired simultaneously the click event
gets suppressed in this below case.
Please note that everything works fine if only messages are printed[for debug purpose]. But the moment I do some DOM manipulation [from inside the focusout
method], like adding a class to a div or insert in span below the input box etc. --The very first click event goes undetected.
When It Occurs
When the input error is corrected and immediately, without clicking anywhere else on the page, the submit button is pressed.
It is only when the button is clicked twice click event is detected.
Below is the sample Jquery snippet that has this same issue.
Steps to re-produce the issue:
- Click on the input box.
- Press the tab button(you would see "input is blank" message below the input box).
Now enter some value in this input box.
Press the submit button directly (make sure you don't click anywhere else). the Click event of submit button is not fired. The first click is just ignored, then, It gets fired on subsequent clicks.
$("#submit").click(function(event){
if(null != $("#watch").val() && $("#watch").val() != ""){
$(".error-msg").text("inside submit: good to submit");
}else{
$(".error-msg").text("inside submit: submit done");
}
});
$("#watch").focusout(function(event){
if(null != $("#watch").val() && $("#watch").val() != ""){
$(".error-msg").html("inside focusout only");
$('.test1').css('display','none');
$('.test1').addClass('testing');
}else{
$(".error-msg").html("input is blank");
$('.test2').addClass('testing');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="test1">test1</div>
<input id="watch" type="text" placeholder="My input"/>
<div class="error-msg"></div>
<button id="submit" type="text">submit</button>
I think this is due to the conflict of event sequence. For click
event to fire, the mousedown
event must be followed by mouseup
event. But here the event sequence after your fourth repro-step is mousedown
> foucusout
> mouseup
. So the click event is never fired.
As a workaround you could try using mousedown
event on button#submit
and using setTimeout
to evaluate the mousedown
handler with a small delay in order to produce the desired result.
$("#submit").mousedown(function(event) {
setTimeout(function() {
if (null != $("#watch").val() && $("#watch").val() != "") {
$(".error-msg").text("inside submit: good to submit");
} else {
$(".error-msg").text("inside submit: submit done");
}
}, 50);
});
$("#watch").focusout(function(event){
if(null != $("#watch").val() && $("#watch").val() != ""){
$(".error-msg").html("inside focusout only");
$('.test1').css('display','none');
$('.test1').addClass('testing');
}else{
$(".error-msg").html("input is blank");
$('.test2').addClass('testing');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="test1">test1</div>
<input id="watch" type="text" placeholder="My input"/>
<div class="error-msg"></div>
<button id="submit" type="text">submit</button>