Search code examples
javascripthtmljqueryfocusblur

Is there a jquery event the runs just before focus leaves an element or just before the next element gains focus?


I have a form with two input elements that are somewhat intertwined. In element#1 (element #2 is right after element#1 in the tabindex order), once the user tries to leave that field, I run an ajax call to check if the value entered is already in the database and if so, use the javascript confirm dialog to ask the user a question. The second element, upon gaining focus, automatically pops up a modal window with choices the user can make. I am using Jquery.

I would like to run the "Does this data exist" ajax call as soon as the user leaves the first element. the Blur event seemed to be what I wanted as this existing data check is needed whether the user made a change or not.

My problem using blur, though, is that its handler runs AFTER the first element loses focus and focus jumps to element#2. So, the blur handler from element #1 pops up the confirm screen at the same time element #2's focus handler pops up the choices modal and I now have 2 popups open at the same time.

I would like to give the user the chance to answer the question in the confirmation alert before the choices for the element#2 pop up.

Is there a Jquery event similar to blur, but that runs just BEFORE focus is actually lost? Or, is there a way to prevent the next element from gaining focus until the blur handler from the first element completes?

Trying to stop propagation or preventDefault() in the Blur handler does nothing because the focus on element#2 has already happened before the blur handler runs.

I've tried setting the tabindex of element#2 to -1 and then programmatically focusing on that element when needed, but tabbing away from this element becomes a problem, and reverse tabbing skips it (jumping straight to element#1) - I still want that element in tabindex ordering, but just don't want it to gain focus until element#1 completes its handler that needs to run when it loses focus.

I have tried setting status variables as well but when I add code to handle the transition between the two elements, I end up with similar issues and it presents additional edge cases complexity. I've also tried messing with mousedown and keydown events and trying to prevent the default processing, but that added significant complexity and room for error as well.

Any ideas would be welcome. Thank you.


Solution

  • Would something like this do the trick?

    Have a variable that indicates if it's okay to show the second popup

    let allowSecondPopup = true;
    

    Have a variable that indicates whether showing the second popup was postponed

    let secondPopupPostponed = false;
    

    Set the variable when the first input receives focus

    $("#input1").on("focus", fuction () {
        allowSecondPopup = false;
    });
    

    Send ajax on blur

    $("#input1").on("blur", function () {
        //$("#input1").disabled(true);
        //$("#input2").disabled(true);
        $.post("https://example.com", { }, fuction (response) {
            if (secondPopupPostponed) {
                // Only show second popup after the ajax-call has finished
                showSecondPopup();
                allowSecondPopup = true;
                secondPopupPostponed = false;
            }
        });
    });
    

    And when the second input receives focus, check the variable

    $("#input2").on("focus", fuction () {
        if (allowSecondPopup) {
            showSecondPopup();
        } else {
            // We're still waiting for the ajax-call to complete. 
            // When the ajax-call completes, the callback will show the second popup.
            secondPopupPostponed = true;
        }
    });