Статьи

Использование API видимости страницы

Несколько недель назад в 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 .