Comments 46
Написали бы об этом опыте. Это так занимательно, насколько я понимаю, что просто слов нет. Только маты.
Да, до сих пор снится мне в страшных снах. Ну ооочень занимательно.
В статье описан один вариант реализации WYSIWYG HTML редактора.

Есть еще второй вариант, так сказать Google Docs way — когда designMode не используется. Вместо него присутствует JS эмуляция, вплоть до того, что курсор рисуется обычным html элементом.
В частности, это позволяет использовать rich text editing на устройствах вроде iPad, где designMode увы не поддерживается.
по-моему, это единственный правильный подход, если хотите сделать нормальный результат на выходе, которым легко управлять.
Затраты на разработку редактора основанного на designMode и contentEditable, думаю, будут на несколько порядков меньше, чем если полностью написать его на js.
А если нужен мини-редактор с 2-я 3-я дополнительными функциями (изменение начертания на курсивное или полужирное и вставка пары тройки специальных символов. Например значков карт для социальной сети любителей покера) то делать решение на без designMode/contentEditable мягко говоря не выгодно.
в свое время свой визивиг делал, да перестал поддерживать, т.к. времени нет на него. Так вот мое резюме — не факт, что вариант гугла будет дороже в конечном итоге. там очень много всего такого, что отличается не только в броузерах, но и в их версиях.

Мой вариант визивига здесь:
code.google.com/p/lwrte/

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

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

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

Костыли они вездесущи.
Да, но это практически полностью лишает пользователя возможности работать с DOM редактируемого документа. Т.е. в standalone-решениях типа google docs и ms docs это и не нужно. Для редакторов, которые создаются для встраивания (для разработчиков), типа ckEditor (ex fckEditor), ASPxHtmlEditor — такой функционал полезен. Кроме того, генерация чистого HTML документа уже становится специфической задачей.

В общем, как уже сказал Beresta, здесь полностью все, что делает в contentEditable моде сам браузер, переносится «на плечи» скрипта (js/html5) редактора.
Вот сейчас смотрю через firebug открытый на редактирование документ в google docs и вижу там iframe c designMode=«on». Что я делаю не так?

На самом деле вариант с заменой iframe на canvas или манипулирование содержимым самостоятельно неработоспособен по одной простой причине — буфер обмена
Моя ошибка. Оказывается старые документы открываются так как они были созданы. В новых уже div. Интересный способ, надо б поизучать
пока только один баг нашёл — нельзя выделять текст мышкой. хотя, вполне возможно, и это можно как-то обойти.
Способ установки фокуса на элемент с возможностью ввода текста уже у гугла подсмотрел. Только у них вместо texarea используется все тот же iframe с designMode=«on» со всеми вытекающими.
Вместо него присутствует JS эмуляция, вплоть до того, что курсор рисуется обычным html элементом.

кстати, а есть такие редакторы уже?
Встраиваемых не встречал пока, только приложения — Google Docs и docs.com от MS.

