Главная » Хабрахабр » Разработка редактора для создания веб сайтов/лендингов (Опыт)

Разработка редактора для создания веб сайтов/лендингов (Опыт)


(Art by http://www.simonstalenhag.se/)

Предыстория / Дисклеймер

Но не думайте, что вы аудитория на которой я отрабатываю текст, просто мне так проще подготовиться.
На данный момент я Front-end разработчик в Conductor/WeWork. Всем привет, данная статья является по факту материалом для моего выступления в понедельник на марафоне в Киеве. Это больше об опыте который я получил на прошлом проекте в компании УТИ(сокращенно), утипути, ути-…. Мы не занимаемся разработкой редакторов, как собственно и я, по вечерам не разрабатываю такие вещи. Это было достаточно давно, но как оказывается, тема актуальна и по сей день, как и косяки связанные с ней.
Речь идет как правило о сайт визитках, лендингах, и более менее функциональных сайтах, но разумеется не о бек офисах или админках.

UTIEditor special for you <3

Зачем нам нужны такие редакторы?

Уверен в свое время в таких поработал каждый, десяток сайт визиток на человека, десяток интернет магазинов и фирменная вишенка — своя CMS.
Вот вы сделали очередной лендинг, сайт визитку и отдали клиенту, а он прибегает через день и просит поменять текст. Тут достаточно много ответов на этот вопрос, многие из вас, я уверен догадываются и так.
Я отвечу на этот вопрос с точки зрения УТИ, компании которая предоставляет услуги по разработке сайтов.
УТИ по сути своей — компания ширпотреб. Для клиента это выглядит, как нечто простое и быстрое. Через еще день, поменять цвет фона и добавить всего одну картинку. Но для вас это означает, что вам нужно выдернуть разработчика/дизайнера с его текущих задач. С этим трудно поспорить, оно так и есть. Соответственно, вы выставляете счет и он не маленький. Не говоря уже о работе менеджера который тратит время на коммуникации. В следующий раз вы уже думаете наперед о таких вещах и начинаете задавать вопросы, закладывать в ТЗ функционал редактирования.
Тут пожалуй стоит перейти к обсуждению этого функционала, ведь он очень разный.
Хотелось бы добавить, что я не буду включать в этот разговор такие CMS как WrodPress, Drupal, мы сконцентрируемся на рынке редакторов. Клиент негодует и жалуется.

Дебри UTI

Первым, что приходит на ум, сделать форму, где пользователь может изменить, то, что он хочет:

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

  • Легко реализовать
  • Легко использовать
  • Решает проблему

Минусы такого подхода:

  • Нет возможности изменить дизайн
  • Нет возможности изменить поведение
  • Нет позиционирования
  • Можно редактировать, только, то, что было заложено в форму

Звезда всех времен и народов. Вы еще не подумали о СKEeditor? По жалуй это следующий шаг улучшить редактируемость контента на сайте.

Где-то на этом месте, до того как я пришел в компанию, у ребят возникла идея, сделать редактор страниц с drag and drop прямо в CKEditor. Тут своего рода возможность форматировать текст и даже вставлять какие-то дополнительные элементы. Чем не полноценная страница? У меня к сожалению не осталось чего либо, что бы я мог показать, но вы попробуйте представить этот ужас 🙂
Но на текущий момент, 2018 год так сказать, CKEditor немного продвинулся в этом направлении, что достаточно, таки забавно.

И зная только backbone и jquery, я уже смело называл себя фронт-енд разработчиком и решил предложить им разработать полноценный редактор, на подобие Wix, Squarespace, Tilda, LPGenerator… Тогда они были по факту моими конкурентами. Но все это было не удобно как в разработке так и в использовании. И так и не узнали и не узнают. Но так как УТИ компания no-name, они об этом не знали. Ох, это только совпадение.
Не узнали они, потому, что все по классике — компании было пофигу на проект.
Это два скринкаста, они не идеальные, с косяками, но я уверен общее представление о редакторе они предоставят. Хотя спонсором марафона выступает Wix.

Дизайнером, продукт менеджером, фронт и бек, а тестов не было и нет. На этом проекте я был один. Тестировщики конечно, были веселые. НО правда были мануал тестировщики, которые приходя в компанию, закалялись в огне реактора. Что бы вы понимали уровень — как-то раз, одному из них выбило:

У парня просто выпал шнур интернета из системника 🙂
Каждый раз по новой мне приходилось объяснять, что можно сделать в редакторе, что нельзя и почему это работает так, а это вот так. И мне зафайлили баг, мол сайт не работает. Своего рода первая линия фидбека. На самом деле, для меня это было прикольно. Приложение выглядит большим, солидным так сказать. Клиентов практически не было и редактор эволюционировал по большей части благодаря им.
Есть у кого-то предположения какой стек я использовал? В прод уходил сколько хочешь раз в день.
Под кодовым названием Filezilla, drag and drop, repeat. Оно не глючит как и не глючило 5ть лет назад.
Ох а какой шикарнйы CI/CD процесс у меня. Если все таки помер, то заливаешь файл из папки бекапа. Сперва конектишся по фтп используя файлзиллу, делаешь билд, выкачиваешь текущий билд, ложишь в папку с названием backup, закачиваешь новый билд, и провереяшь, не умер ли там кто. А учитывая, что редактор был в нескольких проектах, говорить, что я заходил в каждый и проверял не упало ли там, что — я тоже не буду. Но честно сказать, момент с бекапом, я делал не всегда, зависело от набора нового функционала. А мы еще использовали SVN, придает вкуса?

Что же по поводу стека?

Тогда такие термины особо то и не использовались, это было дефакто простая оптимизация. Backbone + jquery + 0 тестов.
Модуля, асинхронная подгрузка аля код сплитинг и серверсайд рендеринг. Разве, что в нем больше шаблонов, заготовок и готовых компонентов. Но сейчас время маркетинга в опенсорсе и итс революшин!
Что бы вы понимали, Wix того времени, от Wix редактора сейчас особо сильно не отличается. Глючит он абсолютно так же, только уже на макбуках с оперативкой от 16гигов, с более крутой системой рендерига под названием виртуал дом и крутых веб движках. Они мигрировали реакт, полностью или нет, я не знаю. Причем UI/UX намного важней. В проектах такого масштаба, инструменты особой роли не играют, это больше разговор о архитектуре и UI/UX. Клиенты как правило будут далекие от разработки, далекие от всех этих CSS правил, свойств, DOM атрибутов и параметров. От него зависит и сложность реализации, перфоманс и уровень желания убить себя при создании веб сайтов вашим редактором. Но не будем о грустном, давайте попробуем рассмотреть поколения редакторов чуть дальше.
Клиенты, если им дай идеальный инструмент редактирования, все равно не смогут им пользоваться. Среди них будут и более менее разбирающиеся люди которые будут обслуживать ваших клиентов и в дальнейшем уводить их. Их поделки будут выглядеть примерно вот так:

Это и правда и не правда, так как веб он просто сложный для гуманитариев, а с другой стороны где-то есть идеальный UI/UX который позволит нажатием кнопки — сделать сайт, сделать, то, что вы хотите.
Но порой это невозможно и приходиться искать золотую середину.

Визуальный HTML редактор

То есть, пользователь мог их двигать. Первоначальная задача была такой — сделай так же как в CKEditor, что бы можно было двигать элементы(текст, картинки) и как-то их редактировать/форматировать.
Так же одним из главных требований была возможность загрузки пользовательского HTML, для дальнейшей работы.
Начал я с того, что сделал элементы на странице draggable. Дело в том, что пользовательский HTML, может быть совершенно любым и не предсказуемым. По началу все казалось хорошо, но чем больше различных заготовок я пробовал, тем хуже все выглядело. Это был хаос. Это ведет и к проблемам элементарной задачи drag and drop, невозможность понять, что за элемент выбрал пользователь и даже банально иметь контроль над страницей.

Текст обернутый в очевидные теги он видит, а текст который находится просто в body, он никак не чувствует: Grapesjs позволяет загружать свой HTML.

Ограничения

С точки зрения юзера это большая свобода. Дать возможность загружать свой HTML, и редактировать его, это конечно смелый ход. Дело в том, что одни и те же по семантике вещи могут быть реализованы совершенно по разному, с использованием совершенно разных подходов. Но вот есть чудесный пример, того как обстоят дела в вебе — A Blue Box

Я уверен, там даже не все варианты реализации. Та же картинка может быть добавлена на страницу с помощью тега или быть задана с помощью background. А представьте, на странице, что-то посложней чем синий квадрат. И как понять, какой инструмент редактирования показывать?
Никак.
Кнопка может быть , а может быть сверстана или той же картинкой.

Ограничение 00

Разумеется мы выбрали второе 🙂 Выбор следующий — запретить ту или иную верстку, сделать стайлгайд или же запретить загружать пользовательский HTML.

Ограничение 01

Раз уж мы запретили загружать пользовательский HTML, то нам нужны свои компоненты/элементы, и это первый шаг к настоящему редактору.

Ограничение 02

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

Рабочее окружение

Мне очень нравится интерфейс фотошопа. Не самая интересная тема, но важная. Рабочей областью вы можете манипулировать как хотите, она по центру и в зависимости от размеров, вы можете скролится как по горизонтали, так и по вертикали. Есть ряд панелей, и рабочая область.

Так же немало меня задел своим дизайном Google Web Designer:

Кстате, это своего рода редактор от Google, кто-то использовал его?

Я не эксперт CSS, и в этот раз мне это далось намного легче, но тогда это были танцы с табличной версткой. Самое сложное, это разбить страницу таким образом. Прежде чем мы пойдем дальше, давайте посмотрим какие вообще лаяуты рабочей области есть.

Фотошоп

LPGenerator

Мое творение

Grapesjs

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

Так перегружен, что надо все прятать

Wix

Зайдя в LPGenerator, вы сразу понимаете, что можно перетянуть какой-то элемент на страницу, видите настройки итд. За 5ть лет, дизайн викса мало поменялся. Это хороший подход. В случае с Wix, все изначально спрятано. Но тут нужно соблюсти баланс. Дело в том, что пользователю не нужно видеть, то, что ему скорей всего и не понадобится на данный момент. Но конечно очевидные вещи как текст или кнопка, можно было бы и вынести на одну из панелей для быстрого доступа. У Wix.com уж слишком много элементов которые вы можете добавить на страницу и по этому они сделали целую галлерею элементов.

При клике на элемент, над ним появляется дополнительный функционал, который относится к элементу.

Реализовать такую штуку тот еще гемор, об этом мы поговорим чуть позже.

Минималист

Squarespace

Набор инструментов очень странный. Минимальный дизайн, рабочая область занимает большую часть экрана, из интерфейса самый необходимый минимум. Например вот так редактируется первый экран с кнопкой:

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

При этом редактор нас как бы перемещает в другую часть приложения.

Я есть грут

Tilda

Очень похоже на WordPress и его панель сверху с функционалом редактирования/публикаций и прочего. Редактируя сайт, вы словно находитесь на нем. Перенести кнопку в любое удобное для вас место, так просто не выйдет. Но при этом, функционал не такой стопорный как у Squarespace и тот же текст поддается редактированию куда проще.
Что бы, что-то добавить, необходимо кликнуть на +. Все ограниченно.

Следствием этого являются такие вот галлереи с кучей различных вариантов одного и того же элемента.

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

Если Flexbox предпочтительно использовать для меню, формочек и прочего набора элементов, то CSS Grids, отлично себя чувствуют именно в глобальных вещах.
Это не туториал по CSS Grids, по этому я объясню по ходу дела в двух словах, но без мега деталей. Если кто не знаком с CSS гридами, то это один из последних способов верстать лаяут страниц.

В одной из прошлых статей я уже говорил об этом
Как выглядит инспекция гридов в хроме: И так наша задача сделать левую и правую панель, а по середине рабочую область где будет отображаться контент веб сайта.
Работать с гридами немного проще в FireFox, это странно, но хром в этом деле отстает.

В то же время в мазиле:

Странно я себя чувствую рекомендуя этот браузер. Есть мини представление грида, показываются семантические лейблы колонок/строк
По этому если хотите побольше информативности, используйте пока FireFox. Время Bugzilla уже прошли.

Давайте начнем с простой разметки

<div class="main"> <div class="left"></div> <div class="content"> <div class="site"></div> </div> <div class="right"></div>
</div>

.left — левая панель
.content — середина, где будет отображаться сайт
.right — правая панель

Мы хотим, что бы наш интерфейс был выстой равной Viewport. Пока это мало на, что похоже. Их мы и будем использовать. Сделать это можно с помощью height: 100%, но есть и вьюпорт юниты vh и vw.

.main { height: 100vw;
}

Это своего рода оси flexbox.
Нам необходимо задать колонки, сделать это можно следующим способом: По умолчанию дочерние элементы превращаются в строки.

.main

Функция minmax, позволяет задавать максимальные и минимальные размеры. Методом проб и ошибок я пришел к достаточно сложному темлейту. Дело в том, что такие свойства как grid-gap влияют на размер подобно border. fr это универсальная единица, которая избавляет нас от подсчетов размеров в пикселях или процентах. fr призван избавить нас от этой боли.

Немного подкрасим и уберем margin на body, он нам немного мешает:

body { margin: 0px; } .left, .content, .right { box-sizing: border-box; border: solid 1px; }

Но это была самая простая часть. Супер. Давайте сделаем его в стандартные 960px и подсветим. Теперь нам необходимо, сделать рабочую область.
.site это наш мнимый сайт.

.site { height: 2000px; width: 960px; background: rebeccapurple;
}

Если это дело сжать, то все еще веселей:

Но

.content { overflow: scroll;
}

Остается только эстетическая часть. Решает проблему. Отступы.

Сделать это можно с помощью margin:

margin: auto; margin-top: 20px; margin-bottom: 20px;

Но тут есть другая проблема. 20px мало или много решать уже вам. Так как maring: auto будет тесно. Если экран слишком маленький, отступов слева и справа не будет. Отступ будет только у левой части. Первое, что приходит на ум это задать margin-left и margin-right, но тут другой прикол. Это такая вот особенность. Если проскролить в право, то там его не будет. Ага. Не вдаваясь в подробности, пофиксить это можно с помощью display: inline-block. Следующее самое очевидное решение это использовать Media Queries. Но при этом у нас поломается margin: auto который очень хорошо себя ведет при больших размерах экрана. На больших экранах display: block + margin: auto, на мелких display: inline-block; margin-left/right: 20px.

.site{ height: 2000px; width: 960px; margin: auto; margin-top: 20px; margin-bottom: 20px; background: rebeccapurple; } @media(max-width: 1350px) { .site { display: inline-block; margin: 20px; } }

Если у кого-то есть идеи получше, добро пожаловать в комментарии. Вот как-то так.

Отображение сайта

Это очень важная вещь. Лаяут готов, теперь необходимо отобразить сайт, который пользователь будет редактировать. Отобразить сайт на редактирования по факту, можно двумя способами. От нее зависит ряд решений. Оба варианта обладают положительными и не очень положительными свойствами. В document, где находится интерфейс вашего редактора или же в iframe.

Тот же document

Но гораздо проблематичней в будущем. Это проще, как ментально так и технически. Дело в том, что если вы добавите, а вы добавите, возможность вставки пользовательского CSS и JS, ваше редактор будет взорван спустя несколько минут.

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

Варианты есть, но они либо слишком тяжелые, либо полностью не защищают. Инкапсулированный CSS пока еще не реальность как и 5 лет назад. Забегая немного вперед, когда вы решите добавить ряд своих готовых шаблонов, ваше же разработчики будут с этим мучаться. Когда пользователь перекосит весь интерфейс и случайно удалит всю свою работу, винить в этом будут вас. Вот если посмотреть на Tilda, у них с этим беда. Как бы не переопределить какой-то стиль.

Кнопочки форматирования текста: Возьмем например первый попавшийся под руку UI этого редактора.

!important на цвете? Вы видите эти стили? В любом случае, переопределить их очень просто вставкой пользовательского HTML в страницу сайта: Эти стили вовсе не нужны, если их отключить то нечего не поменяется.

Но я нашел халявный 2х недельный период с возможностью вставки пользовательского HTML и CSS, и достиг ровно того же эффекта. Признаюсь, я вставил этот код в ручную.

Вот представьте, у вас купили услуг разработать сайт в Tilda за n тысяч долларов, и вы захотели задать собственный стиль ссылкам. Как так можно? Ну с бордерами я утрирую, но вы можете представить любой другой стиль, не говоря уже о пользовательском JS. Все, сайт редактировать пользователь уже не сможет. Причем коллизия, распространяется на даже какой-то вложенный интерфейс, хотя это очевидно.

Но в реальном мире это практически невозможно. Не дать пользователям вставлять собственный код, будет решением этой проблемы. Это возможно с жирными клиентами. Не будете же вы делать кастомные интеграции под каждого пользователя. Но не когда у вас 90% функционала стоит 5-10 баксов.

Iframe

Наверное это единственное где я использовал iframe так долго. Практически полностью инкапсулировать страницу, нам поможет iframe. По этому у нас все под контролем. Мы можем достучаться до контента iframe и даже наоборот, если они на одном домене. Например выделение элементов, которое мы обсудим чуть позже. Но все такие инкапсуляция нас немного озадачивает. Дело в том, что при скролинги контента, вам не придется обновлять позицию выделения/думать о хитрой верстке (хотя лучше так), и дополнительного интерфейса. Выделять его элементами на уровне интерфейса позиционируя над iframe, или в самом iframe?
Разумеется проще это будет делать в самом iframe. По этому например Grapesjs комбинирует два этих подхода: Но вычисления того перекрывается ли ваш интерфейс, интерфейсом редактора будут проще если вы будете рендерить подобные вещи над iframe в одном document.

Выделение происходит элементами в iframe, а дополнительный функционал, чувствительный к перекрытию, рендерится поверх iframe.

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

Wix <head>

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

Grapesjs класс который я "случайно" обновил бордером:

Grapesjs добавляет класс gjs-comp-selected при выделении, который при инспекции хорошо виден и уж поверьте это будет первое, что пользователь скопирует для кастомизации.

Выделение элементов

Прежде чем углубится в более технологически сложную тему, давайте посмотрим, насколько же технологически сложно, сделать выделение элементов на странице 🙂 Как вы думаете, это сложно? Мы немножко забегаем наперед, ведь мы пока не поняли как научить редактор видеть элементы на странице, но это нам не помешает. Если вы очень самоуверенны, то вот как с этим справляются все выше упомянутые редакторы на примере текста:

Мой редактор

Tilda

Grapesjs

Google Web Designer

Wix

А при редактировании

Ну ладно. Часть текст не видно вообще. С точки зрения фронт-енд разработчика это фича.

Но вот посудите сами, вы как пользователь, далекий от разработки сайтов, думаете это ок? Дело в том, что редакторы выделяют по большей части DOM модель. Контент больше того, что вам показывает редактор. Нет это не ок. Это нормально для браузера выделять таким образом для разработчиков, это верно по спецификации. В случае с некоторыми, есть вероятность потерять возможность выбрать элемент.

Что видит пользователь (синий, текст сделал прозрачным, для очевидности проблемы), что выделяется редакторами, браузерами (красный):

Chrome

FireFox

При выделении текста в FF, хром так не умеет.

По моему опыт скажу, что это лапша на ушах продукт менеджеров и/или тестировщиков. Так почему такой косяк во всех редакторах? У них замыленные глаза и такие косяки на первый взгляд элементарные остаются в слепой зоне. Все кто работает над редактором, как правило вряд ли будут ставить line-height: 1px, или пробовать играться с различными стилями и размерами текста. Есть идеи, как выделить элемент?
В выделение необходимо включать такие вещи как margin, padding, border. А клиенты поверьте, сталкиваются с ними на протяжении первых минут.
С точки зрения UI/UX, это может быть технически не понятная вещь, и такие детали реализации как правило остаются на усмотрение разработчика.
Так можно ли сделать выделение юзерфрендли? Модель размеров не простая:

Из моего сандбокса:

Пожалуй самая полезная информация, которую я извлек из msdn:

Но и тут нет ответа на наш вопрос.

Имеем такую вот верстку: Давайте попробуем то, что нам предоставляет DOM в первую очередь.

font-size: 54px; line-height: 0px; /* сделайте сколько хотите, суть не в этом */ border: 10px solid; padding: 10px;

Как получить 62px? Размер видимого контента 62px, браузер нам показывает 40px.

getBoundingClientRect возвращает нам — 40px
clientHeight — 20px
scrollHeight — 41px

Ну вот посмотрите, если выделить текст, то выделение точь в точь такое как нам надо: Можно очень долго играться с математикой, но решения используя такой вот подход, я не нашел.
Но как и ~5ть лет назад, я знал, что разгадка в выделении текста.

Но как же выделять так, как это делает какая-то системная магия? Не удачный пример, но по высоте с которой у нас основная проблема — все круто.

Спустя столько лет я погуглил (научился!), к сожаления как я гуглил и линка утеряна, но вот решение:

const range = document.createRange(); let rangeRect; range.selectNode(elm); rangeRect = range.getBoundingClientRect();

Вуаля! Создаем range, выделяем ноду, и берем от range ClientRect. Можно выделять целые куски страницы (https://developer.mozilla.org/en-US/docs/Web/API/Range). Причем выделение работает на все.

И по высоте и по ширине, идеальное выделение.

Выделил текст, что бы показать системное выделение.) (Выделением в редакторе будет синий бордер, никакого фона.

Есть идеи? Другая менее важная часть выделение, то это как его показывать? Начиная от бордера, заканчивая дополнительным плавающим элементом.
В первую очередь решить делать это в iframe или над iframe, о плюсах и минусах мы говорили выше.
Бордер не подходит, так как он добавляет размера элементу и, что если пользователь задаст свой бордер элементу? Способов куча. Самый надежный способ это сделать либо 4 полоски, и позиционировать их по краям (которые в дальнейшем и будут элементами резайсинга элемента), или же блоком поверх. То же самое и outline, Grapesjs грешит тем, что делает выделение через него.
В моем случае, я использовал ::before, но это тоже не круто. Слишком много позиционирования на странице не есть помощью в оптимизации и без того перегруженного UI. Выбирать лучше из этих двух вариантов, максимум комбинируя их. Так, что чем больше многофункциональных вещей которые вы позиционируете, тем лучше.

Это не все

Но это выделение на уровне "навел и увидел". Мы только, что реализовали выделение. Они не такие противные. С ним еще связаны две проблемы которые я оставлю вам на подумать самим.

  1. Размеры элемента меняются при редактировании. Вам необходимо следить за этим и обновлять выделение. Именно этим болеет мой редактор и Google Web Designer. Не всегда, но частенько.
  2. Что бы сделать лейбл/выделение над элементом, давая понять пользователю, что это за элемент, вам необходимо самим знать, что это. По этому элемент должен быть проинициализирован в вашем редакторе. От этого зависит перфоманс редактора. На странице может быть не одна сотня элементов, и просто взять и проинициализировать все при старте — не всегда лучшая идея. Но в случае с моим редактором, вроде ок. ха-ха. Инициализацию делать можно по клику, по ховеру, по теории частоты использования.

Редактирование

О и вы будете правы, примерно как если бы Илон ответил, что построить ракету === нанять сотню инженеров.
Оборачивать выделенный текст не так просто. Раз уж мы заговорили о выделении на примере текста, давайте быстренько пройдемся по его редактированию.
По факту текст это вторая важная часть в редакторе после картиночек и выделения 🙂
Ну вот как сделать так, что бы когда я выделил часть текст и нажал на какой-то функционал форматирования, я отформатировал именно выделенный текст?
Если вы сын маминой подруги и гениальный разработчик, то вы наверняка скажете — обернуть выделенный текст. Я долго изучал тот же CKEditor и обнаружил чудо: В итоге там будет куча тегов, и как их потом мержить при очередном выделении и форматировании большой вопрос.

contentEditable

(https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/contentEditable)

Он не просто дает нам возможность писать текст, но и форматировать его. Это блин редактор в браузере.

Статейки по теме:

Этот API позволяет выполнять команды форматирования над выделенным текстом:

bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)

Сейчас их все меньше и меньше, но тогда, хром и мазила в некоторых случая выдавала разные обертки под изменение цвета итп. Изменение цвета, отступы, вставка линки, кастомные стили и многое другое можно делать с помощью этого инструмента.
Есть небольшие кросс браузерные причуды. Но это решалось ручным костылем. Это разумеется малость мешало, если пользователь редактировал текст в разных браузера. Просто немного правился тег, после выполнение команды.

В некоторых браузерах, есть функционал по работе с картинками и таблицами. contentEditable можно использовать не только для крутого редактирования текста. Но когда я делал собственные таблицы, очень хотелось это использовать. Это по началу мешало. Но оно все было очень забагованое и не стабильное.

Они активно плакали в своих блогах о разницах в реализации. В то время, contentEditable был очень известной болью, благодаря контрибьютерам CKEditor, CodeMirror, и прочих. В тот момент я столкнулся с кросс браузерными проблемами, по большей части именно из за этой части функционала.

Редактировать текст не прямо на странице, а в отдельном месте и с использованием уже готового редактора, того же CKEditor. Многие редакторы для сайтов делали хитрый ход, который я имел слабость тоже попробовать. Дело в том, что перед вами встанет проблема, которую решить ой как не просто. Но поверьте, это не просто. Вам нужно будет собрать все стили, предоставить тот же фон. Вам необходимо суметь отобразить текст в другом iframe точно так же как он отображается на вашей странице. Тут я не сдался с contentEditable и выбросил все наработки в этом направлении. А фон важен, пользователь хочет видеть как будет смотреться его текст до окончания редактирования/форматирования. Вот Wix, 2018 год. Уж лучше переболеть contentEditable. Кстате это был один из вариантов предоставить фон 🙂 Вроде все ок, но текст обрезается, а порой теряются стили. У них вроде как свой редактор, но текст редактируется в прозрачном iframe. Я встретил такое в одном из дефолтных шаблонов. Открыл текст на редактирования, затем закрыл, и он потерял цвет который у него был до этого. Всех вариантов верстки просто не видно на момент разработки, и даже задолго после. Такие болезни присущи всем редакторам, которые решили пойти таким путем.

До редактирования:

Просто кликнул в сторону и вышел из редактирования:

То есть есть момент с получением стиля обратно.

Ресайз элементов

Так как координаты 0,0 на странице, находятся в верхнем левом углу: Пожалуй единственное, что я хочу сказать на этот счет, так это, то, что если вы тяните за левую/верхнюю часть элемента, при увеличении высоты/ширины вам необходимо обновлять его позицию.


(svg/dom element)

Работа с элементами, VC++, MVC и все такое.

И как-то так получилось, что со знанием Backbone и вопросом, а как же мы будем работать с элементами на странице, я ни на секунду не задумываясь привел аналогию из вышеперечисленных языков/технологий/фреймворков. До того как стать веб разработчиком или же точней до того, как веб стал актуальной сферой роста для специалиста, я игрался с Visual C++, C#, Delphi и прочим.

Так же у элементов есть контроллер который обрабатывает события: У кнопок есть представление, они как-то отображаются, есть модель с параметрами, такими как текст, цвет и тд.


Не знаю, настоящий ли это листинг, но вроде выглядит убедительно.

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

Так есть своего рода контроллер (Router). Backbone, по сути своей маленькая библиотека дающая нам представления (View), Модели (Model) и коллекции (Collection). MV*, MVV, если вы помните такое.
Так вот, очень удачно получилось использовать Backbone, для реализации схожего подхода. В качестве контроллера как правило выступает View. У него была модель с рядом CSS свойств. В первую очередь я реализовал View типичного элемента. У многих элементов View и Model создавалась при загрузке страницы. Поскольку элементы как правило разные, я наследовался от этого элемента и реализовал View под каждый необходимый мне элемент.
При клике на какой либо из элементов, редактор пытался понять, есть ли уже View у элемента. Хотя для таких элементов был специальный атрибут и при ховере с выделением, пользователь видел разумный текст и без полноценной View на элементе. Как правило это было у кастомных больших компонентов, которые редактор не мог понять без помощи. Если этого не получалось, смотрелся .parent от элемента по которому сделали клик. Если нет, то была попытка найти подходящий класс.

Соответственно сразу после клика, Model передавалась во все инструменты которыми могло быть произведено редактирование элемента и происходил их апдейт, что бы отобразить текущее состояние элемента. Когда View находилась, происходила инициализация и запись View и Model, в data- атрибут для быстрого доступа. Но на самом деле, еще тогда никаких лагов не было. Учитывая, что Backbone, не так умен как React, в обновлении DOM, можете представить какой у этого решения перфоманс. Плюс конечно, же не происходил перерендер всего инструмента, а четко ручное обновление HTML. Инструментов бывало штук 50-100 на один элемент и как-то все ок. И никакие ваши virtual dom, не обгонят по скорости ванильный JS. Так, что кода больше, но перфоманс ререндеринга напрямую зависел от меня. НО!, в таких размеров проектах это обусловленно. Это не удобно в разработке — факт. Иначе будет как Wix, мерцать как новогодняя елка при скроле и ховере на совершенно разные части приложения:
При скроле:

При ховере на левые элементы топ меню:

При работе с инструментами, из меню на странице:

Это фантастиш. Это еще ладно скриншоты, включите отображение перерисовки и поработайте с ним. Но зато React.

Но это плохой подход который ухудшаеть перфоманс, чтение HTML, и ведет к ряду проблем с дальнейшей работой. В моем редакторе CSS хранится инлайново, так делают многие редакторы до сих пор. То как это реализовать и организовать уже малость выходить за рамки статьй, быть может в другой раз. Но признаться, это очень простой в реализации подход.
Найболее правильным решением, является создание уникального класса под каждый редактируемый элемент и запись в <style> тег его стилей. Там не паханое поле вариантов и возможностей.

Хранение данных

Я говорю о данных которые !== стилям. Хранить данные можно в data- атрибутах, html и на сервере. Если же данные лучше так просто не показывать, то у формы может быть ID, по которой сервер сам понимает, к какой рассылке она относится и отправляет данные туда куда нужно. Например подписная форма в html может хранить данные об акции.

Редактирование/Предпросмотр/Просмотр

Интерфейс, модели не должны существовать в предпросмотре и просмотре. Необходимо различать эти состояния. Это просто, то, о чем стоит помнить.
Так же подумайте о различных анимациях и тех же ховер эффектах на кнопках. Не стоит даже трафик на них тратить. Они должны быть отключены. В момент редактирования они жутко раздражают.

React? Polymer? Vue(родился позже)? Angular (шутка!)?

Сами веб компоненты очень соблазнительны в данном проекте. Второй и 3тий вариант работы с элементами на странице который я не успел реализовать на том проекте, уже когда стали популярными React и только вышел Polymer, были React компоненты и Web Components.
Веб компоненты разве, что упростили бы работу с данными (Polymer), и ими было бы легче манипулировать. Но тогда был только Shady DOM о котором я давненько писал (https://habr.com/post/259187/), так, что эта идея отпала. Их инкапсулированная натура дает много преимуществ. По факту толку было бы мало, да еще и тяжелей все эти полифилы были.

React

Отрендерить React в ифрейм и дальше с ним работать проблем вообще не составляет: Честно сказать понятия не имею 🙂
Но давайте подумаем.

const rootElement = document.getElementById("root").contentDocument.body;
ReactDOM.render(<App />, rootElement);

Все события и прочее будут работать. Сохранять вы можете просто HTML, за счет ReactDOM.hydrate(element, container[, callback]), словно на фронте после сервер-сайд рендеринга подключать к DOM React. Но конечно, по факту все, что на странице будет иметь свое представление в Virtual DOM хотите вы этого или нет. Это круто. Redux, Flux, Mobx в вашем распоряжении. Это бьет по перфомансу.
Организовать работу с элементами и инструментами, можно по средствам стандартных подходов. Это небольшая оболочка для Backbone. Но тут получается так же каждый элемент будет подконекчен к стору Redux, что не есть хорошо.
Я в свое время боялся добавлять Marrionett к проекту. Но это не известно.
Видится только одна проблема, которая может повлиять на многое. А тут такие траты. Допустим мы перетаскиваем новые элементы написанные на React, на страницу. Как добавлять элементы на страницу? Делать у каждого элемента массив дочерних элементов? Как их правильно встроить в DOM? Так делать можно, учитывая нашу следующую тему которую необходимо обсудить напоследок. Делать ReactDOM.hydrate после изменения HTML?

Responsive and Adaptive

Ну может я вру, они уже применялись, но не были так хорошо известны каждому. В то время еще не было таких понятий. То есть сайт помещался на любом экране, а если места было больше, то там был какой-то продуманный фон. Тогда еще правила верстка на основе 960px. С ростом популярности смартфонов ситуация менялась.

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

Все элементы добавляемые на страницу, позиционируются относительного этого. По факту это элемент или элементы, с позиционированием relative. По факту ВСЕ позиционируется абсолютно. Никакой адаптивности и эластичности дизайна. Пользователь может двигать элементы безгранично куда хочет.


(зачетный интерфейс на разных языках)

Он может натворить дел, когда сайт превратиться не в пойми, что очень быстро, сайт очень хрупкий при таком подходе. Это плюс для него, но и большой минус. И у него нет нормальной верстки.

Ограничение 03

У лендингов есть понятие экраны. Предоставлять готовые куски, экраны. Мы назвали это секцией.

Пользователь не может взять и случайно потянуть пол страницы хлама.
Далеко не ходя, скажу, что адаптивности и отзывчивости тогда не было в редакторах. Это все тот же 960px, но уже более структурированный. Возможно я натыкаюсь на старые шаблоны, но так или иначе они в самом верху и я как и любой другой пробую именно их.
Решено это у них двумя версиями шаблона. Wix, и на данный момент решает это весьма стремным способом. Если вы, что меняете на большой версии, например просто тот же цвет текста, переключаюсь или сжимая браузер до мобильной — этих изменений не будет. Да-да.

поддержки на этот счет 🙂 Интересно пообщаться с первой линией тех.

12 друзей верстки, флекс, гриды.

Поклацайте https://grapesjs.com/, и вы сразу поймете о чем я. 12 колоночная система, знаете?

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

Заготовки, шаблончики и платный сервис/помощь, мутные люди вокруг

Пользователям все равно до лампочки на все ваши элементы верстки и как они должны двигать элементы. Но как ни крути сделать идеальный инструмент сложно. По этому есть заготовки и шаблоны. Создание сайта это творческая работа и как правило, тем кому не повезло работать в вашем редакторе думают совершенно не о том как бы четенько сделать сайт. И чем их больше, тем хуже у вас дела с UI/UX.

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

Итак

Cделать редактор на самом деле не рокет сайнс. Я лишь пожелаю вам удачи. Работа с текстом не такая уж и простая задача, я даже не упоминал undo/redo функционал, его сделать достаточно сложно. Главное это UI/UX. Ну или просто, если вы будете дампить HTML всей страницы в localStorage… Нет, конечно же я так не делал.

Мой редактор работает от силы на двух проектах, его используют разные аудитории, но насколько им это удобно и соответствует результат их ожиданиям — неизвестно. Рокет сайнс научить пользователей им пользоваться. Если у вас есть вопросы, буду рад ответить в коментариях, личке.

S. P. Я буду фиксить, все косяки и товтологии который найду. букв много и я не поэт. Но не стисняйтесь писать в личку, спасибо 🙂


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

[Из песочницы] Валидация сложных форм React. Часть 1

Для начала надо установить компонент react-validation-boo, предполагаю что с react вы знакомы и как настроить знаете. npm install react-validation-boo Чтобы много не болтать, сразу приведу небольшой пример кода. import React, from 'react'; import {connect, Form, Input, logger} from 'react-validation-boo'; class ...

[Перевод] Микросервисы на Go с помощью Go kit: Введение

Эта статья — введение в Go kit. В этой статье я опишу использование Go kit, набора инструментов и библиотек для создания микросервисов на Go. Первая часть в моем блоге, исходный код примеров доступен здесь. Когда вы разрабатываете облачно-ориентированную распределенную систему, ...