Improve state for bold etc.
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Mon, 18 Jul 2011 15:26:31 -0600
changeset 432 bf4a52cafc8b
parent 431 d1545a64f831
child 433 eccd28918621
Improve state for bold etc.

Now depends on the active range's start node if there are no effectively
contained nodes, so for example, "<b>foo[]bar</b>" has true state for
bold instead of false. This better matches browsers.

While I was at it, massively refactored all the copy-paste here, cutting
out a few hundred lines.
editcommands.html
implementation.js
source.html
tests.js
--- a/editcommands.html	Mon Jul 18 13:39:40 2011 -0600
+++ b/editcommands.html	Mon Jul 18 15:26:31 2011 -0600
@@ -1375,6 +1375,63 @@
 <p class=note>Conceptually, a simple modifiable element is a modifiable element
 which specifies a value for at most one command.
 
+<p>If a <a href=#command>command</a> has <dfn id=inline-command-activated-values>inline command activated values</dfn>
+defined but nothing else defines when it is <a href=#indeterminate>indeterminate</a>, it is
+<a href=#indeterminate>indeterminate</a> 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
+<a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a>, there is
+at least one whose <a href=#effective-command-value>effective command value</a> is one of the given
+values and at least one whose <a href=#effective-command-value>effective command value</a> is not one
+of the given values.
+
+<p>If a <a href=#command>command</a> has <a href=#inline-command-activated-values>inline command activated values</a>
+defined, its <a href=#state>state</a> is true if either no <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 is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
+range</a>, and 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>'s
+<a href=#effective-command-value>effective command value</a> is one of the given values; or if there is
+at least one <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 <a href=#effectively-contained>effectively
+contained</a> in the <a href=#active-range>active range</a>, and all of them have an
+<a href=#effective-command-value>effective command value</a> equal to one of the given values.
+<!--
+For bold and similar commands, IE 9 RC seems to consider the state true or
+false depending on the first element.  All other browsers follow the same
+general idea as the spec, considering a range bold only if all text in it is
+bold, and this seems to match at least OpenOffice.org's bold feature.  Opera
+11.11 seemingly doesn't take CSS into account, and only looks at whether
+something descends from a <b>.  I couldn't properly test IE9 because it threw
+exceptions (Error: Unspecified error.) on most of the tests I ran.  But what I
+have here seems to match Firefox 6.0a2 in every case, and Chrome 14 dev in all
+cases with a few exceptions.
+-->
+
+<p>If a command is a <dfn id=standard-inline-value-command>standard inline value command</dfn>, it is
+<a href=#indeterminate>indeterminate</a> 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 range</a>, there
+are two that have distinct <a href=#effective-command-value title="effective command value">effective
+command values</a>.  Its <a href=#value>value</a> is the <a href=#effective-command-value>effective command
+value</a> of the first <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 that is
+<a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a>, or if
+there is no such node, the <a href=#effective-command-value>effective command value</a> of 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>.
+
+<p class=note>The effective command value of the active range's start node
+cannot be null, since the boundary point node of a selection must always be
+either an element or a text node that's the child of an element.
+<!--
+Testing with hiliteColor: Opera 11.11 seems to always return the effective
+command value of the active range's start node.  Chrome 14 dev returns boolean
+false consistently, bizarrely enough.  Firefox 6.0a2 seems to follow the same
+idea as the spec, but it likes to return "transparent", including sometimes
+when the answer really clearly should not be "transparent".  IE9 throws
+exceptions most of the time for backColor, so I can't say for sure, but in the
+few cases where it doesn't throw it returns a random-looking number, so I'll
+assume it's crazy like for foreColor.
+
+I decided on something that would guarantee the following invariant: whenever
+you execute a command with a value provided (assuming value is relevant),
+queryCommandValue() will always return something equivalent to what you set.
+-->
+
+
 
 <h3 id=assorted-inline-formatting-command-algorithms><span class=secno>7.2 </span>Assorted inline formatting command algorithms</h3>
 
@@ -2388,20 +2445,7 @@
   <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>
-nodes that are <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
-range</a>, there are two that have distinct <a href=#effective-command-value title="effective command
-value">effective command values</a>.  Otherwise false.
-
-<p><a href=#value>Value</a>: The <a href=#effective-command-value>effective command value</a> of the first
-<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 that is <a href=#effectively-contained>effectively contained</a>
-in the <a href=#active-range>active range</a>, or if there is no such node, the
-<a href=#effective-command-value>effective command value</a> of 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>.
-
-<p class=note>The effective command value of the active range's start node
-cannot be null, since the boundary point node of a selection must always be
-either an element or a text node that's the child of an element.
+<p><a href=#standard-inline-value-command>Standard inline value command</a>
 
 <p><a href=#relevant-css-property>Relevant CSS property</a>: "background-color"
 
@@ -2418,11 +2462,8 @@
 <a href="#set-the-selection's-value">set the selection's value</a> to "normal".  Otherwise <a href="#set-the-selection's-value">set the
 selection's value</a> to "bold".
 
-<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
-range</a>, there is at least one with <a href=#effective-command-value>effective command value</a>
-less than 600 and at least one with <a href=#effective-command-value>effective command value</a>
-greater than or equal to 600.  Otherwise false.
+<p><a href=#inline-command-activated-values>Inline command activated values</a>: "bold", "600", "700", "800",
+or "900"
 <!--
 The cutoff of 600 (both here and for state) matches Chrome 14 dev.  The cutoff
 used by IE9 and Firefox 6.0a2 seems to be 500, and the distinction isn't
@@ -2440,22 +2481,6 @@
 I'll go with 600 as the cutoff.
 -->
 
-<p><a href=#state>State</a>: True if every <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 that
-is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a> has
-<a href=#effective-command-value>effective command value</a> at least 600, and there is at least one
-such <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.
-<!--
-For bold and similar commands, IE 9 RC seems to consider the state true or
-false depending on the first element.  All other browsers follow the same
-general idea as the spec, considering a range bold only if all text in it is
-bold, and this seems to match at least OpenOffice.org's bold feature.  Opera
-11.11 seemingly doesn't take CSS into account, and only looks at whether
-something descends from a <b>.  I couldn't properly test IE9 because it threw
-exceptions (Error: Unspecified error.) on most of the tests I ran.  But what I
-have here seems to match Firefox 6.0a2 in every case, and Chrome 14 dev in all
-cases with a few exceptions.
--->
-
 <p><a href=#relevant-css-property>Relevant CSS property</a>: "font-weight"
 
 
@@ -2516,20 +2541,7 @@
 <!-- IE10PP2, Firefox 7.0a2, Chrome 14 dev, and Opera 11.50 all do not support
 indeterminate, state, or value for createLink or unlink.  I define
 indeterminate and value anyway because they make sense. -->
