Технология LazyLoad или в простонародье «ленивая загрузка»(её ещё называют бесконечный скроллинг или Infinity Scroll) в Битриксе. Метод, описанный мной, будет точно работать в компонентах catalog.section и news.list.
Суть такого механизма проста: пользователю сначала показывается, например, 15 новостей и потом, как только он докручивает до их конца, сразу же подгружаются следующие 15 элементов. И так, пока не закончатся элементы.
Технические детали
В конце, после списка элементов, мы будем вставлять пустую ссылку, на следующие элементы. В ссылку будем добавлять параметр AJAX_PAGE, он нам ещё понадобится.Выглядеть она будет примерно так:
/news/?PAGEN_2=2&AJAX_PAGE=YФормировать ссылку будем следующим образом:
$paramName = 'PAGEN_'.$arResult['NAV_RESULT']->NavNum; $paramValue = $arResult['NAV_RESULT']->NavPageNomer; $pageCount = $arResult['NAV_RESULT']->NavPageCount; if ($paramValue < $pageCount) { $paramValue = (int) $paramValue + 1; $url = htmlspecialcharsbx( $APPLICATION->GetCurPageParam( sprintf('%s=%s', $paramName, $paramValue), array($paramName, 'AJAX_PAGE',) ) ); echo sprintf('<div class="ajax-pager-wrap"> <a class="ajax-pager-link" data-wrapper-class="news-list" href="%s"></a> </div>', $url); }
Способ первый: без кеширования
Этот способ самый простой и первым приходит в голову.В шаблон компонента, до вывода элементов вставляем такую строку:
if(isset($_GET['AJAX_PAGE'])) { $APPLICATION->RestartBuffer(); }А после вывода элементов вставляем это:
if(isset($_GET['AJAX_PAGE'])) { die(); }Что мы делаем:
Если страницу открываем при помощи AJAX, то перед выводом элементов сбрасываем буфер контента функцией $APPLICATION->RestartBuffer(). А в конце просто выходим. Тем самым мы отдаем только нужный кусок контента при аякс запросе.
Но в этом способе есть большой минус. Функция RestartBuffer() не будет работать при включенном кешировании.
Способ второй: с кешированием
Тут нам на помощь приходит файл component_epilog.php. Он выполняется при каждой загрузке страницы и запускается после того, как отработал шаблон. Как раз то, что нам нужно.Теперь в шаблон компонента, до вывода элементов и после вывода элементов вставляем html комментарий:
<!--RestartBuffer-->В папке с темой для нужного компонента создаем файл component_epilog.php и вставляем в него этот код:
if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die(); if (isset($_GET['AJAX_PAGE'])) { $content = ob_get_contents(); ob_end_clean(); $APPLICATION->RestartBuffer(); list(, $content_html) = explode('<!--RestartBuffer-->', $content); echo $content_html; die(); }
Пример JavaScript кода
(function(){ var ajaxPagerLoadingClass = 'ajax-pager-loading', ajaxPagerWrapClass = 'ajax-pager-wrap', ajaxPagerLinkClass = 'ajax-pager-link', ajaxWrapAttribute = 'wrapper-class', ajaxPagerLoadingTpl = ['<span class="' + ajaxPagerLoadingClass + '">', 'Загрузка…', '</span>'].join(''), busy = false, attachPagination = function (wrapperClass){ var $wrapper = $('.' + wrapperClass), $window = $(window); if($wrapper.length && $('.' + ajaxPagerWrapClass).length){ $window.on('scroll', function() { if(($window.scrollTop() + $window.height()) > ($wrapper.offset().top + $wrapper.height()) && !busy) { busy = true; $('.' + ajaxPagerLinkClass).click(); } }); } }, ajaxPagination = function (e){ e.preventDefault(); busy = true; var wrapperClass = $('.'+ajaxPagerLinkClass).data(ajaxWrapAttribute), $wrapper = $('.' + wrapperClass), $link = $(this); if($wrapper.length){ $('.' + ajaxPagerWrapClass).append(ajaxPagerLoadingTpl); $.get($link.attr('href'), {'AJAX_PAGE' : 'Y'}, function(data) { $('.' + ajaxPagerWrapClass).remove(); $wrapper.append(data); attachPagination(wrapperClass); busy = false; }); } }; $(function() { if($('.'+ajaxPagerLinkClass).length && $('.'+ajaxPagerLinkClass).data(ajaxWrapAttribute).length){ attachPagination($('.'+ajaxPagerLinkClass).data(ajaxWrapAttribute)); $(document).on('click', '.' + ajaxPagerLinkClass, ajaxPagination); } }); })();Теперь при открытии страницы при помощи AJAX запроса, отрабатывает шаблон и вызывается файл component_epilog.php. В нем мы получаем весь контент из буфера, разбиваем его по нашему html комментарию и отдаем клиенту.
Способ третий: с включенным композитным режимом
Если посмотреть на блок-схему работы технологии, то можно заметить, что после исполнения страницы и перед записью её в кеш композита, вызывается событие OnEndBufferContent (оно же вызывается и без технологии). На нём мы и сыграем.Привожу код обработчика для композитного режима:
// при включенном композитном режиме, сохраняем в кеш, контент нужный для отдачи аяксом \Bitrix\Main\EventManager::getInstance()->addEventHandlerCompatible('main', 'OnEndBufferContent', function(&$content){ if (version_compare(SM_VERSION, '14.5.0') >= 0 && CHTMLPagesCache::IsCompositeEnabled()) { if (isset($_SERVER['HTTP_X_REQUESTED_WITH'], $_GET['AJAX_PAGE']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') { list(, $content_html) = explode('<!--RestartBuffer-->', $content); if(is_string($content_html) && strlen($content_html)){ $content = $content_html; } } } });Добавить его нужно в init.php вашего сайта.
Если в настройках композита стоит галочка «Сохранять на диск только страницы без параметров», то в поле «а также страницы содержащие только следующие параметры» надо добавить параметр AJAX_PAGE.
При этом способе код приведённый во втором пункте для файла component_epilog.php с включенным кеширование нужно удалить.