Простой взгляд на бесконечный скроллинг

  • Простой взгляд на бесконечный скроллинг

    Антон Долганин 13 Июня 2014 11:41 14792
    Автоподгрузка, бесконечный скроллинг, «вебдванольная постраничка» — этот подход называют по разному, но суть одна — при прокрутке к концу списка, автоматически подгружается еще контент. В этой статье я опишу простой подход к реализации сего.

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

    Прежде всего разместим вот этот вот шаблон постраничной навигации по адресу /bitrix/templates/.default/components/bitrix/system.pagenavigation. Это обычный шаблон постранички, очень сильно урезанный, мы в нем оставили лишь кнопку "следующая страница", обозвав ее "еще". В это и есть простота подхода :) Код здесь его приводить не буду.

    При желании вы можете оставить эту ссылку, кастомизировав ее под свой стиль, а можете убрать через style="display: none". Кому как удобнее.

    Теперь займемся шаблоном наших элементов. В кастомизируемый шаблон в файл result_modifier.php (если его нет, надо создать) добавляем такой код, который сбрасывает буфер страницы, если идет обращение по ajax.

    if (array_key_exists('is_ajax', $_REQUEST) && $_REQUEST['is_ajax']=='y') {
        $APPLICATION->RestartBuffer();
    }


    Там же в файле component_epilog.php (если нет - создаете) добавляем код (если данный файл в компоненте не принимает участия, то вставляете в самый низ template.php):

    if (array_key_exists('is_ajax', $_REQUEST) && $_REQUEST['is_ajax']=='y') {
        die();
    }


    Здесь, если идет ajax-запрос, прекращаем выполнение. Для тех, кто пока путается в Битриксе: по ajax запрашивается ВСЯ страница, но мы получаем ровно тот кусок контента, который сгенерировал наш компонент списка.

    А также в удобное для вас место (например, в скриптах шаблона сайта) добавляем следующий js-код:

    $(document).on('ready', function(){
        var loading = false;
        $(window).scroll(function() {
            if ($('#infinity-next-page').size() && !loading) {
                if ($(window).scrollTop()+100 >= $(document).height()-$(window).height()) {
                    loading = true;
                    $.get($('#infinity-next-page').attr('href'), {is_ajax: 'y'}, function(data){
                        $('#infinity-next-page').after(data);
                        $('#infinity-next-page').remove();
                        loading = false;
                    });
                }
            }
        });
    });


    Тут все очень просто тоже: при скроллинге, если дошли до футера (там можно подкрутить дельту, если не очень вовремя срабатывает), то ищем ту самую ссылку "еще", берем из нее адрес, и обращаемся по этому адресу по ajax, контент вставляем тут же, а предыдущую кнопку удаляем.

    Вот так все просто. Замечу, что подход seo-оптимизирован, так как поисковик увидит просто кнопку "еще", перейдет по ней, там будет уже вторая страница, и так далее. При желании вы можете закрыть это от поисковика самостоятельно (атрибут rel="nofollow" ). Единственное, я бы посоветовал в robots.txt вставить такую строчку: Disallow: /*is_ajax=* (чтобы аяксовые страницы не индексировались поисковиком).

    Вот и все. Не забудьте, что подход использует библиотеку jQuery.

    В процессе использования выяснилось, что не работает режим правки для подгружаемых элементов. Если для вас это важно, надо сделать следующее. Не использовать второй кусок кода из данного поста, а в footer.php шаблона сайта в самом верху вставить:

    if (array_key_exists('is_ajax', $_REQUEST) && $_REQUEST['is_ajax']=='y') {
        return;
    }

    .
Кирилл
26 Марта 2015 4:35
Антон, помогите плз., сломал голову уже

Хочу по аналогии сделать подгрузку детальных страниц (как здесь: http://goo.gl/P23BiH)
- шаблон bitrix:news.detail
- формирую ссылку "Следующая страница" (отсюда http://goo.gl/JT6WDN), добавляю параметр is_ajax=y
- обрезаю ajax-результат, как в Вашем примере

При ручном клике открывает в новой странице кусок искомого кода, а скрипт не хочет работать.
Шаблон тот же, jQuery присутствует, скрипт один в шаблоне. С bitrix:news.list работает, bitrix:news.detail не могу завести.
Антон Долганин
26 Марта 2015 14:33
Кирилл, к сожалению, совсем нет времени. Обратитесь к разработчику за платной консультацией.
Кирилл
26 Марта 2015 14:35
Одновременно ответили )
Кирилл
26 Марта 2015 14:33
Антон, разобрался, ссори, была ошибка в скриптах.
А подгрузка детальной страницы работает, можно расширить статью!
Денис
23 Июня 2015 17:42
Я так понимаю, что при включенном кешировании этот способ не работает? Просто result_modifier не отрабатывает...
Антон Долганин
23 Июня 2015 20:02
К сожалению, не будет. Этот вариант в статье подразумевает скорее работу с комплексным компонентом - когда работаете с result_modifier комплексного.

Ну либо отключать кеширование. Либо переводить компонент на php-кеш.
Денис
24 Июня 2015 12:20
Можно чуть уточнить? Т.е. когда компонент комплексный (bitrix:catalog, к примеру), то в его result_modifier можно прописывать этот код и он будет вызываться даже при включенном кешировании? Я почему-то думал, что result_modifier ни при каких обстоятельствах не вызывается при включенном кэшировании...
Антон Долганин
25 Июня 2015 4:52
Я бы лучше сказал так: result_modifier НЕ вызывается (постоянно), ТОЛЬКО если компонент в режиме html-кеша (большинство, если не все, компонентов для организации контента в Битрикс работают в этом режиме).

Отдельным особняком стоят комплексные компоненты - это "папки" обычных компонент, внутри комплексных нет никакой логики как правило, нет кеша, они просто рулят тем, какой компонент показать в данный момент. Но вместе с тем у них могут быть и свои result_modifier и component_epilog, которые (так как кеша нет у комплексных) работают всегда.
Денис
29 Июня 2015 13:35
Вот так лучше не делать:
Disallow: /*is_ajax=*

т.к., начиная с третьей страницы, ссылки идут с этим параметром (он не очищается в шаблоне pagenavigation)

Т.е. если так сделать, то поисковик увидит только 1-ую и 2-ую страницы :)
Денис
29 Июня 2015 13:44
Извиняюсь, чушь сморозил. Всё нормально работает - этот параметр не нужно удалять.
Станислав
2 Декабря 2015 21:18
Как модифицировать JS, чтобы эл-ы показываюсь при клике, а не скролле, делаю так:

       $("#infinity-next-page").click(function(){
          if ($('#infinity-next-page').size() && !loading) {
                   loading = true;
                   $.get($('#infinity-next-page').attr('href'), {is_ajax: 'y'}, function(data){
                       $('#infinity-next-page').after(data);
                       $('#infinity-next-page').remove();
                       loading = false;
                   });
                   return false;
          };
       })
 


Первый клик отрабатывает, а последующие нет, что  не так ?
Антон Долганин
3 Декабря 2015 5:40
 $(document).on('click', '#infinity-next-page', function(){ 

Вот так попробуйте начало переписать в вашем примере. Вместо document лучше взять какой-то менее глобальный элемент вокруг постранички, но который есть на странице сразу (а не после загрузки) - например враппер контента.
Станислав
4 Декабря 2015 11:25
Спасибо, помогло решить вопрос, решение гениальное!
Юрий
14 Марта 2017 9:18
Антон, здравствуйте. Метод действительно простой и действенный.

Однако при этом все ссылки из подгружаемого документа проставляются с добавление к URL &is_ajax=y
Я помню, у bitrix'а были какие-то методы по управлению подобными url параметрами , но никак не могу их найти в документации, чтобы сделать примерно так:
if ($_RQUEST['is_ajax']=='y') {
     убрать параметр из автоматически проставляемой URL
}
обычный unset, как я понимаю - не поможет.
Или это можно решить каким-либо ещё более простым способом?

Ещё минус, конечно, - это необходимость правки всех компонентов, где такой автозагрузчик необходимо вставить, из-за чего многократно дублируется код, но это видимо уже неизбежно.
Антон Долганин
15 Марта 2017 15:49
Юрий, сложно понять о чем речь.
Можно ли пример? В смысле ссылку например.
Юрий
15 Марта 2017 16:03
Приветствую! Пример-то уже исправлен давно =)
При получении контента через $.get - для последующей его вставки в код страницы, все ссылки в этом контенте получают URL параметр &is_ajax=y, которого при обычной загрузке страницы не будет.
И при последующем нажатии на такие ссылки - понятное дело пользователь увидит лишь обрезок другой страницы.

Чтобы убрать этот параметр из подгружаемого контента видимо нужно использовать CMain::GetCurPageParam( remove_params ).
ГоспольБог Битрикс
3 Апреля 2017 17:23
уважаемый давайте код лучше пишите и чтобы все было. ИМХО код гавно и не работает
cherep
3 Мая 2017 1:11
Спасибо за отличную статью! Долго бился над решением казалось бы такой простой проблемы, а с вашей помощью сделал рабочий вариант за полчаса ;)