-<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
-range</a>, there are two that have distinct <a href=#effective-command-value title="effective command
-value">effective command values</a>.  Otherwise false.
-
-<p><a href=#value>Value</a>: The <a href=#effective-command-value>effective command value</a> of the first
-<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 that is <a href=#effectively-contained>effectively contained</a>
-in the <a href=#active-range>active range</a>, or if there is no such node, the
-<a href=#effective-command-value>effective command value</a> of 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>.
-
-<p class=note>The effective command value of the active range's start node
-cannot be null, since the boundary point node of a selection must always be
-either an element or a text node that's the child of an element.
+<p><a href=#standard-inline-value-command>Standard inline value command</a>
 
 
 <h3 id=the-fontname-command><span class=secno>7.10 </span><dfn>The <code title="">fontName</code> command</dfn></h3>
@@ -2557,23 +2569,9 @@
 understand CSS font-family syntax?), so I don't think such usability concerns
 apply. -->
 
-<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
-range</a>, there are two that have distinct <a href=#effective-command-value title="effective command
-value">effective command values</a>.  Otherwise false.
-<!-- This follows Firefox 6.0a2.  Chrome 14 dev always returns false. -->
-
-<p><a href=#value>Value</a>: The <a href=#effective-command-value>effective command value</a> of the first
-<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 that is <a href=#effectively-contained>effectively contained</a>
-in the <a href=#active-range>active range</a>, or if there is no such node, the
-<a href=#effective-command-value>effective command value</a> of 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>.
-
-<p class=note>The effective command value of the active range's start node
-cannot be null, since the boundary point node of a selection must always be
-either an element or a text node that's the child of an element.
+<p><a href=#standard-inline-value-command>Standard inline value command</a>
 <!--
-Complicated.
+The value is complicated.
 
 IE 9 RC: Always the empty string.  Not very useful.
 Firefox 4b11: Confusing.  Sometimes it returns generic family names, like
@@ -2589,8 +2587,6 @@
 I'm just going to punt on this and say it should be the resolved value of
 font-family.  I'll leave CSSOM to decide what that means if there are no
 applicable style rules.
-
-For deciding which node should be checked, see comment for hiliteColor.
 -->
 
 <p><a href=#relevant-css-property>Relevant CSS property</a>: "font-family"
@@ -2706,7 +2702,12 @@
 nodes that are <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
 range</a>, there are two that have distinct <a href=#effective-command-value title="effective command
 value">effective command values</a>.  Otherwise false.
-<!-- This follows Firefox 6.0a2.  Chrome 14 dev always returns false. -->
+<!-- This follows Firefox 6.0a2.  Chrome 14 dev always returns false.  Note
+that indeterminacy here keys off the effective command value, while the value
+is based only on an approximation (a number from one to seven).  Thus it's
+possible for every subrange of the selection to have the same value, but for
+the selection to still be indeterminate.  Setting the fontSize to the value
+will make it determinate without changing anything's value. -->
 
 <p><a href=#value>Value</a>:
 <!--
@@ -2738,11 +2739,8 @@
   node, the <a href=#effective-command-value>effective command value</a> of 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>, in either case interpreted as a number of
   pixels.
-  <!-- See comment for hiliteColor on how I decided on this choice of node. -->
-
-  <p class=note>The effective command value of the active range's start node
-  cannot be null, since the boundary point node of a selection must always be
-  either an element or a text node that's the child of an element.
+  <!-- See comment for standard inline value commands on how I decided on this
+  choice of node. -->
 
   <li>Return the <a href=#legacy-font-size-for>legacy font size for</a> <var title="">pixel size</var>.
 </ol>
@@ -2853,21 +2851,7 @@
 applied, false otherwise, which seems fairly useless; authors want to use value
 here, not state.  So I'll match other browsers and not define any state. -->
 
-<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
-range</a>, there are two that have distinct <a href=#effective-command-value title="effective command
-value">effective command values</a>.  Otherwise false.
-<!-- This follows Firefox 6.0a2.  Chrome 14 dev always returns false. -->
-
-<p><a href=#value>Value</a>: The <a href=#effective-command-value>effective command value</a> of the first
-<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 that is <a href=#effectively-contained>effectively contained</a>
-in the <a href=#active-range>active range</a>, or if there is no such node, the
-<a href=#effective-command-value>effective command value</a> of 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>.
-
-<p class=note>The effective command value of the active range's start node
-cannot be null, since the boundary point node of a selection must always be
-either an element or a text node that's the child of an element.
+<p><a href=#standard-inline-value-command>Standard inline value command</a>
 <!--
 The spec essentially matches Firefox 6.0a2 and Chrome 14 dev, as far as how to
 decide what color the node has.  IE9 seems to always return the number 0 for
@@ -2875,9 +2859,6 @@
 string for some reason, and it seems to select the active node a little
 differently.  Opera uses #xxxxxx format for getComputedStyle() but rgb() here,
 and also drops the transparent part of the color if there is any.
-
-For why I chose this node to key the color off of, see the comment for
-hiliteColor.
 -->
 
 <p><a href=#relevant-css-property>Relevant CSS property</a>: "color"
@@ -2919,36 +2900,9 @@
   <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>
-nodes that are <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
-range</a>, there are two that have distinct <a href=#effective-command-value title="effective command
-value">effective command values</a>.  Otherwise false.
-<!-- This follows no one.  Firefox 6.0a2 and Chrome 14 dev both always return
-false.  However, it makes sense. -->
-
-<p><a href=#value>Value</a>: The <a href=#effective-command-value>effective command value</a> of the first
-<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 that is <a href=#effectively-contained>effectively contained</a>
-in the <a href=#active-range>active range</a>, or if there is no such node, the
-<a href=#effective-command-value>effective command value</a> of 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>.
-
-<p class=note>The effective command value of the active range's start node
-cannot be null, since the boundary point node of a selection must always be
-either an element or a text node that's the child of an element.
-<!--
-Opera 11.11 seems to always return the effective command value of the active
-range's start node.  Chrome 14 dev returns boolean false consistently,
-bizarrely enough.  Firefox 6.0a2 seems to follow the same idea as the spec, but
-it likes to return "transparent", including sometimes when the answer really
-clearly should not be "transparent".  IE9 throws exceptions most of the time
-for backColor, so I can't say for sure, but in the few cases where it doesn't
-throw it returns a random-looking number, so I'll assume it's crazy like for
-foreColor.
-
-I decided on something that would guarantee the following invariant: whenever
-you execute a command with a value provided (assuming value is relevant),
-queryCommandValue() will always return something equivalent to what you set.
--->
+<p><a href=#standard-inline-value-command>Standard inline value command</a>
+<!-- For indeterminacy, this follows no one.  Firefox 6.0a2 and Chrome 14 dev
+both always return false.  However, it makes sense. -->
 
 <p><a href=#relevant-css-property>Relevant CSS property</a>: "background-color"
 
