Adjust "effective style" definition for simplicity
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Mon, 21 Mar 2011 14:27:53 -0600
changeset 22 a88df2f75682
parent 21 7b28dc5917ca
child 23 a6e401031af5
Adjust "effective style" definition for simplicity

Also added a definition for underline, but I doubt it works right yet.
editcommands.html
implementation.js
source.html
--- a/editcommands.html	Mon Mar 21 14:08:35 2011 -0600
+++ b/editcommands.html	Mon Mar 21 14:27:53 2011 -0600
@@ -212,13 +212,22 @@
 not be used where only <a class=external data-anolis-spec=html href=http://www.whatwg.org/html/#phrasing-content>phrasing content</a> is expected (not counting unknown or
 obsolete elements, which cannot be used at all).
 
-<p>The <dfn id=effective-style>effective style</dfn> of an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> <var title="">element</var> for a
-given <var title="">property</var> is returned by the following algorithm, which will
-return a CSS value:
+<p>The <dfn id=effective-style>effective style</dfn> of a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> <var title="">node</var> for a given
+<var title="">property</var> is returned by the following algorithm, which will return
+either a CSS value or null:
 
 <ol>
+  <li>If <var title="">node</var> is neither an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> nor a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node, return
+  null.
+
+  <li>If <var title="">node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node and 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> is null, return
+  null.
+
+  <li>If <var title="">node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node, return the <a href=#effective-style>effective
+  style</a> of 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> for <var title="">property</var>.
+
   <li>If <var title="">property</var> is "text-decoration", and the "text-decoration"
-  property of <var title="">element</var> or any of its <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>ancestors</a> computes to
+  property of <var title="">node</var> or any of its <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>ancestors</a> computes to
   "underline", return "underline".  Otherwise, return "none".
 
   <p class=XXX>We ignore the possibility of text-decorations other than
@@ -228,18 +237,18 @@
   <li>If <var title="">property</var> is "background-color":
 
   <ol>
-    <li>While the computed style of "background-color" on <var title="">element</var> is
-    any fully transparent value, and <var title="">element</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=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a>, set <var title="">element</var> to its parent.
+    <li>While the computed style of "background-color" on <var title="">node</var> is
+    any fully transparent value, and <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=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a>, set <var title="">node</var> to 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>.
 
-    <li>If the computed style of "background-color" on <var title="">element</var> is
+    <li>If the computed style of "background-color" on <var title="">node</var> is
     a fully transparent value, return "rgb(255, 255, 255)".
 
     <li>Otherwise, return the computed style of "background-color" for
-    <var title="">element</var>.
+    <var title="">node</var>.
   </ol>
 
-  <li>Return the computed style of <var title="">property</var> for <var title="">element</var>.
+  <li>Return the computed style of <var title="">property</var> for <var title="">node</var>.
 </ol>
 
 <p>The <dfn id=specified-style>specified style</dfn> of an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> for a given
@@ -492,13 +501,8 @@
   <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 not an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a>, abort this
   algorithm. <!-- E.g., a text node child of a document fragment. -->
 
-  <li>If <var title="">node</var> is an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> and the <a href=#effective-style>effective style</a>
-  of <var title="">property</var> is <var title="">new value</var> on <var title="">node</var>, abort this
-  algorithm.
-
-  <li>If <var title="">node</var> is not an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> and the <a href=#effective-style>effective
-  style</a> of <var title="">property</var> is <var title="">new value</var> on
-  <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>, abort this algorithm.
+  <li>If the <a href=#effective-style>effective style</a> of <var title="">property</var> is <var title="">new
+  value</var> on <var title="">node</var>, abort this algorithm.
 
   <li>Let <var title="">current ancestor</var> be <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>.
 
@@ -659,14 +663,8 @@
     this algorithm.
   </ol>
 
