giftd-editor

0.9.37 • Public • Published

Giftd Editor

Оглавление

Описание

Визуальный редактор настроек (кастомизаций) различных страниц - виджеты, емейлы и т.д.

Редактор позволяет изменять различные настройки с возможностью предпросмотра изменений и дальнейшим сохранением значений на бэкенде.

Кроме того, пакет поддерживает возможность расширения путём добавления кастомных полей настроек (по умолчанию с пакетом идут текстовое поле, выпадающий список и список чекбоксов).

Требования

Редактор был разработан таким образом, что его основные элементы находятся в главном окне (странице), а редактируемый контент загружается в iframe. Такой подход позволяет выполнять предпросмотр изменений без перезагрузки основной страницы (что может быть невозможно в случае, если в редактируемом контенте имеется большое количество скриптов, запускаемых при загрузке страницы).

Связь между этими окнами осуществляется с помощью механизма PostMessage.

Требования к подключению скриптов

Для того, чтобы оба окна взаимодействовали корректно, необходимо подключать скрипт редактора перед любыми другими, которые могут добавлять обработчики событий на DOM-элементы (особенно это важно при подключении скрипта на стороне редактируемой страницы). Это объясняется тем, что редактор должен установить свои обработчики раньше всех остальных скриптов, чтобы не допустить выполнения остальных обработчиков по умолчанию.

Для того, чтобы редактор проигнорировал клик по элементам и вызвал оригинальный обработчик события, необходимо кликать по ним с зажатой клавишей Shift.

Требования к редактируемым элементам

Для каждого элемента, который доступен для редактирования, необходимо задать уникальный класс (по умолчанию - giftd-editable), а так же data-атрибут (по умолчанию - data-editable), значением которого нужно указать соответствующий ID редактируемого элемента (см. след. раздел).

Список редактируемых элементов и их настроек

Для того, чтобы редактор знал что именно он должен обрабатывать и как именно, ему необходимо передать список всех возможных элементов и их настроек.

Настройки должны быть сгруппированы произвольным образом. Каждая группа должна иметь ID, название и список настроек.

Полный список должен примерно так (подробнее в разделе Поля и их настройки):

{
    "texts": {
        "id": "widget-texts-settings",
        "title": "Заголовки виджета",
        "settings": {
            "heading": {
                "title": "Заголовок",
                "type": "text",
                "value": "Hello!",
                "inline": true
            },
            "main_text": {
                "title": "Основной текст",
                "type": "text",
                "value": "This is automated message, {user}, please do not reply.",
                "placeholders": {
                    "user": {
                        "title": "Имя пользователя",
                        "value": "John Doe"
                    }
                }
            }
        }
    }
}

Ключами этих настроек (поле settings каждой группы) должны быть уникальные ID элементов (именно эти ID нужно указывать в атрибутах data-editable). Значением - обязательные поля title, type и value, а так же доп. поля в зависимости от типа настройки.

Предпросмотр и сохранение настроек

Функциональность предпросмотра заключается в следующем алгоритме:

  1. При нажатии на кнопку "Предпросмотр" скрипт получает текущие значения всех настроек и выполняет POST-запрос на URL, указанный в параметре savePreviewUrl. В поле settings будет находиться key-value объект всех настроек;
  2. Контроллер по этому адресу должен выполнить сохранение настроек в сессию или в любое другое удобное для него место, после чего вернуть успешный HTTP-ответ (2XX);
  3. После того, как редактор получил ответ на этот запрос, в редактируемый iframe отправляется команда на переход на страницу, указанную в параметре previewUrl (методом GET);
  4. Контроллер, отвечающий за URL previewUrl должен получить сохраненные ранее настройки предпросмотра и выполнить рендеринг страницы виджета с этими значениями. ВНИМАНИЕ: страница на этом URL не должна ничем отличаться от оригинальной страницы редактируемого контента, за исключением новых значений настроек (т.е. скрипт инициализации редактора должен присутствовать, у редактируемых элементов должны быть установлены класс и data-editable атрибут);
  5. Новая страница автоматически переподключится к родительскому редактору и будет доступна для редактирования и повторных вызовов предпросмотра.