@@ -2959,16 +2913,7 @@
 <a href="#set-the-selection's-value">set the selection's value</a> to "normal".  Otherwise <a href="#set-the-selection's-value">set the
 selection's value</a> to "italic".
 
-<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
-range</a>, there is at least one with <a href=#effective-command-value>effective command value</a>
-either "italic" or "oblique" and at least one with <a href=#effective-command-value>effective command
-value</a> "normal".  Otherwise false.
-
-<p><a href=#state>State</a>: True if every <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 that
-is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a> has
-<a href=#effective-command-value>effective command value</a> either "italic" or "oblique", and there is
-at least one such <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.
+<p><a href=#inline-command-activated-values>Inline command activated values</a>: "italic" or "oblique"
 
 <p><a href=#relevant-css-property>Relevant CSS property</a>: "font-style"
 
@@ -3107,16 +3052,7 @@
 
 <!-- TODO: See underline TODO. -->
 
-<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
-range</a>, there is at least one with <a href=#effective-command-value>effective command value</a>
-"line-through" and at least one with <a href=#effective-command-value>effective command value</a> null.
-Otherwise false.
-
-<p><a href=#state>State</a>: True if every <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 that
-is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a> has
-<a href=#effective-command-value>effective command value</a> "line-through", and there is at least one
-such <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.
+<p><a href=#inline-command-activated-values>Inline command activated values</a>: "line-through"
 
 
 <h3 id=the-subscript-command><span class=secno>7.17 </span><dfn>The <code title="">subscript</code> command</dfn></h3>
@@ -3141,10 +3077,7 @@
 contained</a> in the <a href=#active-range>active range</a> with <a href=#effective-command-value>effective command
 value</a> "mixed".  Otherwise false.
 
-<p><a href=#state>State</a>: True if every <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 that
-is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a> has
-<a href=#effective-command-value>effective command value</a> "sub", and there is at least one such
-<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.
+<p><a href=#inline-command-activated-values>Inline command activated values</a>: "sub"
 <!--
 For <sup><sub>foo</sub></sup>, Firefox 6.0a2 and Opera 11.11 say the state is
 true for both superscript and subscript, and indeterminate is false; Chrome 14
@@ -3182,10 +3115,7 @@
 contained</a> in the <a href=#active-range>active range</a> with <a href=#effective-command-value>effective command
 value</a> "mixed".  Otherwise false.
 
-<p><a href=#state>State</a>: True if every <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 that
-is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a> has
-<a href=#effective-command-value>effective command value</a> "super", and there is at least one such
-<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.
+<p><a href=#inline-command-activated-values>Inline command activated values</a>: "super"
 
 <p><a href=#relevant-css-property>Relevant CSS property</a>: "vertical-align"
 
@@ -3241,16 +3171,7 @@
   http://lists.w3.org/Archives/Public/www-style/2011Mar/0591.html.
 -->
 
-<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
-range</a>, there is at least one with <a href=#effective-command-value>effective command value</a>
-"underline" and at least one with <a href=#effective-command-value>effective command value</a> null.
-Otherwise false.
-
-<p><a href=#state>State</a>: True if every <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 that
-is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a> has
-<a href=#effective-command-value>effective command value</a> "underline", and there is at least one
-such <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.
+<p><a href=#inline-command-activated-values>Inline command activated values</a>: "underline"
 
 
 <h3 id=the-unlink-command><span class=secno>7.20 </span><dfn>The <code title="">unlink</code> command</dfn></h3>
@@ -3276,20 +3197,7 @@
 <!-- IE10PP2, Firefox 7.0a2, Chrome 14 dev, and Opera 11.50 all do not support
 indeterminate, state, or value for createLink or unlink.  I define
 indeterminate and value anyway because they make sense. -->
-<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
-range</a>, there are two that have distinct <a href=#effective-command-value title="effective command
-value">effective command values</a>.  Otherwise false.
-
-<p><a href=#value>Value</a>: The <a href=#effective-command-value>effective command value</a> of the first
-<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 that is <a href=#effectively-contained>effectively contained</a>
-in the <a href=#active-range>active range</a>, or if there is no such node, the
-<a href=#effective-command-value>effective command value</a> of 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>.
-
-<p class=note>The effective command value of the active range's start node
-cannot be null, since the boundary point node of a selection must always be
-either an element or a text node that's the child of an element.
+<p><a href=#standard-inline-value-command>Standard inline value command</a>
 
 
 
--- a/implementation.js	Mon Jul 18 13:39:40 2011 -0600
+++ b/implementation.js	Mon Jul 18 15:26:31 2011 -0600
@@ -216,29 +216,6 @@
 		|| ns === htmlNamespace;
 }
 
-// For computing indeterminate flags of the form "True if among editable Text
-// nodes that are effectively contained in the active range, there is at least
-// one with (property X) and at least one with (property not-X).  Otherwise
-// false."
-function indetermHelper(callback) {
-	var nodes = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
-		return isEditable(node)
-			&& node.nodeType == Node.TEXT_NODE;
-	});
-	return nodes.some(callback) && !nodes.every(callback);
-}
-
-// For computing states of the form "True if every editable Text node that is
-// effectively contained in the active range (has property X), and there is at
-// least one such Text node.  Otherwise false."
-function stateHelper(callback) {
-	var nodes = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
-		return isEditable(node)
-			&& node.nodeType == Node.TEXT_NODE;
-	});
-	return nodes.every(callback) && nodes.length >= 1;
-}
-
 // "the directionality" from HTML.  I don't bother caring about non-HTML
 // elements.
 //
@@ -1990,6 +1967,10 @@
 		return null;
 	}
 
+	if (!("relevantCssProperty" in commands[command])) {
+		throw "Bug: no relevantCssProperty for " + command + " in getEffectiveCommandValue";
+	}
+
 	// "Return the resolved value for node of the relevant CSS property for
 	// command."
 	return getComputedStyle(node)[commands[command].relevantCssProperty];
@@ -2961,39 +2942,7 @@
 
 		// "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 command
