12.01.2016

С автоматической дозагрузкой страниц среднестатистический пользователь хорошо знаком благодаря ВКонтакте, Facebook, Twitter и др. соц. сетям. Поделюсь своим подходом к данному вопросу, который подойдёт большинству обычных сайтов.

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

Самые понятные места где обычно владельцам сайтов хочется иметь ajax-загрузку контента в интерфейсе — это ленты новостей или статей, а также каталог товаров. Обычно в разделах такого типа, чтобы не вываливать всё на 1 страницу, информацию разбивают и реализуют постраничную навигацию. В подавляющем большинстве случаев такого рода навигация содержит ссылки на следующую и предыдущую страницу, «пейджинг».

Предлагаемое решение

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

  1. На страницах, за исключением последней, должна присутствовать ссылка на следующую страницу.
  2. Анонсы новостей, статей и краткое описание товаров должно быть обернуто тегом, в конец которого будут добавляться следующие элементы.
  3. Для ссылки на следующую страницу и обёртки должны существовать однозначные jQuery селекторы.

Имея это, по нажатию кнопки, делаем запросы к следующим страницам, берём оттуда данные и вставляем их на текущую страницу, не перезагружая её.

Обратите внимание, что всё происходит именно «по нажатию кнопки». Альтернативный вариант «по достижению конца страницы», отнимает у пользователя возможность воспользоваться «подвалом» сайта, который часто является важной/нужной/красивой составляющей стандартных сайтов.

Реализация дозагрузки на странице

Инструмент я постарался сделать максимально универсальным. Ниже представлен пример реализации дозагрузки архива с записями из блога, который работает под управлением MODx Evolution (для формирования архива использует сниппет Ditto).

Верстка

<html>
    <head>
        …
        <script type="text/javascript" src="/path/jquery-1.11.1.min.js"></script>
        …
    </head>
    <body>
        …
        <div id="abitmore-place">
            <div class="news">…</div>
            <div class="news">…</div>
            <div class="news">…</div>
            <div class="news">…</div>
            <div class="news">…</div>
            <div class="news">…</div>
            …
        </div>
        <div class="pager">
            <a href="…" class="previous">Предыдущая страница</a>
            <a href="…" class="next">Следующая страница</a>
        </div>
        <div class="abitmore-progress"></div>
        <a href="#" id="abitmore-button">Загрузить еще новостей на страницу</a>
        <script src="/path/abitmore.js"></script>
        <script>
            ABM.init( {
                hide : [ '.pager' ],                // массив того, что скрываем после загрузки страницы
                place : '#abitmore-place',          // куда будет добавлять загруженное
                button : '#abitmore-button',        // при click-е на этот элемент происходит дозагрузка
                progress : '#abitmore-progress',    // визуализирует процесс загрузки (не обязательно)
                next : '.pager .next'               // ссылка на следующую страницу
            } );
        </script>
        …
    </body>
</html>

Подключаемый JavaScript-плагин

var ABitMore = ABitMore || {};

ABitMore = new( function() {
    var self = this;

    self.settings = {};

    self.init = function( settings ) {
        self.settings.hide = ( settings.hide == undefined ) ? false : settings.hide;
        self.settings.place = ( settings.place == undefined ) ? false : settings.place;
        self.settings.button = ( settings.button == undefined ) ? false : settings.button;
        self.settings.progress = ( settings.progress == undefined ) ? false : settings.progress;
        self.settings.next = ( settings.next == undefined ) ? false : settings.next;

        if( self.settings.place && self.settings.button && self.settings.next  ) {
            self.settings.url = $( self.settings.next ).attr( 'href' );
            
            for( var i in self.settings.hide ) {
                $( self.settings.hide[i] ).hide();
            }
            
            $( self.settings.progress ).hide();

            $( self.settings.button ).on( 'click', function() {
                $( self.settings.button ).hide();
                $( self.settings.progress ).show();
                
                $.get( self.settings.url, function( response ) {
                    var addedСontent = $( response ).find( self.settings.place ).html();
                    
                     $( self.settings.place ).append( addedСontent );
                    
                    self.settings.url = $( response ).find( self.settings.next ).attr( 'href' );
                    
                    if( self.settings.url != undefined ) {
                        $( self.settings.button ).show();
                    }

                    $( self.settings.progress ).hide();
                } );
            } );
        }
    };
} )();

var ABM = ABitMore;

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

Обратите внимание, что при таком подходе мы обезопасили себя с точки зрения SEO. Если какой-то из поисковиков не будет исполнять javascript для дозагрузки страницы, ему останутся классические ссылки «туда/обратно», которые он сможет проиндексировать и найти все статьи и публикации данного раздела.