Консолидация сложенных элементов форматирования DOM - contenteditable DIV

У меня есть довольный DIV, который связан / синхронизирован с текстовой областью.

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

Я хотел бы иметь возможность очистить код перед отправкой формы textarea на сервер.

В итоге можно получить что-то вроде следующего:

<div>
  <b>
    <i>
        Hel
    </i>
    <i>
        l
    </i>
  </b>
  <i>
    <b>
       o World!
    </b>
  </i>
</div>

Который в идеале будет преобразован в:

<div>
  <b>
    <i>
       Hello World!
    </i>
   </b>
</div>

Если бы я прошел (рекурсивно) по дочерним узлам div, я мог бы предположительно отслеживать форматы (tagName.toUpperCase() == {'B','I' ....} ) // или сделать document.queryCommandState во время которого я мог сделать document.execCommand('removeFormat',false,null) на selectNode(thenode),

Тем не менее, я немного растерялся из-за того, как мог бы отслеживать соседние узлы форматов.

В качестве ссылки вот что я недавно сделал для анализа DOM, чтобы удалить форматирование из тегов IMG: http://jsfiddle.net/tjzGg/

NB: Это похожий вопрос> jquery - консолидировать сложенные элементы DOM, но речь идет о консолидации useCSS линии стиля в один основной стиль. Причина, по которой это другой вопрос, заключается в том, что я пытаюсь объединить текст в едином стиле, но искусственно разделить его на несколько элементов из-за того, как текст был отформатирован. Если вы возьмете contenteditable div и по отдельности выделите один символ за раз, вы получите один символ на элемент.

1 ответ

Решение

У меня есть пара решений, которые имеют свои плюсы и минусы.

Во-первых, во время игры в gmail я обнаружил, что способный к DIV DIV будет "поглощать" соседний узел при условии, что стиль форматирования находится в том же текущем выбранном режиме. Эта "халява" позволила мне просто попытаться реорганизовать порядок, в котором происходит форматирование, чтобы очистить большую часть супа html. Это не полное решение. Идеальным решением было бы иметь самый большой режим форматирования, поскольку родительский элемент с подмножеством текстов будет иметь уменьшающиеся величины как дополнительные вложенные режимы.

В моем приведенном выше искусственном примере результат по сути будет преобразован в:

<div>
   <b>
     <i> 
        Hel
        l
     </i>
    </b> 
....

предостережение: это было проверено только с текстом, без изображений. Я хотел бы представить, что есть одна или две ошибки, связанные с разбором узлов в решении 1 и использованием textContent.length в решении 2.


Решение 1:

Первая работает в Chrome, но в Firefox вызывает execCommand приведет к тому, что выбор узла потеряет фокус и станет невыбранным. Это роковая ошибка, которую я не могу понять или запрограммировать. Это было заброшено, если я не могу понять, как повторно выделить / выбрать только что отформатированный узел.

http://jsfiddle.net/tjzGg/3/

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


Решение 2:

Второй подход - попытаться придумать решение для Firefox, теряющего фокус. Единственный способ справиться с этим - игнорировать выделение целых узлов, а вместо этого выбирать ОДИН символ за раз, смотреть на его форматирование, обнулять и повторно применять в определенном порядке. Это работает в обоих браузерах, но DOM затем разделяется на childNode для каждого персонажа. Я не уверен в том, как лучше их объединить (textContent?).

http://jsfiddle.net/LDVpD/3/


[фон: посмотрел на jsbeautifier, htmlsoup, html tidy, nokogiri, hpricot, jtidy ..... Я действительно удивлен, что по этому вопросу уже нет решения. GMail также сгенерирует "уродливое" форматирование!]

Я знаю, что есть лучшие решения - я хотел бы услышать некоторые предложения.

Обновить

После тестирования становится очевидным, что решение 2 является смехотворно медленным (его не было бы сложно оптимизировать, отслеживая голову, поскольку это прогрессивное "наводнение", но все же оно довольно медленное), и даже можно легко изменить его на обрабатывать текстовые узлы целиком, но решение 1 кажется более подходящим, если оно работает только в Firefox.


Решение 1+2=3:

Я обнаружил, что если бы я применил форматирование в качестве средства переключения, оно работало бы, однако, как и предполагалось, текстовые узлы будут увеличиваться / уменьшаться на основе естественной консолидации соседнего согласованного форматирования. Так что меня осенило, когда я спал, что если бы я создал список текстовых узлов и перешел назад, то мне было бы наплевать, будет ли внутренне DOM (для Firefox!!!) расти / уменьшаться во время применения форматирования. Комбинируя список textNode в решении 2 (а затем извлекая хвостовые узлы), это прекрасно работает. Фактически, итерация вместо повторения текстовых узлов (оригинальный метод решения 1) выполняется еще быстрее.

http://jsfiddle.net/tjzGg/4/

NB: selectNodeContents против selectNode

Другие вопросы по тегам