+7 495 008 8452 пн.-пт. 10:00 – 17:00
Загрузка...
Если у вас возникли какие либо вопросы которые вы не смогли решить по нашим публикациям самостоятельно,
то ждем ваше обращение в нашей службе тех поддержки.


Заметки на полях: использование типа параметров CUSTOM на примере.

Заинтересовал функционал создания кастомных элементов управления в параметрах компонента, а именно тип параметров CUSTOM. В документации данный тип описан очень кратко:
Для типа элемента управления TYPE есть значения:
  • LIST - ... .
  • STRING - ... .
  • CHECKBOX - ... .
  • CUSTOM - позволяет создавать кастомные элементы управления.
http://dev.1c-bitrix.ru/learning/cour...ON_ID=2132

Поиск навёл на интересную статью: произвольный тип параметров компонента в bitrix. Статья содержит описание основных опций данного типа параметров в файле .parameters.php и в качестве примера разбирает компонент map.google.view.

Решили использовать данный тип параметров для механизма комментариев в каталоге (bitrix:catalog.element). Комментарии реализованы с помощью модуля Форум. Идея состоит в том, чтобы указать идентификатор форума не для товара по отдельности, а для целого раздела, а затем в соответствии с разделом элемента каталога, подставлять нужный идентификатор форума в result_modifier.

Задача поставлена, приступаем к реализации. Создаём в файле .parameters.php запись о новом параметре.
$arTemplateParameters["FORUMS_LIST"] = Array(
   "NAME" => GetMessage("F_CUSTOM_FORUMS_LIST"),
   "TYPE" => "CUSTOM",
   "JS_FILE" => $templateFolder . "/settings/settings.js",
   "JS_EVENT" => "OnForumsListSettingsEdit",
   "JS_DATA" => GetMessage("F_CUSTOM_FORUMS_LIST_PARAM_EDIT") . "||" . $templateFolder . "/settings/settings.php" . "||" . $arCurrentValues["IBLOCK_ID"],
   "DEFAULT" => "",
   "HIDDEN" => "N",
);
Из указанной выше статьи получаем описание опций данного типа параметров.
JS_FILE - файл с JS кодом ответственным за отображение кастомной опции
JS_EVENT - callback функция которая будет вызвана после загрузки JS_FILE
JS_DATA - будет передана в JS_EVENT

вообще говоря в JS_EVENT будет передано не JS_DATA, а объект
{
   data:JS_DATA, //как не трудно догадаться тут будет JS_DATA из .parameters.php
   oCont: td,    /* контейнер, в котором предлагается размещать кастомный контрол  управления параметром */
   oInput: input,//input в котором и будет предаваться значение параметра на сервер при сохранении
   popertyID:"MAP_DATA",//название параметра
   propertyParams: { /*...*/ },//Объект содержащий всё тоже, что и массив параметра в .parameters.php
   fChange:function(){ /*...*/ },//callback для вызова, при изменении параметра
   getElements:function(){ /*...*/ }//возвращает объект со всеми параметрами компонента
 }
Естественно не забываем про обновление языкового файла.
<?php
...
$MESS["F_CUSTOM_FORUMS_LIST"] = "Список форумов для отзывов";
$MESS["F_CUSTOM_FORUMS_LIST_PATH"] = "Путь к файлу списка форумов";
$MESS["F_CUSTOM_FORUMS_LIST_PARAM_EDIT"] = "Изменить";
...
?>
Далее создаём в папке шаблона директорию /settings/. В этой директории создаём скрипт вызова диалогового окна (settings.js) и файл вывода формы редактирования значения параметра (settings.php).

Файл settings.js содержит создание объекта window.jsForumsListEditor, конструктор которого создаёт кнопку вызова диалога и делегирует на неё обработчик (JForumsListEditor.prototype.btnClick). В данном обработчике на основе параметров, переданных в опции JS_DATA, формируется URL и данные POST запроса к файлу-обработчику settings.php.
...
function OnForumsListSettingsEdit(arParams) {
   if (null != window.jsForumsListEditor) {
      try {
         window.jsForumsListEditor.Close();
      } catch (e) {}
      
      window.jsForumsListEditor = null;
   }

   window.jsForumsListEditor = new JForumsListEditor(arParams);
}