-  <li>If <var title="">node</var> is an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> and the <a href=#effective-style>effective style</a>
-  of <var title="">property</var> is <var title="">new value</var> on <var title="">node</var>, abort this
-  algorithm.
-
-  <li>If <var title="">node</var> is not an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a>, <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=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a>, and the <a href=#effective-style>effective style</a> of <var title="">property</var>
-  is <var title="">new value</var> on <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>, abort this
-  algorithm.
+  <li>If the <a href=#effective-style>effective style</a> of <var title="">property</var> is <var title="">new
+  value</var> on <var title="">node</var>, abort this algorithm.
 
   <li>If <var title="">node</var> is an <a href=#unwrappable-element>unwrappable element</a>:
 
@@ -687,14 +685,8 @@
   <li>If <var title="">node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#comment><code class=external data-anolis-spec=domcore>Comment</code></a> or <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#processinginstruction><code class=external data-anolis-spec=domcore>ProcessingInstruction</code></a>, abort
   this algorithm.
 
-  <li>If <var title="">node</var> is an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> and the <a href=#effective-style>effective style</a>
-  of <var title="">property</var> is <var title="">new value</var> on <var title="">node</var>, abort this
-  algorithm.
-
-  <li>If <var title="">node</var> is not an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a>, <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=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a>, and the <a href=#effective-style>effective style</a> of <var title="">property</var>
-  is <var title="">new value</var> on <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>, abort this
-  algorithm.
+  <li>If the <a href=#effective-style>effective style</a> of <var title="">property</var> is <var title="">new
+  value</var> on <var title="">node</var>, abort this algorithm.
 
   <li>If <var title="">property</var> is "font-weight" and <var title="">new value</var> is
   "bold", let <var title="">tag</var> be "b".
@@ -937,14 +929,12 @@
 <dd><p><strong>Action</strong>: <a href=#decompose>Decompose</a> the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a>.  If the
 state of the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> for this command is then true, <a href=#style>style</a> each
 returned <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> with <var title="">property</var> "font-weight" and <var title="">new
-value</var> "bold".  Otherwise, <a href=#style>style</a> them with <var title="">new
-value</var> "normal".
+value</var> "normal".  Otherwise, <a href=#style>style</a> them with <var title="">new
+value</var> "bold".
 
