Ссылки на соседние элементы инфоблока

Навигация в детальной новости битриксСегодня мы займемся реализацией очень полезного функционала, который точно есть в WordPress, скорее всего присутствует в других движках, но почему-то не сделан по умолчанию в 1с-Битрикс. А именно, в шаблоне вывода детальной новости (товара в каталоге или вообще любого элемента инфоблока) отобразим ссылки на предыдущий и последующий элементы. Это даст возможность пользователю не возвращаться в список и просматривать материалы сайта «по цепочке».

Технически получить «соседей» фиксированного элемента инфоблока без лишних запросов к базе данных стало возможно после ввода в функцию CIBlockElement::GetList нового параметра «nElementID». Он задает количество соседних элементов с каждой стороны, которые следует включить в выборку.

Итак, первым делом копируем шаблон компонента news.detail (catalog.element или они могут входить в состав комплексного news, catalog) и создаем в директории с template.php файл result_modifier.php

<?
// сортировку берем из параметров компонента
$arSort = array(
		$arParams["SORT_BY1"]=>$arParams["SORT_ORDER1"],
		$arParams["SORT_BY2"]=>$arParams["SORT_ORDER2"],
	);
// выбрать нужно id элемента, его имя и ссылку. Можно добавить любые другие поля, например PREVIEW_PICTURE или PREVIEW_TEXT
$arSelect = array(
		"ID",
		"NAME",
		"DETAIL_PAGE_URL"
	);
// выбираем активные элементы из нужного инфоблока. Раскомментировав строку можно ограничить секцией
$arFilter = array (
		"IBLOCK_ID" => $arResult["IBLOCK_ID"],
		//"SECTION_CODE" => $arParams["SECTION_CODE"],
		"ACTIVE" => "Y",
		"CHECK_PERMISSIONS" => "Y",
	);
// выбирать будем по 1 соседу с каждой стороны от текущего
$arNavParams = array(
		"nPageSize" => 1,
		"nElementID" => $arResult["ID"],
	);
$arItems = Array();
$rsElement = CIBlockElement::GetList($arSort, $arFilter, false, $arNavParams, $arSelect);
$rsElement->SetUrlTemplates($arParams["DETAIL_URL"]);
while($obElement = $rsElement->GetNextElement())
		$arItems[] = $obElement->GetFields();
// возвращается от 1го до 3х элементов в зависимости от наличия соседей, обрабатываем эту ситуацию		
if(count($arItems)==3):
	$arResult["TORIGHT"] = Array("NAME"=>$arItems[0]["NAME"], "URL"=>$arItems[0]["DETAIL_PAGE_URL"]);
	$arResult["TOLEFT"] = Array("NAME"=>$arItems[2]["NAME"], "URL"=>$arItems[2]["DETAIL_PAGE_URL"]);
elseif(count($arItems)==2):
	if($arItems[0]["ID"]!=$arResult["ID"])
		$arResult["TORIGHT"] = Array("NAME"=>$arItems[0]["NAME"], "URL"=>$arItems[0]["DETAIL_PAGE_URL"]);
	else
		$arResult["TOLEFT"] = Array("NAME"=>$arItems[1]["NAME"], "URL"=>$arItems[1]["DETAIL_PAGE_URL"]);
endif;
// в $arResult["TORIGHT"] и $arResult["TOLEFT"] лежат массивы с информацией о соседних элементах
?>

Основная задача выполнена, осталось всего-лишь вывести уже подготовленную информацию. Для этого в template.php в нужное место вставляем код, например такой:

<?if(is_array($arResult["TOLEFT"])):?><a class="fleft" id="previous_page" href="<?=$arResult["TOLEFT"]["URL"]?>">< <?=$arResult["TOLEFT"]["NAME"]?></a><?endif?>
<?if(is_array($arResult["TORIGHT"])):?><a class="fright" id="next_page" href="<?=$arResult["TORIGHT"]["URL"]?>"><?=$arResult["TORIGHT"]["NAME"]?> ></a><?endif?>

Для удобства пользователей можно обрабатывать нажатия клавиш ctrl+стрелка влево и ctrl+стрелка вправо. Создадим или откроем для редактирования в директории редактируемого шаблона файл script.js (функция взята из этой статьи)

document.onkeydown = PageNavigation;

function PageNavigation (event)
{
   if (!document.getElementById)
      return;

   if (window.event) 
      event = window.event;

   if (event.ctrlKey)
   {
      var key = (event.keyCode ? event.keyCode : (event.which ? event.which : null) );
      if (!key)
         return;

      var link = null;
      if (key == 39)
         link = document.getElementById('next_page');
      else if (key == 37)
         link = document.getElementById('previous_page');

      if (link && link.href)
         document.location = link.href;
   }
}

