В этом посте сделаем переход к предыдущей и следующей статье по ссылкам в детальном описании компонента bitrix:news.detail.
Данный код также будет работать и в компоненте bitrix:catalog.element.
Для наглядности, чтобы было понятно, что будем делать, выглядеть это будет вот так, как на моем сайте:
Т.е. открыли статью, любую, если есть элементы до и после они будут выводиться слева или справа. Если статья последняя, значит выводиться будет слева предыдущая статья, и наоборот.
Также, для удобства сделаем возможность листать статьи по клавишам на клавиатуре ← Ctrl и Ctrl →.
Все вычисления сделаем в файле result_modifier.php в шаблоне компонента bitrix:news.detail, а html-код навигации и jQuery-код сделаем в самом шаблоне в файле template.php. В случае включенного управляемого кеширования все будет работать и кешироваться.
Итак, копируем шаблон компонента bitrix:news.detail если не скопирован, если скопирован и нет в нем файла result_modifier.php,то создаем этот файл.
У меня шаблон скопирован сюда, у Вас будет другой путь к шаблону.
PHP-код файла result_modifier.php
<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();
/**
* Bitrix vars
*
* @var CBitrixComponent $component
* @var CBitrixComponentTemplate $this
* @var array $arParams
* @var array $arResult
* @var array $arLangMessages
* @var array $templateData
*
* @var string $templateFile
* @var string $templateFolder
* @var string $parentTemplateFolder
* @var string $templateName
* @var string $componentPath
*
* @var CDatabase $DB
* @var CUser $USER
* @var CMain $APPLICATION
*/
// Прямая сортировка, чтобы последний элемент был справа от текущего, при обратной будет наоборот, слева.
$arSort = array(
'ACTIVE_FROM' => 'ASC',
'ID' => 'ASC',
);
// минимальные поля ID, NAME, DETAIL_PAGE_URL
$arSelect = array(
'ID',
'NAME',
'DETAIL_PAGE_URL',
//'DATE_CREATE',
//'DATE_ACTIVE_FROM',
//'PREVIEW_PICTURE',
//'DETAIL_PICTURE',
);
// выбираем активные элементы из нужного инфоблока по фильтру, вообще фильтр должен совпадать с фильтром компонента
// иначе могут в пагинацию попасть левые элементы инфоблока, которых не будет на сайте.
$arFilter = array(
'IBLOCK_ID' => $arParams['IBLOCK_ID'],
//'SECTION_CODE' => $arParams['SECTION_CODE'],
//'SECTION_CODE' => $arResult['SECTION']['CODE'],
//'SECTION_ID' => $arResult['IBLOCK_SECTION_ID'],
'ACTIVE' => 'Y',
'ACTIVE_DATE' => 'Y',
'SECTION_ACTIVE' => 'Y',
'SECTION_GLOBAL_ACTIVE' => 'Y',
'INCLUDE_SUBSECTIONS' => 'Y',
'CHECK_PERMISSIONS' => 'Y',
'MIN_PERMISSION' => 'R',
);
// тут получим по 1 соседу с каждой стороны от текущего элемента
$arNavParams = array(
'nPageSize' => 1,
'nElementID' => $arResult['ID'],
);
$arElements = Array();
$rsElements = CIBlockElement::GetList($arSort, $arFilter, FALSE, $arNavParams, $arSelect);
if($arParams['DETAIL_URL'])
$rsElements->SetUrlTemplates($arParams['DETAIL_URL']);
while($obElement = $rsElements->GetNextElement()) {
$arElements[] = $obElement->GetFields();
}
// в $arResult['RIGHT_PAGE'] и $arResult['LEFT_PAGE'] массивы с информацией о соседних элементах для текущего
switch(count($arElements))
{
case '3': //Сработает, когда справа и слева есть элементы
{
$RIGHT_PAGE = array_pop($arElements); // Последний элемент справа
$LEFT_PAGE = array_shift($arElements); // Первый элемент слева
$arResult['RIGHT_PAGE'] = Array(
'NAME' => $RIGHT_PAGE['NAME'],
'URL' => $RIGHT_PAGE['DETAIL_PAGE_URL']
);
$arResult['LEFT_PAGE'] = Array(
'NAME' => $LEFT_PAGE['NAME'],
'URL' => $LEFT_PAGE['DETAIL_PAGE_URL']
);
}
break;
case '2': //Сработает либо на первом, либо на последнем элементе
{
$RIGHT_PAGE = array_pop($arElements); // Последний элемент справа
$LEFT_PAGE = array_shift($arElements); // Первый элемент слева
// тут проверяем, слева или справа будет текущий открытый элемент, его исключаем
if($LEFT_PAGE["ID"] && $LEFT_PAGE["ID"] != $arResult["ID"])
{
$arResult['RIGHT_PAGE'] = Array();
$arResult['LEFT_PAGE'] = Array(
'NAME' => $LEFT_PAGE['NAME'],
'URL' => $LEFT_PAGE['DETAIL_PAGE_URL']
);
}
elseif($RIGHT_PAGE && $RIGHT_PAGE != $arResult["ID"])
{
$arResult['LEFT_PAGE'] = Array();
$arResult['RIGHT_PAGE'] = Array(
'NAME' => $RIGHT_PAGE['NAME'],
'URL' => $RIGHT_PAGE['DETAIL_PAGE_URL']
);
}
else
{
$arResult['RIGHT_PAGE'] = Array();
$arResult['LEFT_PAGE'] = Array();
}
}
break;
default: //Если что-то пойдет не так, постраничка выводиться не будет
{
$arResult['RIGHT_PAGE'] = Array();
$arResult['LEFT_PAGE'] = Array();
}
}
Тут следует обратить особое внимание на сортировку элементов в самом начале в массиве:
$arSort = array(
'ACTIVE_FROM' => 'ASC',
'ID' => 'ASC',
);
У меня на сайте задана в статьях обратная сортировка "DESC", если мне взять сортировку из настроек компонента, то соседние элементы будут выбираться наоборот, т.е. в массиве $RIGHT_PAGE будет предыдущий элемент, а в массиве $LEFT_PAGE будет следующий элемент, что для меня не логично и может запутать при большом коде, наоборот получается выборка, я вручную задаю сортировку обратную той, что у компонента, т.е. прямую "ASC" и все работает логично, и правильно.
Также обратите внимание на фильтр $arFilter:
- Он должен совпадать с фильтром компонента, иначе могут в пагинацию попасть те элементы инфоблока, которых не будет видно на сайте.
- На моем сайте переход по соседним статьям не зависит от раздела, сквозной, поэтому ключ SECTION_ID закомментирован, если Вам нужно сделать переход по соседним элементам инфоблока в зависимости от раздела, то надо раскомментировать эту строку/ключ, но учтите, что ID-раздела в разных компонентах может передаваться в шаблон по-разному, где через $arResult, где через $arParams, т.к. компонент может быть комплексным, может быть простым.
HTML-код в файле шаблона template.php
<div class="uk-grid uk-margin-large next-prev-pager">
<div class="uk-width-medium-1-2 uk-text-left uk-text-bold">
<?if(!empty($arResult["LEFT_PAGE"])):?>
<a class="ts-prev-page" title="← ctrl предыдущая" href="<?=$arResult["LEFT_PAGE"]["URL"]?>" data-uk-tooltip> <i class="uk-icon-caret-left"></i> <?=$arResult["LEFT_PAGE"]["NAME"]?></a>
<?endif?>
</div>
<div class="uk-width-medium-1-2 uk-text-right uk-text-bold">
<?if(!empty($arResult["RIGHT_PAGE"])):?>
<a class="ts-next-page" title="следующая ctrl →" href="<?=$arResult["RIGHT_PAGE"]["URL"]?>" data-uk-tooltip><?=$arResult["RIGHT_PAGE"]["NAME"]?> <i class="uk-icon-caret-right"></i></a>
<?endif?>
</div>
</div>
Тут обращаю внимание, что верстка от css-фреймворка Uikit, у Вас как у меня выводиться не будет, нужно применить еще стили, можете скопировать их с моего сайта.
jQuery-код в файле шаблона template.php
<script type="text/javascript">
$(document).keyup(function(event){
event = event || window.event;
var link = null;
if (!event.ctrlKey)
return;
var key = (event.keyCode ? event.keyCode : (event.which ? event.which : null));
if (!key)
return;
if (key == 39)
link = $('.next-prev-pager .ts-next-page');
else if (key == 37)
link = $('.next-prev-pager .ts-prev-page');
if (link && link.attr('href'))
document.location = link.attr('href');
else if(key == 39 || key == 37)
alert('Дальше новостей пока нет, заходите попозже или подпишитесь на мои статьи в форме в самом низу!');
});
</script>
jQuery-код добавьте в самом конце шаблона, самым последним.
Вот, собственно и весь код, навигация по соседним элементам инфоблока готова!