5

How could this be achieved via jQuery?

When the user clicks on any input in the form, it is focussed. When a user clicks out of the form from any input it is blurred, but, the blur does not get triggered between tabbing between inputs in the form itself.

For something like this, we're looking at this basic structure:

<form>
<input ... />
<input ... />
<input ... />
</form>

So again, lets say I click on any input in the form, we know the form is focused. Next, when the user clicks off of ANY input the blur is triggered ONLY if we clicked outside the form.

I've asked this question previously and kindly received input on how to achieve the blurring effect when the last input field in the form was blurred, but not from any element in the input list.

Thanks, Mark Anderson

Mark Anderson
  • 125
  • 2
  • 13

4 Answers4

15

The sequence of events when you're tabbing between inputs:

  Click on input1:  input1 focus

  Clickb on input2: input1 blur
                    input2 focus

  Click outside:    input2 blur

When an input loses focus you need to check if some other element within the form gains focus. Or you can simply check if the active element is still within the form:

$('form').on('focusout', function(event) {
    setTimeout(function() {
        if (!event.delegateTarget.contains(document.activeElement)) {
            console.log('Form blur');
        }
    }, 0);
});

JSFiddle

Note that form doesn't blur on submit, so you may need to add a submit handler if you want to do the same thing on blur and submit.

Also note the use of setTimeout, it's required because blur and focusout events are emitted when an element is about to lose focus, but haven't lost it yet.

Alexey Lebedev
  • 11,988
  • 4
  • 39
  • 47
  • Didn't seem to work when clicking the submit button, but otherwise works as expected. – Wireblue Jul 10 '14 at 05:41
  • @Wireblue thanks for pointing that out, I've updated the answer to reflect that. Technically, the form doesn't "blur" on submit, so I think the best fix is to add `onsubmit` separately. – Alexey Lebedev Jul 10 '14 at 14:11
  • @AlexeyLebedev How would you make this work for a ` – h bob Dec 01 '15 at 05:16
  • 1
    @hbob you're right, I guess focusin/focusout is a better approach after all: http://jsfiddle.net/g3nx9160/ – Alexey Lebedev Dec 01 '15 at 16:49
3

would $('form').focusin()/focusout() not work?

http://api.jquery.com/focusout/

Hailwood
  • 89,623
  • 107
  • 270
  • 423
  • Not going to work. Focusout fires each time a child is blurring. – Alexey Lebedev Feb 19 '11 at 07:03
  • +1: This situation is probably why jQuery has `.focusin()` and `.focusout()`. And thanks for teaching me a new piece of the jQuery API. – mu is too short Feb 19 '11 at 07:05
  • @Alexey Lebedev: But the handler can easily check if anything else in the form does have focus so it will work with a bit of care. – mu is too short Feb 19 '11 at 07:06
  • @mu is too short, I've been trying to figure out *how* this would work for a bit now. If you pass in the event, the `event.target` is what you're blurring from. How can you get *and test* against the active element? (Noting that `document.activeElement` may not work in older Safari etc. **and** I couldn't get it to work with jQuery as a selector.) –  Feb 19 '11 at 07:55
  • @D_N: I spoke too soon. The blur will happen before the focus that you want to check for so it all falls apart. I can't think of a way to make it go without resorting to a timer or even worse kludges. Oh well, +1 to Alexey Lebedev then: a working kludge is still something that works. – mu is too short Feb 20 '11 at 07:37
  • @mu is too short, Agh, too bad. True, though. –  Feb 20 '11 at 07:42
  • Yeah, I found the same thing, spent a couple of hours trying to get it to work, unfortunately when tab is pressed the order is *input loses focus, window gains focus* *focusout called* *next item gains focus* which is stupid, this would work if it simply went to the next item THEN called blur! – Hailwood Feb 20 '11 at 21:04
1

You could do something like this:

var check;

$('form input').focus(function()
   {
    clearInterval(check); // remove setinterval if any
    // do something because the form is being used
   });

$('form input').blur(function()
{
    check = setInterval(function()
    {
        // do something because the form is not being used
    },500); // half-second delay
});

It's not the sexiest solution, but checks for if no focus in your form occurs after .5 seconds. Hope this helps.

TNC
  • 5,388
  • 1
  • 26
  • 28
1

Here's the same basic idea as Alexey's but for jQuery 1.7+ and, at least to my mind, a little more readable because it keeps everything in scope within the same handler:

    $("#myform").on("focusout focusin", "input", function(e){
        if ( e.type == "focusout" ) {
            $("#myform").attr("form-blur-timeout", window.setTimeout(function(){
                console.log("you've left the form!");//do stuff here
            }, 100));
        } else {
            window.clearTimeout($("#myform").attr("form-blur-timeout"));
        }
    });

Enjoy :)

drpitman
  • 11
  • 2