Open kulbergArt opened 9 months ago
Основная затея - унификация кода, минимизация разнообразных пуговок, которые в дальнейшем поддерживать будет все сложнее и сложнее.
Завтра Тимофей нам скажет, что ему не нравится что-нибудь и давайте поменяем в этом диалоге Х на Y. Все бы ничего, но таких итераций мы делаем 100500 в проекте уже много лет, после чего количество пуговок такое, что поддерживать это дальше все сложнее и сложнее. Объем кода растет, банальная правка приводит к тому, что надо поправить 100500 мест или сделать какие-то доп кастыли к текущему. Каждый контрол начинает работать по своему и подчиняться каким-то своим кастылям.
Завтра Тимофей мне скажет, что надо добавить какой-то там диалог.... и для его верстки я буду ждать Артема, Артем будет ждаь Диму, потом это все ко мне приедет, я это сделаю, Тимофей скажет что ему непонравилось, я буду ждать Артема, Артем Диму... Выглядит не очень производительно. По моему скромному мнению надо иметь какой-то базовый набор контролов, чтобы я мог легко поправить непонравившийся диалог без дополнительны приседаний (имею ввиду несложные правки). В случае же с кастомной версткой каждого диалога мы имеем много возможностей по кастомизации и кучу гемора по сапорту, если он требуется.
Оверхед на каждый диалог в виде повторяемых элементов. Если мы это все рендерим в DOM то наверно пофиг, но если мы все это кладем в Javascript - объем растет... Не всегда понятно какой диалог надо на страницу, т.к. мы не знаем какие кнопки пользователь будет жать. Рендерить все диалоги сразу только потому что - затея такая себе ИМХО. В данный момент размер самой либы jBox в сжатом состоянии примерно 50кб. При этом либа выполняет функции диалогов, уведомлений, тултипов. (Для справки наш узкий скролбар в диалоге поиска 70кб, свайпер на панели - 234кб, а ВЕСЬ код мобильной поверх либ - 160кб). Справедливости ради замечу, что для трепыхания jbox надо jquery размером 90кб, но мы и так его используем, т.к. везде пишем на нем (за искл. некоторых моментов) потому что это ускоряет написание и совместимость.
Если у вас есть какие-то аргументы в тему против или за - давайте обсудим. Вариант "что-то плохо с мобильными системами" - можем подумать как это можно улучшить.
Объекты jbox умеют темы. У каждого объекта может быть задано поле theme при создании. Значение этого поля будет добавлено в класс объекта в DOM. Класс добавляетя к обертке .jBox-wrapper в виде jBox-имя-темы - например для уведомления добавится это: jBox-wrapper jBox-Notice jBox-NoticeSmartlab jBox-hasTitle jBox-Notice-color jBox-Notice-green, где NoticeSmartlab - имя темы. Пример как работают наши кастомные уведомления можно увидеть в notification.js. Требуется:
Собираем все это вместе и получаем типа такого: example.zip
Ок, теперь мы знаем что такое темы. Давайте посмотрим на доп функционал, например диалоги. Для примера рассмотрим confirm диалог, который реализован плагином (находится в составе jbox). На примере портфелей portfolio.js portfolio.zip
var commentStockDialog = new jBox('Confirm',
{
id: 'commentSharesDialog',
title: dialogTitle,
confirmButton: 'Сохранить',
deleteButton: 'Удалить',
cancelButton: 'Отмена',
closeOnConfirm: true,
content:'<textarea></textarea>',
_onCreated: function ()
{
// Add a footer to the jBox container
this.footer = jQuery('<div class="jBox-Confirm-footer"/>');
jQuery('<div class="jBox-Confirm-button jBox-Confirm-button-cancel"/>').html(this.options.cancelButton).click(function () { this.options.cancel && this.options.cancel(); this.close(); }.bind(this)).appendTo(this.footer);
this.deleteButton = jQuery('<div class="jBox-Confirm-button jBox-Confirm-button-delete"/>').html(this.options.deleteButton).click(function() { this.options.delete(); this.close()}.bind(this)).appendTo(this.footer);
this.submitButton = jQuery('<div class="jBox-Confirm-button jBox-Confirm-button-submit"/>').html(this.options.confirmButton).appendTo(this.footer);
this.footer.appendTo(this.container);
},
Как мы видем - можно перекрыть создание диалога и вкорячить свои кнопки. Таким образом можно подгадать и вкорячить вообще все свои контролы и сделать дефолтный диалог с закрывашками и т.п. в котором менять только содержимое.
Короче говоря пилим тему типа smart-lab или как-то так. Далее подвешиваем ее к параметрам диалогов и оно работает как работает. Как-то стандартно городим 1 диалог в стиле плагина Confirm и городим все окошки на нем, например.
Окна можно городить вообще без кнопок и т.п. Просто в этом экзампле с кнопками. В футер можно подать любой хтмл который указывается в опциях как footer. Вообще классно открыть jBox.js и поглядеть какие там опции есть - многими можно рулить.
example.zip Добавил экзампл кастомного диалога (опций по минимуму). Т.е. все по образу и подобию confirm. Для опоры темы появилась jBox-Dialog если в DOM посмотреть. Условно всякие падинги можно вешать так же как и на jBox-Confirm и прочее и отдельные можно вешать на свои темы.
@cdb2
@kulbergArt
Внимание! Был изменен (сокращен) js обработки закрытия кастомного поп-апа!
Прежде чем выкатывать добавить во всех модальных окнах .custom-pop-up
элементам custom-pop-up__cover
и custom-pop-up__close
:
js-close-custom-pop-up
если не использует jBoxjs-close-custom-pop-up-jBox
если использует jBox8) Модальное окно. Класс .custom-pop-up
Для унификации модальных окон следует создавать следующую структуру:
<div class="custom-pop-up any-class">
<div class="custom-pop-up__body any-class__body">
<div class="custom-pop-up__cover"></div>
<div class="custom-pop-up__content any-class__content">
<button class="custom-pop-up__close"></button>
<div class="custom-pop-up__title">Заголовок</div>
<!-- Контент поп-апа -->
</div>
</div>
</div>
Элемент <div class="custom-pop-up__title">Заголовок</div>
- опциональный!
где к классу .custom-pop-up
и его потомкам (по БЭМ) привязываются обработчики событий и основные стили из
scss/base/global.scss и
js/files/common.js
Для того, чтобы кнопка или другой элемент (находящийся в поп-апе) закрывал поп-ап при клике ему надо добавить класс js-close-custom-pop-up
а если поп-ап помещен внутрь jBox
заменить класс js-close-custom-pop-up
на js-custom-pop-up-close-jBox
.
Где any-class
- любой микс-класс по БЭМ для дополнительной стилизации, следует заменить или удалить.
Поп-ап должен быть обязательно добавлен в HTML страницы! Есть два оскновных варианта использования:
id
, например <div id="unique-pop-up" class="custom-pop-up">
js-close-custom-pop-up
js-pop-up-opener
и атрибут data-target-id
, содержащий модального окна, для нашего примера: data-target-id="unique-pop-up"
jBox
:
id
, класс .custom-pop-up--open
и атрибут style="display: none;"
Пример: <div id="login-pop-up" class="custom-pop-up custom-pop-up--open" style="display: none;">
и удалить класс _open
js-close-custom-pop-up-jBox
jBox
с кастомным поп-апом воспользаваться функцией initJBoxWithCustomPopUp(options, bindControls)
js-pop-up-opener
или заменяем на другой селектор который прередаем в поле attach
при инициализации jBox
NOTE: Если надо просто информировать пользователя, предпочтительней использовать
custom-pop-up
безjBox
.
А если надо навесить контролы (особенно если они уже написаны) от использоватьcustom-pop-up
внутриjBox
.
Декоратор для инициализации jBox с кастомным поп-апом .custom-pop-up
внутри
/**
* Декоратор для инициализации jBox с кастомным поп-апом `.custom-pop-up` внутри
* @param {Map<String dynamic>} options - объект с опциями и контролами
* @param {*} bindControls - анонимная функция инициализации контролов,
* в которой надо связать кнопки и контролы, переданные в `options`
*
* Пример инициализации с кнопкой `enterButton` и ее контролом `enter`:
* ```js
* initJBoxWithCustomPopUp({
* content: $('#pop-up'),
* attach: $('#pop-up-opener'),
* enterButton: '',
* enter: function () { alert('Нажата кнопка "Войти"'); },
* },
* function () {
* this.enterButton = this.container.find('.login__submit').click(function () { this.options.enter() }.bind(this));
* }
* );
* ```
*
* Пример когда мы навешиваем инициализацию на клик по кнопке
* (при этом поле `attach` отсутствует в опцииях, но надо явно вызывать dialog.open();):
* ```js
* $('#pop-up-opener').click( function () {
* let dialog = initJBoxWithCustomPopUp({
* content: $('#login-pop-up'),
* enterButton: '',
* enter: function () { alert('Нажата кнопка "Войти"'); },
* },
* function () {
* this.enterButton = this.container.find('.login__submit').click(function () { this.options.enter() }.bind(this));
* }
* );
* dialog.open();
* });
* ```
*/
function initJBoxWithCustomPopUp(options, bindControls) {
let dialog = new jBox('Modal', {
...options,
theme: 'with-custom-pop-up',
maxWidth: '100%',
overlay: false,
closeButton: '',
onCreated: function () {
bindControls.bind(this)();
this.closeButton = this.container.find('.js-custom-pop-up-close-jBox').click(function () { this.close() }.bind(this));
},
});
return dialog;
}
Тема jBox
для .custom-pop-up
При инициализации jBox
используется поле theme: 'with-custom-pop-up'
, что добавляет в jBox
css-класс .jBox-with-custom-pop-up
и по нему переопределяются стили контейнера:
/* Переопределение стилей для jBox-with-custom-pop-up */
.jBox-with-custom-pop-up {
width: auto !important;
height: auto !important;
position: fixed !important;
top: 0 !important;
left: 0 !important;
bottom: 0 !important;
right: 0 !important;
border-radius: 8px;
overflow: hidden;
}
.jBox-with-custom-pop-up .jBox-container,
.jBox-with-custom-pop-up .jBox-content {
width: 100%;
height: 100%;
background: transparent !important;
box-shadow: none !important;
}
9) кнопка с классом js-pop-up-opener
открывает поп-ап .custom-pop-up
с id, который указан в атрибуте data-target-id
данной кнопки. (см описание .custom-pop-up
).
Обработчик этой кнопки (без использования jBox
) и поп-апа занимает всего 20 строк кода!
На данный момент, есть 2 окна, которые требуют адаптации: 1) Окно логина: https://bdemetrix.github.io/sl_mobile/build/ 2) Окно удаления комментария: https://bdemetrix.github.io/sl_mobile/build/post.html
Но скоро будет ещё одно мини окошко, без кнопок и т.д.