-		// values.  Otherwise false."
-		return getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
-			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
-		}).map(function(node) {
-			return getEffectiveCommandValue(node, "backcolor");
-		}).filter(function(value, i, arr) {
-			return arr.slice(0, i).indexOf(value) == -1;
-		}).length >= 2;
-	}, value: function() {
-		// "The effective command value of the first editable Text node that is
-		// effectively contained in the active range, or if there is no such
-		// node, the effective command value of the active range's start node."
-		//
-		// Opera uses a different format, so let's be nice and support that for
-		// the time being (since all this resolved value stuff is underdefined
-		// anyway).
-		var node = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
-			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
-		})[0];
-		if (node === undefined) {
-			node = getActiveRange().startContainer;
-		}
-		var value = getEffectiveCommandValue(node, "backcolor");
-		if (/^#[0-9a-f]{6}$/.test(value)) {
-			value = "rgb(" + parseInt(value.slice(1, 3), 16)
-				+ "," + parseInt(value.slice(3, 5), 16)
-				+ "," + parseInt(value.slice(5), 16) + ")";
-		}
-		return value;
-	}, relevantCssProperty: "backgroundColor"
+	}, standardInlineValueCommand: true, relevantCssProperty: "backgroundColor"
 };
 
 //@}
@@ -3008,28 +2957,8 @@
 		} else {
 			setSelectionValue("bold", "bold");
 		}
-	}, indeterm: function() { return indetermHelper(function(node) {
-		// "True if among editable Text nodes that are effectively contained in
-		// the active range, there is at least one with effective command value
-		// less than 600 and at least one with effective command value greater
-		// than or equal to 600."
-		var fontWeight = getEffectiveCommandValue(node, "bold");
-		return fontWeight === "bold"
-			|| fontWeight === "600"
-			|| fontWeight === "700"
-			|| fontWeight === "800"
-			|| fontWeight === "900";
-	})}, state: function() { return stateHelper(function(node) {
-		// "True if every editable Text node that is effectively contained in
-		// the active range has effective command value at least 600, and there
-		// is at least one such text node. Otherwise false."
-		var fontWeight = getEffectiveCommandValue(node, "bold");
-		return fontWeight === "bold"
-			|| fontWeight === "600"
-			|| fontWeight === "700"
-			|| fontWeight === "800"
-			|| fontWeight === "900";
-	})}, relevantCssProperty: "fontWeight"
+	}, inlineCommandActivatedValues: ["bold", "600", "700", "800", "900"],
+	relevantCssProperty: "fontWeight"
 };
 
 //@}
@@ -3060,29 +2989,7 @@
 
 		// "Set the selection's value to value."
 		setSelectionValue("createlink", value);
-	}, indeterm: function() {
-		// "True if among editable Text nodes that are effectively contained in
-		// the active range, there are two that have distinct effective command
-		// values.  Otherwise false."
-		return getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
-			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
-		}).map(function(node) {
-			return getEffectiveCommandValue(node, "createlink");
-		}).filter(function(value, i, arr) {
-			return arr.slice(0, i).indexOf(value) == -1;
-		}).length >= 2;
-	}, value: function() {
-		// "The effective command value of the first editable Text node that is
-		// effectively contained in the active range, or if there is no such
-		// node, the effective command value of the active range's start node."
-		var node = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
-			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
-		})[0];
-		if (node === undefined) {
-			node = getActiveRange().startContainer;
-		}
-		return getEffectiveCommandValue(node, "createlink");
-	}
+	}, standardInlineValueCommand: true
 };
 
 //@}
@@ -3092,29 +2999,7 @@
 	action: function(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 command
-		// values.  Otherwise false."
-		return getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
-			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
-		}).map(function(node) {
-			return getEffectiveCommandValue(node, "fontname");
-		}).filter(function(value, i, arr) {
-			return arr.slice(0, i).indexOf(value) == -1;
-		}).length >= 2;
-	}, value: function() {
-		// "The effective command value of the first editable Text node that is
-		// effectively contained in the active range, or if there is no such
-		// node, the effective command value of the active range's start node."
-		var node = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
-			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
-		})[0];
-		if (node === undefined) {
-			node = getActiveRange().startContainer;
-		}
-		return getEffectiveCommandValue(node, "fontname");
-	}, relevantCssProperty: "fontFamily"
+	}, standardInlineValueCommand: true, relevantCssProperty: "fontFamily"
 };
 
 //@}
@@ -3305,39 +3190,7 @@
 
 		// "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 command
-		// values.  Otherwise false."
-		return getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
-			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
-		}).map(function(node) {
-			return getEffectiveCommandValue(node, "forecolor");
-		}).filter(function(value, i, arr) {
-			return arr.slice(0, i).indexOf(value) == -1;
-		}).length >= 2;
-	}, value: function() {
-		// "The effective command value of the first editable Text node that is
-		// effectively contained in the active range, or if there is no such
-		// node, the effective command value of the active range's start node."
-		//
-		// Opera uses a different format, so let's be nice and support that for
-		// the time being (since all this resolved value stuff is underdefined
-		// anyway).
-		var node = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
-			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
-		})[0];
-		if (node === undefined) {
-			node = getActiveRange().startContainer;
-		}
-		var value = getEffectiveCommandValue(node, "forecolor");
-		if (/^#[0-9a-f]{6}$/.test(value)) {
-			value = "rgb(" + parseInt(value.slice(1, 3), 16)
-				+ "," + parseInt(value.slice(3, 5), 16)
-				+ "," + parseInt(value.slice(5), 16) + ")";
-		}
-		return value;
-	}, relevantCssProperty: "color"
+	}, standardInlineValueCommand: true, relevantCssProperty: "color"
 };
 
 //@}
@@ -3376,28 +3229,7 @@
 		}).filter(function(value, i, arr) {
 			return arr.slice(0, i).indexOf(value) == -1;
 		}).length >= 2;
-	}, value: function() {
-		// "The effective command value of the first editable Text node that is
-		// effectively contained in the active range, or if there is no such
-		// node, the effective command value of the active range's start node."
-		//
-		// Opera uses a different format, so let's be nice and support that for
-		// the time being (since all this resolved value stuff is underdefined
-		// anyway).
-		var node = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
-			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
-		})[0];
-		if (node === undefined) {
-			node = getActiveRange().startContainer;
-		}
-		var value = getEffectiveCommandValue(node, "hilitecolor");
-		if (/^#[0-9a-f]{6}$/.test(value)) {
-			value = "rgb(" + parseInt(value.slice(1, 3), 16)
-				+ "," + parseInt(value.slice(3, 5), 16)
-				+ "," + parseInt(value.slice(5), 16) + ")";
-		}
-		return value;
-	}, relevantCssProperty: "backgroundColor"
+	}, standardInlineValueCommand: true, relevantCssProperty: "backgroundColor"
 };
 
 //@}
@@ -3412,21 +3244,8 @@
 		} else {
 			setSelectionValue("italic", "italic");
 		}
