javascriptjqueryonclickclickfocusout

Not able to detect button press when using focusout and focusin along with Click event


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:

  1. Click on the input box.
  2. Press the tab button(you would see "input is blank" message below the input box).
  3. Now enter some value in this input box.

  4. 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>


Solution

  • 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>