--- a/editcommands.html Fri Jul 08 12:51:44 2011 -0600
+++ b/editcommands.html Fri Jul 08 14:15:56 2011 -0600
@@ -84,25 +84,24 @@
<ol>
<li><a href=#inline-formatting-command-definitions><span class=secno>7.1 </span>Inline formatting command definitions</a></li>
<li><a href=#assorted-inline-formatting-command-algorithms><span class=secno>7.2 </span>Assorted inline formatting command algorithms</a></li>
- <li><a href=#decomposing-a-range-into-nodes><span class=secno>7.3 </span>Decomposing a range into nodes</a></li>
- <li><a href="#clearing-an-element's-value"><span class=secno>7.4 </span>Clearing an element's value</a></li>
- <li><a href=#pushing-down-values><span class=secno>7.5 </span>Pushing down values</a></li>
- <li><a href=#forcing-the-value-of-a-node><span class=secno>7.6 </span>Forcing the value of a node</a></li>
- <li><a href=#setting-the-value-of-a-node><span class=secno>7.7 </span>Setting the value of a node</a></li>
- <li><a href=#the-backcolor-command><span class=secno>7.8 </span>The <code title="">backColor</code> command</a></li>
- <li><a href=#the-bold-command><span class=secno>7.9 </span>The <code title="">bold</code> command</a></li>
- <li><a href=#the-createlink-command><span class=secno>7.10 </span>The <code title="">createLink</code> command</a></li>
- <li><a href=#the-fontname-command><span class=secno>7.11 </span>The <code title="">fontName</code> command</a></li>
- <li><a href=#the-fontsize-command><span class=secno>7.12 </span>The <code title="">fontSize</code> command</a></li>
- <li><a href=#the-forecolor-command><span class=secno>7.13 </span>The <code title="">foreColor</code> command</a></li>
- <li><a href=#the-hilitecolor-command><span class=secno>7.14 </span>The <code title="">hiliteColor</code> command</a></li>
- <li><a href=#the-italic-command><span class=secno>7.15 </span>The <code title="">italic</code> command</a></li>
- <li><a href=#the-removeformat-command><span class=secno>7.16 </span>The <code title="">removeFormat</code> command</a></li>
- <li><a href=#the-strikethrough-command><span class=secno>7.17 </span>The <code title="">strikethrough</code> command</a></li>
- <li><a href=#the-subscript-command><span class=secno>7.18 </span>The <code title="">subscript</code> command</a></li>
- <li><a href=#the-superscript-command><span class=secno>7.19 </span>The <code title="">superscript</code> command</a></li>
- <li><a href=#the-underline-command><span class=secno>7.20 </span>The <code title="">underline</code> command</a></li>
- <li><a href=#the-unlink-command><span class=secno>7.21 </span>The <code title="">unlink</code> command</a></ol></li>
+ <li><a href="#clearing-an-element's-value"><span class=secno>7.3 </span>Clearing an element's value</a></li>
+ <li><a href=#pushing-down-values><span class=secno>7.4 </span>Pushing down values</a></li>
+ <li><a href=#forcing-the-value-of-a-node><span class=secno>7.5 </span>Forcing the value of a node</a></li>
+ <li><a href="#setting-the-selection's-value"><span class=secno>7.6 </span>Setting the selection's value</a></li>
+ <li><a href=#the-backcolor-command><span class=secno>7.7 </span>The <code title="">backColor</code> command</a></li>
+ <li><a href=#the-bold-command><span class=secno>7.8 </span>The <code title="">bold</code> command</a></li>
+ <li><a href=#the-createlink-command><span class=secno>7.9 </span>The <code title="">createLink</code> command</a></li>
+ <li><a href=#the-fontname-command><span class=secno>7.10 </span>The <code title="">fontName</code> command</a></li>
+ <li><a href=#the-fontsize-command><span class=secno>7.11 </span>The <code title="">fontSize</code> command</a></li>
+ <li><a href=#the-forecolor-command><span class=secno>7.12 </span>The <code title="">foreColor</code> command</a></li>
+ <li><a href=#the-hilitecolor-command><span class=secno>7.13 </span>The <code title="">hiliteColor</code> command</a></li>
+ <li><a href=#the-italic-command><span class=secno>7.14 </span>The <code title="">italic</code> command</a></li>
+ <li><a href=#the-removeformat-command><span class=secno>7.15 </span>The <code title="">removeFormat</code> command</a></li>
+ <li><a href=#the-strikethrough-command><span class=secno>7.16 </span>The <code title="">strikethrough</code> command</a></li>
+ <li><a href=#the-subscript-command><span class=secno>7.17 </span>The <code title="">subscript</code> command</a></li>
+ <li><a href=#the-superscript-command><span class=secno>7.18 </span>The <code title="">superscript</code> command</a></li>
+ <li><a href=#the-underline-command><span class=secno>7.19 </span>The <code title="">underline</code> command</a></li>
+ <li><a href=#the-unlink-command><span class=secno>7.20 </span>The <code title="">unlink</code> command</a></ol></li>
<li><a href=#block-formatting-commands><span class=secno>8 </span>Block formatting commands</a>
<ol>
<li><a href=#block-formatting-command-definitions><span class=secno>8.1 </span>Block formatting command definitions</a></li>
@@ -1069,32 +1068,35 @@
that 1) in <b>[foo]</b>, the text node and the <b> are effectively contained
but not contained; and 2) in <b>f[o]o</b>, the text node is effectively
contained but not contained, and the <b> is neither effectively contained nor
-contained. This is used mostly for the "decompose" algorithm, and also for
-most inline commands' states.
+contained.
-->
<ul>
<li><var title="">node</var> is <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in <var title="">range</var>.
<li><var title="">node</var> is <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, it is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code>
- node, and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> is different from <var title="">range</var>'s
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a>.
+ node, its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> is different from <var title="">range</var>'s
+ <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a>, and <var title="">range</var> is not <code class=external data-anolis-spec=domrange title=dom-Range-collapsed><a href=http://html5.org/specs/dom-range.html#dom-range-collapsed>collapsed</a></code>.
+ <!-- So like <b>f[oo]</b> or <b>f[o]o</b> or <b>f[oo</b>}, but not
+ <b>foo[</b>} or <b>f[]oo</b>. -->
<li><var title="">node</var> is <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, it is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node,
- and <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is not 0.
+ <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is not 0, and <var title="">range</var> is not
+ <code class=external data-anolis-spec=domrange title=dom-Range-collapsed><a href=http://html5.org/specs/dom-range.html#dom-range-collapsed>collapsed</a></code>.
<li><var title="">node</var> has at least one <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a>; and all its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a> are
<a href=#effectively-contained>effectively contained</a> in <var title="">range</var>; and either
<var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is not a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendant</a> of <var title="">node</var>
- or is not a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node or <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is zero; and
- either <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is not a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendant</a> of
- <var title="">node</var> or is not a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node or <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a>
- is its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>.
+ or is not a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node or <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is zero or
+ <var title="">range</var> is <code class=external data-anolis-spec=domrange title=dom-Range-collapsed><a href=http://html5.org/specs/dom-range.html#dom-range-collapsed>collapsed</a></code>; and either <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>
+ is not a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendant</a> of <var title="">node</var> or is not a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node or
+ <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> or
+ <var title="">range</var> is <code class=external data-anolis-spec=domrange title=dom-Range-collapsed><a href=http://html5.org/specs/dom-range.html#dom-range-collapsed>collapsed</a></code>.
<!--
Basically, anything whose children are all effectively contained should be
effectively contained itself, except that in a case like <b>f[o]o</b> we
don't want <b> to be effectively contained even though the text node is.
- That's because as soon as we decompose the range, the text node is split and
- the <b> will no longer be effectively contained.
+ That's because we split the text node before we actually do anything, and the
+ <b> will no longer be effectively contained.
-->
</ul>
@@ -1385,37 +1387,7 @@
</ol>
-<h3 id=decomposing-a-range-into-nodes><span class=secno>7.3 </span>Decomposing a range into nodes</h3>
-
-<p>To <dfn id=decompose>decompose</dfn> a <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> <var title="">range</var>:
-
-<p class=note>For this algorithm to be correct, it is essential that user
-agents follow the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#range-mutation-rules>range mutation rules</a>, particularly those for <code title="">splitText()</code>.
-
-<ol>
- <li>If <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> are the same,
- return an empty list.
-
- <li>If <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is an
- <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is
- neither 0 nor the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, run <code class=external data-anolis-spec=domcore title=dom-Text-splitText><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-text-splittext>splitText()</a></code> on its
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> with argument equal to its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a>
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a>.
-
- <li>If <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is an <a href=#editable>editable</a>
- <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is neither 0 nor the
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, run <code class=external data-anolis-spec=domcore title=dom-Text-splitText><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-text-splittext>splitText()</a></code> on its
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> with argument equal to its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a>.
-
- <!-- We want to make sure the returned list contains as many nodes as
- possible, such as by treating <tag>[foo]</tag> as {<tag>foo</tag>}. -->
- <li>Return a list consisting of every <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <a href=#effectively-contained>effectively
- contained</a> in <var title="">range</var>, omitting any whose <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is also
- <a href=#effectively-contained>effectively contained</a> in <var title="">range</var>.
-</ol>
-
-
-<h3 id="clearing-an-element's-value"><span class=secno>7.4 </span>Clearing an element's value</h3>
+<h3 id="clearing-an-element's-value"><span class=secno>7.3 </span>Clearing an element's value</h3>
<p>To <dfn id=clear-the-value>clear the value</dfn> of an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code> <var title="">element</var>:
@@ -1491,7 +1463,7 @@
</ol>
-<h3 id=pushing-down-values><span class=secno>7.5 </span>Pushing down values</h3>
+<h3 id=pushing-down-values><span class=secno>7.4 </span>Pushing down values</h3>
<p>To <dfn id=push-down-values>push down values</dfn> to a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <var title="">node</var>, given a new
value <var title="">new value</var>:
@@ -1635,7 +1607,7 @@
</ol>
-<h3 id=forcing-the-value-of-a-node><span class=secno>7.6 </span>Forcing the value of a node</h3>
+<h3 id=forcing-the-value-of-a-node><span class=secno>7.5 </span>Forcing the value of a node</h3>
<p>To <dfn id=force-the-value>force the value</dfn> of a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <var title="">node</var> to <var title="">new
value</var>:
@@ -1893,22 +1865,22 @@
</ol>
-<h3 id=setting-the-value-of-a-node><span class=secno>7.7 </span>Setting the value of a node</h3>
-
-<p>To <dfn id=set-the-value>set the value</dfn> of a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <var title="">node</var> to <var title="">new
-value</var>:
+<h3 id="setting-the-selection's-value"><span class=secno>7.6 </span>Setting the selection's value</h3>
+
+<p>To <dfn id="set-the-selection's-value">set the selection's value</dfn> to <var title="">new value</var>:
<div class=note>
-<p>The effect of this algorithm is to ensure that the node and all its
-descendants have the style requested, no matter what, producing the simplest
-markup possible to achieve that effect. It's inspired by the approach WebKit
-takes. The only places where the algorithm should fail are when there's an
-!important CSS rule that conflicts with the requested style (which we don't try
-to override because we assume it's !important for a reason), or when it's
-literally impossible to succeed (such as when a text-decoration is propagated
-from an ancestor we can't reach). Any other failures are bugs.
-
-<p>First, if the node is an element with an inline style rule for this
+<p>The effect of this algorithm is to ensure that all nodes effectively
+contained in the selection have the style requested, no matter what, producing
+the simplest markup possible to achieve that effect. It's inspired by the
+approach WebKit takes. The only places where the algorithm should fail are
+when there's an !important CSS rule that conflicts with the requested style
+(which we don't try to override because we assume it's !important for a
+reason), or when it's literally impossible to succeed (such as when a
+text-decoration is propagated from an ancestor we can't reach). Any other
+failures are bugs.
+
+<p>First, if a node is an element with an inline style rule for this
property, we unset it ("clearing styles"). This step also removes <a href=#simple-modifiable-element title="simple modifiable element">simple modifiable elements</a> entirely, and
replaces elements like <code class=external data-anolis-spec=html title="the b element"><a href=http://www.whatwg.org/html/#the-b-element>b</a></code> or <code class=external data-anolis-spec=html title=font><a href=http://www.whatwg.org/html/#font>font</a></code> with <code class=external data-anolis-spec=html title="the span element"><a href=http://www.whatwg.org/html/#the-span-element>span</a></code>s if they aren't simple
styling elements. This will be sufficient if the desired style is inherited
@@ -1964,15 +1936,34 @@
as desired.
</div>
-<p class=XXX>Consider porting this algorithm to operate on runs of consecutive
-siblings instead of individual nodes. We might be able to make some parts
-smarter, and also might be able to make it more efficient.
-
<ol>
<li>Let <var title="">command</var> be the current <a href=#command>command</a>.
- <li>If <var title="">node</var> is not <a href=#editable>editable</a>:
+ <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is an
+ <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node, and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is neither zero
+ nor its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>, call <code class=external data-anolis-spec=domcore title=dom-Text-splitText><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-text-splittext>splitText()</a></code> on the <a href=#active-range>active
+ range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, with argument equal to the <a href=#active-range>active
+ range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a>. Then set the <a href=#active-range>active range</a>'s
+ <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> to the result, and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> to zero.
+ <!-- This last sentence just prettifies the resulting range a bit. -->
+
+ <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is an
+ <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node, and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is neither zero
+ nor its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>, call <code class=external data-anolis-spec=domcore title=dom-Text-splitText><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-text-splittext>splitText()</a></code> on the <a href=#active-range>active
+ range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, with argument equal to the <a href=#active-range>active
+ range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a>.
+
+ <li>Let <var title="">element list</var> be all <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>s
+ <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a>.
+
+ <li>For each <var title="">element</var> in <var title="">element list</var>, <a href=#clear-the-value>clear the
+ value</a> of <var title="">element</var>.
+
+ <li>Let <var title="">node list</var> be all <a href=#editable>editable</a> <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>nodes</a>
+ <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a>.
<!--
+ We skip non-editable nodes.
+
IE9: Allows everything to be modified by execCommand(), regardless of whether
it's editable.
Firefox 4.0: Ignores execCommand() if the start and end of the selection are
@@ -2006,41 +1997,17 @@
are bolded, it will unbold instead of bolding.
-->
- <ol>
- <li>Let <var title="">children</var> be the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a> of <var title="">node</var>.
-
- <li><a href=#set-the-value>Set the value</a> of each member of <var title="">children</var>.
-
- <li>Abort this algorithm.
- </ol>
-
- <li>If <var title="">node</var> is an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>:
+ <li>For each <var title="">node</var> in <var title="">node list</var>:
<ol>
- <li><a href=#clear-the-value>Clear the value</a> of <var title="">node</var>, and let <var title="">new
- nodes</var> be the result.
-
- <li>For each <var title="">new node</var> in <var title="">new nodes</var>,
- <a href=#set-the-value>set the value</a> of <var title="">new node</var>.
-
- <li>If <var title="">node</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is null, abort this algorithm.
+ <li><a href=#push-down-values>Push down values</a> on <var title="">node</var>.
+
+ <li><a href=#force-the-value>Force the value</a> of <var title="">node</var>.
</ol>
-
- <li><a href=#push-down-values>Push down values</a> on <var title="">node</var>.
-
- <li><a href=#force-the-value>Force the value</a> of <var title="">node</var>.
-
- <li>Let <var title="">children</var> be the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a> of <var title="">node</var>.
-
- <li><a href=#set-the-value>Set the value</a> of each member of <var title="">children</var>.
-
- <p class=note>Styling a node involves clearing its styles, which can remove
- it from the tree. Implementers should be careful to compute the list of
- children in full before they begin styling.
</ol>
-<h3 id=the-backcolor-command><span class=secno>7.8 </span><dfn>The <code title="">backColor</code> command</dfn></h3>
+<h3 id=the-backcolor-command><span class=secno>7.7 </span><dfn>The <code title="">backColor</code> command</dfn></h3>
<!--
We have three behaviors to choose from for this one:
@@ -2084,8 +2051,7 @@
<li>If <var title="">value</var> is still not a valid CSS color, or if it is
currentColor, raise a <code class=external data-anolis-spec=domcore title=dom-DOMException-SYNTAX_ERR><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-syntax_err>SYNTAX_ERR</a></code> exception.
- <li><a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>, then <a href=#set-the-value>set the
- value</a> of each returned <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> to <var title="">value</var>.
+ <li><a href="#set-the-selection's-value">Set the selection's value</a> to <var title="">value</var>.
</ol>
<p><a href=#indeterminate>Indeterminate</a>: True if among <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code>
@@ -2102,7 +2068,7 @@
<p><a href=#relevant-css-property>Relevant CSS property</a>: "background-color"
-<h3 id=the-bold-command><span class=secno>7.9 </span><dfn>The <code title="">bold</code> command</dfn></h3>
+<h3 id=the-bold-command><span class=secno>7.8 </span><dfn>The <code title="">bold</code> command</dfn></h3>
<!-- If the selection is collapsed (but not if it contains nothing but is not
collapsed), IE9 wraps the whole line in a <strong>. This seems bizarre and no
@@ -2110,9 +2076,9 @@
(fontName, italic, etc.). Except not for strikethrough, where it just does
nothing if the selection is empty. Why strikethrough? I don't know. -->
-<p><a href=#action>Action</a>: <a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>.
-If the <a href=#state>state</a> is then false, <a href=#set-the-value>set the value</a> of each
-returned <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> to "bold", otherwise <a href=#set-the-value>set the value</a> to "normal".
+<p><a href=#action>Action</a>: If the <a href=#state>state</a> is false, <a href="#set-the-selection's-value">set the
+selection's value</a> to "bold", otherwise <a href="#set-the-selection's-value">set the selection's
+value</a> to "normal".
<p><a href=#indeterminate>Indeterminate</a>: True if among <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code>
nodes that are <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
@@ -2155,7 +2121,7 @@
<p><a href=#relevant-css-property>Relevant CSS property</a>: "font-weight"
-<h3 id=the-createlink-command><span class=secno>7.10 </span><dfn>The <code title="">createLink</code> command</dfn></h3>
+<h3 id=the-createlink-command><span class=secno>7.9 </span><dfn>The <code title="">createLink</code> command</dfn></h3>
<p><a href=#action>Action</a>:
@@ -2178,12 +2144,10 @@
I think that's more useful. See issues.
-->
- <li><a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>, and let <var title="">node
- list</var> be the result.
-
<li>For each <a href=#editable>editable</a> <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/html/#the-a-element>a</a></code> element that has an <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/html/#attr-hyperlink-href>href</a></code>
- attribute and is an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of some <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> in <var title="">node list</var>,
- set that element's <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/html/#attr-hyperlink-href>href</a></code> attribute to <var title="">value</var>.
+ attribute and is an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of some <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <a href=#effectively-contained>effectively
+ contained</a> in the <a href=#active-range>active range</a>, set that <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/html/#the-a-element>a</a></code> element's
+ <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/html/#attr-hyperlink-href>href</a></code> attribute to <var title="">value</var>.
<!-- There are three approaches here. For instance, if you ask browsers to
create a link to "http://example.org" on the "b" here:
@@ -2208,8 +2172,7 @@
really intend to only change the link of part of it?
-->
- <li><a href=#set-the-value>Set the value</a> of each <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> in <var title="">node list</var> to
- <var title="">value</var>.
+ <li><a href="#set-the-selection's-value">Set the selection's value</a> to <var title="">value</var>.
</ol>
<!--
@@ -2223,10 +2186,10 @@
false. -->
-<h3 id=the-fontname-command><span class=secno>7.11 </span><dfn>The <code title="">fontName</code> command</dfn></h3>
-
-<p><a href=#action>Action</a>: <a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>,
-then <a href=#set-the-value>set the value</a> of each returned <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> to <var title="">value</var>.
+<h3 id=the-fontname-command><span class=secno>7.10 </span><dfn>The <code title="">fontName</code> command</dfn></h3>
+
+<p><a href=#action>Action</a>: <a href="#set-the-selection's-value">Set the selection's value</a> to
+<var title="">value</var>.
<!-- UAs differ a bit in the details here:
IE 9 RC: Empty string sets <font face="">
@@ -2279,7 +2242,7 @@
<p><a href=#relevant-css-property>Relevant CSS property</a>: "font-family"
-<h3 id=the-fontsize-command><span class=secno>7.12 </span><dfn>The <code title="">fontSize</code> command</dfn></h3>
+<h3 id=the-fontsize-command><span class=secno>7.11 </span><dfn>The <code title="">fontSize</code> command</dfn></h3>
<p><a href=#action>Action</a>:
@@ -2379,8 +2342,7 @@
allow numeric values. There's no harm in allowing "x-small" and absolute
sizes, I don't think.
- <li><a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>, then <a href=#set-the-value>set the
- value</a> of each returned <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> to <var title="">value</var>.
+ <li><a href="#set-the-selection's-value">Set the selection's value</a> to <var title="">value</var>.
</ol>
<p><a href=#indeterminate>Indeterminate</a>: True if among <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code>
@@ -2448,7 +2410,7 @@
<p><a href=#relevant-css-property>Relevant CSS property</a>: "font-size"
-<h3 id=the-forecolor-command><span class=secno>7.13 </span><dfn>The <code title="">foreColor</code> command</dfn></h3>
+<h3 id=the-forecolor-command><span class=secno>7.12 </span><dfn>The <code title="">foreColor</code> command</dfn></h3>
<p><a href=#action>Action</a>:
@@ -2516,8 +2478,7 @@
<!-- currentColor is bad for the same reason as relative font sizes. It will
confuse the algorithm, and doesn't seem very useful anyway. -->
- <li><a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>, then <a href=#set-the-value>set the
- value</a> of each returned <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> to <var title="">value</var>.
+ <li><a href="#set-the-selection's-value">Set the selection's value</a> to <var title="">value</var>.
</ol>
<!-- Opera 11 seems to return true for the state if there's some color style
@@ -2547,7 +2508,7 @@
<p><a href=#relevant-css-property>Relevant CSS property</a>: "color"
-<h3 id=the-hilitecolor-command><span class=secno>7.14 </span><dfn>The <code title="">hiliteColor</code> command</dfn></h3>
+<h3 id=the-hilitecolor-command><span class=secno>7.13 </span><dfn>The <code title="">hiliteColor</code> command</dfn></h3>
<!-- IE 9 RC doesn't support this. It uses backColor instead, but Gecko and
Opera treat that differently, while all non-IE browsers treat hiliteColor the
@@ -2578,8 +2539,7 @@
you could conceive of it being useful, but it will still confuse the
algorithm, so ban it for now anyway. -->
- <li><a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>, then <a href=#set-the-value>set the
- value</a> of each returned <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> to <var title="">value</var>.
+ <li><a href="#set-the-selection's-value">Set the selection's value</a> to <var title="">value</var>.
</ol>
<p><a href=#indeterminate>Indeterminate</a>: True if among <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code>
@@ -2607,12 +2567,11 @@
<p><a href=#relevant-css-property>Relevant CSS property</a>: "background-color"
-<h3 id=the-italic-command><span class=secno>7.15 </span><dfn>The <code title="">italic</code> command</dfn></h3>
-
-<p><a href=#action>Action</a>: <a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>.
-If the <a href=#state>state</a> is then false, <a href=#set-the-value>set the value</a> of each
-returned <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> to "italic", otherwise <a href=#set-the-value>set the value</a> to
-"normal".
+<h3 id=the-italic-command><span class=secno>7.14 </span><dfn>The <code title="">italic</code> command</dfn></h3>
+
+<p><a href=#action>Action</a>: If the <a href=#state>state</a> is false, <a href="#set-the-selection's-value">set the
+selection's value</a> to "italic", otherwise <a href="#set-the-selection's-value">set the selection's
+value</a> to "normal".
<p><a href=#indeterminate>Indeterminate</a>: True if among <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code>
nodes that are <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
@@ -2628,7 +2587,7 @@
<p><a href=#relevant-css-property>Relevant CSS property</a>: "font-style"
-<h3 id=the-removeformat-command><span class=secno>7.16 </span><dfn>The <code title="">removeFormat</code> command</dfn></h3>
+<h3 id=the-removeformat-command><span class=secno>7.15 </span><dfn>The <code title="">removeFormat</code> command</dfn></h3>
<!--
Tested in IE 9, Firefox 4.0, Chrome 12 dev, Opera 11.00.
@@ -2700,8 +2659,22 @@
<li>Remove <var title="">element</var> from its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
</ol>
- <li><a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>, and let <var title="">node
- list</var> be the result.
+ <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is an
+ <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node, and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is neither zero
+ nor its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>, call <code class=external data-anolis-spec=domcore title=dom-Text-splitText><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-text-splittext>splitText()</a></code> on the <a href=#active-range>active
+ range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, with argument equal to the <a href=#active-range>active
+ range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a>. Then set the <a href=#active-range>active range</a>'s
+ <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> to the result, and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> to zero.
+ <!-- This last sentence just prettifies the resulting range a bit. -->
+
+ <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is an
+ <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node, and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is neither zero
+ nor its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>, call <code class=external data-anolis-spec=domcore title=dom-Text-splitText><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-text-splittext>splitText()</a></code> on the <a href=#active-range>active
+ range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, with argument equal to the <a href=#active-range>active
+ range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a>.
+
+ <li>Let <var title="">node list</var> consist of all <a href=#editable>editable</a> <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>nodes</a>
+ <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a>.
<li>For each <var title="">node</var> in <var title="">node list</var>, while <var title="">node</var>'s
<a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is an <a href=#editable>editable</a> <a href=#html-element>HTML element</a> <a href=#in-the-same-editing-host>in the
@@ -2711,10 +2684,9 @@
<a href=#split-the-parent>split the parent</a> of the one-<a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> list consisting of
<var title="">node</var>.
- <li>For each of the entries in the following list, in the given order:
- <a href=#decompose>decompose</a> the <a href=#active-range>active range</a> again; then <a href=#set-the-value>set
- the value</a> of the resulting <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>nodes</a> to null, with <var title="">command</var>
- as given.
+ <li>For each of the entries in the following list, in the given order,
+ <a href="#set-the-selection's-value">set the selection's value</a> to null, with <var title="">command</var> as
+ given.
<!-- For cases like <p style=font-weight:bold>foo[bar]baz</p>. -->
<ol>
@@ -2733,12 +2705,11 @@
</ol>
-<h3 id=the-strikethrough-command><span class=secno>7.17 </span><dfn>The <code title="">strikethrough</code> command</dfn></h3>
-
-<p><a href=#action>Action</a>: <a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>.
-If the <a href=#state>state</a> is then false, <a href=#set-the-value>set the value</a> of each
-returned <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> to "line-through", otherwise <a href=#set-the-value>set the value</a> to
-null.
+<h3 id=the-strikethrough-command><span class=secno>7.16 </span><dfn>The <code title="">strikethrough</code> command</dfn></h3>
+
+<p><a href=#action>Action</a>: If the <a href=#state>state</a> is false, <a href="#set-the-selection's-value">set the
+selection's value</a> to "line-through", otherwise <a href="#set-the-selection's-value">set the selection's
+value</a> to null.
<p class=XXX>Has all the same problems as <a href=#the-underline-command>the <code title="">underline</code> command</a>.
@@ -2757,22 +2728,17 @@
<code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node. Otherwise false.
-<h3 id=the-subscript-command><span class=secno>7.18 </span><dfn>The <code title="">subscript</code> command</dfn></h3>
+<h3 id=the-subscript-command><span class=secno>7.17 </span><dfn>The <code title="">subscript</code> command</dfn></h3>
<p><a href=#action>Action</a>:
<ol>
- <li><a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>, and let <var title="">node
- list</var> be the result.
-
<li>Let <var title="">state</var> be the <a href=#state>state</a>.
- <li><a href=#set-the-value>Set the value</a> of each <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> in <var title="">node list</var> to
- "baseline".
-
- <li>If <var title="">state</var> is false, <a href=#decompose>decompose</a> the <a href=#active-range>active
- range</a> again and <a href=#set-the-value>set the value</a> of each returned <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a>
- to "sub".
+ <li><a href="#set-the-selection's-value">Set the selection's value</a> to "baseline".
+
+ <li>If <var title="">state</var> is false, <a href="#set-the-selection's-value">set the selection's value</a> to
+ "sub".
</ol>
<p><a href=#indeterminate>Indeterminate</a>: True if either among <a href=#editable>editable</a>
@@ -2802,22 +2768,17 @@
<p><a href=#relevant-css-property>Relevant CSS property</a>: "vertical-align"
-<h3 id=the-superscript-command><span class=secno>7.19 </span><dfn>The <code title="">superscript</code> command</dfn></h3>
+<h3 id=the-superscript-command><span class=secno>7.18 </span><dfn>The <code title="">superscript</code> command</dfn></h3>
<p><a href=#action>Action</a>:
<ol>
- <li><a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>, and let <var title="">node
- list</var> be the result.
-
<li>Let <var title="">state</var> be the <a href=#state>state</a>.
- <li><a href=#set-the-value>Set the value</a> of each <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> in <var title="">node list</var> to
- "baseline".
-
- <li>If <var title="">state</var> is false, <a href=#decompose>decompose</a> the <a href=#active-range>active
- range</a> again and <a href=#set-the-value>set the value</a> of each returned <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a>
- to "super".
+ <li><a href="#set-the-selection's-value">Set the selection's value</a> to "baseline".
+
+ <li>If <var title="">state</var> is false, <a href="#set-the-selection's-value">set the selection's value</a> to
+ "super".
</ol>
<p><a href=#indeterminate>Indeterminate</a>: True if either among <a href=#editable>editable</a>
@@ -2836,11 +2797,11 @@
<p><a href=#relevant-css-property>Relevant CSS property</a>: "vertical-align"
-<h3 id=the-underline-command><span class=secno>7.20 </span><dfn>The <code title="">underline</code> command</dfn></h3>
-
-<p><a href=#action>Action</a>: <a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>.
-If the <a href=#state>state</a> is then false, <a href=#set-the-value>set the value</a> of each
-returned <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> to "underline", otherwise <a href=#set-the-value>set the value</a> to null.
+<h3 id=the-underline-command><span class=secno>7.19 </span><dfn>The <code title="">underline</code> command</dfn></h3>
+
+<p><a href=#action>Action</a>: If the <a href=#state>state</a> is false, <a href="#set-the-selection's-value">set the
+selection's value</a> to "underline", otherwise <a href="#set-the-selection's-value">set the selection's
+value</a> to null.
<div class=XXX>
<p>There are a lot of problems with underline color and thickness, because
@@ -2906,7 +2867,7 @@
<code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node. Otherwise false.
-<h3 id=the-unlink-command><span class=secno>7.21 </span><dfn>The <code title="">unlink</code> command</dfn></h3>
+<h3 id=the-unlink-command><span class=secno>7.20 </span><dfn>The <code title="">unlink</code> command</dfn></h3>
<p><a href=#action>Action</a>:
--- a/implementation.js Fri Jul 08 12:51:44 2011 -0600
+++ b/implementation.js Fri Jul 08 14:15:56 2011 -0600
@@ -1289,35 +1289,40 @@
return true;
}
- // "node is range's start node, it is a Text node, and its length is
- // different from range's start offset."
+ // "node is range's start node, it is a Text node, its length is different
+ // from range's start offset, and range is not collapsed."
if (node == range.startContainer
&& node.nodeType == Node.TEXT_NODE
- && getNodeLength(node) != range.startOffset) {
+ && getNodeLength(node) != range.startOffset
+ && !range.collapsed) {
return true;
}
- // "node is range's end node, it is a Text node, and range's end offset is
- // not 0."
+ // "node is range's end node, it is a Text node, range's end offset is not
+ // 0, and range is not collapsed."
if (node == range.endContainer
&& node.nodeType == Node.TEXT_NODE
- && range.endOffset != 0) {
+ && range.endOffset != 0
+ && !range.collapsed) {
return true;
}
// "node has at least one child; and all its children are effectively
// contained in range; and either range's start node is not a descendant of
- // node or is not a Text node or range's start offset is zero; and either
- // range's end node is not a descendant of node or is not a Text node or
- // range's end offset is its end node's length."
+ // node or is not a Text node or range's start offset is zero or range is
+ // collapsed; and either range's end node is not a descendant of node or is
+ // not a Text node or range's end offset is its end node's length or range
+ // is collapsed."
if (node.hasChildNodes()
&& [].every.call(node.childNodes, function(child) { return isEffectivelyContained(child, range) })
&& (!isDescendant(range.startContainer, node)
|| range.startContainer.nodeType != Node.TEXT_NODE
- || range.startOffset == 0)
+ || range.startOffset == 0
+ || range.collapsed)
&& (!isDescendant(range.endContainer, node)
|| range.endContainer.nodeType != Node.TEXT_NODE
- || range.endOffset == getNodeLength(range.endContainer))) {
+ || range.endOffset == getNodeLength(range.endContainer
+ || range.collapsed))) {
return true;
}
@@ -1876,58 +1881,6 @@
//@}
-///// Decomposing a range into nodes /////
-//@{
-
-function decomposeRange(range) {
- // "If range's start and end are the same, return an empty list."
- if (range.startContainer == range.endContainer
- && range.startOffset == range.endOffset) {
- return [];
- }
-
- // "If range's start node is an editable Text node and its start offset is
- // neither 0 nor the length of its start node, run splitText() on its start
- // node with argument equal to its start offset."
- if (isEditable(range.startContainer)
- && range.startContainer.nodeType == Node.TEXT_NODE
- && range.startOffset != 0
- && range.startOffset != getNodeLength(range.startContainer)) {
- // Account for UAs not following range mutation rules
- if (range.startContainer == range.endContainer) {
- var newEndOffset = range.endOffset - range.startOffset;
- var newText = range.startContainer.splitText(range.startOffset);
- range.setStart(newText, 0);
- range.setEnd(newText, newEndOffset);
- } else {
- var newText = range.startContainer.splitText(range.startOffset);
- range.setStart(newText, 0);
- }
- }
-
- // "If range's end node is an editable Text node and its end offset is
- // neither 0 nor the length of its end node, run splitText() on its end
- // node with argument equal to its end offset."
- if (isEditable(range.endContainer)
- && range.endContainer.nodeType == Node.TEXT_NODE
- && range.endOffset != 0
- && range.endOffset != getNodeLength(range.endContainer)) {
- // IE seems to mutate the range incorrectly here, so we need correction
- // here as well.
- var newStart = [range.startContainer, range.startOffset];
- var newEnd = [range.endContainer, range.endOffset];
- range.endContainer.splitText(range.endOffset);
- range.setStart(newStart[0], newStart[1]);
- range.setEnd(newEnd[0], newEnd[1]);
- }
-
- // "Return a list consisting of every node effectively contained in range,
- // omitting any whose parent is also effectively contained in range."
- return getEffectivelyContainedNodes(range);
-}
-
-//@}
-
///// Clearing an element's value /////
//@{
@@ -2465,54 +2418,68 @@
//@}
-///// Setting the value of a node /////
+///// Setting the selection's value /////
//@{
-function setNodeValue(node, command, newValue) {
- // "If node is not editable:"
- if (!isEditable(node)) {
- // "Let children be the children of node."
- var children = Array.prototype.slice.call(node.childNodes);
-
- // "Set the value of each member of children."
- for (var i = 0; i < children.length; i++) {
- setNodeValue(children[i], command, newValue);
- }
-
- // "Abort this algorithm."
- return;
- }
-
- // "If node is an Element:"
- if (node.nodeType == Node.ELEMENT_NODE) {
- // "Clear the value of node, and let new nodes be the result."
- var newNodes = clearValue(node, command);
-
- // "For each new node in new nodes, set the value of new node, with the
- // same inputs as this invocation of the algorithm."
- for (var i = 0; i < newNodes.length; i++) {
- setNodeValue(newNodes[i], command, newValue);
- }
-
- // "If node's parent is null, abort this algorithm."
- if (!node.parentNode) {
- return;
- }
- }
-
- // "Push down values on node."
- pushDownValues(node, command, newValue);
-
- // "Force the value of node."
- forceValue(node, command, newValue);
-
- // "Let children be the children of node."
- var children = Array.prototype.slice.call(node.childNodes);
-
- // "Set the value of each member of children."
- for (var i = 0; i < children.length; i++) {
- setNodeValue(children[i], command, newValue);
- }
+function setSelectionValue(command, newValue) {
+ // "If the active range's start node is an editable Text node, and its
+ // start offset is neither zero nor its start node's length, call
+ // splitText() on the active range's start node, with argument equal to the
+ // active range's start offset. Then set the active range's start node to
+ // the result, and its start offset to zero."
+ if (isEditable(getActiveRange().startContainer)
+ && getActiveRange().startContainer.nodeType == Node.TEXT_NODE
+ && getActiveRange().startOffset != 0
+ && getActiveRange().startOffset != getNodeLength(getActiveRange().startContainer)) {
+ // Account for browsers not following range mutation rules
+ if (getActiveRange().startContainer == getActiveRange().endContainer) {
+ var newEnd = getActiveRange().endOffset - getActiveRange().startOffset;
+ var newNode = getActiveRange().startContainer.splitText(getActiveRange().startOffset);
+ getActiveRange().setStart(newNode, 0);
+ getActiveRange().setEnd(newNode, newEnd);
+ } else {
+ getActiveRange().setStart(getActiveRange().startContainer.splitText(getActiveRange().startOffset), 0);
+ }
+ }
+
+ // "If the active range's end node is an editable Text node, and its end
+ // offset is neither zero nor its end node's length, call splitText() on
+ // the active range's end node, with argument equal to the active range's
+ // end offset."
+ if (isEditable(getActiveRange().endContainer)
+ && getActiveRange().endContainer.nodeType == Node.TEXT_NODE
+ && getActiveRange().endOffset != 0
+ && getActiveRange().endOffset != getNodeLength(getActiveRange().endContainer)) {
+ // IE seems to mutate the range incorrectly here, so we need correction
+ // here as well.
+ var newStart = [getActiveRange().startContainer, getActiveRange().startOffset];
+ var newEnd = [getActiveRange().endContainer, getActiveRange().endOffset];
+ getActiveRange().endContainer.splitText(getActiveRange().endOffset);
+ getActiveRange().setStart(newStart[0], newStart[1]);
+ getActiveRange().setEnd(newEnd[0], newEnd[1]);
+ }
+
+ // "Let element list be all editable Elements effectively contained in the
+ // active range.
+ //
+ // "For each element in element list, clear the value of element."
+ getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
+ return isEditable(node) && node.nodeType == Node.ELEMENT_NODE;
+ }).forEach(function(element) {
+ clearValue(element, command);
+ });
+
+ // "Let node list be all editable nodes effectively contained in the active
+ // range.
+ //
+ // "For each node in node list:"
+ getAllEffectivelyContainedNodes(getActiveRange(), isEditable).forEach(function(node) {
+ // "Push down values on node."
+ pushDownValues(node, command, newValue);
+
+ // "Force the value of node."
+ forceValue(node, command, newValue);
+ });
}
//@}
@@ -2540,12 +2507,8 @@
throw "SYNTAX_ERR";
}
- // "Decompose the active range, then set the value of each returned
- // node to value."
- var nodeList = decomposeRange(getActiveRange());
- for (var i = 0; i < nodeList.length; i++) {
- setNodeValue(nodeList[i], "backcolor", value);
- }
+ // "Set the selection's value to value."
+ setSelectionValue("backcolor", value);
}, indeterm: function() {
// "True if among editable Text nodes that are effectively contained in
// the active range, there are two that have distinct effective values.
@@ -2578,13 +2541,12 @@
//@{
commands.bold = {
action: function() {
- // "Decompose the active range. If the state is then false, set the
- // value of each returned node to "bold", otherwise set the value to
- // "normal"."
- var nodeList = decomposeRange(getActiveRange());
- var newValue = commands.bold.state() ? "normal" : "bold";
- for (var i = 0; i < nodeList.length; i++) {
- setNodeValue(nodeList[i], "bold", newValue);
+ // "If the state is false, set the selection's value to "bold",
+ // otherwise set the selection's value to "normal"."
+ if (!commands.bold.state()) {
+ setSelectionValue("bold", "bold");
+ } else {
+ setSelectionValue("bold", "normal");
}
}, indeterm: function() { return indetermHelper(function(node) {
// "True if among editable Text nodes that are effectively contained in
@@ -2620,16 +2582,13 @@
throw "SYNTAX_ERR";
}
- // "Decompose the active range, and let node list be the result."
- var nodeList = decomposeRange(getActiveRange());
-
// "For each editable a element that has an href attribute and is an
- // ancestor of some node in node list, set that element's href
- // attribute to value."
+ // ancestor of some node effectively contained in the active range, set
+ // that a element's href attribute to value."
//
// TODO: We don't actually do this in tree order, not that it matters
// unless you're spying with mutation events.
- nodeList.forEach(function(node) {
+ getAllEffectivelyContainedNodes(getActiveRange()).forEach(function(node) {
getAncestors(node).forEach(function(ancestor) {
if (isEditable(ancestor)
&& isHtmlElement(ancestor, "a")
@@ -2639,10 +2598,8 @@
});
});
- // "Set the value of each node in node list to value."
- for (var i = 0; i < nodeList.length; i++) {
- setNodeValue(nodeList[i], "createlink", value);
- }
+ // "Set the selection's value to value."
+ setSelectionValue("createlink", value);
}
};
//@}
@@ -2651,12 +2608,8 @@
//@{
commands.fontname = {
action: function(value) {
- // "Decompose the active range, then set the value of each returned
- // node to value."
- var nodeList = decomposeRange(getActiveRange());
- for (var i = 0; i < nodeList.length; i++) {
- setNodeValue(nodeList[i], "fontname", value);
- }
+ // "Set the selection's value to value."
+ setSelectionValue("fontname", value);
}, indeterm: function() {
// "True if among editable Text nodes that are effectively contained in
// the active range, there are two that have distinct effective values.
@@ -2760,12 +2713,8 @@
throw "SYNTAX_ERR";
}
- // "Decompose the active range, then set the value of each returned
- // node to value."
- var nodeList = decomposeRange(getActiveRange());
- for (var i = 0; i < nodeList.length; i++) {
- setNodeValue(nodeList[i], "fontsize", value);
- }
+ // "Set the selection's value to value."
+ setSelectionValue("fontsize", value);
}, indeterm: function() {
// "True if among editable Text nodes that are effectively contained in
// the active range, there are two that have distinct effective values.
@@ -2844,12 +2793,8 @@
throw "SYNTAX_ERR";
}
- // "Decompose the active range, then set the value of each returned
- // node to value."
- var nodeList = decomposeRange(getActiveRange());
- for (var i = 0; i < nodeList.length; i++) {
- setNodeValue(nodeList[i], "forecolor", value);
- }
+ // "Set the selection's value to value."
+ setSelectionValue("forecolor", value);
}, indeterm: function() {
// "True if among editable Text nodes that are effectively contained in
// the active range, there are two that have distinct effective values.
@@ -2902,12 +2847,8 @@
throw "SYNTAX_ERR";
}
- // "Decompose the active range, then set the value of each returned
- // node to value."
- var nodeList = decomposeRange(getActiveRange());
- for (var i = 0; i < nodeList.length; i++) {
- setNodeValue(nodeList[i], "hilitecolor", value);
- }
+ // "Set the selection's value to value."
+ setSelectionValue("hilitecolor", value);
}, indeterm: function() {
// "True if among editable Text nodes that are effectively contained in
// the active range, there are two that have distinct effective values.
@@ -2940,13 +2881,12 @@
//@{
commands.italic = {
action: function() {
- // "Decompose the active range. If the state is then false, set the
- // value of each returned node to "italic", otherwise set the value to
- // "normal"."
- var nodeList = decomposeRange(getActiveRange());
- var newValue = commands.italic.state() ? "normal" : "italic";
- for (var i = 0; i < nodeList.length; i++) {
- setNodeValue(nodeList[i], "italic", newValue);
+ // "If the state is false, set the selection's value to "italic",
+ // otherwise set the selection's value to "normal"."
+ if (!commands.italic.state()) {
+ setSelectionValue("italic", "italic");
+ } else {
+ setSelectionValue("italic", "normal");
}
}, indeterm: function() { return indetermHelper(function(node) {
// "True if among editable Text nodes that are effectively contained in
@@ -2993,15 +2933,52 @@
element.parentNode.removeChild(element);
});
- // "Decompose the active range, and let node list be the result."
- var nodeList = decomposeRange(getActiveRange());
-
+ // "If the active range's start node is an editable Text node, and its
+ // start offset is neither zero nor its start node's length, call
+ // splitText() on the active range's start node, with argument equal to
+ // the active range's start offset. Then set the active range's start
+ // node to the result, and its start offset to zero."
+ if (isEditable(getActiveRange().startContainer)
+ && getActiveRange().startContainer.nodeType == Node.TEXT_NODE
+ && getActiveRange().startOffset != 0
+ && getActiveRange().startOffset != getNodeLength(getActiveRange().startContainer)) {
+ // Account for browsers not following range mutation rules
+ if (getActiveRange().startContainer == getActiveRange().endContainer) {
+ var newEnd = getActiveRange().endOffset - getActiveRange().startOffset;
+ var newNode = getActiveRange().startContainer.splitText(getActiveRange().startOffset);
+ getActiveRange().setStart(newNode, 0);
+ getActiveRange().setEnd(newNode, newEnd);
+ } else {
+ getActiveRange().setStart(getActiveRange().startContainer.splitText(getActiveRange().startOffset), 0);
+ }
+ }
+
+ // "If the active range's end node is an editable Text node, and its
+ // end offset is neither zero nor its end node's length, call
+ // splitText() on the active range's end node, with argument equal to
+ // the active range's end offset."
+ if (isEditable(getActiveRange().endContainer)
+ && getActiveRange().endContainer.nodeType == Node.TEXT_NODE
+ && getActiveRange().endOffset != 0
+ && getActiveRange().endOffset != getNodeLength(getActiveRange().endContainer)) {
+ // IE seems to mutate the range incorrectly here, so we need
+ // correction here as well.
+ var newStart = [getActiveRange().startContainer, getActiveRange().startOffset];
+ var newEnd = [getActiveRange().endContainer, getActiveRange().endOffset];
+ getActiveRange().endContainer.splitText(getActiveRange().endOffset);
+ getActiveRange().setStart(newStart[0], newStart[1]);
+ getActiveRange().setEnd(newEnd[0], newEnd[1]);
+ }
+
+ // "Let node list consist of all editable nodes effectively contained
+ // in the active range."
+ //
// "For each node in node list, while node's parent is an editable HTML
// element in the same editing host as node, and node's parent is not a
// prohibited paragraph child and does not have local name "a" or
// "audio" or "br" or "img" or "video" or "wbr", split the parent of
// the one-node list consisting of node."
- nodeList.forEach(function(node) {
+ getAllEffectivelyContainedNodes(getActiveRange(), isEditable).forEach(function(node) {
while (isEditable(node.parentNode)
&& isHtmlElement(node.parentNode)
&& !isProhibitedParagraphChild(node.parentNode)
@@ -3010,9 +2987,8 @@
}
});
- // "For each of the entries in the following list, in the given order:
- // decompose the active range again; then set the value of the
- // resulting nodes to null, with command as given."
+ // "For each of the entries in the following list, in the given order,
+ // set the selection's value to null, with command as given."
[
"subscript",
"bold",
@@ -3024,9 +3000,7 @@
"strikethrough",
"underline",
].forEach(function(command) {
- decomposeRange(getActiveRange()).forEach(function(node) {
- setNodeValue(node, command, null);
- });
+ setSelectionValue(command, null);
});
}
};
@@ -3036,13 +3010,12 @@
//@{
commands.strikethrough = {
action: function() {
- // "Decompose the active range. If the state is then false, set the
- // value of each returned node to "line-through", otherwise set the
- // value to null."
- var nodeList = decomposeRange(getActiveRange());
- var newValue = commands.strikethrough.state() ? null : "line-through";
- for (var i = 0; i < nodeList.length; i++) {
- setNodeValue(nodeList[i], "strikethrough", newValue);
+ // "If the state is false, set the selection's value to "line-through",
+ // otherwise set the selection's value to null."
+ if (!commands.strikethrough.state()) {
+ setSelectionValue("strikethrough", "line-through");
+ } else {
+ setSelectionValue("strikethrough", null);
}
}, indeterm: function() { return indetermHelper(function(node) {
// "True if among editable Text nodes that are effectively contained in
@@ -3063,24 +3036,15 @@
//@{
commands.subscript = {
action: function() {
- // "Decompose the active range, and let node list be the result."
- var nodeList = decomposeRange(getActiveRange());
-
// "Let state be the state."
var state = commands.subscript.state();
- // "Set the value of each node in node list to "baseline"."
- for (var i = 0; i < nodeList.length; i++) {
- setNodeValue(nodeList[i], "subscript", "baseline");
- }
-
- // "If state is false, decompose the active range again and set the
- // value of each returned node to "sub"."
+ // "Set the selection's value to "baseline"."
+ setSelectionValue("subscript", "baseline");
+
+ // "If state is false, set the selection's value to "sub"."
if (!state) {
- nodeList = decomposeRange(getActiveRange());
- for (var i = 0; i < nodeList.length; i++) {
- setNodeValue(nodeList[i], "subscript", "sub");
- }
+ setSelectionValue("subscript", "sub");
}
}, indeterm: function() {
// "True if either among editable Text nodes that are effectively
@@ -3107,24 +3071,15 @@
//@{
commands.superscript = {
action: function() {
- // "Decompose the active range, and let node list be the result."
- var nodeList = decomposeRange(getActiveRange());
-
// "Let state be the state."
var state = commands.superscript.state();
- // "Set the value of each node in node list to "baseline"."
- for (var i = 0; i < nodeList.length; i++) {
- setNodeValue(nodeList[i], "superscript", "baseline");
- }
-
- // "If state is false, decompose the active range again and set the
- // value of each returned node to "super"."
+ // "Set the selection's value to "baseline"."
+ setSelectionValue("superscript", "baseline");
+
+ // "If state is false, set the selection's value to "super"."
if (!state) {
- nodeList = decomposeRange(getActiveRange());
- for (var i = 0; i < nodeList.length; i++) {
- setNodeValue(nodeList[i], "superscript", "super");
- }
+ setSelectionValue("superscript", "super");
}
}, indeterm: function() {
// "True if either among editable Text nodes that are effectively
@@ -3151,13 +3106,12 @@
//@{
commands.underline = {
action: function() {
- // "Decompose the active range. If the state is then false, set the
- // value of each returned node to "underline", otherwise set the value
- // to null."
- var nodeList = decomposeRange(getActiveRange());
- var newValue = commands.underline.state() ? null : "underline";
- for (var i = 0; i < nodeList.length; i++) {
- setNodeValue(nodeList[i], "underline", newValue);
+ // "If the state is false, set the selection's value to "underline",
+ // otherwise set the selection's value to null."
+ if (!commands.underline.state()) {
+ setSelectionValue("underline", "underline");
+ } else {
+ setSelectionValue("underline", null);
}
}, indeterm: function() { return indetermHelper(function(node) {
// "True if among editable Text nodes that are effectively contained in
--- a/preprocess Fri Jul 08 12:51:44 2011 -0600
+++ b/preprocess Fri Jul 08 14:15:56 2011 -0600
@@ -25,6 +25,7 @@
'cdlength': '<code data-anolis-spec=domcore title=dom-CharacterData-length>length</code>',
'child': '<span data-anolis-spec=domcore title=concept-tree-child>child</span>',
'children': '<span data-anolis-spec=domcore title=concept-tree-child>children</span>',
+ 'collapsed': '<code data-anolis-spec=domrange title=dom-Range-collapsed>collapsed</code>',
'collection': '<span data-anolis-spec=domcore title=concept-collection>collection</span>',
'contained': '<span data-anolis-spec=domrange>contained</span>',
'comment': '<code data-anolis-spec=domcore>Comment</code>',
@@ -136,6 +137,7 @@
'selcollapse': '<code data-anolis-spec=domrange title=dom-Selection-collapse>collapse(\\1)</code>',
'selectallchildren': '<code data-anolis-spec=domrange title=dom-Selection-selectAllChildren>selectAllChildren(\\1)</code>',
'setattribute': '<code data-anolis-spec=domcore title=dom-Element-setAttribute>setAttribute(\\1)</code>',
+ 'splittext': '<code data-anolis-spec=domcore title=dom-Text-splitText>splitText(\\1)</code>',
}
for key in fnreplace:
--- a/source.html Fri Jul 08 12:51:44 2011 -0600
+++ b/source.html Fri Jul 08 14:15:56 2011 -0600
@@ -1024,32 +1024,35 @@
that 1) in <b>[foo]</b>, the text node and the <b> are effectively contained
but not contained; and 2) in <b>f[o]o</b>, the text node is effectively
contained but not contained, and the <b> is neither effectively contained nor
-contained. This is used mostly for the "decompose" algorithm, and also for
-most inline commands' states.
+contained.
-->
<ul>
<li><var>node</var> is [[contained]] in <var>range</var>.
<li><var>node</var> is <var>range</var>'s [[startnode]], it is a [[text]]
- node, and its [[nodelength]] is different from <var>range</var>'s
- [[startoffset]].
+ node, its [[nodelength]] is different from <var>range</var>'s
+ [[startoffset]], and <var>range</var> is not [[collapsed]].
+ <!-- So like <b>f[oo]</b> or <b>f[o]o</b> or <b>f[oo</b>}, but not
+ <b>foo[</b>} or <b>f[]oo</b>. -->
<li><var>node</var> is <var>range</var>'s [[endnode]], it is a [[text]] node,
- and <var>range</var>'s [[endoffset]] is not 0.
+ <var>range</var>'s [[endoffset]] is not 0, and <var>range</var> is not
+ [[collapsed]].
<li><var>node</var> has at least one [[child]]; and all its [[children]] are
<span>effectively contained</span> in <var>range</var>; and either
<var>range</var>'s [[startnode]] is not a [[descendant]] of <var>node</var>
- or is not a [[text]] node or <var>range</var>'s [[startoffset]] is zero; and
- either <var>range</var>'s [[endnode]] is not a [[descendant]] of
- <var>node</var> or is not a [[text]] node or <var>range</var>'s [[endoffset]]
- is its [[endnode]]'s [[length]].
+ or is not a [[text]] node or <var>range</var>'s [[startoffset]] is zero or
+ <var>range</var> is [[collapsed]]; and either <var>range</var>'s [[endnode]]
+ is not a [[descendant]] of <var>node</var> or is not a [[text]] node or
+ <var>range</var>'s [[endoffset]] is its [[endnode]]'s [[length]] or
+ <var>range</var> is [[collapsed]].
<!--
Basically, anything whose children are all effectively contained should be
effectively contained itself, except that in a case like <b>f[o]o</b> we
don't want <b> to be effectively contained even though the text node is.
- That's because as soon as we decompose the range, the text node is split and
- the <b> will no longer be effectively contained.
+ That's because we split the text node before we actually do anything, and the
+ <b> will no longer be effectively contained.
-->
</ul>
@@ -1340,39 +1343,6 @@
</ol>
<!-- @} -->
-<h3>Decomposing a range into nodes</h3>
-<!-- @{ -->
-<p>To <dfn>decompose</dfn> a [[range]] <var>range</var>:
-
-<p class=note>For this algorithm to be correct, it is essential that user
-agents follow the [[rangemutationrules]], particularly those for <code
-title>splitText()</code>.
-
-<ol>
- <li>If <var>range</var>'s [[rangestart]] and [[rangeend]] are the same,
- return an empty list.
-
- <li>If <var>range</var>'s [[rangestart]] [[bpnode]] is an
- <span>editable</span> [[text]] node and its [[rangestart]] [[bpoffset]] is
- neither 0 nor the [[nodelength]] of its [[rangestart]] [[bpnode]], run <code
- data-anolis-spec=domcore title=dom-Text-splitText>splitText()</code> on its
- [[rangestart]] [[bpnode]] with argument equal to its [[rangestart]]
- [[bpoffset]].
-
- <li>If <var>range</var>'s [[rangeend]] [[bpnode]] is an <span>editable</span>
- [[text]] node and its [[rangeend]] [[bpoffset]] is neither 0 nor the
- [[nodelength]] of its [[rangeend]] [[bpnode]], run <code
- data-anolis-spec=domcore title=dom-Text-splitText>splitText()</code> on its
- [[rangeend]] [[bpnode]] with argument equal to its [[rangeend]] [[bpoffset]].
-
- <!-- We want to make sure the returned list contains as many nodes as
- possible, such as by treating <tag>[foo]</tag> as {<tag>foo</tag>}. -->
- <li>Return a list consisting of every [[node]] <span>effectively
- contained</span> in <var>range</var>, omitting any whose [[parent]] is also
- <span>effectively contained</span> in <var>range</var>.
-</ol>
-<!-- @} -->
-
<h3>Clearing an element's value</h3>
<!-- @{ -->
<p>To <dfn>clear the value</dfn> of an [[element]] <var>element</var>:
@@ -1869,22 +1839,22 @@
</ol>
<!-- @} -->
-<h3>Setting the value of a node</h3>
+<h3>Setting the selection's value</h3>
<!-- @{ -->
-<p>To <dfn>set the value</dfn> of a [[node]] <var>node</var> to <var>new
-value</var>:
+<p>To <dfn>set the selection's value</dfn> to <var>new value</var>:
<div class=note>
-<p>The effect of this algorithm is to ensure that the node and all its
-descendants have the style requested, no matter what, producing the simplest
-markup possible to achieve that effect. It's inspired by the approach WebKit
-takes. The only places where the algorithm should fail are when there's an
-!important CSS rule that conflicts with the requested style (which we don't try
-to override because we assume it's !important for a reason), or when it's
-literally impossible to succeed (such as when a text-decoration is propagated
-from an ancestor we can't reach). Any other failures are bugs.
-
-<p>First, if the node is an element with an inline style rule for this
+<p>The effect of this algorithm is to ensure that all nodes effectively
+contained in the selection have the style requested, no matter what, producing
+the simplest markup possible to achieve that effect. It's inspired by the
+approach WebKit takes. The only places where the algorithm should fail are
+when there's an !important CSS rule that conflicts with the requested style
+(which we don't try to override because we assume it's !important for a
+reason), or when it's literally impossible to succeed (such as when a
+text-decoration is propagated from an ancestor we can't reach). Any other
+failures are bugs.
+
+<p>First, if a node is an element with an inline style rule for this
property, we unset it ("clearing styles"). This step also removes <span
title="simple modifiable element">simple modifiable elements</span> entirely, and
replaces elements like [[b]] or [[font]] with [[span]]s if they aren't simple
@@ -1941,15 +1911,34 @@
as desired.
</div>
-<p class=XXX>Consider porting this algorithm to operate on runs of consecutive
-siblings instead of individual nodes. We might be able to make some parts
-smarter, and also might be able to make it more efficient.
-
<ol>
<li>Let <var>command</var> be the current <span>command</span>.
- <li>If <var>node</var> is not <span>editable</span>:
+ <li>If the <span>active range</span>'s [[startnode]] is an
+ <span>editable</span> [[text]] node, and its [[startoffset]] is neither zero
+ nor its [[startnode]]'s [[length]], call [[splittext|]] on the <span>active
+ range</span>'s [[startnode]], with argument equal to the <span>active
+ range</span>'s [[startoffset]]. Then set the <span>active range</span>'s
+ [[startnode]] to the result, and its [[startoffset]] to zero.
+ <!-- This last sentence just prettifies the resulting range a bit. -->
+
+ <li>If the <span>active range</span>'s [[endnode]] is an
+ <span>editable</span> [[text]] node, and its [[endoffset]] is neither zero
+ nor its [[endnode]]'s [[length]], call [[splittext|]] on the <span>active
+ range</span>'s [[endnode]], with argument equal to the <span>active
+ range</span>'s [[endoffset]].
+
+ <li>Let <var>element list</var> be all <span>editable</span> [[element]]s
+ <span>effectively contained</span> in the <span>active range</span>.
+
+ <li>For each <var>element</var> in <var>element list</var>, <span>clear the
+ value</span> of <var>element</var>.
+
+ <li>Let <var>node list</var> be all <span>editable</span> [[nodes]]
+ <span>effectively contained</span> in the <span>active range</span>.
<!--
+ We skip non-editable nodes.
+
IE9: Allows everything to be modified by execCommand(), regardless of whether
it's editable.
Firefox 4.0: Ignores execCommand() if the start and end of the selection are
@@ -1983,37 +1972,13 @@
are bolded, it will unbold instead of bolding.
-->
- <ol>
- <li>Let <var>children</var> be the [[children]] of <var>node</var>.
-
- <li><span>Set the value</span> of each member of <var>children</var>.
-
- <li>Abort this algorithm.
- </ol>
-
- <li>If <var>node</var> is an [[element]]:
+ <li>For each <var>node</var> in <var>node list</var>:
<ol>
- <li><span>Clear the value</span> of <var>node</var>, and let <var>new
- nodes</var> be the result.
-
- <li>For each <var>new node</var> in <var>new nodes</var>,
- <span>set the value</span> of <var>new node</var>.
-
- <li>If <var>node</var>'s [[parent]] is null, abort this algorithm.
+ <li><span>Push down values</span> on <var>node</var>.
+
+ <li><span>Force the value</span> of <var>node</var>.
</ol>
-
- <li><span>Push down values</span> on <var>node</var>.
-
- <li><span>Force the value</span> of <var>node</var>.
-
- <li>Let <var>children</var> be the [[children]] of <var>node</var>.
-
- <li><span>Set the value</span> of each member of <var>children</var>.
-
- <p class=note>Styling a node involves clearing its styles, which can remove
- it from the tree. Implementers should be careful to compute the list of
- children in full before they begin styling.
</ol>
<!-- @} -->
@@ -2061,8 +2026,7 @@
<li>If <var>value</var> is still not a valid CSS color, or if it is
currentColor, raise a [[SYNTAX_ERR]] exception.
- <li><span>Decompose</span> the <span>active range</span>, then <span>set the
- value</span> of each returned [[node]] to <var>value</var>.
+ <li><span>Set the selection's value</span> to <var>value</var>.
</ol>
<p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
@@ -2087,9 +2051,9 @@
(fontName, italic, etc.). Except not for strikethrough, where it just does
nothing if the selection is empty. Why strikethrough? I don't know. -->
-<p><span>Action</span>: <span>Decompose</span> the <span>active range</span>.
-If the <span>state</span> is then false, <span>set the value</span> of each
-returned [[node]] to "bold", otherwise <span>set the value</span> to "normal".
+<p><span>Action</span>: If the <span>state</span> is false, <span>set the
+selection's value</span> to "bold", otherwise <span>set the selection's
+value</span> to "normal".
<p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
nodes that are <span>effectively contained</span> in the <span>active
@@ -2155,12 +2119,10 @@
I think that's more useful. See issues.
-->
- <li><span>Decompose</span> the <span>active range</span>, and let <var>node
- list</var> be the result.
-
<li>For each <span>editable</span> [[a]] element that has an [[href]]
- attribute and is an [[ancestor]] of some [[node]] in <var>node list</var>,
- set that element's [[href]] attribute to <var>value</var>.
+ attribute and is an [[ancestor]] of some [[node]] <span>effectively
+ contained</span> in the <span>active range</span>, set that [[a]] element's
+ [[href]] attribute to <var>value</var>.
<!-- There are three approaches here. For instance, if you ask browsers to
create a link to "http://example.org" on the "b" here:
@@ -2185,8 +2147,7 @@
really intend to only change the link of part of it?
-->
- <li><span>Set the value</span> of each [[node]] in <var>node list</var> to
- <var>value</var>.
+ <li><span>Set the selection's value</span> to <var>value</var>.
</ol>
<!--
@@ -2202,8 +2163,8 @@
<h3><dfn>The <code title>fontName</code> command</dfn></h3>
<!-- @{ -->
-<p><span>Action</span>: <span>Decompose</span> the <span>active range</span>,
-then <span>set the value</span> of each returned [[node]] to <var>value</var>.
+<p><span>Action</span>: <span>Set the selection's value</span> to
+<var>value</var>.
<!-- UAs differ a bit in the details here:
IE 9 RC: Empty string sets <font face="">
@@ -2356,8 +2317,7 @@
allow numeric values. There's no harm in allowing "x-small" and absolute
sizes, I don't think.
- <li><span>Decompose</span> the <span>active range</span>, then <span>set the
- value</span> of each returned [[node]] to <var>value</var>.
+ <li><span>Set the selection's value</span> to <var>value</var>.
</ol>
<p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
@@ -2493,8 +2453,7 @@
<!-- currentColor is bad for the same reason as relative font sizes. It will
confuse the algorithm, and doesn't seem very useful anyway. -->
- <li><span>Decompose</span> the <span>active range</span>, then <span>set the
- value</span> of each returned [[node]] to <var>value</var>.
+ <li><span>Set the selection's value</span> to <var>value</var>.
</ol>
<!-- Opera 11 seems to return true for the state if there's some color style
@@ -2555,8 +2514,7 @@
you could conceive of it being useful, but it will still confuse the
algorithm, so ban it for now anyway. -->
- <li><span>Decompose</span> the <span>active range</span>, then <span>set the
- value</span> of each returned [[node]] to <var>value</var>.
+ <li><span>Set the selection's value</span> to <var>value</var>.
</ol>
<p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
@@ -2586,10 +2544,9 @@
<h3><dfn>The <code title>italic</code> command</dfn></h3>
<!-- @{ -->
-<p><span>Action</span>: <span>Decompose</span> the <span>active range</span>.
-If the <span>state</span> is then false, <span>set the value</span> of each
-returned [[node]] to "italic", otherwise <span>set the value</span> to
-"normal".
+<p><span>Action</span>: If the <span>state</span> is false, <span>set the
+selection's value</span> to "italic", otherwise <span>set the selection's
+value</span> to "normal".
<p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
nodes that are <span>effectively contained</span> in the <span>active
@@ -2677,8 +2634,22 @@
<li>Remove <var>element</var> from its [[parent]].
</ol>
- <li><span>Decompose</span> the <span>active range</span>, and let <var>node
- list</var> be the result.
+ <li>If the <span>active range</span>'s [[startnode]] is an
+ <span>editable</span> [[text]] node, and its [[startoffset]] is neither zero
+ nor its [[startnode]]'s [[length]], call [[splittext|]] on the <span>active
+ range</span>'s [[startnode]], with argument equal to the <span>active
+ range</span>'s [[startoffset]]. Then set the <span>active range</span>'s
+ [[startnode]] to the result, and its [[startoffset]] to zero.
+ <!-- This last sentence just prettifies the resulting range a bit. -->
+
+ <li>If the <span>active range</span>'s [[endnode]] is an
+ <span>editable</span> [[text]] node, and its [[endoffset]] is neither zero
+ nor its [[endnode]]'s [[length]], call [[splittext|]] on the <span>active
+ range</span>'s [[endnode]], with argument equal to the <span>active
+ range</span>'s [[endoffset]].
+
+ <li>Let <var>node list</var> consist of all <span>editable</span> [[nodes]]
+ <span>effectively contained</span> in the <span>active range</span>.
<li>For each <var>node</var> in <var>node list</var>, while <var>node</var>'s
[[parent]] is an <span>editable</span> <span>HTML element</span> <span>in the
@@ -2688,10 +2659,9 @@
<span>split the parent</span> of the one-[[node]] list consisting of
<var>node</var>.
- <li>For each of the entries in the following list, in the given order:
- <span>decompose</span> the <span>active range</span> again; then <span>set
- the value</span> of the resulting [[nodes]] to null, with <var>command</var>
- as given.
+ <li>For each of the entries in the following list, in the given order,
+ <span>set the selection's value</span> to null, with <var>command</var> as
+ given.
<!-- For cases like <p style=font-weight:bold>foo[bar]baz</p>. -->
<ol>
@@ -2712,10 +2682,9 @@
<h3><dfn>The <code title>strikethrough</code> command</dfn></h3>
<!-- @{ -->
-<p><span>Action</span>: <span>Decompose</span> the <span>active range</span>.
-If the <span>state</span> is then false, <span>set the value</span> of each
-returned [[node]] to "line-through", otherwise <span>set the value</span> to
-null.
+<p><span>Action</span>: If the <span>state</span> is false, <span>set the
+selection's value</span> to "line-through", otherwise <span>set the selection's
+value</span> to null.
<p class=XXX>Has all the same problems as <span>the <code
title>underline</code> command</span>.
@@ -2740,17 +2709,12 @@
<p><span>Action</span>:
<ol>
- <li><span>Decompose</span> the <span>active range</span>, and let <var>node
- list</var> be the result.
-
<li>Let <var>state</var> be the <span>state</span>.
- <li><span>Set the value</span> of each [[node]] in <var>node list</var> to
- "baseline".
-
- <li>If <var>state</var> is false, <span>decompose</span> the <span>active
- range</span> again and <span>set the value</span> of each returned [[node]]
- to "sub".
+ <li><span>Set the selection's value</span> to "baseline".
+
+ <li>If <var>state</var> is false, <span>set the selection's value</span> to
+ "sub".
</ol>
<p><span>Indeterminate</span>: True if either among <span>editable</span>
@@ -2785,17 +2749,12 @@
<p><span>Action</span>:
<ol>
- <li><span>Decompose</span> the <span>active range</span>, and let <var>node
- list</var> be the result.
-
<li>Let <var>state</var> be the <span>state</span>.
- <li><span>Set the value</span> of each [[node]] in <var>node list</var> to
- "baseline".
-
- <li>If <var>state</var> is false, <span>decompose</span> the <span>active
- range</span> again and <span>set the value</span> of each returned [[node]]
- to "super".
+ <li><span>Set the selection's value</span> to "baseline".
+
+ <li>If <var>state</var> is false, <span>set the selection's value</span> to
+ "super".
</ol>
<p><span>Indeterminate</span>: True if either among <span>editable</span>
@@ -2816,9 +2775,9 @@
<h3><dfn>The <code title>underline</code> command</dfn></h3>
<!-- @{ -->
-<p><span>Action</span>: <span>Decompose</span> the <span>active range</span>.
-If the <span>state</span> is then false, <span>set the value</span> of each
-returned [[node]] to "underline", otherwise <span>set the value</span> to null.
+<p><span>Action</span>: If the <span>state</span> is false, <span>set the
+selection's value</span> to "underline", otherwise <span>set the selection's
+value</span> to null.
<div class=XXX>
<p>There are a lot of problems with underline color and thickness, because