Битрикс: красивая страница админки
Рассматривается сферическая страница в вакууме. Нет никакого модуля или компонента. Только один файл (скрипт) с формой и кодом, который эту форму обрабатывает. Если создавать страницу админки в своём модуле, то файлы-скрипты задействованы будут другие, но приёмы оформления (именно на них сделан акцент статьи) остаются те же самые.
Добавление своей страницы в админке
Для добавления своей страницы нужно сделать три вещи: 1) технический скрипт, запускающий саму страницу; 2) скрипт с кодом страницы; 3) ссылка на страницу в самой админке битрикса.
Добавляем технический скрипт. Внутри в нём только отсылка к скрипту, в котором расположена вся логика страницы. Мой пример: /bitrix/admin/captcha_settings.php с содержимым:
<?php
require $_SERVER['DOCUMENT_ROOT'] . '/local/php_interface/include/captcha_settings/index.php';
Далее создаём скрипт /local/php_interface/include/captcha_settings/index.php. Пустая минимальная заготовка:
<?php
/**
* Самописная страница админки битрикса
*/
declare(strict_types=1);
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin.php';
/**
* @var CMain $APPLICATION
*/
$APPLICATION->SetTitle('Красивая админка');
?><div>Заготовка страницы админки</div>
<?php
require $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_admin.php';
Третий компонент для нашей страницы админки - добавить ссылку на эту страницу в меню внутри битриксовой админки. Меню ссылается именно на технический скрипт - тот, в котором нет логики, а только подключение другого скрипта. Для этого нужно подписаться на встроенное событие построения меню админки. Внутри события в массив добавляем свой пункт меню. Пример без сторонних классов и методов (хотя, конечно, лучше всё красиво распределять по классам для порядка в коде) нужно разместить, например, в /bitrix/php_interface/init.php. Примеры подписывания на события, когда есть классы и методы, реализующие обработку события.
// Пункт в админке в разделе "Сервисы"
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
'main',
'OnBuildGlobalMenu',
function (&$aGlobalMenu, &$aModuleMenu) use ($APPLICATION) {
if ($APPLICATION->GetFileAccessPermission('/bitrix/admin/captcha_settings.php') > 'D') {
// Проверили наличие прав у пользователя на данную страницу
$aModuleMenu[] = [
'parent_menu' => 'global_menu_services',
'sort' => 150,
'text' => 'Настройка каптч',
'title' => 'Настройка каптч',
'url' => 'captcha_settings.php',
'more_url' => [],
'icon' => 'sonet_menu_icon',
'page_icon' => '',
];
}
}
);
Тут используется древнее битриксовое событие OnBuildGlobalMenu. Сами себе придумываем название для пункта меню, порядок сортировки, и можем позаимствовать иконку из недр битрикса, если свою пока делать некогда. sonet_menu_icon - это один из блоков из картинки /bitrix/panel/main/images/icons-sprite-14.png, который объявлен в /bitrix/panel/main/admin.css
Итогом этих трёх шагов становится добавленный пункт меню и сама страница-заготовка:
За кадром остаётся вопрос назначения прав на эту страницу админки. Если коротко, то это делается через [Контент / Структура сайта / Файлы и папки]. Переходим в каталог /bitrix/admin. Находим свою страницу (captcha_settings). Рядом с файлом кнопка-бутерброд и там "Права на доступ продукта". Нужным группам пользователей разрешаем. А тем, кому это не нужно видеть - запрещаем.
Стилизованное наполнение страницы
Теперь некрасивую заготовку превратим в современный дизайн административных страниц. Я опишу лишь несколько элементов с отсылками к их описаниям официальной документации. В этой статье не затрагиваем стилизацию таблиц. Только форма с полями и какие-то тексты-пояснения на странице.
Первое, что нужно сделать - сделать красивый фон-подложку. Описываю свой вариант, который нашёл методом научного тыка. Будет полезно, если в комментариях к этой статье кто-то поделится более универсальным вариантом, если такой существует.
Заменим тело страницы на такой код:
<?php
$request = \Bitrix\Main\Context::getCurrent()->getRequest();
\Bitrix\Main\UI\Extension::load([
'ui.forms',
'ui.layout-form',
]);
?>
<form method="post" name="post_form" action="<?php echo $request->getRequestUri();?>">
<div class="ui-form ui-form-section">
<div>Заготовка страницы админки</div>
</div>
</form>
Вся эта страница админки - это будет одна большая форма. Сразу пропишем параметры формы. Обработчиком формы будет этот же скрипт. Тут мы подключили пару расширений из битриксовой UI-библиотеки. Это позволило получить белый фон в форме.
Далее создадим красивый заголовок и под ним в две колонки: подзаголовок и инпут checkbox. Мне удалось найти красивый заголовок только в расширении ui.sidepanel-content. Наверняка, есть и другие, - помогите их найти, посоветуйте в комментариях. Разметка по строкам и колонкам доступны благодаря расширению ui.layout-form, которое подключили ранее. Внешний вид для чекбокса берётся из стилей расширения ui.forms. Код примет такой вид:
<?php
$request = \Bitrix\Main\Context::getCurrent()->getRequest();
\Bitrix\Main\UI\Extension::load([
'ui.forms',
'ui.layout-form',
'ui.sidepanel-content',
]);
?>
<form method="post" name="post_form" action="<?php echo $request->getRequestUri();?>">
<div class="ui-form ui-form-section">
<div class="ui-form-row"><div class="ui-slider-heading-3">Какие запросы проверять</div></div>
<div class="ui-form-row">
<div class="ui-form-label"><div class="ui-ctl-label-text">Активность</div></div>
<div class="ui-form-content">
<div class="ui-form-row">
<label class="ui-ctl ui-ctl-checkbox">
<input type="checkbox" class="ui-ctl-element" name="captcha_all_requests">
<div class="ui-ctl-label-text">Проверять каждый запрос до тех пор, пока не появится признак успешного прохождения проверки</div>
</label>
</div>
</div>
</div>
</div>
</form>
Ещё расширим форму. Добавим второй заголовок, так же инпут checkbox, но уже с дополнительной ссылкой и ещё пару текстовых инпутов со своими подписями. Все нужные стили уже есть благодаря трём подключенным ранее расширениям битрикса. HTML-разметка формы:
<form method="post" name="post_form" action="<?php echo $request->getRequestUri();?>">
<div class="ui-form ui-form-section">
<div class="ui-form-row"><div class="ui-slider-heading-3">Какие запросы проверять</div></div>
<div class="ui-form-row">
<div class="ui-form-label"><div class="ui-ctl-label-text">Активность</div></div>
<div class="ui-form-content">
<div class="ui-form-row">
<label class="ui-ctl ui-ctl-checkbox">
<input type="checkbox" class="ui-ctl-element" name="captcha_all_requests">
<div class="ui-ctl-label-text">Проверять каждый запрос до тех пор, пока не появится признак успешного прохождения проверки</div>
</label>
</div>
</div>
</div>
<div class="ui-form-row"><div class="ui-slider-heading-3">Google Recaptcha v3</div></div>
<div class="ui-form-row">
<div class="ui-form-label">
<div class="ui-ctl-label-text">Активность</div>
</div>
<div class="ui-form-content">
<div class="ui-form-row">
<label class="ui-ctl ui-ctl-checkbox">
<input
type="checkbox"
class="ui-ctl-element"
name="google_active"
>
<div class="ui-ctl-label-text">
Активация будет использовать бесплатный месячный лимит запросов
</div>
</label>
<a
href="https://www.google.com/recaptcha/admin/site/12345678"
class="ui-form-link"
target="_blank"
>личный кабинет сервиса</a>
</div>
</div>
</div>
<div class="ui-form-row">
<div class="ui-form-label"><div class="ui-ctl-label-text">Доступы</div></div>
<div class="ui-form-content">
<div class="ui-form-row">
<div class="ui-form-label"><div class="ui-ctl-label-text">Ключ сайта</div></div>
<div class="ui-ctl ui-ctl-textbox ui-ctl-w50">
<input type="text" class="ui-ctl-element" name="google_site_key" value="">
</div>
</div>
<div class="ui-form-row">
<div class="ui-form-label"><div class="ui-ctl-label-text">Секретный ключ</div></div>
<div class="ui-ctl ui-ctl-textbox ui-ctl-w50">
<input type="text" class="ui-ctl-element" name="google_secret_key" value="">
</div>
</div>
</div>
</div>
</div>
</form>
Форма стала выглядеть так:
Добавим ещё пару элементов из расширения ui.alerts: сообщение с иконкой. Представим, что есть переменная, которая определяет успешный вид сообщения или тревожный вид сообщения. Разметка сообщения получится такой:
<div class="ui-form-row">
<div class="ui-alert <?php echo $isGoogleFreePeriod ? 'ui-alert-success ui-alert-icon-info' : 'ui-alert-warning ui-alert-icon-warning';?>">
<span class="ui-alert-message">
<?php echo $isGoogleFreePeriod
? 'Ещё не исчерпан бесплатный месячный лимит запросов в Google Recaptcha v3'
: 'Бесплатные запросы на этот месяц закончились';?>
</span>
</div>
</div>
Какие иконки тут могут быть?! Можно догадаться только заглянув в исходные стили: ui-alert-icon-warning, ui-alert-icon-danger, ui-alert-icon-info и ui-alert-icon-forbidden.
Успешный вид сообщения на странице выглядит так:
Есть и другого типа иконка-подсказка из расширения ui.hint. Добавим одну такую после подписи Активность. Разметка:
<div class="ui-form-label">
<div class="ui-ctl-label-text">Активность</div>
<a href="https://developers.google.com/recaptcha/docs/v3?hl=ru" target="_blank">
<span class="ui-hint-icon"></span>
</a>
</div>
Перечисленных элементов вполне достаточно для начала, чтобы сделать кастомную страницу админки в битриксе. И при этом задействовать все встроенные в битрикс стили. Во всём примере не было написано ни единого собственного стиля - всё из поставки битрикса. По ссылкам в статье можно попасть в документацию по этим расширениям и там найти ещё уйму других.
Интерактив
Мы создали кастомную страницу с формой. Но пока не сделали сохранения. Приведу пример, как можно добавить JavaScript, отправить форму на этот же скрипт, обработать результат и отобразить пользователю сообщение о результате.
Внутри ui-form-section добавляем последним узлом кнопку со стандартными классами для оформления и одним своим классом, чтобы на него навесить потом обработчик:
<div class="ui-btn-container">
<button type="submit" class="ui-btn ui-btn-success js-btn-save">Сохранить</button>
</div>
Чтобы стилизовать кнопку, подключим расширение ui.buttons. И сразу ещё подключим расширение для показа всплывающего сообщения - ui.dialogs.messagebox (в этом расширении есть не только стили, но и JavaScript функции). В разметке всё готово. Перед закрывающим тегом <form> (хотя можно и в другое место) добавляем тег <script> с кодом, котрый:
- Описывает некий глобальный объект, внутри которого находятся все полезные функции
- Функция init() из набора выполняет начальную инициализацию всего нужного на странице: в нашем случае только навешивание обработчика клика на кнопку
- Функция initClickSubmitButton() выполняет код, который добавляет обработчик обытия клика на кнопку
- Функция submitFormHandler() выполняет сбор данных с формы и отправку запроса на сервер. Показал полностью ручой сбор данных для каждого из четырёх инпутов, чтобы корректно обработать чекбосы. Внутри есть пример показа битриксового диалогового окна - в примере оно отобразит результат обработки, который придёт с сервера.
- Битриксовая функция BX.ready(function () {} выполнится один раз при старте страницы и запустит нашу функию инициализации всего необходимого.
Как видно тут чистый JavaScript (без jQuery и каких-либо ещё библиотек) и несколько функций от битрикса:
<script>
window.captchaSettings = {
init: function () {
"use strict";
window.captchaSettings.initClickSubmitButton();
},
initClickSubmitButton: function () {
"use strict";
const $buttons = document.querySelectorAll(".js-btn-save");
Array.prototype.forEach.call($buttons, function ($button) {
$button.addEventListener("click", window.captchaSettings.submitFormHandler);
});
},
submitFormHandler: function (event) {
"use strict";
if (!!event) {
event.preventDefault();
const $form = document.querySelector("[name=\"post_form\"]");
let url = "";
if (!!$form && $form.getAttribute("action")) {
url = $form.getAttribute("action");
}
let request = new XMLHttpRequest();
let formData = new FormData();
let isCaptchaAllRequests = "N";
const captchaAllRequestsInput = document.querySelector("[name=\"captcha_all_requests\"]");
if (!!captchaAllRequestsInput) {
isCaptchaAllRequests = captchaAllRequestsInput.checked ? "Y" : "N";
}
let isGoogleActive = "N";
const activeGoogleInput = document.querySelector("[name=\"google_active\"]");
if (!!activeGoogleInput) {
isGoogleActive = activeGoogleInput.checked ? "Y" : "N";
}
let googleSiteKey = "";
const googleSiteKeyInput = document.querySelector("[name=\"google_site_key\"]");
if (!!googleSiteKeyInput) {
googleSiteKey = googleSiteKeyInput.value;
}
let googleSecretKey = "";
const googleSecretKeyInput = document.querySelector("[name=\"google_secret_key\"]");
if (!!googleSecretKeyInput) {
googleSecretKey = googleSecretKeyInput.value;
}
formData.append("captcha_all_requests", isCaptchaAllRequests);
formData.append("google_active", isGoogleActive);
formData.append("google_site_key", googleSiteKey);
formData.append("google_secret_key", googleSecretKey);
request.open("POST", url, true);
request.responseType = "json";
request.send(formData);
request.onload = function () {
if (request.readyState === 4 && request.status === 200) {
const jsonResponse = request.response;
if (jsonResponse.hasOwnProperty("success") && jsonResponse.success) {
let message = "";
if (jsonResponse.hasOwnProperty("messages") && jsonResponse.messages) {
message = jsonResponse.messages.join("; ");
}
BX.UI.Dialogs.MessageBox.show(
{
message: "<div class=\"ui-alert ui-alert-success\">" +
"<span class=\"ui-alert-message\">" + message + "</span>" +
"</div>",
title: "Сохранение",
modal: true,
buttons: BX.UI.Dialogs.MessageBoxButtons.OK,
onOk: function (messageBox) {
messageBox.close();
}
}
);
} else {
// Запрос выполнился, но там какие-то ошибки
BX.UI.Dialogs.MessageBox.show(
{
message: "<div class=\"ui-alert ui-alert-danger\">" +
"<span class=\"ui-alert-message\">В результате запроса получены ошибки</span>" +
"</div>",
title: "Сохранение",
modal: true,
buttons: BX.UI.Dialogs.MessageBoxButtons.OK,
onOk: function (messageBox) {
messageBox.close();
}
}
);
}
} else {
// Запрос не выполнился
BX.UI.Dialogs.MessageBox.show(
{
message: "<div class=\"ui-alert ui-alert-danger\">" +
"<span class=\"ui-alert-message\">Запрос не выполнился. " + request.status +
": " + request.statusText + "</span>" + "</div>",
title: "Сохранение",
modal: true,
buttons: BX.UI.Dialogs.MessageBoxButtons.OK,
onOk: function (messageBox) {
messageBox.close();
}
}
);
}
}
}
}
};
BX.ready(function () {
"use strict";
window.captchaSettings.init();
});
</script>
Сам по себе JavaScript не отработает полностью без соотвествующей обработки на бэкенде. Поэтому в этот же скрипт добавим обработку на PHP:
// Сохраняем настройки
if ($request->isPost()) {
$arResponse = ['success' => false, 'messages' => []];
$isError = false;
if (
($requestCaptchaAllRequests = $request->getPost('captcha_all_requests'))
&& ('Y' === $requestCaptchaAllRequests || 'N' === $requestCaptchaAllRequests)
) {
try {
\Bitrix\Main\Config\Option::set('custom_main', 'settings_captcha_all_requests', $requestCaptchaAllRequests);
} catch (\Exception $exception) {
$isError = true;
$arResponse['messages'][] = 'Fail set "settings_captcha_all_requests": ' . $exception->getMessage();
}
}
if (
($requestGoogleActive = $request->getPost('google_active'))
&& ('Y' === $requestGoogleActive || 'N' === $requestGoogleActive)
) {
try {
\Bitrix\Main\Config\Option::set('custom_main', 'settings_captcha_google_active', $requestGoogleActive);
} catch (\Exception $exception) {
$isError = true;
$arResponse['messages'][] = 'Fail set "settings_captcha_google_active": ' . $exception->getMessage();
}
}
$requestGoogleSiteKey = $request->getPost('google_site_key') ?? '';
try {
\Bitrix\Main\Config\Option::set('custom_main', 'settings_captcha_google_site_key', $requestGoogleSiteKey);
} catch (\Exception $exception) {
$isError = true;
$arResponse['messages'][] = 'Fail set "settings_captcha_google_site_key": ' . $exception->getMessage();
}
$requestGoogleSecretKey = $request->getPost('google_secret_key') ?? '';
try {
\Bitrix\Main\Config\Option::set('custom_main', 'settings_captcha_google_secret_key', $requestGoogleSecretKey);
} catch (\Exception $exception) {
$isError = true;
$arResponse['messages'][] = 'Fail set "settings_captcha_google_secret_key": ' . $exception->getMessage();
}
if (!$isError) {
$arResponse['success'] = true;
$arResponse['messages'][] = 'Настройки сохранены';
}
try {
$strResponse = \Bitrix\Main\Web\Json::encode($arResponse);
} catch (\Exception $exception) {
AddMessage2Log('Не удалось получить Json: ' . $exception->getMessage());
$strResponse = '{}';
}
global $APPLICATION;
$APPLICATION->restartBuffer();
header('Content-Type: application/json; charset=UTF-8');
\CMain::finalActions($strResponse);
}
Тут мы просто ловим входящие параметры и сохраняем их в базу данных (в данном случае через битриксовый механизм сохранения настроек модуля). Своего модуля у нас нет, поэтому сохраняем всё в выдуманный модуль custom_main, - да так тоже работает в битриксе. На выходе возвращаем в браузер ответ в виде JSON.
Теперь форма стала рабочей: она сохраняется!
Но ещё нужно при открытии страницы в форму подставлять те значения, которые уже есть в настройках в базе данных.
В итоге вся страница (PHP + HTML + JavaScript) этого примера примет такой вид:
<?php
/**
* Самописная страница админки битрикса
*/
declare(strict_types=1);
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin.php';
/**
* @var CMain $APPLICATION
*/
$APPLICATION->SetTitle('Красивая админка');
$request = \Bitrix\Main\Context::getCurrent()->getRequest();
\Bitrix\Main\UI\Extension::load([
'ui.forms',
'ui.layout-form',
'ui.sidepanel-content',
'ui.alerts',
'ui.hint',
'ui.buttons',
'ui.dialogs.messagebox',
]);
$isGoogleFreePeriod = true;
// Сохраняем настройки
if ($request->isPost()) {
$arResponse = ['success' => false, 'messages' => []];
$isError = false;
if (
($requestCaptchaAllRequests = $request->getPost('captcha_all_requests'))
&& ('Y' === $requestCaptchaAllRequests || 'N' === $requestCaptchaAllRequests)
) {
try {
\Bitrix\Main\Config\Option::set('custom_main', 'settings_captcha_all_requests', $requestCaptchaAllRequests);
} catch (\Exception $exception) {
$isError = true;
$arResponse['messages'][] = 'Fail set "settings_captcha_all_requests": ' . $exception->getMessage();
}
}
if (
($requestGoogleActive = $request->getPost('google_active'))
&& ('Y' === $requestGoogleActive || 'N' === $requestGoogleActive)
) {
try {
\Bitrix\Main\Config\Option::set('custom_main', 'settings_captcha_google_active', $requestGoogleActive);
} catch (\Exception $exception) {
$isError = true;
$arResponse['messages'][] = 'Fail set "settings_captcha_google_active": ' . $exception->getMessage();
}
}
$requestGoogleSiteKey = $request->getPost('google_site_key') ?? '';
try {
\Bitrix\Main\Config\Option::set('custom_main', 'settings_captcha_google_site_key', $requestGoogleSiteKey);
} catch (\Exception $exception) {
$isError = true;
$arResponse['messages'][] = 'Fail set "settings_captcha_google_site_key": ' . $exception->getMessage();
}
$requestGoogleSecretKey = $request->getPost('google_secret_key') ?? '';
try {
\Bitrix\Main\Config\Option::set('custom_main', 'settings_captcha_google_secret_key', $requestGoogleSecretKey);
} catch (\Exception $exception) {
$isError = true;
$arResponse['messages'][] = 'Fail set "settings_captcha_google_secret_key": ' . $exception->getMessage();
}
if (!$isError) {
$arResponse['success'] = true;
$arResponse['messages'][] = 'Настройки сохранены';
}
try {
$strResponse = \Bitrix\Main\Web\Json::encode($arResponse);
} catch (\Exception $exception) {
AddMessage2Log('Не удалось получить Json: ' . $exception->getMessage());
$strResponse = '{}';
}
global $APPLICATION;
$APPLICATION->restartBuffer();
header('Content-Type: application/json; charset=UTF-8');
\CMain::finalActions($strResponse);
}
?>
<form method="post" name="post_form" action="<?php echo $request->getRequestUri();?>">
<div class="ui-form ui-form-section">
<div class="ui-form-row"><div class="ui-slider-heading-3">Какие запросы проверять</div></div>
<div class="ui-form-row">
<div class="ui-form-label"><div class="ui-ctl-label-text">Активность</div></div>
<div class="ui-form-content">
<div class="ui-form-row">
<label class="ui-ctl ui-ctl-checkbox">
<input
type="checkbox"
class="ui-ctl-element"
name="captcha_all_requests"
<?php echo 'Y' === \Bitrix\Main\Config\Option::get('custom_main', 'settings_captcha_all_requests') ? ' checked' : '';?>
>
<div class="ui-ctl-label-text">Проверять каждый запрос до тех пор, пока не появится признак успешного прохождения проверки</div>
</label>
</div>
</div>
</div>
<div class="ui-form-row"><div class="ui-slider-heading-3">Google Recaptcha v3</div></div>
<div class="ui-form-row">
<div class="ui-form-label">
<div class="ui-ctl-label-text">Активность</div>
<a href="https://developers.google.com/recaptcha/docs/v3?hl=ru" target="_blank">
<span class="ui-hint-icon"></span>
</a>
</div>
<div class="ui-form-content">
<div class="ui-form-row">
<div class="ui-alert <?php echo $isGoogleFreePeriod ? 'ui-alert-success ui-alert-icon-info' : 'ui-alert-warning ui-alert-icon-warning';?>">
<span class="ui-alert-message">
<?php echo $isGoogleFreePeriod
? 'Ещё не исчерпан бесплатный месячный лимит запросов в Google Recaptcha v3'
: 'Бесплатные запросы на этот месяц закончились';?>
</span>
</div>
</div>
<div class="ui-form-row">
<label class="ui-ctl ui-ctl-checkbox">
<input
type="checkbox"
class="ui-ctl-element"
name="google_active"
<?php echo 'Y' === \Bitrix\Main\Config\Option::get('custom_main', 'settings_captcha_google_active') ? ' checked' : '';?>
> <div class="ui-ctl-label-text">
Активация будет использовать бесплатный месячный лимит запросов
</div>
</label>
<a
href="https://www.google.com/recaptcha/admin/site/12345678"
class="ui-form-link"
target="_blank"
>личный кабинет сервиса</a>
</div>
</div>
</div>
<div class="ui-form-row">
<div class="ui-form-label"><div class="ui-ctl-label-text">Доступы</div></div>
<div class="ui-form-content">
<div class="ui-form-row">
<div class="ui-form-label"><div class="ui-ctl-label-text">Ключ сайта</div></div>
<div class="ui-ctl ui-ctl-textbox ui-ctl-w50">
<input
type="text"
class="ui-ctl-element"
name="google_site_key"
value="<?php echo \Bitrix\Main\Config\Option::get('custom_main', 'settings_captcha_google_site_key');?>"
>
</div>
</div>
<div class="ui-form-row">
<div class="ui-form-label"><div class="ui-ctl-label-text">Секретный ключ</div></div>
<div class="ui-ctl ui-ctl-textbox ui-ctl-w50">
<input
type="text"
class="ui-ctl-element"
name="google_secret_key"
value="<?php echo \Bitrix\Main\Config\Option::get('custom_main', 'settings_captcha_google_site_key');?>"
>
</div>
</div>
</div>
</div>
<div class="ui-btn-container">
<button type="submit" class="ui-btn ui-btn-success js-btn-save">Сохранить</button>
</div>
</div>
<script>
window.captchaSettings = {
init: function () {
"use strict";
window.captchaSettings.initClickSubmitButton();
},
initClickSubmitButton: function () {
"use strict";
const $buttons = document.querySelectorAll(".js-btn-save");
Array.prototype.forEach.call($buttons, function ($button) {
$button.addEventListener("click", window.captchaSettings.submitFormHandler);
});
},
submitFormHandler: function (event) {
"use strict";
if (!!event) {
event.preventDefault();
const $form = document.querySelector("[name=\"post_form\"]");
let url = "";
if (!!$form && $form.getAttribute("action")) {
url = $form.getAttribute("action");
}
let request = new XMLHttpRequest();
let formData = new FormData();
let isCaptchaAllRequests = "N";
const captchaAllRequestsInput = document.querySelector("[name=\"captcha_all_requests\"]");
if (!!captchaAllRequestsInput) {
isCaptchaAllRequests = captchaAllRequestsInput.checked ? "Y" : "N";
}
let isGoogleActive = "N";
const activeGoogleInput = document.querySelector("[name=\"google_active\"]");
if (!!activeGoogleInput) {
isGoogleActive = activeGoogleInput.checked ? "Y" : "N";
}
let googleSiteKey = "";
const googleSiteKeyInput = document.querySelector("[name=\"google_site_key\"]");
if (!!googleSiteKeyInput) {
googleSiteKey = googleSiteKeyInput.value;
}
let googleSecretKey = "";
const googleSecretKeyInput = document.querySelector("[name=\"google_secret_key\"]");
if (!!googleSecretKeyInput) {
googleSecretKey = googleSecretKeyInput.value;
}
formData.append("captcha_all_requests", isCaptchaAllRequests);
formData.append("google_active", isGoogleActive);
formData.append("google_site_key", googleSiteKey);
formData.append("google_secret_key", googleSecretKey);
request.open("POST", url, true);
request.responseType = "json";
request.send(formData);
request.onload = function () {
if (request.readyState === 4 && request.status === 200) {
const jsonResponse = request.response;
if (jsonResponse.hasOwnProperty("success") && jsonResponse.success) {
let message = "";
if (jsonResponse.hasOwnProperty("messages") && jsonResponse.messages) {
message = jsonResponse.messages.join("; ");
}
BX.UI.Dialogs.MessageBox.show(
{
message: "<div class=\"ui-alert ui-alert-success\">" +
"<span class=\"ui-alert-message\">" + message + "</span>" +
"</div>",
title: "Сохранение",
modal: true,
buttons: BX.UI.Dialogs.MessageBoxButtons.OK,
onOk: function (messageBox) {
messageBox.close();
}
}
);
} else {
// Запрос выполнился, но там какие-то ошибки
BX.UI.Dialogs.MessageBox.show(
{
message: "<div class=\"ui-alert ui-alert-danger\">" +
"<span class=\"ui-alert-message\">В результате запроса получены ошибки</span>" +
"</div>",
title: "Сохранение",
modal: true,
buttons: BX.UI.Dialogs.MessageBoxButtons.OK,
onOk: function (messageBox) {
messageBox.close();
}
}
);
}
} else {
// Запрос не выполнился
BX.UI.Dialogs.MessageBox.show(
{
message: "<div class=\"ui-alert ui-alert-danger\">" +
"<span class=\"ui-alert-message\">Запрос не выполнился. " + request.status +
": " + request.statusText + "</span>" + "</div>",
title: "Сохранение",
modal: true,
buttons: BX.UI.Dialogs.MessageBoxButtons.OK,
onOk: function (messageBox) {
messageBox.close();
}
}
);
}
}
}
}
};
BX.ready(function () {
"use strict";
window.captchaSettings.init();
});
</script>
</form>
<?php
require $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_admin.php';
По итогу этой статьи:
- Разобрались, какие есть UI-расширения битрикса, зачем они нужны и как их подключать
- Научились комбинировать блоки разметки, чтобы составить красивую страницу админки
- Научились работать со страницей из JavaScript'а
- Нучились сохранять данные после отправки их с фронта
- Научились пользоваться встроенным битриксовым диалоговым окном
Комментарии
Отправить комментарий