function JForumsListEditor(arParams) {
   this.arParams = arParams;
   this.jsOptions = this.arParams.data.split('||');
   
   var obButton = this.arParams.oCont.appendChild(BX.create('BUTTON', {
      html: this.jsOptions[0]
   }));
   
   obButton.on click = BX.delegate(this.btnClick, this);
   
   this.saveData = BX.delegate(this.__saveData, this);
}
...
Файл settings.php содержит десериализацию текущего сохранённого значения параметра и вывод формы редактирования этого значения.
<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_before.php");
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_js.php");

$sDirName = dirname(pathinfo(__FILE__, PATHINFO_DIRNAME));
$sPath = substr($sDirName, strlen($_SERVER['DOCUMENT_ROOT']));

__IncludeLang($sDirName . "/lang/" . LANGUAGE_ID . "/settings.php");

$obJSPopup = new CJSPopup("",
   array(
      "TITLE"  => GetMessage("CFL_SET_POPUP_TITLE"),
      "SUFFIX" => "forums_list",
      "ARGS"   => ""
   )
);

$arData = array();
if ($_REQUEST["LIST_DATA"]) {
   CUtil::JSPostUnescape();
   
   if (CheckSerializedData($_REQUEST["LIST_DATA"])) {
      $arData = unserialize($_REQUEST["LIST_DATA"]);
   }
}

if (!isset($arData["ITEMS"]))
   $arData["ITEMS"] = array();

$arSections = array();
$arForums = array();
$iItemsCNT = 0;
if (CModule::IncludeModule("iblock") && CModule::IncludeModule("forum")) {
   ...
}
?>
<sc ript type="text/javascript" src="<?=$sPath?>/settings/settings_load.js"></sc ript>
<sc ript type="text/javascript">
   var jsMess = {
      noname: "-",
      itemDel: "<?=CUtil::JSEscape(GetMessage("CFL_ITEM_DELETE"))?>",
   };
   
   BX.loadCSS('<?=$sPath?>/settings/settings.css');
   
   window._global_BX_UTF = <?=(defined('BX_UTF') && (BX_UTF == true)) ? 'true' : 'false'?>;
   
   var arSections = [];
   <?php foreach ($arSections as $iSectionID => $arSection):?>
      arSections.push({"id": "<?=$iSectionID?>", "name": "<?=$arSection["NAME"]?>", "style": "<?=$arSection["STYLE"]?>"});
   <?php endforeach;?>
   
   var arForums = [];
   <?php foreach ($arForums as $iForumID => $arForum):?>
      arForums.push({"id": "<?=$iForumID?>", "name": "<?=$arForum["NAME"]?>"});
   <?php endforeach;?>
   
   function getSelectHTML(arItems, sInputName) {...}
   
   function itemAdd() {...}
   
   function itemDelete(i) {...}
</sc ript>

