Как я делал Drag and Drop WYSIWYG HTML билдер с возможностью вставки сторонних JS библиотек

в 6:56, , рубрики: javascript, jquery, wysiwyg, Веб-разработка

Суть проекта

jQuery Drag and Drop WYSIWYG HTML билдер генерирует Bootstrap HTML и JS. Редактор выделяет необходимый JS код (около 0% — 15%) из своего исходника и предоставляет его в результирующем HTML для обеспечения инициализации сторонних JS библиотек во фронтенде.


Идея

Вдохновителем моего проекта был успешный продукт Visual Composer — редактор для WordPress, который относится к современному тренду — Drag and Drop Page Builder. После анализа множества аналогичных билдеров я обнаружил:

  • Пользователи этих билдеров в основном это: конечные пользователи сайтов визиток, разработчики сайтов которым нужно ускорить производство;
  • Конечным пользователям нужны возможности простейшей верстки текстов, картинок, видео и им нравится возможности Drag and Drop;
  • Разработчики сайтов экономят время на интеграции JS библиотек (slider, parallax, video background и т.д.);
  • Билдеры предоставляют возможность управлять: непосредственно введенным статическим контентом (текстом, картинками, видео и т.д.), динамическим содержимым из БД, различными сторонними JS библиотеками;
  • Все билдеры рендерят HTML на стороне сервера средствами PHP, что создает необходимость разработки достаточно объемного взаимодействия между PHP и JS.

Затем я пришел к выводу, что если пожертвовать возможностью управления динамическим содержимым из БД, то можно сделать билдер на чистом JavaScript. И после разработки моего проекта я сделал такие выводы:

  • итоговый исходник на JS имеет красивую и компактную ООП архитектуру;
  • билдер на JS не требует AJAX запросов для рендеринга HTML в режиме редактирования — следовательно, работает быстрее;
  • итоговый исходник на JS проще для понимания, чем PHP/JS классического билдера — следовательно низкий порог входа для расширения билдера;
  • интеграция билдера требует подключения JS/CSS и нескольких JS строк;
  • добавив в билдер один раз какую либо JS библиотеку автоматически, она может быть использована в любой платформе, куда этот билдер интегрирован.


Философия

При проектировании я оттолкнулся от такой формулировки задачи: нужно облегчить пользователю конвертацию его данных и дизайнерских идей в HTML. Почему пользователь не может (или не хочет) сам писать HTML:

  • В HTML много дублирующей информации которая захламляет внешний вид;
  • HTML дерево разбавлено промежуточными и вспомогательными узлами, несущими информацию о разметке и только для браузера;
  • В HTML используются не интуитивно понятные идентификатры (теги, атрибуты, классы);
  • Пользователю удобно сразу видеть результат своих действий;
  • Пользователю удобнее работать в режиме диалога — ему нужен ограниченный список дальнейших вариантов действий с описанием на каждом шаге.


Архитектура редактора

Вдохновителем архитектуры проекта был механизм shortcodes в CMS WordPress. Само название шорткодов говорит о краткой записи какого-то куска HTML/JS с понятными и действительно важными для пользователями атрибутами. Шорткоды — это примерно тоже самое, что и XML: дерево тегов с атрибутами, просто вместо символов "<>" используются символы "[]". Идея в том, чтобы кратко описывать документ с помощью иерархии.

Первые версии моего проекта хранили результат редактирования в шорткодах, но в последствии я от них отказался, потому что он не могут нормально парсится поисковыми системами и мне хотелось убрать дублирующее описание одного и того же документа — я все уложил в HTML со специальными «data» атрибутами. Конечно, тут есть минус — нагромождение атрибутов, утяжеляющее страницу. В ответ на это можно сказать, что разработчики сайтов тоже довольно часто нагромождают HTML ненужными классами, особенно это часто бывает в CMS для какой-либо универсализации. Это, конечно, не снимает проблему но, хотя бы немного успокаивает.

Получается, если мы делаем WYSIWYG редактор шорткодов, нам нужно в процессе редактирования поддерживать постоянную связь между шорткодами и HTML узлами. По сути получается, что у нас есть 2 модели документа: DOM и шорткоды, которые постоянно синхронизируются между собой, причем шорткодную модель пользователю легче редактировать. Шорткоды в своем проекте я называю элементы, их атрибуты — параметры. Элемент может иметь дочерние элементы. У каждого элемента есть 2 точки связи с DOM — корневая (входная) и та, к которой присоединяются корневые узлы элементов детей (выходная).

Параметры

Параметр должен быть удобным для редактирования. У параметра должно быть описание. Я объявил базовый класс параметра со следующими основными методами:

  • рендеринг — формирование HTML параметра;
  • возврат значения — функция получения введенного пользователем значения;
  • активация — функция вызывается в момент завершения рендеринга формы обычно необходима для подключения сторонних JS библиотек для облегчения редактирования параметра.

Элементы

Элемент может иметь какой-либо список параметров. У элемента должно быть описание. Я объявил базовый класс элемента со следующими основными методами:

  • рендеринг — формирование HTML элемента с присоединением к входной и выходной точкам DOM;
  • активация — функция вызывается в момент завершения рендеринга иерархии элементов обычно необходима для подключения сторонних JS библиотек.

Форма редактирования параметров элементов

Для каждого элемента можно открыть форму редактирования его параметров. Форма просто по очереди рендерит параметры и вызывает событие активации. На основании описаний параметров пользователь может быстро разобраться как работает элемент в деталях. При сохранении отредактированных параметров алгоритм обновления элемента следующий (описанный в базовом классе элемента):

  • вызывается функцию jQuery — detach для: отсоединения корневого узла элемента от DOM и для отсоединения всех корневых узлов дочерних элементов;
  • элемент рендерится заново;
  • снова подсоединяется обоими точками к DOM;
  • элемент активируется заново.

Кнопки для управления элементами в редакторе

В режиме редактирования всегда при рендеринге элемента в его корневой DOM элемент добавляется HTML блок с кнопками и JS обработчиками — контролы элемента. Для контролов легко настроить CSS так, чтобы они появлялись, не сильно мешая содержимому документа.

Формат хранения

Параметры элемента и его тип хранятся в составе атрибутов корневого DOM узла данного элемента. Выходной узел помечается специальным атрибутом для парсера. Перед сохранением из документа DOM удаляются контролы и всевозможные вспомогательные классы типа: resizable, draggable, sortable и т.д. В начало результирующего HTML добавляются включения необходимых CSS/JS файлов, которые затребовали использованные в документе сторонние JS библиотеки. Если сторонние JS библиотеки были использованы, в начало добавляется еще и загрузчик.

Компиляция загрузчика

Загрузчик — это вырезка из JS-исходника самого редактора. В загрузчик добавляются:

  • необходимые настройки, которые были переданы редактору;
  • вспомогательные функции;
  • классы всех использованнх элементов в данном документе;
  • метод активации, если он есть для каждого элемента;
  • метод рендеринга для элементов, для которых JS библиотека требует перерендеринг (например OWL Carousel);
  • парсер иерархии елементов с запуском рендеринга (если это требуется) и запуском метода активации


Открытые вопросы

Возможно ли придумать такую архитектуру подобного WYSIWYG редактора, чтобы минимизировать «data» атрибуты и JS загрузчик до уровня, к которому никто не смог бы предъявить претензии по объему.

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

Автор: andy133

Источник


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js