-	}, indeterm: function() { return indetermHelper(function(node) {
-		// "True if among editable Text nodes that are effectively contained in
-		// the active range, there is at least one with effective command value
-		// either "italic" or "oblique" and at least one with effective command
-		// value "normal". Otherwise false."
-		var value = getEffectiveCommandValue(node, "italic");
-		return value == "italic" || value == "oblique";
-	})}, state: function() { return stateHelper(function(node) {
-		// "True if every editable Text node that is effectively contained in
-		// the active range has effective command value either "italic" or
-		// "oblique", and there is at least one such Text node.  Otherwise
-		// false."
-		var value = getEffectiveCommandValue(node, "italic");
-		return value == "italic" || value == "oblique";
-	})}, relevantCssProperty: "fontStyle"
+	}, inlineCommandActivatedValues: ["italic", "oblique"],
+	relevantCssProperty: "fontStyle"
 };
 
 //@}
@@ -3543,18 +3362,7 @@
 		} else {
 			setSelectionValue("strikethrough", "line-through");
 		}
-	}, indeterm: function() { return indetermHelper(function(node) {
-		// "True if among editable Text nodes that are effectively contained in
-		// the active range, there is at least one with effective command value
-		// "line-through" and at least one with effective command value null.
-		// Otherwise false."
-		return getEffectiveCommandValue(node, "strikethrough") == "line-through";
-	})}, state: function() { return stateHelper(function(node) {
-		// "True if every editable Text node that is effectively contained in
-		// the active range has effective command value "line-through", and
-		// there is at least one such Text node. Otherwise false."
-		return getEffectiveCommandValue(node, "strikethrough") == "line-through";
-	})}
+	}, inlineCommandActivatedValues: ["line-through"]
 };
 
 //@}
@@ -3585,12 +3393,8 @@
 		return (nodes.some(function(node) { return getEffectiveCommandValue(node, "subscript") == "sub" })
 			&& nodes.some(function(node) { return getEffectiveCommandValue(node, "subscript") != "sub" }))
 			|| nodes.some(function(node) { return getEffectiveCommandValue(node, "subscript") == "mixed" });
-	}, state: function() { return stateHelper(function(node) {
-		// "True if every editable Text node that is effectively contained in
-		// the active range has effective command value "sub", and there is at
-		// least one such Text node. Otherwise false."
-		return getEffectiveCommandValue(node, "subscript") == "sub";
-	})}, relevantCssProperty: "verticalAlign"
+	}, inlineCommandActivatedValues: ["sub"],
+	relevantCssProperty: "verticalAlign"
 };
 
 //@}
@@ -3623,12 +3427,8 @@
 		return (nodes.some(function(node) { return getEffectiveCommandValue(node, "superscript") == "super" })
 			&& nodes.some(function(node) { return getEffectiveCommandValue(node, "superscript") != "super" }))
 			|| nodes.some(function(node) { return getEffectiveCommandValue(node, "superscript") == "mixed" });
-	}, state: function() { return stateHelper(function(node) {
-		// "True if every editable Text node that is effectively contained in
-		// the active range has effective command value "super", and there is
-		// at least one such Text node. Otherwise false."
-		return getEffectiveCommandValue(node, "superscript") == "super";
-	})}, relevantCssProperty: "verticalAlign"
+	}, inlineCommandActivatedValues: ["super"],
+	relevantCssProperty: "verticalAlign"
 };
 
 //@}
@@ -3643,18 +3443,7 @@
 		} else {
 			setSelectionValue("underline", "underline");
 		}
-	}, indeterm: function() { return indetermHelper(function(node) {
-		// "True if among editable Text nodes that are effectively contained in
-		// the active range, there is at least one with effective command value
-		// "underline" and at least one with effective command value null.
-		// Otherwise false."
-		return getEffectiveCommandValue(node, "underline") === "underline";
-	})}, state: function() { return stateHelper(function(node) {
-		// "True if every editable Text node that is effectively contained in
-		// the active range has effective command value "underline", and there
-		// is at least one such Text node. Otherwise false."
-		return getEffectiveCommandValue(node, "underline") === "underline";
-	})}
+	}, inlineCommandActivatedValues: ["underline"]
 };
 
 //@}
@@ -3698,29 +3487,7 @@
 		for (var i = 0; i < hyperlinks.length; i++) {
 			clearValue(hyperlinks[i], "unlink");
 		}
-	}, indeterm: function() {
-		// "True if among editable Text nodes that are effectively contained in
-		// the active range, there are two that have distinct effective command
-		// values.  Otherwise false."
-		return getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
-			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
-		}).map(function(node) {
-			return getEffectiveCommandValue(node, "unlink");
-		}).filter(function(value, i, arr) {
-			return arr.slice(0, i).indexOf(value) == -1;
-		}).length >= 2;
-	}, value: function() {
-		// "The effective command value of the first editable Text node that is
-		// effectively contained in the active range, or if there is no such
-		// node, the effective command value of the active range's start node."
-		var node = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
-			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
-		})[0];
-		if (node === undefined) {
-			node = getActiveRange().startContainer;
-		}
-		return getEffectiveCommandValue(node, "unlink");
-	}
+	}, standardInlineValueCommand: true
 };
 
 //@}
@@ -7528,16 +7295,94 @@
 		cssStylingFlag = String(value).toLowerCase() == "false";
 	}
 };
-
 //@}