<fo rm name="bx_popup_form_forums_list">
   <input type="hidden" name="save" value="Y" />
   
   <?php $obJSPopup->ShowTitlebar();?>
   <?php $obJSPopup->StartDescription("bx-edit-menu");?>
      <p><b><?=GetMessage("CFL_SET_POPUP_WINDOW_TITLE")?></b></p>
      <p class="note"><?=GetMessage("CFL_SET_POPUP_WINDOW_DESCRIPTION")?></p>
   <?php $obJSPopup->StartContent();?>
      <table border="0" cellpadding="2" cellspacing="0" class="bx-width100 internal">
         <thead>
            <tr class="heading">
               <td style="width: 10%;">&nbsp;</td>
               <td style="width: 40%;"><b><?=GetMessage("CFL_EDIT_SECTION")?></b></td>
               <td style="width: 40%;"><b><?=GetMessage("CFL_EDIT_FORUM")?></b></td>
               <td style="width: 10%;">&nbsp;</td>
            </tr>
         </thead>
      </table>
      <div id="bx_forumslist_layout" class="bx-menu-layout">
         <?php $iCount = 0;?>
         <?php foreach ($arData["ITEMS"] as $arItem):?>
            <?php
            $iItemsCNT++;
            $iCount++;
            ?>
            <div class="bx-menu-placement" id="bx_item_placement_<?=$iCount?>">
               <div class="bx-edit-menu-item" id="bx_item_row_<?=$iCount?>">
                  <table id="bx_forumslist_layout_tbl_<?=$iCount?>" class="bx-width100 internal forumslist-table">
                     <tr>
                        <td style="width: 10%;">
                           <input type="hidden" name="ids[]" value="<?=$iCount?>" />
                           <?=$iCount?>
                        </td>
                        
                        <td valign="top" style="width: 40%;">
                           <select name="section_<?=$iCount?>" style="width: 100%;">
                              <?php foreach ($arSections as $iSectionID => $arSection):?>
                                 <option value="<?=$iSectionID?>"<?=(($iSectionID == $arItem["section"]) ? " selected=\"selected\"" : "")?><?=(strlen($arSection["STYLE"]) > 0 ? 'st yle="' . $arSection["STYLE"] . '"' : '')?>>
                                    <?=$arSection["NAME"]?>&nbsp;[<?=$iSectionID?>]
                                 </option>
                              <?php endforeach;?>
                           </select>
                        </td>
                        
                        <td valign="top" style="width: 40%;">
                           <select name="forum_<?=$iCount?>" style="width: 100%;">
                              <?php foreach ($arForums as $iForumID => $arForum):?>
                                 <option value="<?=$iForumID?>"<?=(($iForumID == $arItem["forum"]) ? " selected=\"selected\"" : "")?>>
                                    <?=$arForum["NAME"]?>&nbsp;[<?=$iForumID?>]
                                 </option>
                              <?php endforeach;?>
                           </select>
                        </td>
                        
                        <td style="width: 10%;">
                           <span on click="itemDelete(<?=$iCount?>)" class="rowcontrol delete" title="<?=GetMessage("CFL_ITEM_DELETE")?>"></span>
                        </td>
                     </tr>
                  </table>
               </div>
            </div>
         <?php endforeach;?>
      </div>
      <br />
      <input type="button" on Click="itemAdd();" value="<?=GetMessage("CFL_ITEM_ADD")?>" />
      <input type="hidden" id="bx_item_cnt" value="<?=$iItemsCNT?>" />
   <?php $obJSPopup->StartButtons();?>
      <input type="submit" value="<?=GetMessage("CFL_SET_SUBMIT")?>" on click="return jsFLEditor.__saveChanges();" />
      <?php $obJSPopup->ShowStandardButtons(array("cancel"));?>
   <?php $obJSPopup->EndButtons();?>
</form>
<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_admin_js.php");
Также данный файл содержит подключение скрипта settings_load.js и файла-стилей settings.css. Скрипт settings_load.js содержит методы для формирования массива значений параметра (arItems), "ликвидации" повторяющихся значений (tmpArray) и сериализации этих значений в строку (jsFLEditor.__serialize).
var jsFLEditor = {
   arData: null,
   obForm: null,
   
   __serialize: function(obj) {...},
   
   __saveChanges: function() {...}
}
Файл settings.css содержит стили кнопки удаления строки (системные стили в диалоговом окне оказались не доступны).

Таким образом механизм обработки параметров данного типа получается следующим:
1. Скрипт-обработчик параметров компонента встречает запись о параметре типа CUSTOM, загружает файл, указанный в опции JS_FILE и вызывает callback-функцию, указанную в опции JS_EVENT. При вызове в функцию передаётся объект с данными, указанными в опции JS_DATA.
2. Callback-функция создаёт объект window.jsForumsListEditor, конструктор которого размещает на основной форме настройки параметров компонента кнопку "Изменить" для редактирования значения параметра.
custom_param_001.png
3. По нажатию на кнопку создаётся и отображается на экране экземпляр окна диалога new BX.CDialog({}). В этом окне, в соответствии с параметрами вызова диалога, подгружается форма  редактирования значений (settings.php).
4. После заполнения формы и нажатия на кнопку "Сохранить", выполняется запись значения в сериализованном виде (jsFLEditor.__saveChanges) и закрытие диалогового окна.
custom_param_002.png

Назад в раздел

Подписаться на новые материалы раздела:
Загрузка...