Редактор разметки JavaScript с использованием объекта выбора и диапазона

Я пытаюсь написать редактор разметки на основе JavaScript (WYSIWIG), используя выделение и объект диапазона. У меня пока нет проблем с доступом к этим объектам.

Мои проблемы начинаются здесь:

Используя объект диапазона, я могу получить доступ к его свойствам startContainer/StartOffset и EndContainer/Endoffset. Это означает, что я возвращаю информацию об узле, с которого начинается мой выбор, включая внутреннюю позицию и ту же информацию о конце выбора.

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

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

Пример:

This <i>is my</i><b>sample</b> text.

Теперь я хотел бы подчеркнуть часть «мой образец».

Это означает, что что-то вроде этого должно быть построено из выбора «моего образца»:

This <i>is <u>my</u></i><b><u>sample</u></b> text.

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

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

Я надеюсь, что этот вопрос ясен, и я извиняюсь за его общую форму. Но я действительно схожу с ума по этому делу...


person Tobi    schedule 12.07.2011    source источник


Ответы (1)


Существует встроенный метод document.execCommand() (MSDN, MDN), который сделает это за вас. В случае подчеркивания это будет

document.execCommand("Underline", false, null);

jsFiddle: http://jsfiddle.net/3NcEP/

Обратите внимание, что это работает только с редактируемым содержимым (с использованием contenteditable или designMode) в большинстве браузеров.

Если вам нужно применить к выделению какой-либо стиль, который не предоставляется ни одной из встроенных команд, вам придется самостоятельно обрабатывать все узлы в выделении, при необходимости разделяя его на каждом конце выделения. Это нетривиально. Кроме того, IE ‹ 9 не поддерживает диапазон DOM а Selection и делает все совершенно иначе. Если вам нужно работать с этими браузерами, вам может помочь такая библиотека, как моя собственная Rangy.

person Tim Down    schedule 12.07.2011
comment
Большое спасибо за ответ. Меня не волнует совместимость с IE, но я боюсь, что мне придется пойти нетривиальным путем... Мне нужна возможность вставлять спаны с произвольными классами. Есть ли существующий редактор, который мог бы меня вдохновить? Или алгоритмы где-то существуют? - person Tobi; 12.07.2011
comment
@Tobi: взгляните на модуль применения класса CSS в Rangy: code.google.com /p/rangy/wiki/CSSClassApplierModule - person Tim Down; 12.07.2011
comment
этот модуль применения css выглядит интересно! Во-первых, мне нужно решить еще одну проблему: теперь я подумал о том, чтобы выяснить, нарушает ли выделение существующую древовидную структуру, сравнивая range.startContainer и range.endContainer. Если истина, sel находится в том же узле, поэтому ничего. сломан, и в него можно вставить новый узел. Если false, выбор пересекает уже существующую древовидную структуру. Я понял, что это обнаружение не работает постоянно: иногда это правда, иногда нет, хотя я всегда выбираю один и тот же узел. Есть ли диф. между мышью и клавиатурой? - person Tobi; 13.07.2011
comment
@Tobi: То, как браузеры представляют выбор, различается, но я не уверен, что это имеет отношение к этой проблеме. Шаги, необходимые для определения того, может ли диапазон быть окружен или нет, четко определены в спецификации DOM Range: w3.org/TR/DOM-Level-2-Traversal-Range/. Если вы используете Rangy, вы можете использовать метод диапазона canSurroundContents(). - person Tim Down; 17.07.2011