-<dd><p><strong>State</strong>: True if every <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> that is
-<a href=#effectively-contained>effectively contained</a> in the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> has computed font-weight at
-least 700, and the <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> of every <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node that is <a href=#effectively-contained>effectively
-contained</a> in the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> has computed font-weight at least 700.
-Otherwise false.
+<dd><p><strong>State</strong>: True if every <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> that is <a href=#effectively-contained>effectively
+contained</a> in the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> has <a href=#effective-style>effective style</a> either null
+or at least 700 for font-weight.  Otherwise false.
 
 <dd><p><strong>Value</strong>: Always the empty string.
 <!-- We have lots of options here (and presumably for all the others where
@@ -1173,18 +1163,32 @@
 <dd><p><strong>Action</strong>: <a href=#decompose>Decompose</a> the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a>.  If the
 state of the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> for this command is then true, <a href=#style>style</a> each
 returned <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> with <var title="">property</var> "font-style" and <var title="">new
-value</var> "italic".  Otherwise, <a href=#style>style</a> them with <var title="">new
-value</var> "normal".
+value</var> "normal".  Otherwise, <a href=#style>style</a> them with <var title="">new
+value</var> "italic".
 
-<dd><p><strong>State</strong>: True if every <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> that is
-<a href=#effectively-contained>effectively contained</a> in the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> has computed font-style
-"italic" or "oblique", and the <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> of every <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node that is
-<a href=#effectively-contained>effectively contained</a> in the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> has computed font-style
-"italic" or "oblique".  Otherwise false.
+<dd><p><strong>State</strong>: True if every <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> that is <a href=#effectively-contained>effectively
+contained</a> in the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> has <a href=#effective-style>effective style</a> either null,
+"italic", or "oblique" for font-style.  Otherwise false.
 
 <dd><p><strong>Value</strong>: Always the empty string.
 
 
+<dt><code title=""><dfn id=command-underline title=command-underline>underline</dfn></code>
+
+<dd><p><strong>Action</strong>: <a href=#decompose>Decompose</a> the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a>.  If the
+state of the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> for this command is then true, <a href=#style>style</a> each
+returned <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> with <var title="">property</var> "text-decoration" and <var title="">new
+value</var> "none".  Otherwise, <a href=#style>style</a> them with <var title="">new
+value</var> "underline".
+
+<dd><p><strong>State</strong>: True if every <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> that is <a href=#effectively-contained>effectively
+contained</a> in the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> has <a href=#effective-style>effective style</a> either null
+or "underline" for text-decoration.  Otherwise false.
+
+<dd><p><strong>Value</strong>: Always the empty string.
+</dl>
+
+
 <dt><code title=""><dfn id=command-unlink title=command-unlink>unlink</dfn></code>
 
 <dd><p><strong>Action</strong>: The user agent must execute the following
@@ -1232,18 +1236,6 @@
 <dd><p><strong>Value</strong>: Always the empty string.
 
 
-<dt><code title=""><dfn id=command-underline title=command-underline>underline</dfn></code>
-
-<dd class=XXX><p><strong>Action</strong>: ???  This is totally unreasonable,
-because CSS text-decoration is a nightmare.  Styling is easy, unstyling is only
-possible through massive hacks.
-
-<dd class=XXX><p><strong>State</strong>: ...
-
-<dd><p><strong>Value</strong>: Always the empty string.
-</dl>
-
-
 <h2 class=no-num id=references>References</h2><!--REFS-->
 <p>All references are normative unless marked "Non-normative".</p>
 <div id=anolis-references><dl></dl></div>
--- a/implementation.js	Mon Mar 21 14:08:35 2011 -0600
+++ b/implementation.js	Mon Mar 21 14:27:53 2011 -0600
@@ -272,50 +272,68 @@
 /**
  * "effective style" per edit command spec
  */
-function getEffectiveStyle(element, property) {
+function getEffectiveStyle(node, property) {
+	// "If node is neither an Element nor a Text node, return null."
+	if (node.nodeType != Node.ELEMENT_NODE
+	&& node.nodeType != Node.TEXT_NODE) {
+		return null;
+	}
+
+	// "If node is a Text node and its parent is null, return null."
+	if (node.nodeType == Node.TEXT_NODE
+	&& !node.parentNode) {
+		return null;
+	}
+
+	// "If node is a Text node, return the effective style of its parent for
+	// property."
+	if (node.nodeType == Node.TEXT_NODE) {
+		return getEffectiveStyle(node.parentNode, property);
+	}
+
 	// "If property is "text-decoration", and the "text-decoration" property of
-	// element or any of its ancestors computes to "underline", return
+	// node or any of its ancestors computes to "underline", return
 	// "underline". Otherwise, return "none"."
 	if (property == "textDecoration") {
 		do {
-			if (getComputedStyle(element).textDecoration == "underline") {
+			if (getComputedStyle(node).textDecoration == "underline") {
 				return "underline";
 			}
-			element = element.parentNode;
-		} while (element && element.nodeType == Node.ELEMENT_NODE);
+			node = node.parentNode;
+		} while (node && node.nodeType == Node.ELEMENT_NODE);
 		return "none";
 	}
 
 	// "If property is "background-color":"
 	if (property == "backgroundColor") {
-		// "While the computed style of "background-color" on element is any
-		// fully transparent value, and element's parent is an Element, set
-		// element to its parent."
+		// "While the computed style of "background-color" on node is any
+		// fully transparent value, and node's parent is an Element, set
+		// node to its parent."
 		//
 		// Another lame hack to avoid flawed APIs.
-		while ((getComputedStyle(element).backgroundColor == "rgba(0, 0, 0, 0)"
-		|| getComputedStyle(element).backgroundColor === ""
-		|| getComputedStyle(element).backgroundColor == "transparent")
-		&& element.parentNode
-		&& element.parentNode.nodeType == Node.ELEMENT_NODE) {
-			element = element.parentNode;
+		while ((getComputedStyle(node).backgroundColor == "rgba(0, 0, 0, 0)"
+		|| getComputedStyle(node).backgroundColor === ""
+		|| getComputedStyle(node).backgroundColor == "transparent")
+		&& node.parentNode
+		&& node.parentNode.nodeType == Node.ELEMENT_NODE) {
+			node = node.parentNode;
 		}
 
-		// "If the computed style of "background-color" on element is a fully
+		// "If the computed style of "background-color" on node is a fully
 		// transparent value, return "rgb(255, 255, 255)"."
-		if (getComputedStyle(element).backgroundColor == "rgba(0, 0, 0, 0)"
-        || getComputedStyle(element).backgroundColor === ""
-        || getComputedStyle(element).backgroundColor == "transparent") {
+		if (getComputedStyle(node).backgroundColor == "rgba(0, 0, 0, 0)"
+        || getComputedStyle(node).backgroundColor === ""
+        || getComputedStyle(node).backgroundColor == "transparent") {
 			return "rgb(255, 255, 255)";
 		}
 
 		// "Otherwise, return the computed style of "background-color" for
-		// element."
-		return getComputedStyle(element).backgroundColor;
+		// node."
+		return getComputedStyle(node).backgroundColor;
 	}
 
-	// "Return the computed style of property for element."
-	return getComputedStyle(element)[property];
+	// "Return the computed style of property for node."
+	return getComputedStyle(node)[property];
 }
 
 /**
@@ -646,17 +664,9 @@
 		return;
 	}
 
-	// "If node is an Element and the effective style of property is new value
-	// on node, abort this algorithm."
-	if (node.nodeType == Node.ELEMENT_NODE
-	&& cssValuesEqual(property, getEffectiveStyle(node, property), newValue)) {
-		return;
-	}
-
-	// "If node is not an Element and the effective style of property is new
-	// value on node's parent, abort this algorithm."
-	if (node.nodeType != Node.ELEMENT_NODE
-	&& cssValuesEqual(property, getEffectiveStyle(node.parentNode, property), newValue)) {
+	// "If the effective style of property is new value on node, abort this
+	// algorithm."
+	if (cssValuesEqual(property, getEffectiveStyle(node, property), newValue)) {
 		return;
 	}
 
@@ -782,19 +792,9 @@
 		}
 	}
 
-	// "If node is an Element and the effective style of property is new value
-	// on node, abort this algorithm."
-	if (node.nodeType == Node.ELEMENT_NODE
-	&& cssValuesEqual(property, getEffectiveStyle(node, property), newValue)) {
-		return;
-	}
-
-	// "If node is not an Element, node's parent is an Element, and the
-	// effective style of property is new value on node's parent, abort this
+	// "If the effective style of property is new value on node, abort this
 	// algorithm."
-	if (node.nodeType != Node.ELEMENT_NODE
-	&& node.parentNode.nodeType == Node.ELEMENT_NODE
-	&& cssValuesEqual(property, getEffectiveStyle(node.parentNode, property), newValue)) {
+	if (cssValuesEqual(property, getEffectiveStyle(node, property), newValue)) {
 		return;
 	}
 
@@ -832,19 +832,9 @@
 		return;
 	}
 
-	// "If node is an Element and the effective style of property is new value
-	// on node, abort this algorithm."
-	if (node.nodeType == Node.ELEMENT_NODE
-	&& cssValuesEqual(property, getEffectiveStyle(node, property), newValue)) {
-		return;
-	}
-
-	// "If node is not an Element, node's parent is an Element, and the
-	// effective style of property is new value on node's parent, abort this
+	// "If the effective style of property is new value on node, abort this
 	// algorithm."
-	if (node.nodeType != Node.ELEMENT_NODE
-	&& node.parentNode.nodeType == Node.ELEMENT_NODE
-	&& cssValuesEqual(property, getEffectiveStyle(node.parentNode, property), newValue)) {
+	if (cssValuesEqual(property, getEffectiveStyle(node, property), newValue)) {
 		return;
 	}
 
@@ -977,7 +967,7 @@
 		case "bold":
 		// "Decompose the Range. If the state of the Range for this command is
 		// then true, style each returned Node with property "font-weight" and
-		// new value "bold". Otherwise, style them with new value "normal"."
+		// new value "normal". Otherwise, style them with new value "bold"."
 		var nodeList = decomposeRange(range);
 		var newValue = getState("bold", range) ? "normal" : "bold";
 		for (var i = 0; i < nodeList.length; i++) {
@@ -1088,7 +1078,7 @@
 		case "italic":
 		// "Decompose the Range. If the state of the Range for this command is
 		// then true, style each returned Node with property "font-style" and
-		// new value "italic". Otherwise, style them with new value "normal"."
+		// new value "normal". Otherwise, style them with new value "italic"."
 		var nodeList = decomposeRange(range);
 		var newValue = getState("italic", range) ? "normal" : "italic";
 		for (var i = 0; i < nodeList.length; i++) {
@@ -1096,6 +1086,18 @@
 		}
 		break;
 
+		case "underline":
+		// "Decompose the Range. If the state of the Range for this command is
+		// then true, style each returned Node with property "text-decoration"
+		// and new value "none". Otherwise, style them with new value
+		// "underline"."
+		var nodeList = decomposeRange(range);
+		var newValue = getState("underline", range) ? "none" : "underline";
+		for (var i = 0; i < nodeList.length; i++) {
+			styleNode(nodeList[i], "textDecoration", newValue);
+		}
+		break;
+
 		default:
 		break;
 	}
@@ -1126,38 +1128,34 @@
 			continue;
 		}
 
-		var element;
-		if (node.nodeType == Node.TEXT_NODE) {
-			element = node.parentNode;
-		} else {
-			element = node;
-		}
-
-		if (element.nodeType != Node.ELEMENT_NODE) {
-			continue;
-		}
-
-		var style = getComputedStyle(element);
-
 		if (commandId == "bold") {
-			// "True if every Element that is effectively contained in the
-			// Range has computed font-weight at least 700, and the parent of
-			// every Text node that is effectively contained in the Range has
-			// computed font-weight at least 700. Otherwise false."
-			if (style.fontWeight != "bold"
-			&& style.fontWeight != "700"
-			&& style.fontWeight != "800"
-			&& style.fontWeight != "900") {
+			// "True if every Node that is effectively contained in the Range
+			// has effective style either null or at least 700 for font-weight.
+			// Otherwise false."
+			var weight = getEffectiveStyle(node, "fontWeight");
+			if (weight !== null
+			&& weight !== "bold"
+			&& weight !== "700"
+			&& weight !== "800"
+			&& weight !== "900") {
 				return false;
 			}
 		} else if (commandId == "italic") {
-			// "True if every Element that is effectively contained in the
-			// Range has computed font-style "italic" or "oblique", and the
-			// parent of every Text node that is effectively contained in the
-			// Range has computed font-style "italic" or "oblique". Otherwise
-			// false."
-			if (style.fontStyle != "italic"
-			&& style.fontStyle != "oblique") {
+			// "True if every Node that is effectively contained in the Range
+			// has effective style either null, "italic", or "oblique" for
+			// font-style. Otherwise false."
+			var style = getEffectiveStyle(node, "fontStyle");
+			if (style !== null
+			&& style !== "italic"
+			&& style !== "oblique") {
+				return false;
+			}
+		} else if (commandId == "underline") {
+			// "True if every Node that is effectively contained in the Range
+			// has effective style either null or "underline" for
+			// text-decoration. Otherwise false."
+			var decoration = getEffectiveStyle(node, "textDecoration");
+			if (decoration !== null && decoration !== "underline") {
 				return false;
 			}
 		}
--- a/source.html	Mon Mar 21 14:08:35 2011 -0600
+++ b/source.html	Mon Mar 21 14:27:53 2011 -0600
@@ -202,13 +202,22 @@
 not be used where only [[phrasingcontent]] is expected (not counting unknown or
 obsolete elements, which cannot be used at all).
 
-<p>The <dfn>effective style</dfn> of an [[element]] <var>element</var> for a
-given <var>property</var> is returned by the following algorithm, which will
-return a CSS value:
+<p>The <dfn>effective style</dfn> of a [[node]] <var>node</var> for a given
+<var>property</var> is returned by the following algorithm, which will return
+either a CSS value or null:
 
 <ol>
+  <li>If <var>node</var> is neither an [[element]] nor a [[text]] node, return
+  null.
+
+  <li>If <var>node</var> is a [[text]] node and its [[parent]] is null, return
+  null.
+
+  <li>If <var>node</var> is a [[text]] node, return the <span>effective
+  style</span> of its [[parent]] for <var>property</var>.
+
   <li>If <var>property</var> is "text-decoration", and the "text-decoration"
-  property of <var>element</var> or any of its [[ancestors]] computes to
+  property of <var>node</var> or any of its [[ancestors]] computes to
   "underline", return "underline".  Otherwise, return "none".
 
   <p class=XXX>We ignore the possibility of text-decorations other than
@@ -218,18 +227,18 @@
   <li>If <var>property</var> is "background-color":
 
   <ol>
-    <li>While the computed style of "background-color" on <var>element</var> is
-    any fully transparent value, and <var>element</var>'s [[parent]] is an
-    [[element]], set <var>element</var> to its parent.
+    <li>While the computed style of "background-color" on <var>node</var> is
+    any fully transparent value, and <var>node</var>'s [[parent]] is an
+    [[element]], set <var>node</var> to its [[parent]].
 
-    <li>If the computed style of "background-color" on <var>element</var> is
+    <li>If the computed style of "background-color" on <var>node</var> is
     a fully transparent value, return "rgb(255, 255, 255)".
 
     <li>Otherwise, return the computed style of "background-color" for
-    <var>element</var>.
+    <var>node</var>.
   </ol>
 
-  <li>Return the computed style of <var>property</var> for <var>element</var>.
+  <li>Return the computed style of <var>property</var> for <var>node</var>.
 </ol>
 
 <p>The <dfn>specified style</dfn> of an [[element]] for a given
@@ -488,13 +497,8 @@
   <li>If <var>node</var>'s [[parent]] is not an [[element]], abort this
   algorithm. <!-- E.g., a text node child of a document fragment. -->
 
-  <li>If <var>node</var> is an [[element]] and the <span>effective style</span>
-  of <var>property</var> is <var>new value</var> on <var>node</var>, abort this
-  algorithm.
-
-  <li>If <var>node</var> is not an [[element]] and the <span>effective
-  style</span> of <var>property</var> is <var>new value</var> on
-  <var>node</var>'s [[parent]], abort this algorithm.
+  <li>If the <span>effective style</span> of <var>property</var> is <var>new
+  value</var> on <var>node</var>, abort this algorithm.
 
   <li>Let <var>current ancestor</var> be <var>node</var>'s [[parent]].
 
@@ -655,14 +659,8 @@
     this algorithm.
   </ol>
 
-  <li>If <var>node</var> is an [[element]] and the <span>effective style</span>
-  of <var>property</var> is <var>new value</var> on <var>node</var>, abort this
-  algorithm.
-
-  <li>If <var>node</var> is not an [[element]], <var>node</var>'s [[parent]] is
-  an [[element]], and the <span>effective style</span> of <var>property</var>
-  is <var>new value</var> on <var>node</var>'s [[parent]], abort this
-  algorithm.
+  <li>If the <span>effective style</span> of <var>property</var> is <var>new
+  value</var> on <var>node</var>, abort this algorithm.
 
   <li>If <var>node</var> is an <span>unwrappable element</span>:
 
@@ -683,14 +681,8 @@
   <li>If <var>node</var> is a [[comment]] or [[processinginstruction]], abort
   this algorithm.
 
-  <li>If <var>node</var> is an [[element]] and the <span>effective style</span>
-  of <var>property</var> is <var>new value</var> on <var>node</var>, abort this
-  algorithm.
-
-  <li>If <var>node</var> is not an [[element]], <var>node</var>'s [[parent]] is
-  an [[element]], and the <span>effective style</span> of <var>property</var>
-  is <var>new value</var> on <var>node</var>'s [[parent]], abort this
-  algorithm.
+  <li>If the <span>effective style</span> of <var>property</var> is <var>new
+  value</var> on <var>node</var>, abort this algorithm.
 
   <li>If <var>property</var> is "font-weight" and <var>new value</var> is
   "bold", let <var>tag</var> be "b".
@@ -939,14 +931,12 @@
 <dd><p><strong>Action</strong>: <span>Decompose</span> the [[range]].  If the
 state of the [[range]] for this command is then true, <span>style</span> each
 returned [[node]] with <var>property</var> "font-weight" and <var>new
-value</var> "bold".  Otherwise, <span>style</span> them with <var>new
-value</var> "normal".
+value</var> "normal".  Otherwise, <span>style</span> them with <var>new
+value</var> "bold".
 
-<dd><p><strong>State</strong>: True if every [[element]] that is
-<span>effectively contained</span> in the [[range]] has computed font-weight at
-least 700, and the [[parent]] of every [[text]] node that is <span>effectively
-contained</span> in the [[range]] has computed font-weight at least 700.
-Otherwise false.
+<dd><p><strong>State</strong>: True if every [[node]] that is <span>effectively
+contained</span> in the [[range]] has <span>effective style</span> either null
+or at least 700 for font-weight.  Otherwise false.
 
 <dd><p><strong>Value</strong>: Always the empty string.
 <!-- We have lots of options here (and presumably for all the others where
@@ -1185,18 +1175,32 @@
 <dd><p><strong>Action</strong>: <span>Decompose</span> the [[range]].  If the
 state of the [[range]] for this command is then true, <span>style</span> each
 returned [[node]] with <var>property</var> "font-style" and <var>new
-value</var> "italic".  Otherwise, <span>style</span> them with <var>new
-value</var> "normal".
+value</var> "normal".  Otherwise, <span>style</span> them with <var>new
+value</var> "italic".
 
-<dd><p><strong>State</strong>: True if every [[element]] that is
-<span>effectively contained</span> in the [[range]] has computed font-style
-"italic" or "oblique", and the [[parent]] of every [[text]] node that is
-<span>effectively contained</span> in the [[range]] has computed font-style
-"italic" or "oblique".  Otherwise false.
+<dd><p><strong>State</strong>: True if every [[node]] that is <span>effectively
+contained</span> in the [[range]] has <span>effective style</span> either null,
+"italic", or "oblique" for font-style.  Otherwise false.
 
 <dd><p><strong>Value</strong>: Always the empty string.
 
 
+<dt><code title><dfn title=command-underline>underline</dfn></code>
+
+<dd><p><strong>Action</strong>: <span>Decompose</span> the [[range]].  If the
+state of the [[range]] for this command is then true, <span>style</span> each
+returned [[node]] with <var>property</var> "text-decoration" and <var>new
+value</var> "none".  Otherwise, <span>style</span> them with <var>new
+value</var> "underline".
+
+<dd><p><strong>State</strong>: True if every [[node]] that is <span>effectively
+contained</span> in the [[range]] has <span>effective style</span> either null
+or "underline" for text-decoration.  Otherwise false.
+
+<dd><p><strong>Value</strong>: Always the empty string.
+</dl>
+
+
 <dt><code title><dfn title=command-unlink>unlink</dfn></code>
 
 <dd><p><strong>Action</strong>: The user agent must execute the following
@@ -1244,18 +1248,6 @@
 <dd><p><strong>Value</strong>: Always the empty string.
 
 
-<dt><code title><dfn title=command-underline>underline</dfn></code>
-
-<dd class=XXX><p><strong>Action</strong>: ???  This is totally unreasonable,
-because CSS text-decoration is a nightmare.  Styling is easy, unstyling is only
-possible through massive hacks.
-
-<dd class=XXX><p><strong>State</strong>: ...
-
-<dd><p><strong>Value</strong>: Always the empty string.
-</dl>
-
-
 <h2 class=no-num id=references>References</h2><!--REFS-->
 <p>All references are normative unless marked "Non-normative".</p>
 <div id=anolis-references></div>