-(function() {
+
+//@{ Some final setup
+Object.keys(commands).forEach(function(command) {
 	// "If a command does not have a relevant CSS property specified, it
 	// defaults to null."
-	for (var command in commands) {
-		if (!("relevantCssProperty" in commands[command])) {
-			commands[command].relevantCssProperty = null;
-		}
-	}
-})();
+	if (!("relevantCssProperty" in commands[command])) {
+		commands[command].relevantCssProperty = null;
+	}
+
+	// "If a command has inline command activated values defined but
+	// nothing else defines when it is indeterminate, it is indeterminate
+	// if among editable Text nodes effectively contained in the active
+	// range, there is at least one whose effective command value is one of
+	// the given values and at least one whose effective command value is
+	// not one of the given values."
+	if ("inlineCommandActivatedValues" in commands[command]
+	&& !("indeterminate" in commands[command])) {
+		commands[command].indeterminate = function() {
+			var values = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
+				return isEditable(node)
+					&& node.nodeType == Node.TEXT_NODE;
+			}).map(function(node) { return getEffectiveCommandValue(node, command) });
+
+			var matchingValues = values.filter(function(value) {
+				return commands[command].inlineCommandActivatedValues.indexOf(value) != -1;
+			});
+
+			return matchingValues.length >= 1
+				&& values.length - matchingValues.length >= 1;
+		};
+	}
+
+	// "If a command has inline command activated values defined, its state
+	// is true if either no editable Text node is effectively contained in
+	// the active range, and the active range's start node's effective
+	// command value is one of the given values; or if there is at least
+	// one editable Text node effectively contained in the active range,
+	// and all of them have an effective command value equal to one of the
+	// given values."
+	if ("inlineCommandActivatedValues" in commands[command]) {
+		commands[command].state = function() {
+			var nodes = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
+				return isEditable(node)
+					&& node.nodeType == Node.TEXT_NODE;
+			});
+
+			if (nodes.length == 0) {
+				return commands[command].inlineCommandActivatedValues
+					.indexOf(getEffectiveCommandValue(getActiveRange().startContainer, command)) != -1;
+			} else {
+				return nodes.every(function(node) {
+					return commands[command].inlineCommandActivatedValues
+						.indexOf(getEffectiveCommandValue(node, command)) != -1;
+				});
+			}
+		};
+	}
+
+	// "If a command is a standard inline value command, it is
+	// indeterminate if among editable Text nodes that are effectively
+	// contained in the active range, there are two that have distinct
+	// effective command values. Its value is the effective command value
+	// of the first editable Text node that is effectively contained in the
+	// active range, or if there is no such node, the effective command
+	// value of the active range's start node."
+	if ("standardInlineValueCommand" in commands[command]) {
+		commands[command].indeterminate = function() {
+			return getAllEffectivelyContainedNodes(getActiveRange())
+				.filter(function(node) { return isEditable(node) && node.nodeType == Node.TEXT_NODE })
+				.map(function(node) { return getEffectiveCommandValue(node, command) })
+				.length >= 2;
+		};
+
+		commands[command].value = function() {
+			var refNode = getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
+				return isEditable(node)
+					&& node.nodeType == Node.TEXT_NODE;
+			})[0];
+
+			if (typeof refNode == "undefined") {
+				refNode = getActiveRange().startContainer;
+			}
+
+			return getEffectiveCommandValue(refNode, command);
+		};
+	}
+});
+//@}
 
 // vim: foldmarker=@{,@} foldmethod=marker
--- a/source.html	Mon Jul 18 13:39:40 2011 -0600
+++ b/source.html	Mon Jul 18 15:26:31 2011 -0600
@@ -1334,6 +1334,63 @@
 <p class=note>Conceptually, a simple modifiable element is a modifiable element
 which specifies a value for at most one command.
 
+<p>If a <span>command</span> has <dfn>inline command activated values</dfn>
+defined but nothing else defines when it is <span>indeterminate</span>, it is
+<span>indeterminate</span> if among <span>editable</span> [[text]] nodes
+<span>effectively contained</span> in the <span>active range</span>, there is
+at least one whose <span>effective command value</span> is one of the given
+values and at least one whose <span>effective command value</span> is not one
+of the given values.
+
+<p>If a <span>command</span> has <span>inline command activated values</span>
+defined, its <span>state</span> is true if either no <span>editable</span>
+[[text]] node is <span>effectively contained</span> in the <span>active
+range</span>, and the <span>active range</span>'s [[startnode]]'s
+<span>effective command value</span> is one of the given values; or if there is
+at least one <span>editable</span> [[text]] node <span>effectively
+contained</span> in the <span>active range</span>, and all of them have an
+<span>effective command value</span> equal to one of the given values.
+<!--
+For bold and similar commands, IE 9 RC seems to consider the state true or
+false depending on the first element.  All other browsers follow the same
+general idea as the spec, considering a range bold only if all text in it is
+bold, and this seems to match at least OpenOffice.org's bold feature.  Opera
+11.11 seemingly doesn't take CSS into account, and only looks at whether
+something descends from a <b>.  I couldn't properly test IE9 because it threw
+exceptions (Error: Unspecified error.) on most of the tests I ran.  But what I
+have here seems to match Firefox 6.0a2 in every case, and Chrome 14 dev in all
+cases with a few exceptions.
+-->
+
+<p>If a command is a <dfn>standard inline value command</dfn>, it is
+<span>indeterminate</span> if among <span>editable</span> [[text]] nodes that
+are <span>effectively contained</span> in the <span>active range</span>, there
+are two that have distinct <span title="effective command value">effective
+command values</span>.  Its <span>value</span> is the <span>effective command
+value</span> of the first <span>editable</span> [[text]] node that is
+<span>effectively contained</span> in the <span>active range</span>, or if
+there is no such node, the <span>effective command value</span> of the
+<span>active range</span>'s [[startnode]].
+
+<p class=note>The effective command value of the active range's start node
+cannot be null, since the boundary point node of a selection must always be
+either an element or a text node that's the child of an element.
+<!--
+Testing with hiliteColor: Opera 11.11 seems to always return the effective
+command value of the active range's start node.  Chrome 14 dev returns boolean
+false consistently, bizarrely enough.  Firefox 6.0a2 seems to follow the same
+idea as the spec, but it likes to return "transparent", including sometimes
+when the answer really clearly should not be "transparent".  IE9 throws
+exceptions most of the time for backColor, so I can't say for sure, but in the
+few cases where it doesn't throw it returns a random-looking number, so I'll
+assume it's crazy like for foreColor.
+
+I decided on something that would guarantee the following invariant: whenever
+you execute a command with a value provided (assuming value is relevant),
+queryCommandValue() will always return something equivalent to what you set.
+-->
+
+
 <!-- @} -->
 <h3>Assorted inline formatting command algorithms</h3>
 <!-- @{ -->
@@ -2367,20 +2424,7 @@
   <li><span>Set the selection's value</span> to <var>value</var>.
 </ol>
 
-<p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
-nodes that are <span>effectively contained</span> in the <span>active
-range</span>, there are two that have distinct <span title="effective command
-value">effective command values</span>.  Otherwise false.
-
-<p><span>Value</span>: The <span>effective command value</span> of the first
-<span>editable</span> [[text]] node that is <span>effectively contained</span>
-in the <span>active range</span>, or if there is no such node, the
-<span>effective command value</span> of the <span>active range</span>'s
-[[startnode]].
-
-<p class=note>The effective command value of the active range's start node
-cannot be null, since the boundary point node of a selection must always be
-either an element or a text node that's the child of an element.
+<p><span>Standard inline value command</span>
 
 <p><span>Relevant CSS property</span>: "background-color"
 
@@ -2398,11 +2442,8 @@
 <span>set the selection's value</span> to "normal".  Otherwise <span>set the
 selection's value</span> to "bold".
 
-<p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
-nodes that are <span>effectively contained</span> in the <span>active
-range</span>, there is at least one with <span>effective command value</span>
-less than 600 and at least one with <span>effective command value</span>
-greater than or equal to 600.  Otherwise false.
+<p><span>Inline command activated values</span>: "bold", "600", "700", "800",
+or "900"
 <!--
 The cutoff of 600 (both here and for state) matches Chrome 14 dev.  The cutoff
 used by IE9 and Firefox 6.0a2 seems to be 500, and the distinction isn't
@@ -2420,22 +2461,6 @@
 I'll go with 600 as the cutoff.
 -->
 
-<p><span>State</span>: True if every <span>editable</span> [[text]] node that
-is <span>effectively contained</span> in the <span>active range</span> has
-<span>effective command value</span> at least 600, and there is at least one
-such [[text]] node.  Otherwise false.
-<!--
-For bold and similar commands, IE 9 RC seems to consider the state true or
-false depending on the first element.  All other browsers follow the same
-general idea as the spec, considering a range bold only if all text in it is
-bold, and this seems to match at least OpenOffice.org's bold feature.  Opera
-11.11 seemingly doesn't take CSS into account, and only looks at whether
-something descends from a <b>.  I couldn't properly test IE9 because it threw
-exceptions (Error: Unspecified error.) on most of the tests I ran.  But what I
-have here seems to match Firefox 6.0a2 in every case, and Chrome 14 dev in all
-cases with a few exceptions.
--->
-
 <p><span>Relevant CSS property</span>: "font-weight"
 
 <!-- @} -->
