В браузерах всегда не хватало какого-нибудь индикатора того, находится ли страница в активном табе.
Вот несколько примеров того, как это можно использовать:
- У вас на сайте есть видео и вы хотите поставить его на паузу, пока пользователь сделал неактивным таб с вашей страницей.
- Другой типовой пример: изменить title и favicon страницы, когда она скрыта.
- Или, например, оповестить пользователя о новых комментариях или других событиях, если ваш сайт находится в неактивном табе (так делают многие соц. сети)
Начнем с демо, а потом посмотрим, зачем это нужно и как это работает.
Запустите видео и перейдите на соседнюю вкладку браузера. Видео должно остановиться (если у Вас поддерживается visibilityChange)
visibilitychange С недавнего времени в новых (нормальных) браузерах появилось
Page Visibility API
. Давайте посмотрим, как это работает. В целом, все просто:
JS
document.addEventListener('visibilitychange', function(e) {
console.log('hidden:' + document.hidden,
'state:' + document.visibilityState)
}, false);
document.visibilityState — может быть "visible"
, "hidden"
или "prerender"
. C visible и hidden все понятно. prerender — значит, что содержимое страницы в настоящее время находится в состоянии отрисовки. Документ может инициализироваться в этом состоянии, но никогда не сможет перейти к состоянию «prerender» от другого значения. Производители браузеров не исключают добавления новых значений document.visibilityState в будущем.
document.hidden — true
или false
соответственно.
Не все так безоблачно. Т.к. API и стандарт сырые, вот с чем приходится сталкиваться сегодня (2013):
- событие visibilitychange, в зависимости от браузера, называется
"visibilitychange"
,"mozvisibilitychange"
,"msvisibilitychange"
,"webkitvisibilitychange"
. - поле document.visibilityState, в зависимости от браузера, называется
"visibilityState"
,"mozVisibilityState"
,"msVisibilityState"
,"webkitVisibilityState"
. - поле document.hidden, в зависимости от браузера, называется
"hidden"
,"mozHidden"
,"msHidden"
,"webkitHidden"
. Кошмар… Дорогой друг, если ты читаешь эту статью и используешь visibilitychange api этак в 2015-ом году, можешь пропустить весь последующий говнокод. А пока, в связи с этим переходным периодом пока надо писать что-то типа:
JS
var hidden, state, visibilityChange;
if (typeof document.hidden !== "undefined") {
hidden = "hidden";
visibilityChange = "visibilitychange";
state = "visibilityState";
} else if (typeof document.mozHidden !== "undefined") {
hidden = "mozHidden";
visibilityChange = "mozvisibilitychange";
state = "mozVisibilityState";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
state = "msVisibilityState";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
state = "webkitVisibilityState";
}
// Add a listener that constantly changes the title
document.addEventListener(visibilityChange, function() {
console.log('state = ' + document[state], 'hidden = ' + document[hidden]);
}, false);
А вот и код демки в начале статьи
HTML
<div>
<video id="videoElement" controls width="400" height="300">
<source src="/blogdemo/video/chrome.webm" type="video/webm" />
<source src="/blogdemo/video/chrome.ogv" type="video/ogg" />
<source src="/blogdemo/video/chrome.mp4" type="video/mp4; codecs='avc1.42E01E, mp4a.40.2'" />
</video>
</div>
JS
// видео изначально стоит на паузе (true в ковычках потому-что это sessionStorage)
sessionStorage.isPaused = "true";
// зададим тестовые переменные для hidden property и события visibility change
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") {
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.mozHidden !== "undefined") {
hidden = "mozHidden";
visibilityChange = "mozvisibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
var videoElement = document.getElementById("videoElement");
// если страница скрыта - поставить видео на паузу
// если страница активна - продолжить воспроизведение
function handleVisibilityChange() {
if (document[hidden]) {
videoElement.pause();
} else if (sessionStorage.isPaused !== "true") {
videoElement.play();
}
}
// предупредить, если браузер не поддерживает addEventListener или Page Visibility API
if (typeof document.addEventListener === "undefined" || typeof hidden === "undefined") {
alert("Демо требует нормального браузера с поддержкой Page Visibility API.");
} else {
// обработка visibilityChange
document.addEventListener(visibilityChange, handleVisibilityChange, false);
videoElement.addEventListener("pause", function () {
if (!document[hidden]) {
sessionStorage.isPaused = "true";
}
}, false);
videoElement.addEventListener("play", function () {
sessionStorage.isPaused = "false";
}, false);
// установить title страницы
videoElement.addEventListener("timeupdate", function () {
document.title = Math.floor(videoElement.currentTime) + " сек";
}, false);
}
IE к версии 15 обещают саппорт?
В 10-м все будет
http://caniuse.com/#search=pagevisibility
10 что-ли в полном фарше будет? Как то не по миксофтски это
походу так, .. но, статистика ослика за все время его существования не оставляет надежд на то, что все будет ровно и красиво :(
Кстати, если не включать видео и переключится на таб видео включится)
:P
Спасибо за информацию и пример.
Только в вашем примере, если не запускать видео, а после загрузки страницы, переключиться на другую вкладку и вернуться, то видео автоматически запустится. :)
Мелочи, но все-таки маленький недочет для завершенного модуля.
решал подобную задачу, используя события onfocus и onblur