Caret positions in HTML

Working on behavior:richtext again. This time for Sciter2.
The behavior:richtext is the thing behind Sciter’s <richtext> element or <div contenteditable> in Web browsers.

behavior:richtext in Sciter1 uses “flat” DOM model: div:element, paragraph:element, that model is similar to the RichTextBox in Windows.
But in Sciter2 new behavior:richtext uses standard DOM model of HTML content: element:node, text:node, comment:node.
That change requires me to rethink concept of caret positions again.

Consider this markup:

<p>12<b>34</b><i>56</i><p>

That is rendered as:

123456

Question is: how many caret positions in this paragraph?

All known contenteditable implemenatations will give you 7 caret positions here: before 1,  between 1 and 2, … after 7. So they follow approach used by WYSIWYG editors like Word and others.

Now consider these tasks, insert text "AB" in that paragraph between ‘4’ and ‘5’ so it will go in these locations:

  1. Inside <b> : 1234AB56,  12<b>34AB</b><i>56</i>;
  2. Inside <i> : 1234AB56  12<b>34</b><i>AB56</i><p>;
  3. Between <b> and <i> : 1234AB56  12<b>34</b>AB<i>56</i>;

Problem here as we can see: single caret position (visual) actually represents at least three physical DOM insertion points.

That kind of problme is typical for WYSIWYG editing implementations. In flat models where text is just a sequence of "styled characters" this is probably not a major issue but in HTML WYSIWYG something needs to be done I think.  

In Sciter1 I am using "directional" caret approach – physical caret locations are dependent from direction from where caret arrive to that position:

  • so when you move caret rightwards you caret stops at these locations: <b>3|4|</b><i>5|6|</i>
  • and if from the left then <b>|3|4</b><i>|5|6</i>

This covers tasks #1 and #2 above. But #3 is still not covered. Something needs to be done here, thinking.

Actually this kind of problem is not just about characters inside text and spans. It is also about cases like this:

<ul>
  <li>first</li>
  <li>second</li>
</ul>
<pre>some code</pre>

 What would you do if you need to insrert paragraph with text between list and <pre> block:

<ul>
  <li>first</li>
  <li>second</li>
</ul>
<p>some text</p>
<pre>some code</pre>

You can try it here in your browser:

  • first
  • second
some code