@@ -2496,20 +2521,7 @@
 <!-- IE10PP2, Firefox 7.0a2, Chrome 14 dev, and Opera 11.50 all do not support
 indeterminate, state, or value for createLink or unlink.  I define
 indeterminate and value anyway because they make sense. -->
-<p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
-nodes that are <span>effectively contained</span> in the <span>active
-range</span>, there are two that have distinct <span title="effective command
-value">effective command values</span>.  Otherwise false.
-
-<p><span>Value</span>: The <span>effective command value</span> of the first
-<span>editable</span> [[text]] node that is <span>effectively contained</span>
-in the <span>active range</span>, or if there is no such node, the
-<span>effective command value</span> of the <span>active range</span>'s
-[[startnode]].
-
-<p class=note>The effective command value of the active range's start node
-cannot be null, since the boundary point node of a selection must always be
-either an element or a text node that's the child of an element.
+<p><span>Standard inline value command</span>
 
 <!-- @} -->
 <h3><dfn>The <code title>fontName</code> command</dfn></h3>
@@ -2537,23 +2549,9 @@
 understand CSS font-family syntax?), so I don't think such usability concerns
 apply. -->
 
-<p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
-nodes that are <span>effectively contained</span> in the <span>active
-range</span>, there are two that have distinct <span title="effective command
-value">effective command values</span>.  Otherwise false.
-<!-- This follows Firefox 6.0a2.  Chrome 14 dev always returns false. -->
-
-<p><span>Value</span>: The <span>effective command value</span> of the first
-<span>editable</span> [[text]] node that is <span>effectively contained</span>
-in the <span>active range</span>, or if there is no such node, the
-<span>effective command value</span> of the <span>active range</span>'s
-[[startnode]].
-
-<p class=note>The effective command value of the active range's start node
-cannot be null, since the boundary point node of a selection must always be
-either an element or a text node that's the child of an element.
+<p><span>Standard inline value command</span>
 <!--
-Complicated.
+The value is complicated.
 
 IE 9 RC: Always the empty string.  Not very useful.
 Firefox 4b11: Confusing.  Sometimes it returns generic family names, like
@@ -2569,8 +2567,6 @@
 I'm just going to punt on this and say it should be the resolved value of
 font-family.  I'll leave CSSOM to decide what that means if there are no
 applicable style rules.
-
-For deciding which node should be checked, see comment for hiliteColor.
 -->
 
 <p><span>Relevant CSS property</span>: "font-family"
@@ -2686,7 +2682,12 @@
 nodes that are <span>effectively contained</span> in the <span>active
 range</span>, there are two that have distinct <span title="effective command
 value">effective command values</span>.  Otherwise false.
-<!-- This follows Firefox 6.0a2.  Chrome 14 dev always returns false. -->
+<!-- This follows Firefox 6.0a2.  Chrome 14 dev always returns false.  Note
+that indeterminacy here keys off the effective command value, while the value
+is based only on an approximation (a number from one to seven).  Thus it's
+possible for every subrange of the selection to have the same value, but for
+the selection to still be indeterminate.  Setting the fontSize to the value
+will make it determinate without changing anything's value. -->
 
 <p><span>Value</span>:
 <!--
@@ -2718,11 +2719,8 @@
   node, the <span>effective command value</span> of the <span>active
   range</span>'s [[startnode]], in either case interpreted as a number of
   pixels.
-  <!-- See comment for hiliteColor on how I decided on this choice of node. -->
-
-  <p class=note>The effective command value of the active range's start node
-  cannot be null, since the boundary point node of a selection must always be
-  either an element or a text node that's the child of an element.
+  <!-- See comment for standard inline value commands on how I decided on this
+  choice of node. -->
 
   <li>Return the <span>legacy font size for</span> <var>pixel size</var>.
 </ol>
@@ -2833,21 +2831,7 @@
 applied, false otherwise, which seems fairly useless; authors want to use value
 here, not state.  So I'll match other browsers and not define any state. -->
 
-<p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
-nodes that are <span>effectively contained</span> in the <span>active
-range</span>, there are two that have distinct <span title="effective command
-value">effective command values</span>.  Otherwise false.
-<!-- This follows Firefox 6.0a2.  Chrome 14 dev always returns false. -->
-
-<p><span>Value</span>: The <span>effective command value</span> of the first
-<span>editable</span> [[text]] node that is <span>effectively contained</span>
-in the <span>active range</span>, or if there is no such node, the
-<span>effective command value</span> of the <span>active range</span>'s
-[[startnode]].
-
-<p class=note>The effective command value of the active range's start node
-cannot be null, since the boundary point node of a selection must always be
-either an element or a text node that's the child of an element.
+<p><span>Standard inline value command</span>
 <!--
 The spec essentially matches Firefox 6.0a2 and Chrome 14 dev, as far as how to
 decide what color the node has.  IE9 seems to always return the number 0 for
@@ -2855,9 +2839,6 @@
 string for some reason, and it seems to select the active node a little
 differently.  Opera uses #xxxxxx format for getComputedStyle() but rgb() here,
 and also drops the transparent part of the color if there is any.
-
-For why I chose this node to key the color off of, see the comment for
-hiliteColor.
 -->
 
 <p><span>Relevant CSS property</span>: "color"
@@ -2899,36 +2880,9 @@
   <li><span>Set the selection's value</span> to <var>value</var>.
 </ol>
 
