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

标签 javascript html dom formatting contenteditable

我有一个可内容编辑的 DIV,它链接/同步回文本区域。

contenteditable DIV 是一个免费的沙箱,它将在调用时创建格式化元素等。然而,这通常会导致元素堆叠困惑。

我希望能够在将文本区域表单发送到服务器之前清理代码。

最终可能会得到如下结果:

<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 ,在此期间我可以在 selectNode(thenode) 上执行 document.execCommand('removeFormat',false,null) )

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

这里作为引用的是我最近对 ​​DOM 解析所做的操作,以删除 IMG 标签的格式:http://jsfiddle.net/tjzGg/

注意:这是一个类似的问题> jquery - consolidate stacked DOM elements但它是将 useCSS 样式行合并为一种主要样式。这是一个不同的问题的原因是,我希望将文本与通用样式合并,但由于文本的格式设置而人为地分割为多个元素。如果您采用 contenteditable div 并一次单独加粗一个字符,最终每个元素将显示一个字符。

最佳答案

我有几个解决方案,各有优缺点。

首先,我在玩 gmail 时发现,只要格式样式与当前选定的模式相同,contenteditable 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 会被拆分为每个字符的子节点。我不确定组合它们的最佳方式(textContent?)。

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


[背景:查看了 jsbeautifier、htmlsoup、html tidy、nokogiri、hpricot、jtidy ..... 我真的很惊讶,这个问题还没有解决方案。 GMail 也会生成“丑陋”的格式!]

我知道有更好的解决方案 - 我很想听听一些建议。

更新

经过测试,很明显解决方案 2 慢得离谱(通过跟踪头部来优化它并不复杂,因为它是一种渐进的“洪水”,但仍然相当慢),甚至可以轻松地修改它以处理整个 textNode,但如果解决方案 1 仅适用于 Firefox,那么它似乎是更好的方法。


解决方案1+2=3:

我发现,如果我应用格式作为切换的方法,它会起作用,但是正如预测的那样,文本节点会根据相邻匹配格式的自然合并而增大/缩小。因此,我在 sleep 时突然意识到,如果我创建一个文本节点列表,并从后到前,我就可以不在乎 DOM(对于 Firefox!!!) 在应用格式时内部是否增长/收缩。结合解决方案 2 的 textNode 列表(然后弹出尾部节点),效果非常好。事实上,迭代而不是递归文本节点(原始解决方案 1 方法)甚至更快。

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

注意:selectNodeContents 与 selectNode

关于javascript - 合并堆叠的 DOM 格式化元素 - contenteditable DIV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16226671/

相关文章:

jquery - 单击 div 不会滚动到元素,因为它应该使用 jQuery

javascript - 使用 localStorage 显示最近访问的 n 个页面

jquery - 如何防止 replaceWith 制作多个文本节点?

javascript - 在 React 中将数据传递给父级

javascript - 使用 Javascript/Angular 读取 JSON 值

javascript - 防止在内联编辑模式下编辑特定可编辑行的单元格

html - 顶部图像与顶部图像一致?

python - 如何使用 xml.dom 库在 python 中序列化 XML 文档

javascript - ExtJS addEvents - 它是可选的吗?

javascript - 在 React 和 Redux 中重新渲染所有组件