JavaScript виджет: бесконечная загрузка твитов

Владимир | | CSS, HTML, JavaScript, Web разработка.

load on scroll

В последнее время я часто замечаю на различных сайтах виджеты, которые подгружают контент при определённых действиях посетителя. Такой подход позволяет с одной стороны, сократить количество данных на странице, а с другой – при необходимости показывать практически неограниченный объем информации.

Рассмотрим небольшой практический пример.

Допустим, мы хотим показать в сайдбаре виджет с твитами из какой-нибудь ленты (естественно, существует множество готовых решений, но сейчас не о них речь, кроме того, данное решение можно использовать для загрузки любого контента).

На первый взгляд всё предельно просто, twitter предоставляет API, с помощью которого можно получить твиты любого пользователя (если они открыты). Вставить их сайдбар тоже не проблема.

Но на практике возникает несколько интересных моментов.

1) Информация от twitter не является основным контентом сайта и не должна влиять на скорость загрузки страницы. Кроме того, доступность сервиса также не должна влиять на работу сайта.

2) Твиты могут появляться довольно быстро, поэтому чтобы информация в виджете была всегда актуальной от кеширования придётся отказаться.

3) Т.к. твиты не являются основным содержимым страницы, то посетитель скорее всего не заметит если они появятся через некоторое время после загрузки основной части страницы.

4) Не ясно, сколько именно твитов нужно выводить. Части посетителей эта информация будет не интересна вообще, но пользователи этого сервиса, возможно, захотят прочитать несколько десятков сообщений.

5) Количество места, выделенного под виджет, обычно ограничено. И необходимо чтобы загрузка новых твитов не «ломала» дизайн.

Таким образом, нам нужно загружать твиты после загрузки страницы и желательно, чтобы от посетителя требовался минимум действий для загрузки новых твитов.

Теперь рассмотрим сам виджет.

Начнём с алгоритма.

1) Создаём на странице область с фиксированной высотой и вертикальным полосой прокрутки.

2) После загрузки страницы подгружаем в эту область твиты с помощью JavaScript.

3) Если пользователь переместит ползунок скролла в крайнее нижнее положение – загружаем следующую «порцию» твитов.

Посмотреть как работает такой виджет можно на демонстрационной страничке. И сразу же даю ссылку на архив с этим примером.

Source

Разметка виджета с твитами может выглядеть следующим образом.

<div id="tweets">
    <div class="loader hidden"></div>
</div>

Как видите, после первоначальной загрузки внутри виджета будет находится только один элемент – картинка с изображением загрузчика. Стили для неё мы установим таким образом, чтобы она всегда находилась в центре виджета.

.loader {
    background-image: url('ajax-loader.gif');
    width: 400px;
    height: 300px;
    background-repeat: no-repeat;
    background-position: center center;
    position: fixed;
}

Значения width и height должны совпадать с соответствующими значениями, установленными для виджета (div#tweets).

#tweets {
    height: 300px;
    width: 400px;
    overflow: auto;
    position: relative;
    border: solid 1px #999;
    margin: 3em auto 0 auto;
}

Переходим к загрузке твитов

Основная сложность заключается в том, что нам нужно с помощью JavaScript выполнить кросс-доменный запрос к серверу twitter’а. Такие запросы запрещены политикой безопасности браузеров, поэтому использовать обычный AJAX запрос не получится.

Тем не менее, благодаря тому, что Twitter API поддерживает JSONP задача решается достаточно просто.

$(function() {
    //параметры для получения твитов
    var user_id = '24147920';
    var tweets_url = 'http://api.twitter.com/1/statuses/user_timeline.json';
    var page = 1;
    var tweets_num = 10;
    
    //список твитов и картинка загрузчика
    var container = $('#tweets');
    var loader = $('.loader');
    
    //шаблон для поиска ссылок в твитах (упрощенный)
    var pattern = /(http\S+)/gi;
    
    //загружаем первую страницу твитов
    get_tweets(page);
    
    //обработчик события scroll
    container.scroll(function() {
        //это условие выполняется когда ползунок находится в крайнем нижнем положении
        if  (container[0].scrollTop == container[0].scrollHeight - container[0].clientHeight){
            //показываем загрузчик
            loader.removeClass('hidden');
            //загружаем очередную страницу твитов
            page = page + 1;
            get_tweets(page);
        }
    });
    
    //эта функция загружает твиты, ищет ссылки и ставит для них
    //соответствующий тег <a href="...">, вставляет твиты в список
    function get_tweets(page) {
        $.getJSON(
            //формируем запрос на получение твитов (используется JSONP)
            tweets_url + '?user_id=' + user_id + '&page=' + page + '&count=' + tweets_num + '&callback=?',
            function(data) {
                $(data).each(function(i, tweet) {
                    //формируем ссылки
                    var text = tweet.text.replace(pattern, '<a href="$1" target="_blank">$1</a>');
                    //вставляем твит в список
                    container.append('<div class="tweet">' + text + '</div>');
                });
                //прячем загрузчик
                loader.addClass('hidden');
            }
        );
    }
});