Дело скорее всего в том, что порог вхождения в случае полной эмуляции существенно выше — нужна серьезная команда и большое количество времени что бы функциональный редактор сделать.
С разработкой wysiwyg редактора знаком совсем не понаслышке :)
Форматирование с помощью execCommand, в большинстве случаев — просто кошмар! Нормально (те более-менее одинаково во всех браузерах) работают только манипуляции со списками и блочное форматирование. Все остальное лучше реализовать самостоятельно — хотя это очень непросто.
В первой версии мы во многом положились именно на execCommand и очень быстро поняли, что неправы :(
В делоперской версии это уже исправлено, но до ее выхода еще не близко
А разница в реализации textRange с легкостью вынесет мозг начинающему разработчику
А как вы решаете проблему с UnDo/ReDo? Я так понимаю, что после изменения dom без использования execCommand они уже не работают и их надо реализовать руками, да?

Я пробовал использовать команду insertHTML, но результат меня печалит.
Похоже придется в своей тестовой поделке использовать таки диапазоны.

document.execCommand(«insertHTML»,true,"
"); — например в хроме не работает если курсор в самой правой части текста внутри параграфа.
Про поведение оперы я вежливо промолчу. Она под win норовит забыть отрисовать изменения в блоке с contentEditable. Ох.
С UnDo/ReDo в текущей версии полагались почти полностью на встроенную реализацию — результат не очень. В новой версии отслеживаем события редактора и при наличии изменений добавляем новый уровень к истории. Шоткаты отката/повтора переопределили.
insertHTML тоже не используем — собственная реализация работы с textRange и DOM. Если интересно — можете посмотреть в нашем гите ветку master
О! А еще гениальная придумка MS с позиционированием выбранной области по символам, и где она окажется в dom-дереве это как правило большой сюрприз.

А еще чего стоит баг отображения если в редактируемом тексте встречается <br> непосредственно перед закрывающим </p>

Тоже не по наслышки знаком. Фазу к черту execCommand уже прошел и в рабочей версии =)
В FireFox'е execCommand-команда «inserthtml» разрешает вставлять произвольный html-код. Это позволяет заменить другие execCommand-команды на свои варианты. Большая проблема только в том, что другие браузеры не работают с inserthtml. :(
Так то оно — так. Но без анализа вставляемого кода и того, куда он вставляется — вероятность получить совсем кривой html — почти 100%
inserthtml к сожалению ведет себя вовсе не так здорово, как кажется на первый взгляд.
Он бааажный.
Кстати нету его только в IE, если не путаю.
В IE у textRange есть метод pasteHTML.
Про inserthtml я это и говорил — слишком много надо делать, чтобы с его помощью получить валидный хтмл — имхо, оно того не стоит
Ну «куда вставляется» как раз понятно — либо в позицию курсора, либо обрамляем выделение.
по поводу генерации одинакового кода, а заодно и зачистки вордовского мусора делал так:

сделана ф-я cleanup (выдранная из tiny 2.x на то время 3 еще не было) добавлены regex'ы для унификации html (тоесть киляем все что не нужно, все что нужно приводим к эдиному виду)

вешаемся на onchange (и ему подобные события) и onblur и вызываем эту ф-ию

чтобы ф-ия не положила браузер при каждом вызове onchange — сверяем количество символов до и после и если разница больше N тогда запускаем зачистку

года два назад делал, за основу был взят пример из этой же статьи, суммарно вышло 500 с хвостиком строк js кода, что было в сотню раз меньше чем tiny (требовался минимальный функционал b,i,ul,ol и вставка из ворда)
Если команды редактора генерят корректный код, то так часто чистить не нужно. Только при вставке, переключении в исходник и обратно и перед сохранением
Команды редактора, при условии что мы юзаем execcommand, генерят не желательный код, те же span'ы с классами и стилями.

Повеситься на вставку ну никак не получается, по этому пришлось извращаться с запоминанием количества символов.

Переключалки в исходник нет как таковой — редактор для секретарш.

И самое главное: зачистка на сохранении это конечно хорошо и обязательно, но тогда возможны ситуации когда, к примеру я скопипастил текст, дописал\подправил давлю на сохранить оно его зачищает и делает не красивым\не таким как задумано и сохраняет.
Именно по этому зачистка должна происходить по чаще, чтобы пользователь максимально рано увидел результат.
Я имел ввиду «правильные» кооманды, которые не пользуют execCommand :)
Почему нельзя подцепиться за вставку текста? Для нормальных браузеров есть событие paste (если не ошибаюсь даже ie его поддерживает) для оперы по keydown ловим ctrl+v и с небольшим таймаутом запускаем очистку. Единственное, что не ловится в таком варианте — вставка через контекстное меню в опере
Вставка, кстати, может производится т.о.:
Выделяется кусок текста и перетаскивается в область редактирования — так же, приходится учитывать.
А если использовать какое-нибудь TeX-подобное промежуточное представление текста, которое будет рендериться в зависимости от пользовательского клиента? Правда, придется либо активно использовать AJAX для сохранения временных файлов на сервере, либо терпеть оверхэд по памяти…
Only those users with full accounts are able to leave comments. Log in, please.