Несколько недель назад в MAX я имел удовольствие выступить с половиной презентации с Грегом Уилсоном на тему «Передовой HTML». Одним из API, который я продемонстрировал аудитории, был API Page Visibility . Как вы, вероятно, догадываетесь, это базовый API, позволяющий узнать, видна ли ваша страница конечному пользователю. У него пока нет полной поддержки, но это (еще раз) еще один отличный пример того, что вы можете добавить в свой код с относительной легкостью, чтобы улучшить работу ваших конечных пользователей.
Так насколько хорошо это поддерживается? Внедрение ниже взято из превосходного CanIUse и будет актуальным независимо от того, когда вы читаете эту запись в блоге:
Я думаю, что вы могли бы обобщить это как «хорошая поддержка рабочего стола, плохой мобильный». При этом API прост в использовании и не наносит никакого вреда вашему коду, если его не поддерживает конечный пользователь. Давайте рассмотрим простой пример.
В приведенном ниже сценарии у меня есть вызов AJAX, который запускается каждые (приблизительно) 2 секунды для получения новостной ленты с сервера.
<!DOCTYPE html>
<html>
<body>
<div id="newswell"></div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
var newsDiv;
function getData() {
$.ajax({url:"news.json"}).done(function(data) {
newsDiv.innerHTML += "<p><b>Posted at " + new Date() + "<br/>" + data.message;
//call it again in 2 seconds
window.setTimeout(getData, 2000);
}).fail(function(xhr,status,e) {
console.dir(e);
});
}
$(document).ready(function() {
newsDiv = document.querySelector("#newswell");
getData();
});
</script>
</body>
</html>
Я предполагаю, что приведенный выше код достаточно тривиален, чтобы не нуждаться в каких-либо объяснениях, но если я ошибаюсь, просто дайте мне знать в комментариях. Теперь давайте посмотрим на обновленную версию с использованием API.
<!DOCTYPE html>
<html>
<body>
<div id="newswell"></div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
var newsDiv;
var active = true;
function isVisible() {
if("webkitHidden" in document) return !document.webkitHidden;
if("mozHidden" in document) return !document.mozHidden;
if("hidden" in document) return !document.hidden;
//worse case, just return true
return true;
}
function getData() {
$.ajax({url:"news.json"}).done(function(data) {
newsDiv.innerHTML += "<p><b>Posted at " + new Date() + "<br/>" + data.message;
//call it again in 2 seconds
if(isVisible()) window.setTimeout(getData, 2000);
else active = false;
}).fail(function(xhr,status,e) {
console.dir(e);
});
}
$(document).ready(function() {
newsDiv = document.querySelector("#newswell");
$(document).bind("visibilitychange webkitvisibilitychange mozvisibilitychange",function(e) {
console.log("VS CHANGE");
console.log(isVisible());
if(isVisible() && !active) {
active = true;
getData();
}
});
getData();
});
</script>
</body>
</html>
Давайте решать это по крупицам. Во-первых, обратите внимание на использование обработчика событий в блоке document.ready. События Page Visibility по-прежнему имеют префикс, поэтому я встроил поддержку для версий без префиксов, Chrome и Mozilla. (Помните, что IE поддерживает это, так что теоретически я мог бы добавить префикс IE также, если это необходимо. Мне бы очень хотелось, чтобы кто-нибудь мог проверить, есть ли у IE этот префикс или нет.)
Говоря о префиксах, я построил функцию isVisible, которая оборачивает чеки в свойство document.hidden. Это основной способ определить, видим ли наш документ.
Как насчет активной переменной? Поскольку мы имеем дело с вызовами AJAX и асинхронным дерьмом, у нас сложная ситуация. Мы можем или не можем, чтобы текущий вызов AJAX срабатывал при изменении видимости. Если мы перешли от скрытого к видимому, но у нас уже был AJAX-вызов, мы не хотим его запускать сейчас. Если у нас есть один активный, обработчик обратного вызова будет обрабатывать планирование следующего вызова. Таким образом мы гарантируем, что мы не удвоим наши AJAX-вызовы и не забудем начать процесс заново.
Обязательно проверьте спецификацию, на которую я ссылался выше. У них также есть интересное демо. Вместо того чтобы останавливать свои AJAX-вызовы, они просто замедляют их. Я вижу, как оба способа справляются с этим эффективно.
Вы можете продемонстрировать это здесь: http://raymondcamden.com/demos/2013/may/28/crap.html . Если вы хотите, вы также можете демо-версию предварительной версии страницы здесь: http://raymondcamden.com/demos/2013/may/28/pre_crap.html
Простите за имена файлов. Я не уверен, что я думал там.
У этого API есть только один реальный недостаток. Согласно спецификации, браузер должен сообщать как скрытый, когда свернут. В моем тестировании это не было правдой. На самом деле, он не будет отображаться как скрытый, если вы поместите другое приложение впереди. Он сообщил только скрытый, когда я переключился на другую вкладку. Опять же, я считаю, что это лучше, чем ничего, и дополнительный код (10 строк?) Достаточно тривиален, чтобы он стоил вашего времени. EDIT: FYI, Firefox делает обратите внимание, когда вы сворачиваете приложение. Путь, Firefox.
Позже сегодня (скорее всего, сегодня вечером у меня большая презентация), я собираюсь показать еще один пример этого с использованием Edge Animate .