jquery need alternative to focusout()
Asked Answered
C

3

11

Given the sample markup:

<div>
    <input />
    <input />
    <input />
</div>

How can one, via jQuery, determine that div has lost focus?

I can use focusout() but that's not quite what I need. With focusout, it will get triggered as one tabs from input to input, as it's actually detecting (via event bubbling) that the input is losing focus.

Another way to word the requirement: I need to know when focus has moved OUTSIDE of the div.

I asked a similar question before:

jquery focusin() and preventing bubbling

But that was related to a pop-up UI and one can get around that by inserting a blank DIV behind it and putting a click/focus event on that as a trigger but that's won't work for this situation.

The next thought I had was to test for focusin when calling focusout:

    $(".myobject").focusout(function(element) {
    if(!($(this).focusin())){
        console.log('doYourThing ' + $(this));
    }
});

Alas, that doesn't work (I'm guessing due to the fact that it's evaluating focusin during the focusout event and, as such, it hasn't detected focusin yet.

Any clever solutions to this problem? Am I maybe missing a native jQuery event that does exactly what I'm looking for?

UPDATE:

Actually, the simplified question:

I need the equivalent of $('div').blur() but that would actually work on a div (since blur can't be triggered from a div)

Conventionality answered 21/6, 2010 at 21:49 Comment(0)
M
4

Well, what might work would be to bind a "focus" handler to everything, and you know when you're not in the <div> when you get a "focus" event elsewhere.

$('body').live('focus', (function() {
  var inDiv = false;
  return function(e) {
    if ($(this).closest('#theDiv').length)
      inDiv = true;
    else {
      if (inDiv)
        alert("just lost focus!");
      inDiv = false;
    }
  };
 });
Medlar answered 21/6, 2010 at 22:7 Comment(1)
OK @DA - note that I had the call to live() a little wrong, so if you're having problems with what I did just check my updateMedlar
Q
18

Taking Pointy's answer and going a little further with it.

creating a (simple) focuslost event plugin

(function($) {
    // will store the last focus chain
    var currentFocusChain = $();
    // stores a reference to any DOM objects we want to watch focus for
    var focusWatch = [];

    function checkFocus() {
        var newFocusChain = $(":focus").parents().andSelf();
        // elements in the old focus chain that aren't in the new focus chain...
        var lostFocus = currentFocusChain.not(newFocusChain.get());
        lostFocus.each(function() {
            if ($.inArray(this, focusWatch) != -1) {
                $(this).trigger('focuslost');
            }
        });
        currentFocusChain = newFocusChain;
    }
    // bind to the focus/blur event on all elements:
    $("*").live('focus blur', function(e) { 
        // wait until the next free loop to process focus change
        // when 'blur' is fired, focus will be unset
        setTimeout(checkFocus, 0);
    });

    $.fn.focuslost = function(fn) {
        return this.each(function() {
            // tell the live handler we are watching this event
            if ($.inArray(this, focusWatch) == -1) focusWatch.push(this);
            $(this).bind('focuslost', fn);
        });
    };
})(jQuery);

Example Use

$("div").focuslost(function() {
  $(this).append("<div>Lost Focus!</div>");
});

jsfiddle demo

Quixote answered 21/6, 2010 at 22:49 Comment(4)
!!! Whoa, you went all out for that answer! This is a great little plugin! I had to give Pointy the answer as he got in first but I really appreciate this plugin. I know we can use this in several places! Seems that this should almost be a core part of jQuery at some point.Conventionality
i cannot use this plugin with jquery .on() method.. can you solve this problem?Fill
Great answer, just what I needed for an issue I was having with focusout using the "tab" key in IESigler
Awesome! I should have used this much earlier.Leclaire
S
5

Another plugin to look at is Ben Alman's Outside Events plugin. It allows you to detect when any of the following events are triggered on anything outside of a specific element and its children: clickoutside, dblclickoutside, focusoutside, bluroutside, mousemoveoutside, mousedownoutside, mouseupoutside, mouseoveroutside, mouseoutoutside, keydownoutside, keypressoutside, keyupoutside, changeoutside, selectoutside, submitoutside.

Sextet answered 22/6, 2010 at 18:16 Comment(1)
Ben Alman has some great plugins, and this just happens to be one of them.Quixote
M
4

Well, what might work would be to bind a "focus" handler to everything, and you know when you're not in the <div> when you get a "focus" event elsewhere.

$('body').live('focus', (function() {
  var inDiv = false;
  return function(e) {
    if ($(this).closest('#theDiv').length)
      inDiv = true;
    else {
      if (inDiv)
        alert("just lost focus!");
      inDiv = false;
    }
  };
 });
Medlar answered 21/6, 2010 at 22:7 Comment(1)
OK @DA - note that I had the call to live() a little wrong, so if you're having problems with what I did just check my updateMedlar

© 2022 - 2024 — McMap. All rights reserved.