Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
72
rated 0 times [  79] [ 7]  / answers: 1 / hits: 48252  / 9 Years ago, wed, march 11, 2015, 12:00:00

The problem is with the behaviour of the event visibilitychange.



It's triggered:
- When I switch to a different tab inside the browser window.




  • When I click in minimize / restore buttons for the browser window.



(this is ok)



It's not triggered:
- When I switch to a different window/program using ALT+TAB.




  • When I switch to a different window/program clicking on taskbar.



(this SHOULD trigger, because, just like when minimizing, the window's visibility may change)






W3 Page Visibility API Documentation: http://www.w3.org/TR/page-visibility/



There is no definition of page visibility regarding ALT+TAB/program switching in the spec sheet. I'm guessing it has something to do in between the OS and the Browser.






TESTED IN




  • Browsers:
    Chrome 40.0.2214.115 m / Firefox 36.0.1 / Internet Explorer 11.0.9600.17107

  • OS: Windows 8.1






Is there a workaround to fix this behaviour? The implementation is fairly simple, I listen to the visibilitychange event using jQuery, and then in its callback, I check for the value of document.visibilityState, but the problem is that the event is not firing when expected.



$(document).on('visibilitychange', function() {

if(document.visibilityState == 'hidden') {
// page is hidden
} else {
// page is visible
}
});


This can be done without jQuery too, but the ALT+TAB and taskbar switch hide/show expected behaviour is still missing:



if(document.addEventListener){
document.addEventListener(visibilitychange, function() {
// check for page visibility
});
}


I've also tried the ifvisible.js module (https://github.com/serkanyersen/ifvisible.js) but the behaviour is the same.



ifvisible.on('blur', function() {
// page is hidden
});

ifvisible.on('focus', function() {
// page is visible
});


I haven't tested in other browsers because if I can't make it work in Chrome on Windows I really don't care about the other browsers yet.



Any help or suggestions?






UPDATE



I tried using different vendor prefixes for the event name (visibilitychange, webkitvisibilitychange, mozvisibilitychange, msvisibilitychange) but but still the event is not triggered when I switch to a different program in the taskbar or ALT+TAB, or even if I open the start menu thing in windows with the windows key, which covers the whole screen.



I can reproduce the exact same issue in Chrome, Firefox and Internet Explorer.



UPDATE #2



Here's a roundup post I wrote for this issue and a workaround in pure Javascript to solve the encountered problems.



UPDATE #3



Edited to include a copy of the sourced blog post. (see accepted answer)


More From » html

 Answers
11

Here's a roundup post I wrote for this issue and a workaround in pure JavaScript to solve the encountered problems.


Edited to include a copy of the sourced blog post:





In any kind of javascript application we develop there may be a
feature or any change in the application which reacts according to the
current user visibility state, this could be to pause a playing video
when the user ALT+TABs to a different window, tracking stats about how
the users interact with our application, how often does him switch to
a different tab, how long does it take him to return and a lot of
performance improvements that can benefit from this kind of API.


The Page Visibility API provides us with two top-level attributes:
document.hidden (boolean) and document.visibilityState (which could be
any of these strings: “hidden”, “visible”, “prerender”, “unloaded”).
This would not be not good enough without an event we could listen to
though, that’s why the API also provides the useful visibilitychange
event.


So, here’s a basic example on how we could take action on a visibility
change:


function handleVisibilityChange() {
if(document.hidden) {
// the page is hidden
} else {
// the page is visible
}
}

document.addEventListener("visibilitychange", handleVisibilityChange, false);

We could also check for document.visibilityState value.


Dealing with vendor issues George Berkeley by John Smibert


Some of the implementations on some browsers still need that the
attributes or even the event name is vendor-prefixed, this means we
may need to listen to the msvisibilitychange event or check for the
document.webkitHidden or the document.mozHidden attributes. In order
to do so, we should check if any vendor-prefixed attribute is set, and
once we know which one is the one used in the current browser (only if
there’s the need for a prefix), we can name the event and attributes
properly.


Here’s an example approach on how to handle these prefixes:


var browserPrefixes = ['moz', 'ms', 'o', 'webkit'];

// get the correct attribute name
function getHiddenPropertyName(prefix) {
return (prefix ? prefix + 'Hidden' : 'hidden');
}

// get the correct event name
function getVisibilityEvent(prefix) {
return (prefix ? prefix : '') + 'visibilitychange';
}

// get current browser vendor prefix
function getBrowserPrefix() {
for (var i = 0; i < browserPrefixes.length; i++) {
if(getHiddenPropertyName(browserPrefixes[i]) in document) {
// return vendor prefix
return browserPrefixes[i];
}
}

// no vendor prefix needed
return null;
}

// bind and handle events
var browserPrefix = getBrowserPrefix();

function handleVisibilityChange() {
if(document[getHiddenPropertyName(browserPrefix )]) {
// the page is hidden
console.log('hidden');
} else {
// the page is visible
console.log('visible');
}
}

document.addEventListener(getVisibilityEvent(browserPrefix), handleVisibilityChange, false);

Other issues There is a challenging issue around the “Page Visibility”
definition: how to determine if the application is visible or not if
the window focus is lost for another window, but not the actual
visibility on the screen? what about different kinds of visibility
lost, like ALT+TAB, WIN/MAC key (start menu / dash), taskbar/dock
actions, WIN+L (lock screen), window minimize, window close, tab
switching. What about the behaviour on mobile devices?


There’s lots of ways in which we may lose or gain visibility and a lot
of possible interactions between the browser and the OS, therefore I
don’t think there’s a proper and complete “visible page” definition in
the W3C spec. This is the definition we get for the document.hidden
attribute:


HIDDEN ATTRIBUTE On getting, the hidden attribute MUST return true if
the Document contained by the top level browsing context (root window
in the browser’s viewport) [HTML5] is not visible at all. The
attribute MUST return false if the Document contained by the top level
browsing context is at least partially visible on at least one screen.


If the defaultView of the Document is null, on getting, the hidden
attribute MUST return true.


To accommodate accessibility tools that are typically full screen but
still show a view of the page, when applicable, this attribute MAY
return false when the User Agent is not minimized but is fully
obscured by other applications.


I’ve found several inconsistencies on when the event is actually
fired, for example (Chrome 41.0.2272.101 m, on Windows 8.1) the event
is not fired when I ALT+TAB to a different window/program nor when I
ALT+TAB again to return, but it IS fired if I CTRL+TAB and then
CTRL+SHIFT+TAB to switch between browser tabs. It’s also fired when I
click on the minimize button, but it’s not fired if the window is not
maximized and I click my editor window which is behing the browser
window. So the behaviour of this API and it’s different
implementations are still obscure.


A workaround for this, is to compensate taking advantage of the better
implemented focus and blur events, and making a custom approach to the
whole “Page Visibility” issue using an internal flag to prevent
multiple executions, this is what I’ve come up with:


var browserPrefixes = ['moz', 'ms', 'o', 'webkit'],
isVisible = true; // internal flag, defaults to true

// get the correct attribute name
function getHiddenPropertyName(prefix) {
return (prefix ? prefix + 'Hidden' : 'hidden');
}

// get the correct event name
function getVisibilityEvent(prefix) {
return (prefix ? prefix : '') + 'visibilitychange';
}

// get current browser vendor prefix
function getBrowserPrefix() {
for (var i = 0; i < browserPrefixes.length; i++) {
if(getHiddenPropertyName(browserPrefixes[i]) in document) {
// return vendor prefix
return browserPrefixes[i];
}
}

// no vendor prefix needed
return null;
}

// bind and handle events
var browserPrefix = getBrowserPrefix(),
hiddenPropertyName = getHiddenPropertyName(browserPrefix),
visibilityEventName = getVisibilityEvent(browserPrefix);

function onVisible() {
// prevent double execution
if(isVisible) {
return;
}

// change flag value
isVisible = true;
console.log('visible');
}

function onHidden() {
// prevent double execution
if(!isVisible) {
return;
}

// change flag value
isVisible = false;
console.log('hidden');
}

function handleVisibilityChange(forcedFlag) {
// forcedFlag is a boolean when this event handler is triggered by a
// focus or blur eventotherwise it's an Event object
if(typeof forcedFlag === "boolean") {
if(forcedFlag) {
return onVisible();
}

return onHidden();
}

if(document[hiddenPropertyName]) {
return onHidden();
}

return onVisible();
}

document.addEventListener(visibilityEventName, handleVisibilityChange, false);

// extra event listeners for better behaviour
document.addEventListener('focus', function() {
handleVisibilityChange(true);
}, false);

document.addEventListener('blur', function() {
handleVisibilityChange(false);
}, false);

window.addEventListener('focus', function() {
handleVisibilityChange(true);
}, false);

window.addEventListener('blur', function() {
handleVisibilityChange(false);
}, false);

I welcome any feedback on this workaround. Some other great sources
for ideas on this subject:


Using the Page Visibility API Using PC Hardware more efficiently in
HTML5: New Web Performance APIs, Part 2 Introduction to the Page
Visibility API Conclusion The technologies of the web are continuously
evolving, we’re still recovering from a dark past where tables where
the markup king, where semantics didn’t mattered, and they weren’t any
standards around how a browser should render a page.


It’s important we push these new standards forward, but sometimes our
development requirements make us still need to adapt to these kind of
transitions, by handling vendor prefixes, testing in different
browsers and differents OSs or depend on third-party tools to properly
identify this differences.


We can only hope for a future where the W3C specifications are
strictly revised, strictly implemented by the browser developer teams,
and maybe one day we will have a common standard for all of us to work
with.


As for the Page Visibility API let’s just kinda cite George Berkeley
and say that:


“being visible” is being perceived.



[#67475] Tuesday, March 10, 2015, 9 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
isaacvalentinn

Total Points: 325
Total Questions: 120
Total Answers: 131

Location: North Korea
Member since Tue, Jun 16, 2020
4 Years ago
isaacvalentinn questions
Mon, Jan 18, 21, 00:00, 3 Years ago
Mon, Nov 23, 20, 00:00, 4 Years ago
Wed, Sep 23, 20, 00:00, 4 Years ago
;