Skip to content Skip to sidebar Skip to footer

Consolidate Stacked Dom Formatting Elements - Contenteditable Div

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 be

Solution 1:

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

Post a Comment for "Consolidate Stacked Dom Formatting Elements - Contenteditable Div"