nopr
nopr

Reputation: 88

Detecting when a child outside of element gets focus

Here's the basic setup: I have a thin bar at the top of a website containing accessibility-related links. If javascript is enabled, this is hidden (negative margin). However, I would like to show the bar whenever a user tabs through the links. Here's what I'm doing:

var bar = $("#bar");
bar.find("a").on("focus", function(){
    if(bar.css("margin-top") == "-50px"){
        bar.animate({ marginTop: 0 }, 250);
    }
});

That works. However, when it comes to closing this bar it gets a bit tricky. If I bind a blur event to the a, it will hide when I tab through each link. I want to hide it only when all links are blurred.

I would like to do this:

bar.find("a").on("blur", function(){
    // If no links inside #bar have focus now:
    bar.animate({ marginTop: -50 }, 250);
});

How?

Upvotes: 4

Views: 1221

Answers (2)

jAndy
jAndy

Reputation: 235992

Do it like so:

bar.find("a").on("blur", function() {    
    setTimeout(function() { 
        if( $('a:focus').length === 0 ) {
            // If no links inside #bar have focus now:
            bar.animate({ marginTop: -50 }, 250);
        }
    }, 15);
});

This one queries for all anchors which might have a focus, if the .length is zero, we should know that we can hide that bar now. I didn't test that code yet, please let me know.

See http://api.jquery.com/focus-selector/

Example: http://jsfiddle.net/e4PaN/

Upvotes: 1

Matt
Matt

Reputation: 75317

Because the blur event fires before the focus event fires, you should set a timeout in the blur event, and cancel it in the focus event.

(function () {

    var bar = $("#bar");
    var timeout;

    bar.find("a").on("focus", function(){
        clearTimeout(timeout);

        if(bar.css("margin-top") == "-50px"){
            bar.animate({ marginTop: 0 }, 250);
        }
    });

    bar.find("a").on("blur", function(){
        timeout = setTimeout(function () {
            // If no links inside #bar have focus now:
            bar.animate({ marginTop: -50 }, 250);
        }, 1);
    });

}());

Upvotes: 1

Related Questions