Coding with Jesse

Detecting focus of a browser window

May 16th, 2007

If you have some constantly running Ajax or JavaScript updates on a page, it might be nice to pause these when the browser is minimized or in the background, or when the user switches to another tab. After all, there's no sense in using the user's CPU and network if they aren't even watching what you're doing.

To achieve this, we can use the window.onfocus and window.onblur events like this:

function onBlur() {
	document.body.className = 'blurred';
};
function onFocus(){
	document.body.className = 'focused';
};

if (/*@[email protected]*/false) { // check for Internet Explorer
	document.onfocusin = onFocus;
	document.onfocusout = onBlur;
} else {
	window.onfocus = onFocus;
	window.onblur = onBlur;
}

These events work in every major browser (Firefox, Internet Explorer 6/7, Safari & Opera).

Unfortunately, there's no way to tell with JavaScript if the browser is visible to the user. For example, they might be chatting on IM in a small window in front of the browser. You'll also find that the page is 'blurred' when you click into the location bar of the browser (except in Safari). You might want to display a message like "PAUSED" (think Super Mario Brothers) so people know why everything has stopped moving.

I've set up a demo page where you can try this out.

[Update October 14, 2008 - Seems the blur event handler would fire in Internet Explorer when the focus went from the body to an input or link. I've changed them to use document.onfocusin and document.onfocusout instead, which seems to work better. Now, putting focus from the body into an input causes them both to be fired, but one right after the other (onfocusout, onfocusin) resulting in a final "focused" state.]


Interested in web development? Subscribe to my newsletter!

Comments

1 . Frederico Padilha at 2007-05-16T18:43:55.000Z

Frederico Padilha

Nicee, I guess that pages that use a lot of JS will do the users a great favor in disabling some stuff that keeps taking resources from the computer... But if only programmers where that considerate ahahaha =)!

2 . Georges Jentgen at 2007-05-16T20:25:42.000Z

Georges Jentgen

Never thought about this before, but as I am currently programming a live website analyzer with heavy Ajax-use, this will come in very handy. So I will disable every AJAX-calls when they are not needed. Awesome! Thanks for the tip!

3 . Aaron Bassett at 2007-05-17T10:18:05.000Z

Aaron Bassett

Your post has really got me thinking about how I could use the onblur event to enhance different applications I've been working on....or just how you could annoy your users, window.onblur=window.focus();
I even wrote a quick post about my experiments with this: http://foobr.co.uk/2007/05/annoying_users_with_onblur/

It doesn't just apply to AJAX or Javascript heavy pages either. With externalInterface we could use this technique to interact with Flash. Videos which pause when you switch applications is the first application that comes to mind.

4 . Jesse Skinner at 2007-05-17T10:49:01.000Z

Jesse Skinner

@Aaron - nice idea. Not annoying users, of course, but pausing video. I wonder what else we can do with this...

5 . dandyna at 2007-05-17T11:02:37.000Z

dandyna

nifty tip, Jesse!

6 . Georges Jentgen at 2007-05-17T12:10:41.000Z

Georges Jentgen

Another Idea I just got and what I will implement next into my PHP-Frameowork:

onBlur: graying out the page with some sort of "pause" message. Maybe a sitemap or some ads? :)

7 . Aaron Bassett at 2007-05-17T14:44:33.000Z

Aaron Bassett

@Georges: I don't think it would be viable to put actual content into the onblur'd page because as soon as the user tries to click on say an ad the window will receive focus again and the ad will disapear.

Unless you made the user cancel the onblur'd page through a link or similar rather than just clearing it when the window gains focus. But this I think could become a nuisance (and perhaps confusing).

When I go back to a page I expect to be able to work with it right away. I don't expect to have to tell it that I want it to become active again :)

8 . Mika at 2008-01-10T09:17:20.000Z

Mika

Hey man,

This really doesn't work in Firefox on Mac...it works when you switch between Firefox windows, but not when switching to another application.

/M

9 . Greeny at 2008-01-29T15:06:56.000Z

Greeny

