Иногда перед контент-менеджерами стоит задача выводить в произвольной части статьи какой-нибудь интерактивный элемент, например слайдер или фотогалерею с возможностью увеличить изображение нажатием мышки. При этом контент-менеджер часто не обладает навыками вёрстки, которые позволили бы ему ограничится готовым сниппетом сладера или галереи и инструмента «медиабиблиотека». Удобный вариант такой вставки реализован в WordPress, когда в плагине фотогалереи менеджер может загрузить и отредактировать формат подготовленные фотографии, а в тело статьи в нужном месте вставить специальный код например [gallary_123] где 123 — это уникальный идентификатор той фотогалереи которую он только что создал и наполнил. Такой формат мы и реализуем на 1С Битрикс «Управление сайтом».
Создадим инфоблок фотогалерий
Итак, у меня установлено коробочное решение, «Мебельная компания» на основе редакции «Старт», на момент написания статьи, версия ядра 18.1.5. Создаём инфоблок со следующими основными настройками:

Как видите настройки шаблонов URL адресов нам не нужны, оставляем название, символьный код и привязку к сайту. Так же обратите внимание что свойства инфоблока хранятся в отдельной таблице.
Во вкладке «Доступ» устанавливаем «Чтение» для всех пользователей, чтобы наши фотографии могли видеть все посетители сайта просматривающие новость с фотогалереей. Затем добавляем единственное свойство «Фотографии».
Свойство должно быть множественным т.к. фотографий в галерее у нас может быть сколько угодно, а так же обязательным к заполнению (мы ведь не можем выводить пустую фотогалерею).
В дополнительных настройках свойства «Фотографии» необходимо отметить флажёк «Выводить поле для описания значения», это нужно для того, чтобы контент-менеджер мог описать загружаемое изображение и позже пользователь мог видеть это описание при просмотре галереи. Та же я рекомендую ограничить тип загружаемых файлов, будем позволять грузить только изображение, защита от дурака так сказать. Инфоблок готов к использованию.
Давайте создадим тестовый элемент галереи для одной из существующих новостей и закинем несколько фотографий найденных в гугл по запросу «выставка мебели», у меня получилось следующее:
Если кто-то не знает как задать описание фотографии, щёлкните по значку карандаша под фото и во всплывающем окне заполните поле «Описание» вот так:
Можно готовить компонент галереи.
Готовим шаблон компонента фото-галереи
Т.к. наша галерея основана на инфоблоке, самым очевидным компонентом для её показа будет обычная детальная страница новости т.е. bitrix:news.detail. Создадим тестовый раздел и разместим там компонент bitrix:news.detail, компонент необходимо настроить на работу с только что созданным инфоблоком «Фотогалерея», отключить все параметры устанавливающие заголовки и описания страницы, отключить показ всевозможных доп.свойств типа дата изменения элемента, детальное описание и т.п.
В свойстве «ID новости» можно сразу указать ID тестовой галереи, в моём случае это 33, это нужно для удобства настройки шаблона. В параметрах компонента в поле «Свойства», свойство MORE_PHOTO нужно указать вручную, его не будет в списке доступных свойств инфоблока т.к. это свойство типа «Файл»:
Обязательно отключите режим Ajax в параметрах компонента!
Базовые настройки сделаны, можно сохранять и копировать шаблон компонента для последующей кастомизации. Я скопировал шаблон компонента bitrix:news.detail в дефолтный шаблон сайт и назвал его gallary, вам советую сделать так же чтобы не запутаться в дальнейшем:
В качестве плагина для фотогалереи я предлагаю использовать всем хорошо знакомый Fancybox, который можно скачать с официального сайта http://fancyapps.com/fancybox/3/ в последней версии этот плагин предоставляет очень симпатичное оформление фотогалереи прямо из коробки.
Что необходимо подключить:
- последнюю стабильную минифицированную версию JQuery
- сам плагин jquery.fancybox.min.js
- стили jquery.fancybox.min.css
Подключаем, файлы я предварительно раскидал по папкам css и js внутри папки шаблон /bitrix/templates/furniture_gray/
1 2 3 4 5 6 7 8 9 10 |
//Где-то вначале use Bitrix\Main\Page\Asset; //и в блоке header //Подключаем и выводим CSS Asset::getInstance()->addCss(SITE_TEMPLATE_PATH. '/css/jquery.fancybox.min.css' ); //Подключаем пользовательские и выводим стандартные js скрипты Asset::getInstance()->addJs(SITE_TEMPLATE_PATH."/js/jquery-3.2.1.min.js"); Asset::getInstance()->addJs(SITE_TEMPLATE_PATH."/js/jquery.fancybox.min.js"); |
Теперь необходимо настроить сам шаблон. Идём в папку с шаблоном, у меня это /bitrix/templates/.default/components/bitrix/news.detail/gallary/ , здесь необходимо создать файл result_modifier.php в котором предварительно подготовить картинки к показу в галереи.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<? if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die(); //Предварительно готовим картинки if($arResult['PROPERTIES']['MORE_PHOTO']['VALUE']){ $photos = []; foreach ($arResult['PROPERTIES']['MORE_PHOTO']['VALUE'] as $key => $photoId) { $arPhoto = CFile::ResizeImageGet($photoId, ["width" => 150, "height" => 150], BX_RESIZE_IMAGE_EXACT, true, false, false, 100); $arPhotoBig = CFile::ResizeImageGet($photoId, ["width" => 800, "height" => 600], BX_RESIZE_IMAGE_PROPORTIONAL, true, false, false, 100); $photos[] = ['SRC'=>$arPhoto['src'], 'SRC_BIG' => $arPhotoBig['src'], 'ALT'=>$arResult['PROPERTIES']['MORE_PHOTO']['DESCRIPTION'][$key]]; } //И сохраняем в кеш только нужные данные $arResult['GALLARY_PHOTOS'] = $photos; $this->__component->SetResultCacheKeys(['GALLARY_PHOTOS']); } ?> |
Всегда используйте конструкцию $this->__component->SetResultCacheKeys([‘CUSTOM_PROPERTY_KEY’]); для кеширования данных в result_modifier.php, так вы будете хранить в кеше строго-ограниченные данные, не переполняя его, чем сэкономите память и повысите быстродействие сайта.
И сам шаблон template.php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die(); $this->setFrameMode(true); if($arResult['GALLARY_PHOTOS']) { //А есть ли вообще картинки?> <div class="gallary"> <? foreach ($arResult['GALLARY_PHOTOS'] as $key => $photo) { ?> <div class="gallary_item"> <a href="<?=$photo['SRC_BIG'];?>" class="fancybox" data-fancybox="images" data-caption="<?=$photo['ALT'];?>" > <img src="<?=$photo['SRC'];?>" alt="<?=$photo['ALT'];?>"> </a> </div> <? } ?> </div> <? } ?> |
Если вы всё подключили правильно галерея уже начнёт работать. Давайте добавим немного красоты путём стилизации наших классов gallary и gallary_item и изображений внутри. Для универсальности предлагаю использовать файл стилей компонента галереи. Пропишем следующий стиль:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
.gallary { display: flex; flex-direction: row; justify-content: space-between; } .gallary_item { overflow: hidden; position: relative; } .gallary_item img { width: 100%; height: auto; max-width: 100%; display:block; -webkit-transition:all 0.2s ease-out; -moz-transition:all 0.2s ease-out; -o-transition:all 0.2s ease-out; -ms-transition:all 0.2s ease-out; transition:all 0.2s ease-out; } .gallary_item:hover img { -webkit-transform:scale(1.1); -moz-transform:scale(1.1); -o-transform:scale(1.1); -ms-transform:scale(1.1); transform:scale(1.1); } |
Получается примерно такой эффект:
Внешний вид галереи после применения стилей. В реальности эффект более плавный
Ну что же, компонент готов, теперь можно заняться его вставкой в детальный текст элемента инфоблока, например новостной статьи.
Вставка галереи в тело статьи
Для начала нам нужно кастомизировать компонент news.detail новостного раздела, не важно отдельный это компонент или входит в состав комплексного. Нам потребуется отредактировать файл result_modifier.php, template.php и component_epilog.php, начнём с result_modifier.php.
Первым делом скопируйте шаблон компонента на основе которого сделан раздел новостей, в моём случае это комплексный компонент bitrix:news, копируем шаблон компонента в дефолтный шаблон сайта, я назвал его news_block. Далее идём в папку компонент news.detail, т.е. /bitrix/templates/.default/components/bitrix/news/news_block/bitrix/news.detail/.default/ и создаём файлыresult_modifier.php иcomponent_epilog.php. В result_modifier.php необходимо добавить следующий код для кеширования шаблона.
1 2 3 4 |
<? if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die(); //Кешируем данные после обновления буфера шаблона $this->__component->SetResultCacheKeys(array("CACHED_TPL")); ?> |
В файл component_epilog.php нужно вставить специальную конструкцию, которая будет искать в теле статьи «хеш-тег» #GALLARY_ID_123# где 123 — идентификатор галереи (элемента инфоблока) и подгружать на его место компонент галереи (который мы ранее настроили) с переданным в него ID-шником 123. Весь код выглядит так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die(); //Заменяем хеш-тег GALLARY_ID на компонент echo preg_replace_callback( "/#GALLARY_ID_([\d]+)#/is".BX_UTF_PCRE_MODIFIER, create_function('$matches', 'ob_start(); $GLOBALS["APPLICATION"]->IncludeComponent("bitrix:news.detail", "gallary", Array( "ACTIVE_DATE_FORMAT" => "d.m.Y", "ADD_ELEMENT_CHAIN" => "N", "ADD_SECTIONS_CHAIN" => "N", "AJAX_MODE" => "N", "AJAX_OPTION_ADDITIONAL" => "", "AJAX_OPTION_HISTORY" => "N", "AJAX_OPTION_JUMP" => "N", "AJAX_OPTION_STYLE" => "N", "BROWSER_TITLE" => "-", "CACHE_GROUPS" => "N", "CACHE_TIME" => "36000000", "CACHE_TYPE" => "A", "CHECK_DATES" => "N", "DETAIL_URL" => "", "DISPLAY_BOTTOM_PAGER" => "N", "DISPLAY_DATE" => "N", "DISPLAY_NAME" => "N", "DISPLAY_PICTURE" => "N", "DISPLAY_PREVIEW_TEXT" => "N", "DISPLAY_TOP_PAGER" => "N", "ELEMENT_CODE" => "", "ELEMENT_ID" => $matches[1], // ID галереи найденный в теге #GALLARY_ID_xxx# "FIELD_CODE" => array( 0 => "", 1 => "", ), "IBLOCK_ID" => "5", //Код инфоблока галери "IBLOCK_TYPE" => "news", //Тип инфоблока "IBLOCK_URL" => "", "INCLUDE_IBLOCK_INTO_CHAIN" => "N", "MESSAGE_404" => "", "META_DESCRIPTION" => "-", "META_KEYWORDS" => "-", "PAGER_BASE_LINK_ENABLE" => "N", "PAGER_SHOW_ALL" => "N", "PAGER_TEMPLATE" => ".default", "PAGER_TITLE" => "Страница", "PROPERTY_CODE" => array( // Свойства 0 => "", 1 => "MORE_PHOTO", 2 => "", ), "SET_BROWSER_TITLE" => "N", "SET_CANONICAL_URL" => "N", "SET_LAST_MODIFIED" => "N", "SET_META_DESCRIPTION" => "N", "SET_META_KEYWORDS" => "N", "SET_STATUS_404" => "N", "SET_TITLE" => "N", "SHOW_404" => "N", "STRICT_SECTION_CHECK" => "N", "USE_PERMISSIONS" => "N", "USE_SHARE" => "N", ), false ); $retrunStr = @ob_get_contents(); ob_get_clean(); return $retrunStr;'), $arResult["CACHED_TPL"]); ?> |
Обратите внимание что вместо привычного $APPLICATION использовано $GLOBALS[«APPLICATION»], это нужно для видимости объекта внутри временной функции. Так же обратите внимание на $matches[1] это динамический параметр передаваемый в параметры вызова компонента news.detail, в нём содержится ID галереи.
Осталось поправить файл шаблона template.php, на второй сточке, сразу после проверки обращения к файлу пишем код:
1 |
<? ob_start(); ?> |
а в конце кода пишем:
1 2 3 4 |
<? $this->__component->arResult["CACHED_TPL"] = @ob_get_contents(); ob_get_clean(); ?> |
Манипуляции с component_epilog.php сделаны чтобы обойти кеширование. Как вы уже поняли весь этот «финт» основан на манипуляции буфера вывода.
Вместо заключения
Теперь ваш контент-менеджер может без труда вставлять фото-галереи прямо в тело статьи и ему не нужно разбираться в вёрстке и стилях. Порядок действия теперь такой:
- Создание галереи в инфоблоке галерей, после сохранения менеджер запоминает ID элемента инфоблока ( в моём случае это ID 33)
- В нужном месте детального описания новости (инфоблок новости) необходимо вставить следующий код #GALLARY_ID_33#
Вставка галереи в тело статьи в форме редактирования элемента инфоблока. И вот результат:
Я думаю не надо объяснять что так можно вставлять что угодно, слайдеры, формы опроса, товарные предложения и т.д. Желаю удачи!
Огромное спасибо!
Супер! Спасибо большое автору, все получилось (хотя и не с первого раза) и прекрасно работает! Не заострено внимание на том, что в файле «component_epilog.php» нужно поменять на свои значения тип инфоблока («IBLOCK_TYPE» => «news», //Тип инфоблока ) и код инфоблока галереи («IBLOCK_ID» => «5», //Код инфоблока галери»), ну и сложные компоненты иногда не так разложены по подпапкам, как тут описано, но все-таки разобраться можно.
ЕЩЕ РАЗ ОГРОМНАЯ БЛАГОДАРНОСТЬ!
Рад был помочь! Спасибо за обратную связь! Учту эти моменты и допишу в статью.
Спасибо за решение! А как быть если таким образом нужно вывести не 1 а 2 разных компонента, например?
Здравствуйте. Нужно будет добавить ещё один «хеш-тег» и вызов preg_replace_callback() в component_epilog.php