Прежде всего, мы подготавливаем данные, которые нужны для работы с Twitter API (строки 3-6). Для данного примера я использовал свою собственную ленту твитов, но вы можете вывести любую другую. Также не принципиально сколько твитов загружать за раз, главное, чтобы после первоначальной загрузки появилась полоса прокрутки.

Для получения твитов используем метод getJSON (строки 33-46, библиотека jQuery).

В первом её параметре передаём запрос на получение твитов. В него мы включаем:
— id пользователя ('?user_id=' + user_id);
— номер страницы ('&page=' + page);
— количество твитов на странице ('&count=' + tweets_num);
— имя функции, которая будет вызвана после получения данных ('&callback=?') – его jQuery формирует автоматически и подставляет вместо знака вопроса.

После получения твитов нам остается только добавить их в список (строки 36-42). При этом, мы ищем ссылки в тексте твитов и обрамляем их тегом <a>.

Завершающий этап – установка обработчика для события scroll (строки 19-28).

Здесь нужно только проверить достигнут конец списка или нет. Если достигнут, показываем загрузчик (убираем класс hidden) и вызываем функцию get_tweets, которой передаём номер нужно страницы. В противном случае, не делаем ничего.

Всё. Можно считать, что виджет в рабочем состоянии. Конечно, перед размещением на рабочем сайте нужно будет его немного доработать, например, добавить вывод сообщение об ошибке при отсутствии доступа к twitter'у. Но, думаю, с этой задачей вы легко справитесь сами 😉

Успехов!

Интересное

Глянцевая и матовая печать фотокниг и свадебных фотоальбомов

Любителям страйкбола будет интересно почитать про камуфляж Горка его расцветки и разновидности.

  • Хорошее решение, спасибо. Но я бы подгружал не когда до конца прокрутили, а чуть раньше. Тогда ненужно показывать индикатор загрузки, скруль себе и скруль.

    • Начать загрузку раньше не сложно. Достаточно изменить условие (строка 21). Но нужно будет учесть, что в этом случае событие scroll может возникнуть несколько раз на участке около нижней границы. Особенно это будет заметно если есть ощутимая задержка при получении очередной страницы с твитами. Пользователь за это время сможет несколько раз дернуть скролл вверх-вниз.
      Т.е. нужно добавить блокировку отправки очередного запроса на время пока не будет получен ответ от предыдущего.

  • А как исключить реплаи из получившегося списка твитов?

    • if (tweet.in_reply_to_user_id == null) {
      //показываем твит
      }
      else {
      //пропускаем
      }

  • Гмыг. Зачётный код.

  • отличный виджет. думаю будет хорошей заменой стандартному всегда висящему.

  • Ну я бы не сказал, что она бесконечная, все ограничено оперативной памятью пользователя. Когда крутишь подобные странички в соц. сетях, чем ниже прокрутишь, тебе сильнее тормозит браузер и съедает памяти, так как верх DOM модели страницы (списка твитов в данном случае) он не удаляет а хранит всегда. Идея еще одна удалять верх, и также его прогружать, если пользователь скролит вверх.

    • Довольно спорная идея — запрашивать по несколько раз одни и те же данные. Каждый запрос сам по себе потребляет ресурсы и занимает некоторое время.

  • как реализовать такую же ве

  • Как реализовать такую же вещь только для сайта?? Например мой сайт http://www.blogproobzor.ru и я хочу сделать такую же подгрузку комментариев . 

    • Я не совсем понимаю. Этот загрузчик реализован именно для сайтов, т.е. вы можете вставить его в любую часть страницы.
      С загрузкой комментариев немного сложнее. Нужно изменить строку 35 (последний листинг). В ней указать URL скрипта, который вернет комментарии. И, соответственно, написать серверный скрипт, который будет формировать массив с комментариями.

  • Pingback: JavaScript виджет: бесконечная загрузка твитов | Разработка программного обеспечения()

  • Alexbel

    в опере у кого-нибудь работает?)

  • Роман

    Классный у вас сайтик…

    __________________
    http://двд-курс.рф/

  • Nizulko

    Уважаемый автор, а как сделать автообновление этого блока по  результату появления нового твита?..

    • Дело в том, что twitter сам не сможет отправить данные браузеру. Поэтому
      загрузку должен инициировать Ваш скрипт, причем запускать ее через
      какие-то промежутки времени (если Вы хотите постоянно обновлять ленту).

      Сделать это можно примерно так
      window.setInterval(get_tweets(1), 1000) //обновление каждую секунду
      При
      этом get_tweets нужно будет немного переписать так, чтобы она вставляла
      твиты в начало списка, а не в конец (или написать новую функцию).

      Другое
      дело, что если пользователь прокрутит скрол вниз, то новые твиты будут
      не видны, а список будет «дергаться» при добавлении твитов в его начало.
      Т.е. нужно будет делать какие-нибудь оповещения, похожие на сообщения о
      новых твитах в web интерфейсе твиттера.