Есть 3 типичных метода, используемых, чтобы определить, может ли пользователь видеть страницу HTML, однако ни один из них не работает идеально:
W3C Page Visibility API должен делать это (поддерживается начиная с: Firefox 10, MSIE 10, Chrome 13). Однако этот API вызывает события только тогда, когда вкладка браузера полностью переопределена (например, когда пользователь переключается с одной вкладки на другую). API не вызывает события, когда видимость не может быть определена со 100% точностью (например, Alt + Tab для переключения на другое приложение).
Использование методов фокусировки / размытия дает много ложных срабатываний. Например, если пользователь отображает меньшее окно в верхней части окна браузера, окно браузера теряет фокус ( onblur
поднятый), но пользователь все еще может его видеть (поэтому его все равно необходимо обновить). Смотрите также http://javascript.info/tutorial/focus
- Полагаясь на активность пользователя (движение мыши, щелчки, ввод ключа), вы также получаете много ложных срабатываний. Подумайте о том же случае, что и выше, или о пользователе, просматривающем видео.
Чтобы улучшить несовершенное поведение, описанное выше, я использую комбинацию из 3 методов: W3C Visibility API, затем методы фокусировки / размытия и пользовательской активности, чтобы уменьшить вероятность ложных срабатываний. Это позволяет управлять следующими событиями:
- Замена вкладки браузера на другую (точность 100%, благодаря API видимости страницы W3C)
- Страница потенциально скрыта другим окном, например, из-за Alt + Tab (вероятностный = не на 100% точный)
- Внимание пользователя потенциально не сфокусировано на HTML-странице (вероятностный = не точный на 100%)
Вот как это работает: когда документ теряет фокус, пользовательская активность (например, перемещение мыши) в документе отслеживается, чтобы определить, является ли окно видимым или нет. Вероятность видимости страницы обратно пропорциональна времени последнего пользовательского действия на странице: если пользователь долгое время не выполняет никаких действий с документом, скорее всего, страница не видна. Приведенный ниже код имитирует API видимости страницы W3C: он ведет себя так же, но имеет небольшой процент ложных срабатываний. Он имеет преимущество быть мультибраузером (протестировано на Firefox 5, Firefox 10, MSIE 9, MSIE 7, Safari 5, Chrome 9).
<div id = "x"> </ div>
<Скрипт>
/ **
Регистрирует обработчик для события для данного объекта.
@param obj объект, который будет вызывать событие
@param evType тип события: щелчок, нажатие клавиши, наведение мыши, ...
@param fn функция обработчика событий
@param isCapturing установить режим события (true = событие захвата, false = событие всплытия)
@return true, если обработчик событий был правильно подключен
* /
function addEvent (obj, evType, fn, isCapturing) {
if (isCapturing == null) isCapturing = false;
if (obj.addEventListener) {
// Fire Fox
obj.addEventListener (evType, fn, isCapturing);
вернуть истину;
} else if (obj.attachEvent) {
// MSIE
var r = obj.attachEvent ('on' + evType, fn);
возврат г;
} еще {
вернуть ложь;
}
}
// зарегистрироваться на потенциальное изменение видимости страницы
addEvent (документ, "потенциальная возможность изменения", функция (событие) {
document.getElementById ("x"). innerHTML + = "потенциалVisilityChange: потенциалHidden =" + document.potentialHidden + ", document.potentiallyHiddenSince =" + document.potentiallyHiddenSince + "s <br>";
});
// зарегистрироваться в API видимости страницы W3C
var hidden = null;
var visibilityChange = null;
if (typeof document.mozHidden! == "undefined") {
скрытый = "mozHidden";
visibilityChange = "mozvisibilitychange";
} else if (typeof document.msHidden! == "undefined") {
скрытый = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden! == "undefined") {
скрытый = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
} else if (typeof document.hidden! == "hidden") {
скрытый = «скрытый»;
visibilityChange = "visibilitychange";
}
if (hidden! = null && visibilityChange! = null) {
addEvent (document, visibilityChange, function (event) {
document.getElementById ("x"). innerHTML + = visibilityChange + ":" + hidden + "=" + document [hidden] + "<br>";
});
}
var потенциальноPageVisibility = {
pageVisibilityChangeThreshold: 3 * 3600, // в секундах
init: function () {
function setAsNotHidden () {
var dispatchEventRequired = document.potentialHidden;
document.potentialHidden = FALSE;
document.potentiallyHiddenSince = 0;
if (dispatchEventRequired) dispatchPageVisibilityChangeEvent ();
}
function initPotentiallyHiddenDetection () {
if (! hasFocusLocal) {
// окно не имеет фокуса => проверка активности пользователя в окне
lastActionDate = new Date ();
if (timeoutHandler! = null) {
clearTimeout (timeoutHandler);
}
timeoutHandler = setTimeout (checkPageVisibility, потенциальноPageVisibility.pageVisibilityChangeThreshold * 1000 + 100); // +100 мс, чтобы избежать проблем с округлением в Firefox
}
}
function dispatchPageVisibilityChangeEvent () {
unifiedVisilityChangeEventDispatchAllowed = FALSE;
var evt = document.createEvent ("Event");
evt.initEvent («потенциальная возможность изменения», правда, правда);
document.dispatchEvent (EVT);
}
function checkPageVisibility () {
var потенциальноHiddenDuration = (hasFocusLocal || lastActionDate == null? 0: Math.floor ((new Date (). getTime () - lastActionDate.getTime ()) / 1000));
document.potentiallyHiddenSince = potentialHiddenDuration;
if (потенциалHiddenDuration> = потенциалPageVisibility.pageVisibilityChangeThreshold &&! document.potentialHidden) {
// порог изменения видимости страницы raiched => повысить четность
document.potentialHidden = TRUE;
dispatchPageVisibilityChangeEvent ();
}
}
var lastActionDate = null;
var hasFocusLocal = true;
var hasMouseOver = true;
document.potentialHidden = FALSE;
document.potentiallyHiddenSince = 0;
var timeoutHandler = null;
addEvent (document, "pageshow", function (event) {
document.getElementById ( "х") innerHTML + = "pageshow / док: <br>".
});
addEvent (document, "pagehide", function (event) {
document.getElementById ( "х") innerHTML + = "pagehide / док: <br>".
});
addEvent (окно, "pagehow", функция (событие) {
document.getElementById ( "х") innerHTML + = "pageshow / выиграть: <br>". // поднял, когда страница впервые показывает
});
addEvent (окно, "pagehide", функция (событие) {
document.getElementById ( "х") innerHTML + = "pagehide / выиграть: <br>". // не поднят
});
addEvent (document, "mousemove", function (event) {
lastActionDate = new Date ();
});
addEvent (document, "mouseover", function (event) {
hasMouseOver = TRUE;
setAsNotHidden ();
});
addEvent (document, "mouseout", function (event) {
hasMouseOver = FALSE;
initPotentiallyHiddenDetection ();
});
addEvent (окно, «размытие», функция (событие) {
hasFocusLocal = FALSE;
initPotentiallyHiddenDetection ();
});
addEvent (окно, «фокус», функция (событие) {
hasFocusLocal = TRUE;
setAsNotHidden ();
});
setAsNotHidden ();
}
}
potentialPageVisibility.pageVisibilityChangeThreshold = 4; // 4 секунды для тестирования
potentialPageVisibility.init ();
</ Скрипт>
Поскольку в настоящее время не существует работающего кросс-браузерного решения без ложных срабатываний, вам следует подумать дважды об отключении периодической активности на вашем веб-сайте.
requestAnimationFrame
API или используйте современную функцию, которая уменьшает частотуsetTimeout
/,setInterval
когда окно не видно (например, 1 секунда в Chrome).