合并堆叠的DOM格式元素 - contenteditable DIV

时间:2013-04-26 00:04:03

标签: javascript html5 dom formatting contenteditable

我有一个令人满意的DIV,它被链接/同步回到textarea。

令人满意的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的childNodes,我可能会跟踪格式(tagName.toUpperCase() == {'B','I' ....} ) //或执行document.queryCommandState,在此期间我可以执行document.execCommand('removeFormat',false,null) selectNode(thenode)

但是,我对如何跟踪格式的相邻节点有点迷失。

这里引用的是我最近为DOM解析从IMG标签中删除格式所做的事情:http://jsfiddle.net/tjzGg/

注意:这是一个类似的问题&gt; jquery - consolidate stacked DOM elements但它是关于将useCSS样式行合并为一种主要样式。这是一个不同的问题的原因是我希望用一种共同的风格来整合文本,但由于文本的格式化,人为地分割了多个元素。如果你采用一个可信的div并且一次单独加粗一个字符,那么每个元素最终会有一个字符。

1 个答案:

答案 0 :(得分:1)

我有几个有其优点和缺点的解决方案。

首先,我发现在gmail中玩游戏时,如果格式化样式处于相同的当前所选模式,那么可信任的DIV将“吸收”相邻节点。这个“免费赠品”让我只是试图重新组织格式化的排序来清理大部分的html汤。这不是一个完整的解决方案。理想的解决方案是拥有最大的格式化模式,因为子级文本将具有递减嵌套模式的子级文本。

在我上面的人工例子中,结果本身就会被转换成:

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

警告:这是仅使用文本进行测试,没有图像。由于解决方案1中的节点解析以及解决方案2中使用textContent.length,我认为在处理时存在一两个错误。


解决方案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的速度非常慢(通过跟踪头部来优化它并不复杂,因为它是一个渐进的“洪水”,但仍然很慢)甚至一个人很容易修改它以处理整个textNodes,但如果解决方案1仅在Firefox中有效,那么解决方案1似乎是一种更好的方法。


解决方案1 ​​+ 2 = 3:

我发现,如果我将格式化作为切换方式应用,那么正如预测的那样,文本节点会根据相邻匹配格式的自然合并而增长/缩小。所以当我睡觉的时候,我突然意识到如果我创建了一个文本节点列表,并且从后到前,我可以更少关心内部DOM(对于Firefox !!!)在应用格式化时正在增长/缩小。结合Solution 2的textNode列表(然后弹出尾节点)这很有效。事实上,迭代而不是递归文本节点(原始的解决方案1方法)甚至更快。

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

注意:selectNodeContents与selectNode