BDemetrix / BDemetrix.github.io

3 stars 2 forks source link

Адаптация всплывающих окно под jbox #53

Open kulbergArt opened 9 months ago

kulbergArt commented 9 months ago

На данный момент, есть 2 окна, которые требуют адаптации: 1) Окно логина: https://bdemetrix.github.io/sl_mobile/build/ 2) Окно удаления комментария: https://bdemetrix.github.io/sl_mobile/build/post.html

Но скоро будет ещё одно мини окошко, без кнопок и т.д.

image image

cdb2 commented 9 months ago

Документация jBox

  1. Зачем?

Основная затея - унификация кода, минимизация разнообразных пуговок, которые в дальнейшем поддерживать будет все сложнее и сложнее.

Завтра Тимофей нам скажет, что ему не нравится что-нибудь и давайте поменяем в этом диалоге Х на Y. Все бы ничего, но таких итераций мы делаем 100500 в проекте уже много лет, после чего количество пуговок такое, что поддерживать это дальше все сложнее и сложнее. Объем кода растет, банальная правка приводит к тому, что надо поправить 100500 мест или сделать какие-то доп кастыли к текущему. Каждый контрол начинает работать по своему и подчиняться каким-то своим кастылям.

Завтра Тимофей мне скажет, что надо добавить какой-то там диалог.... и для его верстки я буду ждать Артема, Артем будет ждаь Диму, потом это все ко мне приедет, я это сделаю, Тимофей скажет что ему непонравилось, я буду ждать Артема, Артем Диму... Выглядит не очень производительно. По моему скромному мнению надо иметь какой-то базовый набор контролов, чтобы я мог легко поправить непонравившийся диалог без дополнительны приседаний (имею ввиду несложные правки). В случае же с кастомной версткой каждого диалога мы имеем много возможностей по кастомизации и кучу гемора по сапорту, если он требуется.

Оверхед на каждый диалог в виде повторяемых элементов. Если мы это все рендерим в DOM то наверно пофиг, но если мы все это кладем в Javascript - объем растет... Не всегда понятно какой диалог надо на страницу, т.к. мы не знаем какие кнопки пользователь будет жать. Рендерить все диалоги сразу только потому что - затея такая себе ИМХО. В данный момент размер самой либы jBox в сжатом состоянии примерно 50кб. При этом либа выполняет функции диалогов, уведомлений, тултипов. (Для справки наш узкий скролбар в диалоге поиска 70кб, свайпер на панели - 234кб, а ВЕСЬ код мобильной поверх либ - 160кб). Справедливости ради замечу, что для трепыхания jbox надо jquery размером 90кб, но мы и так его используем, т.к. везде пишем на нем (за искл. некоторых моментов) потому что это ускоряет написание и совместимость.

Если у вас есть какие-то аргументы в тему против или за - давайте обсудим. Вариант "что-то плохо с мобильными системами" - можем подумать как это можно улучшить.

  1. Как делать темы.

Объекты 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);

        },

Как мы видем - можно перекрыть создание диалога и вкорячить свои кнопки. Таким образом можно подгадать и вкорячить вообще все свои контролы и сделать дефолтный диалог с закрывашками и т.п. в котором менять только содержимое.

cdb2 commented 9 months ago

Короче говоря пилим тему типа smart-lab или как-то так. Далее подвешиваем ее к параметрам диалогов и оно работает как работает. Как-то стандартно городим 1 диалог в стиле плагина Confirm и городим все окошки на нем, например.

cdb2 commented 9 months ago

Окна можно городить вообще без кнопок и т.п. Просто в этом экзампле с кнопками. В футер можно подать любой хтмл который указывается в опциях как footer. Вообще классно открыть jBox.js и поглядеть какие там опции есть - многими можно рулить.

cdb2 commented 9 months ago

example.zip Добавил экзампл кастомного диалога (опций по минимуму). Т.е. все по образу и подобию confirm. Для опоры темы появилась jBox-Dialog если в DOM посмотреть. Условно всякие падинги можно вешать так же как и на jBox-Confirm и прочее и отдельные можно вешать на свои темы.

BDemetrix commented 9 months ago

@cdb2
@kulbergArt

Внимание! Был изменен (сокращен) js обработки закрытия кастомного поп-апа! Прежде чем выкатывать добавить во всех модальных окнах .custom-pop-up элементам custom-pop-up__cover и custom-pop-up__close:

Инструкция

Инструкция в 8 и 9 пунктах:

8) Модальное окно. Класс .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 страницы! Есть два оскновных варианта использования:

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 строк кода!