-<p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
-nodes that are <span>effectively contained</span> in the <span>active
-range</span>, there are two that have distinct <span title="effective command
-value">effective command values</span>.  Otherwise false.
-<!-- This follows no one.  Firefox 6.0a2 and Chrome 14 dev both always return
-false.  However, it makes sense. -->
-
-<p><span>Value</span>: The <span>effective command value</span> of the first
-<span>editable</span> [[text]] node that is <span>effectively contained</span>
-in the <span>active range</span>, or if there is no such node, the
-<span>effective command value</span> of the <span>active range</span>'s
-[[startnode]].
-
-<p class=note>The effective command value of the active range's start node
-cannot be null, since the boundary point node of a selection must always be
-either an element or a text node that's the child of an element.
-<!--
-Opera 11.11 seems to always return the effective command value of the active
-range's start node.  Chrome 14 dev returns boolean false consistently,
-bizarrely enough.  Firefox 6.0a2 seems to follow the same idea as the spec, but
-it likes to return "transparent", including sometimes when the answer really
-clearly should not be "transparent".  IE9 throws exceptions most of the time
-for backColor, so I can't say for sure, but in the few cases where it doesn't
-throw it returns a random-looking number, so I'll assume it's crazy like for
-foreColor.
-
-I decided on something that would guarantee the following invariant: whenever
-you execute a command with a value provided (assuming value is relevant),
-queryCommandValue() will always return something equivalent to what you set.
--->
+<p><span>Standard inline value command</span>
+<!-- For indeterminacy, this follows no one.  Firefox 6.0a2 and Chrome 14 dev
+both always return false.  However, it makes sense. -->
 
 <p><span>Relevant CSS property</span>: "background-color"
 
@@ -2940,16 +2894,7 @@
 <span>set the selection's value</span> to "normal".  Otherwise <span>set the
 selection's value</span> to "italic".
 
-<p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
-nodes that are <span>effectively contained</span> in the <span>active
-range</span>, there is at least one with <span>effective command value</span>
-either "italic" or "oblique" and at least one with <span>effective command
-value</span> "normal".  Otherwise false.
-
-<p><span>State</span>: True if every <span>editable</span> [[text]] node that
-is <span>effectively contained</span> in the <span>active range</span> has
-<span>effective command value</span> either "italic" or "oblique", and there is
-at least one such [[text]] node.  Otherwise false.
+<p><span>Inline command activated values</span>: "italic" or "oblique"
 
 <p><span>Relevant CSS property</span>: "font-style"
 
@@ -3089,16 +3034,7 @@
 
 <!-- TODO: See underline TODO. -->
 
-<p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
-nodes that are <span>effectively contained</span> in the <span>active
-range</span>, there is at least one with <span>effective command value</span>
-"line-through" and at least one with <span>effective command value</span> null.
-Otherwise false.
-
-<p><span>State</span>: True if every <span>editable</span> [[text]] node that
-is <span>effectively contained</span> in the <span>active range</span> has
-<span>effective command value</span> "line-through", and there is at least one
-such [[text]] node.  Otherwise false.
+<p><span>Inline command activated values</span>: "line-through"
 
 <!-- @} -->
 <h3><dfn>The <code title>subscript</code> command</dfn></h3>
@@ -3124,10 +3060,7 @@
 contained</span> in the <span>active range</span> with <span>effective command
 value</span> "mixed".  Otherwise false.
 
-<p><span>State</span>: True if every <span>editable</span> [[text]] node that
-is <span>effectively contained</span> in the <span>active range</span> has
-<span>effective command value</span> "sub", and there is at least one such
-[[text]] node.  Otherwise false.
+<p><span>Inline command activated values</span>: "sub"
 <!--
 For <sup><sub>foo</sub></sup>, Firefox 6.0a2 and Opera 11.11 say the state is
 true for both superscript and subscript, and indeterminate is false; Chrome 14
@@ -3166,10 +3099,7 @@
 contained</span> in the <span>active range</span> with <span>effective command
 value</span> "mixed".  Otherwise false.
 
-<p><span>State</span>: True if every <span>editable</span> [[text]] node that
-is <span>effectively contained</span> in the <span>active range</span> has
-<span>effective command value</span> "super", and there is at least one such
-[[text]] node.  Otherwise false.
+<p><span>Inline command activated values</span>: "super"
 
 <p><span>Relevant CSS property</span>: "vertical-align"
 
@@ -3226,16 +3156,7 @@
   http://lists.w3.org/Archives/Public/www-style/2011Mar/0591.html.
 -->
 
-<p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
-nodes that are <span>effectively contained</span> in the <span>active
-range</span>, there is at least one with <span>effective command value</span>
-"underline" and at least one with <span>effective command value</span> null.
-Otherwise false.
-
-<p><span>State</span>: True if every <span>editable</span> [[text]] node that
-is <span>effectively contained</span> in the <span>active range</span> has
-<span>effective command value</span> "underline", and there is at least one
-such [[text]] node.  Otherwise false.
+<p><span>Inline command activated values</span>: "underline"
 
 <!-- @} -->
 <h3><dfn>The <code title>unlink</code> command</dfn></h3>
@@ -3261,20 +3182,7 @@
 <!-- IE10PP2, Firefox 7.0a2, Chrome 14 dev, and Opera 11.50 all do not support
 indeterminate, state, or value for createLink or unlink.  I define
 indeterminate and value anyway because they make sense. -->
-<p><span>Indeterminate</span>: True if among <span>editable</span> [[text]]
-nodes that are <span>effectively contained</span> in the <span>active
-range</span>, there are two that have distinct <span title="effective command
-value">effective command values</span>.  Otherwise false.
-
-<p><span>Value</span>: The <span>effective command value</span> of the first
-<span>editable</span> [[text]] node that is <span>effectively contained</span>
-in the <span>active range</span>, or if there is no such node, the
-<span>effective command value</span> of the <span>active range</span>'s
-[[startnode]].
-
-<p class=note>The effective command value of the active range's start node
-cannot be null, since the boundary point node of a selection must always be
-either an element or a text node that's the child of an element.
+<p><span>Standard inline value command</span>
 
 <!-- @} -->
 
--- a/tests.js	Mon Jul 18 13:39:40 2011 -0600
+++ b/tests.js	Mon Jul 18 15:26:31 2011 -0600
@@ -81,11 +81,10 @@
 	bold: [
 	//@{
 		'foo[]bar',
+		'<b>foo[]bar</b>',
 		'<span>foo</span>{}<span>bar</span>',
 		'<span>foo[</span><span>]bar</span>',
 		'foo[bar]baz',
-		'foo]bar[baz',
-		'{<p><p> <p>foo</p>}',
 		'foo[bar<i>baz]qoz</i>quz',
 
 		'foo<span contenteditable=false>[bar]</span>baz',