Сжатый вариант кода:

document.onkeydown=PageNavigation;function PageNavigation(a){if(!document.getElementById)return;if(window.event)a=window.event;if(a.ctrlKey){var b=(a.keyCode?a.keyCode:(a.which?a.which:null));if(!b)return;var c=null;if(b==39)c=document.getElementById('next_page');else if(b==37)c=document.getElementById('previous_page');if(c&&c.href)document.location=c.href}}

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

Если вам понравилась статья, подписывайтесь на обновления блога по rss или присоединяйтесь в twitter

Поделиться ссылкой с друзьями:

Метки: , , ,

Категории: Bitrix

Комментарии (29)

  1. Kola:

    Я не большой специалист по js и строчка if (!document.getElementById) return; меня немного удивила. Причем ту статью я читал раньше, но как-то обратил внимание на это только сейчас. И часто эта функция может отсутствовать, Алексей?

  2. Serge:

    Смотрю стандартную демку.
    Пишу в настройках компонента новостей в поле «Название шаблона:» — arrows
    И получаю такую навигацию.
    Шаблон живет тут:
    /bitrix/components/bitrix/system.pagenavigation/templates/arrows/

  3. Serge:

    а.. прочитал ещё раз..
    совсем про другое речь идет..
    пошел дальше :)

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

  5. Almat:

    не подскажешь как сделать рейтинг для каждого товара виде звезд?

  6. Делаю все как написано — ничего не происходит ((

  7. Виктория:

    Спасибо, ваша статья очень помогла.

  8. андрей:

    в arParams не попадает $arParams["SORT_ORDER1"] можешь помочь??

  9. Alexander Kozlov:

    Спасибо! Спер, все работает!

  10. Ярослав:

    Спасибо, пригодилось!

  11. sap:

    А как ограничеть эту нагигацыю пределами разделов инфоблока, чтобы пользователь не перепрыгивал с тостера на телевизор, если они добавлены рядом?

  12. В коде выше есть закомментированная строка
    //"SECTION_CODE" => $arParams["SECTION_CODE"]
    Она отвечает за ограничение секцией. Можно вместо CODE поставить ID, смотря как реализована адресация.

  13. sap:

    Спсибо! Действительно, нужно было просто вместо code вписать id

  14. sap:

    Что то похоже что это только в catalog.element работат, а в news.detail нет..

  15. sap:

    нет работат, только для ограничения по разделам нужно заменять вызов «SECTION_CODE» => $arParams["SECTION_CODE"],
    на
    «IBLOCK_SECTION_ID» => $arParams["IBLOCK_SECTION_ID"],

    если используется построение адреса с использованием ID раздела

  16. sap:

    хотя раздел это всё равно не ограничивает как в catalog.element ((

  17. Виталий:

    Не могу понять как реализорвать Превью картинки сл и пред. новости подскажите?

    В result modifer и в шаблоне

  18. Мария:

    Все хорошо работает)
    Но почему то весь catalog.element оказывается под подвалом на странице…
    После нескольких бесцельных листаний туда обратно по элементам все становится на место.
    С чем это может быть связано???

  19. Алексей Валеев:

    Мария, перемещение блоков на странице в 99% случаев связано с неправильной таблицей стилей css. Возможно дело в кэше.

  20. Александр:

    Спасибо большое, то, что нужно!

  21. Александр:

    Огромное спасибо, очень полезный код, полезная статья!

  22. Вася:

    А как сделать ссылки на соседние секции? У меня, допустим, Секция «Одежда», «Обувь», «Аксессуары». Хочу, что в Одежде были ссылки генерируемые на Обувь и Аксессуарах. Все 3 находятся внутри одного раздела

  23. Вова-Володя:

    На сайте в компоненте catalog.element уже есть свой файл result_modifier.php
    Встраиваю в него всё из вашего примера, чего там не хватало. В шаблоне тоже добавляю в нужном месте блок вывода ссылок. И натурально ничего не происходит. Как быть, где искать? Подскажите пожалуйста.

  24. Владимир:

    Здравствуйте!
    Подскажите пожалуйста, как можно сделать так, чтобы при детальном просмотре новости можно было переходить к следующей и предыдущей не по ID новости, а по числу сортировки (которое 500 по умолчанию)? Что нужно поменять в вашем коде?

  25. Владимир, смотрите строчки 23 и 8 result_modifier.php

  26. Таня:

    Вася:
    04.06.2014 в 17:14

    А как сделать ссылки на соседние секции?

    Мне тоже очень нужно!! Подскажите!

  27. Ксения:

    Спасибо! Огромное!

  28. реальное спасибо! и почему такую простую но нужную фичу не могут сделать в самом битриксе…

  29. Елена:

    Спасибо огромное!!!