83

How do you test if the browser has focus?

Wayne Koorts
  • 10,861
  • 13
  • 46
  • 72
Rod
  • 14,529
  • 31
  • 118
  • 230
  • See also http://stackoverflow.com/questions/483741/how-to-determine-which-html-page-element-has-focus which can answer this question as well. – Alexander Bird Jun 29 '11 at 15:12
  • 15
    Try `document.hasFocus()`, which returns a boolean. It's built into the spec, so it can be done without jQuery. – Braden Best Feb 04 '13 at 21:41
  • For someone who want check pages' visibility (which is _not_ as same as focus), please checkout [Page Visibility API](https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API) for more details. – tsh Apr 19 '18 at 10:08

4 Answers4

162

use the hasFocus method of the document. You can find detailed description and an example here: hasFocus method

EDIT: Added fiddle http://jsfiddle.net/Msjyv/3/

HTML

Currently <b id="status">without</b> focus...

JS

function check()
{
    if(document.hasFocus() == lastFocusStatus) return;

    lastFocusStatus = !lastFocusStatus;
    statusEl.innerText = lastFocusStatus ? 'with' : 'without';
}

window.statusEl = document.getElementById('status');
window.lastFocusStatus = document.hasFocus();

check();
setInterval(check, 200);
cvsguimaraes
  • 12,910
  • 9
  • 49
  • 73
gumape
  • 2,832
  • 2
  • 18
  • 9
  • 3
    I tried the example from the above link and it worked well in IE7+, Chrome, and FF4. +1 for you. – Joseph Lust May 03 '11 at 14:56
  • 1
    Great little function, works much better than other jQuery equivalents I have run across. – Heath Aug 31 '11 at 20:10
  • 3
    More useful than the accepted answer, I had problems with the timer loading while the window was out of focus. – Kokos Oct 17 '11 at 14:06
  • This is not supported by Opera. The calming fact is that they are in process of switching the rendering engine to Webkit :) – Nikola Petkanski Feb 25 '13 at 08:38
  • 6
    In the meantime you can use some thing like this to get the functionality in Opera: `if(typeof document.hasFocus === 'undefined') { document.hasFocus = function () { return document.visibilityState == 'visible'; } }` – Kent Apr 02 '13 at 09:37
  • currently `document.hasFocus` always returns true on Mac Chromium, so you should use another approach until the bug is fixed – sNiCKY Apr 14 '13 at 14:11
  • this solution works on IE9, FF 28.0 and Chrome 34.x. Previously I tried with window.onfocus and window.onblur. that worked in FF and Chrome but not in IE. – Farish May 09 '14 at 11:24
  • The solution will now work in all browsers, including the latest Opera since they recently converted their rendering engine to Webkit. – Fizzix May 16 '14 at 00:18
  • @sNiCKY It is `document.hasFocus()` to check the visibility state. `document.hasFocus` returns `true` for the property's existence only. – hexalys Jun 20 '14 at 02:29
  • Does this work on mobile browsers? On some devices, some mobile browser window threads and timers are frozen when not active, no? – Domi Mar 09 '15 at 11:39
  • This answer/question is a lot like http://stackoverflow.com/questions/354718/detect-which-form-input-has-focus-using-javascript-or-jquery The accepted answer is a hack whereas the most upvoted answer contains a much simpler answer from the standards. – Ruan Mendes Apr 29 '15 at 18:13
79

I haven't tested this in other browsers, but it seems to work in Webkit. I'll let you try IE. :o)

Try it out: http://jsfiddle.net/ScKbk/

After you click to start the interval, change the focus of the browser window to see the result change. Again, tested only in Webkit.

var window_focus;

$(window).focus(function() {
    window_focus = true;
}).blur(function() {
    window_focus = false;
});

$(document).one('click', function() {
    setInterval(function() {
        $('body').append('has focus? ' + window_focus + '<br>');
    }, 1000);
});​
d-coder
  • 1,180
  • 1
  • 11
  • 17
user113716
  • 318,772
  • 63
  • 451
  • 440
  • @jball - Must be IE? In Webkit and Firefox any activation of the window triggers the focus. I wonder if there's a workaround for IE. Also, did you test on your page? Maybe there an issue because the jsFiddle uses frames? – user113716 Aug 13 '10 at 19:39
  • Chrome actually. After further testing, my first comment might be wrong - the tab key breaking it seems to be more consistent. – jball Aug 13 '10 at 19:40
  • @jball - I'm guessing that the tab key breaks it because jsFiddle has lots of input elements in other frames. Get rid of the frames, and I'll bet it will work a little better for you. – user113716 Aug 13 '10 at 19:42
  • I believe each frame has its own `window` object, so if you were to use frames, you would probably just need to include the script in each one. – user113716 Aug 13 '10 at 19:45
  • 4
    Use `window.top` to check the topmost window. – Mårten Wikström Jun 17 '11 at 15:26
  • This works when returning to the page from doing something in a popup, cheers! – SSH This May 20 '13 at 16:38
  • Is there a way to check the result on page/tab/window load without using click function ? – query Apr 28 '15 at 22:51
3

Simple javascript snippet

Event based:

function focuschange(fclass) {
    var elems=['textOut','textFocus'];
    for (var i=0;i<elems.length;i++) {
        document.getElementById(elems[i]).
            setAttribute('class',fclass);
    }
}
window.addEventListener("blur",function(){focuschange('havnt')});
window.addEventListener("focus",function(){focuschange('have')});
focuschange('havnt');
.have                { background:#CFC; }
#textOut.have:after  { content:'';      }
.havnt               { background:#FCC; }
#textOut.havnt:after { content:' not';  }
<span id='textOut'>Have</span><span id='textFocus'> focus</span>

Interval pool based:

setInterval(function() {
    var fclass='havnt';
    if (document.hasFocus()) {
      fclass='have';
    };
    var elems=['textOut','textFocus'];
    for (var i=0;i<elems.length;i++) {
        document.getElementById(elems[i]).
            setAttribute('class',fclass);
    }
},100);
#textOut.have:after  { content:'';     }
#textOut.havnt:after { content:' not'; }
.have  { background:#CFC; }
.havnt { background:#FCC; }
<span id='textOut'>Have</span><span id='textFocus'> focus</span>
F. Hauri - Give Up GitHub
  • 64,122
  • 17
  • 116
  • 137
  • I like this answer because of the *event based solution*. Imho, it should be the prefered way always. – quasi Sep 12 '20 at 11:56
1

HTML:

<button id="clear">clear log</button>
<div id="event"></div>​

Javascript:

$(function(){

    $hasFocus = false;

    $('#clear').bind('click', function() { $('#event').empty(); });

    $(window)
        .bind('focus', function(ev){
            $hasFocus = true;
            $('#event').append('<div>'+(new Date()).getTime()+' focus</div>');
        })
        .bind('blur', function(ev){
            $hasFocus = false;
            $('#event').append('<div>'+(new Date()).getTime()+' blur</div>');
        })
        .trigger('focus');

    setInterval(function() {
        $('#event').append('<div>'+(new Date()).getTime()+' has focus '+($hasFocus ? 'yes' : 'no')+'</div>');
    }, 1000);
});​

test

UPDATE:

I'll fix it, but IE does not work very well

test update

andres descalzo
  • 14,887
  • 13
  • 64
  • 115