Функциональность сохранения настроек аналогична предпросмотру за исключением сохранения промежуточных настроек. При нажатии на кнопку "Сохранить" редактор отправляет текущие значения на URL, указанный в параметре saveUrl, который должен сохранить настройки и выполнить рендеринг страницы виджета с новыми значениями. Как и в случае предпросмотра, эта страница не должна ничем отличаться от оригинальной редактируемой страницы, за исключением новых значений настроек.

Установка

yarn add giftd-editor # или npm install giftd-editor

Подключение

### Plain JS
<script src="giftd-editor.min.js"></script>

После подключения скрипта будет доступна глобальная переменная window.Giftd, позволяющая инициализировать редактор как со стороны основной страницы, так и со стороны редактируемого контента.

Import/require

// ES6 import:
import GiftdEditor from 'giftd-editor'

// require():
const GiftdEditor = require('giftd-editor');

После подключения в переменной GiftdEditor будет находиться объект, позволяющий инициализировать редактор как со стороны основной страницы, так и со стороны редактируемого контента.

Настройки

Основное окно редактора

Модуль редактора должен быть инициализирован со следующими обязательными параметрами:

Параметр Тип Описание
editables object Список всех настроек и их параметров
containerId string ID DOM-элемента, в который будет добавлен iframe редактируемого контента
url string URL редактируемого контента (на этой странице так же должен быть инициализирован скрипт редактора)
savePreviewUrl string URL сохранения настроек для предпросмотра изменений
saveUrl string URL для сохранения настроек (на этой странице так же должен быть инициализирован скрипт редактора)
Giftd.initEditor({
    editables: {},
    containerId: 'editor-container',
    url: '/widget/edit-mode',
    savePreviewUrl: '/widget/save-preview',
    saveUrl: '/widget/save'
})

Кроме того, редактор поддерживает опциональные настройки:

Параметр Тип Описание Значение по умолчанию
title string Название редактируемого элемента Пустая строка
subtitle string Описание редактируемого элемента Пустая строка
locale string Язык интерфейса редактора (en или ru) en
translations object Переводы отдельных строк (см. раздел "Локализация") Пустой объект
editorContainer string ID элемента, в котором расположен тег <giftd-editor> editor-app
loadingClass string Название CSS-класса, который добавляется контейнеру редактируемого iframe giftd-editor-loading

Окно редактируемого контента

Модуль редактируемого контента должен быть инициализирован со следующими обязательными параметрами:

Параметр Тип Описание
editables object Список всех настроек и их параметров
editablesSelector string Селектор редактируемых DOM-элементов
previewUrl string URL предпросмотра изменений; редактор перенаправит страницу на этот адрес после сохранения настроек для предпросмотра
Giftd.initContent({
    editables: {},
    editablesSelector: '.giftd-editable',
    previewUrl: '/widget/preview'
})

Редактируемый контент на данный момент не имеет дополнительных опциональных настроек.

Поля и их настройки

Редактор поставляется со следующими типами полей:

  1. Текст - обычный текст, который редактируется с помощью contenteditable, либо текст с предопределенными вставками (плейсхолдеры);
  2. Выпадающий список;
  3. Один или несколько чекбоксов;
  4. Color Picker.

У каждого типа поля имеется свой набор параметров.

Общие параметры

Параметр Тип Описание
title string Название редактируемой настройки. Отображается в окне редактора
type string Тип редактируемой настройки
value mixed Значение настройки по умолчанию

Текст (text)

Параметр Тип Описание
inline boolean true - если текст должен редактироваться с помощью contenteditable. Параметр игнорируется, если у настройки есть параметр placeholders.
placeholders placeholders object Список возможных вставок (плейсхолдеров)

Каждый элемент параметра placeholders должен иметь следующие параметры:

Параметр Тип Описание
title string Описание плейсхолдера. Отображается в виде тултипа при наведении на плейсхолдер.
value string Значение плейсхолдера по умолчанию.

Выпадающий список (select)

Параметр Тип Описание
options options object Список возможных значений выпадающего списка

Каждый элемент параметра options должен иметь следующие параметры:

Параметр Тип Описание
value mixed Значение опции
label string Лейбл опции

Список чекбоксов (checkboxes)

Параметр Тип Описание
options options object Список значений чекбоксов

Каждый элемент параметра options должен иметь следующие параметры:

Параметр Тип Описание
value mixed Значение чекбокса
label string Лейбл чекбокса, возможно использовать HTML

Значением настройки с типом checkboxes будет массив, состоящий из отмеченных значений (поле value).

Color Picker (colorpicker)

Параметр Тип Описание
settings object Дополнительные настройки компонента

Поле settings может иметь следующие настройки:

Параметр Тип Описание По умолч.
color_type string Тип цвета (hex, rgb, rgba, hsl, hsla), который будет передан в качестве значения hex

В зависимости от значения color_type в поле попадет цвет с одним из следующих форматов:

  • hex (по умолчанию): #245EA7;
  • rgb: rgb(36, 94, 167);
  • rgba: rgba(36, 94, 167, 0.5);
  • hsl: hsl(213, 64%, 39%);
  • hsl: hsla(213, 64%, 39%, 0.5).

Загрузка изображений(image-upload)

Параметр Тип Описание
settings object Дополнительные настройки компонента

Поле settings может иметь следующие настройки:

Параметр Тип Описание Обязательно? По умолч.
upload_url string Адрес загрузки изображения. Запрос отправляется методом POST Да --
field string Название поля, в котором будет отправлен файл изображения Нет file
headers object Список заголовков и их значений, которые должны быть отправлены вместе с запросом Нет --
response_src string Путь к адресу изображения в JSON-ответе от upload_url Нет data.src

Внимание: адрес, указанный в параметре upload_url при успешной загрузке должен вернуть JSON со структурой, указанной в параметре response_src!

Например, если вы не указывали значение параметра response_src, то компонент будет ожидать JSON-ответ со следующей структурой:

{
    "data": {
        "src": "https://example.org/image.png"
    }
}

В пути data.src (значение response_src по умолчанию) должен находиться URL к загруженному изображению.

Если ваш ответ выглядит (например) так:

{
    "response": {
        "upload": {
            "id": 1,
            "src_big": "https://example.org/image_big.png",
            "src_medium": "https://example.org/image_medium.png",
            "src_thumb": "https://example.org/image_thumb.png"
        }
    }
}

и вы хотите, чтобы значением поля стал адрес medium-изображения, параметр response_src должен выглядеть так: response.upload.src_medium.

События окна редактора

Окно редактора на данный момент поддерживает 2 события: beforePreview и beforeSave. Первое событие вызывается перед сохранением данных предпросмотра, второе - перед сохранением данных.

Обработчики этих событий можно зарегистрировать в параметре events:

Giftd.initEditor({
    events: {
        beforePreview: function (service, values, resolve, reject) {
            console.log('In beforePreview()')
            return resolve()
        },
        beforeSave: function (service, values, resolve, reject) {
            console.log('In beforeSave()')
            return resolve()
        }
    }
})

Оба метода принимают следующие аргументы:

  • service - инстанс класса EditorService;
  • values - key-value объект измененных настроек (editables);
  • resolve - функция, которую необходимо вызвать по завершению работы обработчика события, в том случае, если данные можно сохранять;
  • reject - функция, которую необходимо вызвать по завершению работа обработчика события, в том случае, если должна произойти отмена сохранения данных.

Передача произвольных данных

Кроме передачи системных данных, пакет поддерживает передачу произвольных пользовательских данных. Для того, чтобы устроить такую передачу, необходимо выполнить следующую настройку на обоих сторонах редактора:

Сторона редактируемого контента:

В параметре requestHandlers настроек редактора необходимо указать функции-передатчики данных, каждая из которых должна возвращать Promise-объект:

Giftd.initContent({
    requestHandlers: {
        getLinkValues: function (data) {
            return new Promise(function (resolve, reject) {
                var links = [];

                $('a' + data).each(function () {
                    links.push($(this).attr('href'))
                })

                return resolve(links)
            })
        }
    }
})

Сторона редактора:

На данный момент единственным способом запроса данных являются события beforePreview и beforeSave. Следующий пример показывает как можно запросить все ссылки со страницы редактируемого контента (обработчик, зарегистрированный в первом пункте):

Giftd.initEditor({
    events: {
        beforeSave: function (service, values, resolve, reject) {
            service.initiateDataTransfer('getLinkValues', '.my-class', (err, result) {
                if (err !== null) {
                    console.error('Error occuried', err)
                    return reject() // Запрещаем сохранение данных
                }

                // Добавляем ссылки к данным
                // и вызываем сохранение.

                values.links = result.join(';')

                return resolve(values)
            })
        }
    }
})

Добавление новых полей

Vue-компонент

Добавление нового поля необходимо начать с создания необходимого Vue-компонента.

В каждый компонент передается объект editable в качестве атрибута (property). Таким образом, базовый компонент может выглядеть следующим образом (используется Single File Component:

<template>
    <div class="giftd-editor-password-component">
        <div class="form-group">
            <label :for="componentId">Enter Password:</label>
            <input type="password" v-model="editable.value" class="form-control" :id="componentId">
        </div>
    </div>
</template>

<script>
export default {
    props: ['editable'], // Обязательно
    data() {
        return {
            componentId: `giftd-editor-password-component-${Math.random().toString().replace('.', '_')}`
        }
    }
}
</script>

В случае с простыми полями можно воспользоваться биндингом моделей Vue и указать в v-model непосредственно поле value объекта editable. В этом случае изменения будут поступать в редактор сразу же и без необходимости выполнять доп. действия.

Если же вам нужно реализовать более сложную логику, задавайте новое значение с помощью методов (editable.value = 'my-value';).

Объект editable, передаваемый в компонент, содержит следующие поля:

Поле Тип Описание
component string Название Vue-компонента этого поля
name string ID текущей настройки
value mixed Значение настройки
title string Название настройки
placeholders placeholders object Список плейсхолдеров настройки
options options object Список опций настройки
original object Список всех полей из оригинального объекта

Поле original содержит в себе оригинальный объект, переданный в редактор в момент его инициализации.

Регистрация поля

Для того, чтобы редактор мог обработать новый тип поля, его необходимо зарегистрировать в системе.

import Giftd from 'giftd-editor'
import Password from './my-custom-components/Password.vue'

Регистрация полей происходит с помощью вызова метода registerFields:

Giftd.registerFields([
    {
        type: 'password',
        name: 'Password',
        component: Password,
    }
])

Поле type каждого объекта массива, передаваемого в метод registerFields, определяет тип настройки, который будет указан в объекте editables при инициализации редактора и редактируемого контента.

Поле name определяет название компонента, которое будет использовано для рендеринга динамического компонента в главном окне редактора.

Поле component содержит в себе непосредственно сам объект Vue-компонента.

После регистрации нужных полей можно выполнять инициализацию редактора (Giftd.initEditor()) или редактируемого контента (Giftd.initContent()).

Добавление поля в список настраиваемых элементов

Для того, чтобы нужный элемент пометился как настраиваемый, добавьте новое поле в список editables, а так же добавьте класс giftd-editable и атрибут data-editable на странице редактируемого контента.

{
    "my_password": {
        "type": "password",
        "title": "Пароль",
        "value": "secret",
        "inline": false,
    }
}

Package Sidebar

Install

npm i giftd-editor

Homepage

giftd.tech

Weekly Downloads

6

Version

0.9.37

License

MIT

Last publish

Collaborators

  • giftd