Important point Jesse! Consider global energy savings if all websites would be optimized to use CPU only when focused.

10 . Al at 2008-03-26T15:06:17.000Z

Al

Have you tried to add a textarea to the document and then minimize the window when the textarea is still selected? Works in IE but not in Firefox. I tell this because in the tipical ajax chats, is useful to keep the focus in the textarea all the time, so the user can type another message without having to get the mouse. Problem is that with Firefox the onblur event doesn't happen at all because the browser thinks the focus is still in the textarea. Is there any workaround for this?

11 . vituko at 2008-12-24T12:44:25.000Z

vituko

Very, very important question!!!

It doesnt work at least in firefox when switching tabs...

What about mouseout? It will always be fired... Maybe with a timeout : 5 -10 seconds to avoid perturbing.

mouseout -> background-mode (some processes may continue but not the heaviest : animations,...) and maybe let a "big sticky button" (don't leave foreground-mode), I can have a small window with focus and I'm still seeing my browser behind.
It can be interesting to allow progressives modes or configure witch widgets let running (monitoring widgets,...)

For web applications, it's a kernel question, but... nowadays I have no time... to test.

Good post

Vituko

12 . Stanislav Bozhkov at 2009-04-01T17:12:33.000Z

Stanislav Bozhkov

It was useful 10x.

13 . Manish Dubey at 2009-05-27T14:52:19.000Z

Manish Dubey

It works in firefox if u use document.onfocus and document.onblur instead of windows.onfocus and windows.onblur

but again too work in chrome u need windows.onfocus and windows.onblur

Its working in safari as said but I want a script where I can get the change of tabs too in safari.

Any help plz email at [email protected]

14 . hari at 2009-08-03T07:32:52.000Z

hari

Its simply great idea.

Thanks

15 . karthik at 2009-09-07T09:43:23.000Z

karthik

nice thoughts...

what if the user clicks on the status bar(which many of us habitual of clicking system time, expanding status icons etc...) when browser window continues to show our application running??? wudn't our dependency on focus management cause problem when application is not actually out of focus but just technically??? for ex. we pause video when user watches it but we do pause because we got onblur...

16 . wijey at 2009-11-08T06:41:43.000Z

wijey

big thanks to you bro... This is really helpfull

17 . andy frusciante at 2009-11-15T16:09:27.000Z

andy frusciante

wowww.. this is what i've been searching. there is something 'sucks' bout the IE compatiblity. n i found it now

18 . Juergen Riemer at 2009-11-23T12:49:39.000Z

Juergen Riemer

Hi Jesse,

focus and blur will fire on any such event in the dom (depending on the browser). This means every time you click on a different elements e.g. checkbox in the very same page you'll have a chance to fire a blur/focus sequence.
I would not base any important behaviour on blur/focus events of the window/self object

19 . Jack at 2010-03-23T09:53:57.000Z

Jack

Good stuff! Btw, instead of using that ugly IE detection code, you could consider this instead:

if (!+"\v1") {
// we have IE
}

20 . Jason at 2010-07-17T18:35:35.000Z

Jason

I know this is an old thread, but it's still a good one. I used your onBlur function to create a "screensaver" for when my users have the browser open to my page, but the focus is on another program like Photoshop. Then, I make them click to get out of the screen saver mode so that I can display whatever I want and be guaranteed that they get it.

Thanks for the concise script and explanation.

Jase

21 . Gerrit van Aaken at 2010-08-13T14:39:24.000Z

Gerrit van Aaken

Unfortunately, as Juergen mentioned, all versions of Internet Explorer fire an "out" event, immediately followed by an "in" event, every time you click on any element on the page. So your solution is not for everybody!

22 . arush at 2011-02-23T00:30:45.000Z

arush

Gerrit,
Why does that matter? if you wanted a seamless experience as if the blur/focus glitch never happened, you could just put a rule to say if the blur/focus event (due to clicking on an element) lasted for less than, say 5milliseconds, then act as if it never happened. This can easily be achieved with setTimeout()

23 . Hari at 2011-05-21T04:35:57.000Z

Hari

Hi Jesse,

you have got very nice stuff. Appreciated.
I have a question which is related to browser close event. I have a client who is into portal development and the site has signout option. usually users are not clicking on the signout link instead they are closing the browser directly.with which it is affecting the performance. so the plan is to prompt the user whenever trying to close the browser or using Alt+F4.(but not on everytime page load). so i have a working script which does everything what i need and mentioned above, but it is working only in IE6. we do have requirement for IE7/8/9. so what i noticed is IE7/8/9 is not supporting the window.event.ClientX<0 && window.event.clientY<0 which helps me in firing the onbeforeunload and onunlod upon refresh.

Please help me out if you have an alternate soln or a workaround for this.

24 . Jesse Skinner at 2011-05-21T04:41:39.000Z

Jesse Skinner

@Hari - Are you doing something with the clientX and clientY mouse coordinates? The onbeforeunload event is often triggered without a mouse, eg. clicking the back button or a keyboard shortcut. If possible, I'd suggest finding a way to handle the event without those properties.

25 . Jesse Skinner at 2011-05-21T04:44:55.000Z

Jesse Skinner

@Hari - I'd also suggest addressing the session problem directly if you can, rather than bother your users. Perhaps have a 20 minute timeout and delete old sessions automatically?

26 . Revolt at 2011-06-15T12:30:39.000Z

Revolt

Great script but it doesn't detects if the window is blured before loading the page
For example, open a window and resize it so you can see your browser in the background and refresh your "demo page" and quickly before it finishes loading switch to the resized window and you'll see that the "demo page" considers it focused.

27 . David at 2011-08-12T15:04:06.000Z

David

This is great. In cases where your markup/JS is added to a host page that you don't have direct control over, you may want to honor any onblur/focus callbacks that exist for that page:

var oldOnFocus = window.onfocus && typeof window.onfocus === 'function' ? window.onfocus : function () {};
window.onfocus = function () { oldOnFocus(); onFocus(); };

28 . Daniyalzade at 2011-08-30T18:42:20.000Z

Daniyalzade

You might want to modify the name of the tab onfocus/blur so that with tabs it is still possible to see the effect. In my local copy I modified the script as follows:

[[
function onBlur() {
document.body.className = 'blurred';
document.title = 'blurred';
};
function onFocus(){
document.body.className = 'focused';
document.title = 'focused';
};
]]

29 . Gerrit van Aaken at 2011-09-19T09:47:26.000Z

Gerrit van Aaken

@arush:

Now I’ve got something like this:

if ($.browser.msie) {
document.onfocusin = onFocusCheck;
document.onfocusout = onBlurCheck;
} else {
window.onfocus = onFocus;
window.onblur = onBlur;
}


function onBlur() {
}

function onFocus(){
}

function onFocusCheck() {
var now = new Date();
lastIn = now.getTime();
if ((lastIn - lastOut) > 100) {
onFocus();
}
}

function onBlurCheck() {
var now = new Date();
lastOut = now.getTime();
if (!timeTaking) {
timeTaking = true;
setTimeout(onBlurCheckAgain, 100);
}
}

function onBlurCheckAgain() {
var now = new Date();
rightnow = now.getTime();
if ((rightnow - lastIn) > 1200) { onBlur(); }
timeTaking = false;
}

30 . Azaz at 2011-12-29T06:37:50.000Z

Azaz

Nice Post Mate, Is there any way we can prevent blur event on location bar or search bar? I am writing a firefox extension and having this issue cant figure out any way to prevetn location bar or event search bar. Any help will be appriciated.

31 . vishesh at 2012-04-24T09:00:35.000Z

vishesh

waste everything

32 . Eric Mesquita at 2013-02-27T13:58:06.000Z

Eric Mesquita

Very nice, but did you notice that onBlur and onFocus are executed twice? Try this:
function onBlur() {
document.body.className = 'blurred';
console.log('onBlur');
};
function onFocus(){
document.body.className = 'focused';
console.log('onFocus');
};
I try figure it out but i had no success.