整合堆叠的DOM格式元素 - 可容忍的DIV [英] Consolidate stacked DOM formatting elements - contenteditable DIV

查看:119
本文介绍了整合堆叠的DOM格式元素 - 可容忍的DIV的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个内容丰富的DIV,它被链接/同步到一个textarea。



contenteditable DIV是一个免费的沙箱,将创建格式化元素等等,因为它们被援引。然而,这确实导致了混乱的堆叠元素。



我想在将文本表单发送到服务器之前清理代码



可能会得到以下结果:

 < div> 
< b>
< i>
Hel
< / i>
< i>
l
< / i>
< / b>
< i>
< b>
o世界!
< / 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) code>。



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



作为参考,我最近为DOM解析从IMG标签中删除格式: http://jsfiddle.net/ tjzGg /



注意:这是一个类似的问题> jquery - 整合堆栈的DOM元素,但它是将 useCSS 样式线整合为一个主要样式。这是一个不同的问题的原因是,我正在寻找合并文本的一种常见的风格,而是人为地分割多个元素,因为文本的格式如何。如果你一个人拥有一个可容忍的div,并且一个人一个字一个字,那么每个元素就会有一个字符。

解决方案

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



首先,我发现在gmail里玩耍时,一个可满足的DIV将会吸收相邻的节点,只要格式化样式与当前选定的模式相同。这个免费赠品让我仅仅试图重组格式化的排序,以清理大部分的html汤。这不是一个完整的解决方案。理想的解决方案是将最大的格式化模式作为父级,子集文本在降低幅度时将是更多的嵌套模式。



在我上面的人工例子中,结果将固有地转换为:

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

注意事项:这是仅用文本测试,没有图像。我想象在解决方案1中的节点解析和解决方案2中使用textContent.length时,会遇到一个或两个错误。






解决方案1 ​​



第一个在Chrome中工作,但在Firefox中调用 execCommand 将导致节点选择失去焦点并被取消选择。这是一个致命的缺陷,我似乎不能理解或编程。这已经被放弃,除非我可以弄清楚如何重新突出/选择新格式化的节点。



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



我会




解决方案2



第二种方法是尝试为Firefox失去焦点的解决方案。我可以处理的唯一方法是忽略选择整个节点,而是一次选择一个字符,查看其格式,按一定顺序重新应用。这两个浏览器都可以工作,但是然后将DOM分解为每个字符的 childNode 。我不确定最合适的方法(textContent?)。



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






[背景:看看jsbeautifier,htmlsoup,html整洁,nokogiri,hpricot,jtidy .. ...我真的很惊讶,已经没有解决方案了。我们知道有更好的解决方案 - 我很乐意听到一些建议。


更新



测试后很明显,解决方案2是可笑的(优化并不复杂)它通过跟踪头,因为它是一个渐进的洪水,但仍然是相当缓慢),甚至可以轻松地修改它来处理整个textNodes,但解决方案1似乎是一个更好的方法,如果它只在Firefox工作。 p>




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



我发现,如果我将格式化作为切换的手段,它将按照预期的方式工作,基于相邻匹配格式的自然合并,文本节点将增长/缩小。所以在睡觉的时候我明白了,如果我创建了一个文本节点列表,并且从后面到前面,我可以关心在内部使用DOM(对于Firefox !!!)在应用格式化时增长/缩小。结合解决方案2的textNode列表(然后弹出尾部节点)这很好。实际上,迭代而不是递归文本节点(原始解决方案1方法)更快。



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



注意:selectNodeContents vs selectNode


I have a contenteditable DIV which is linked/synced-back to a textarea.

The contenteditable DIV is a free-for-all sandbox which will create formatting elements etc as they are being invoked. However this does result often in messy stacked elements.

I would like to be able to clean up the code before the textarea form is sent to the server.

It is possible to end up with something like the following:

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

Which would ideally be converted to:

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

If I walked (recursively) through the childNodes of the div I could presumably keep track of the formats (tagName.toUpperCase() == {'B','I' ....} ) // or do a document.queryCommandState during which I could do a document.execCommand('removeFormat',false,null) on the selectNode(thenode).

However, I'm a bit lost on how I might keep track across neighbouring nodes of the formats.

As reference here is what I recently did for DOM parsing to remove formatting from IMG tags: http://jsfiddle.net/tjzGg/

NB: This is a similar question> jquery - consolidate stacked DOM elements but it is about consolidating useCSS style lines into one main style. The reason this is a different question is that I am looking to consolidate text with a common style but artificially split over multiple elements because of how the text was formatted. If you take a contenteditable div and individually bold one character at a time you will end up with a single character per element.

解决方案

I have a couple solutions which have their pros and cons.

First, I discovered while playing around in gmail that a contenteditable DIV will 'absorb' a neighbouring node provided the formatting style is in the same current selected mode. This 'freebie' allowed me to merely attempt to reorganize the ordering in which formatting occurs to clean up the majority of the html soup. This is not a complete solution. The ideal solution would be to have the largest formatting mode as the parent with the subset texts would have in decreasing magnitudes be the further nested modes.

In my above artificial example the result would inherently be converted into:

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

caveat: This was tested with text only, no images. I would imagine there is a bug or two when dealing with due to the node parsing in solution 1 and use of textContent.length in solution 2.


Solution 1:

The first works in Chrome, but in Firefox invoking execCommand will cause the node selection to lose focus and become unselected. This is a fatal flaw that I cannot seem to understand or program around. This has been abandoned unless I can figure out how to re-highlight/select the newly formatted node.

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

I would love to be able to get this one working with Firefox. Any suggestions on where I'm going wrong here.


Solution 2:

The second approach is to try come up with a solution for Firefox losing focus. The only way I could handle that is to ignore selecting whole nodes but instead select ONE character at a time, look at its formatting, nuke and reapply in a certain order. This works in both browsers but the DOM is then split into a childNode for each character. I'm not sure of the best way to combine them (textContent?).

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


[background: looked at jsbeautifier, htmlsoup, html tidy, nokogiri, hpricot, jtidy ..... I'm really surprised that there is no solution on this already. GMail will generate 'ugly' formatting as well!]

I know there are better solutions - I'd love to hear some suggestions.

Update

After testing, it is obvious that solution 2 is ridiculously slow (it would not be complicated to optimize it by keeping track of the head as it is a progressive 'flood' but still it is quite slow) and even one could easily modify it to process entire textNodes but solution 1 seems like a better approach if it only worked in Firefox.


Solution 1+2=3:

I found out that if I applied the formatting as a means to toggle it would work however as predicted the text nodes would grow/shrink based on natural consolidation of neighbouring matched formatting. So it dawned on me while sleeping that if I created a list of text nodes, and went from back to front I could care less if internally the DOM (for Firefox!!!) was growing/shrinking while formatting was being applied. Combining Solution 2's textNode list (and then popping off the tail nodes) this works great. In fact iterating instead of recursing the text nodes (original Solution 1 method) is even faster.

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

NB: The selectNodeContents vs selectNode

这篇关于整合堆叠的DOM格式元素 - 可容忍的DIV的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