Define backColor to be same as hiliteColor
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Fri, 08 Jul 2011 11:21:25 -0600
changeset 372 52911b299925
parent 371 e9b08040054c
child 373 00855ed1a269
Define backColor to be same as hiliteColor
editcommands.html
implementation.js
source.html
tests.js
--- a/editcommands.html	Thu Jul 07 14:50:34 2011 -0600
+++ b/editcommands.html	Fri Jul 08 11:21:25 2011 -0600
@@ -38,7 +38,7 @@
 <body class=draft>
 <div class=head id=head>
 <h1>HTML Editing Commands</h1>
-<h2 class="no-num no-toc" id=work-in-progress-&mdash;-last-update-7-july-2011>Work in Progress &mdash; Last Update 7 July 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-&mdash;-last-update-8-july-2011>Work in Progress &mdash; Last Update 8 July 2011</h2>
 <dl>
  <dt>Editor
  <dd>Aryeh Gregor &lt;ayg+spec@aryeh.name&gt;
@@ -471,7 +471,7 @@
 in that it will only run the command if it's enabled, but it doesn't make much
 sense to only have the command run if the start is editable.
 
-It's not clear to me what the point of this command is.  There's no way we're
+It's not clear to me what the point of this method is.  There's no way we're
 going to always return true if the command will do something and false if it
 won't.  I just stuck with a really conservative definition that happens to be
 convenient: if there's nothing selected, obviously nothing will work, and we
@@ -1152,7 +1152,7 @@
     <li>Return the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-attribute-value title=concept-attribute-value>value</a> of <var title="">node</var>'s <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/html/#attr-hyperlink-href>href</a></code> attribute.
   </ol>
 
-  <li>If <var title="">command</var> is "hiliteColor":
+  <li>If <var title="">command</var> is "backColor" or "hiliteColor":
 
   <ol>
     <li>While the <a href=http://www.w3.org/TR/CSS21/cascade.html#computed-value>computed value</a> of "background-color" on <var title="">node</var> is
@@ -1224,8 +1224,8 @@
 different name.
 
 <ol>
-  <li>If <var title="">command</var> is "hiliteColor" and the <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>'s
-  display property does not compute to "inline", return null.
+  <li>If <var title="">command</var> is "backColor" or "hiliteColor" and the
+  <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>'s display property does not compute to "inline", return null.
 
   <li>If <var title="">command</var> is "createLink" or "unlink":
 
@@ -2019,28 +2019,24 @@
 
 <h3 id=the-backcolor-command><span class=secno>7.8 </span><dfn>The <code title="">backColor</code> command</dfn></h3>
 
-<p><a href=#action>Action</a>:
-
-<div class=XXX>
-<p>We have three behaviors to choose from for this one:
-
-<ol>
-  <li>Chrome 11 dev and IE 9 RC treat it the same as hiliteColor (although IE 9
-  RC doesn't support hiliteColor itself).
-
-  <li>Firefox 4 in non-CSS mode sets the bgcolor of the nearest td or body, or
-  something like that.  In testing, it seems to jump out of contenteditable
-  elements to style non-editable ancestors, which is alarming.
-
-  <li>Firefox 4 in CSS mode and Opera 11 set the background of the nearest
-  block container, although it doesn't seem to be very dependable (probably I
-  just don't get what exactlyit's doing).
-</ol>
-
-<p>(1) is obviously redundant, but has plurality support, so we could spec it
-that way if the other ways were useless.
-
-<p>(3) is incoherent from a user perspective.  For instance, if you try it on
+<!--
+We have three behaviors to choose from for this one:
+
+1) Chrome 11 dev and IE 9 RC treat it the same as hiliteColor (although IE 9 RC
+doesn't support hiliteColor itself).
+
+2) Firefox 4 in non-CSS mode sets the bgcolor of the nearest td or body, or
+something like that.  In testing, it seems to jump out of contenteditable
+elements to style non-editable ancestors, which is alarming.
+
+3) Firefox 4 in CSS mode and Opera 11 set the background of the nearest block
+container, although it doesn't seem to be very dependable (probably I just
+don't get what exactlyit's doing).
+
+(1) is obviously redundant, but has plurality support, so we could spec it that
+way if the other ways were useless.
+
+(3) is incoherent from a user perspective.  For instance, if you try it on
 paragraphs the background will have big gaps where the margins are.  If you try
 it on an inline element that's a child of the editing host, it will do nothing
 or apply the background to everything or such, even though such an inline
@@ -2049,15 +2045,38 @@
 elements all have no margins, or if we wrap things in a div if they have
 margins, or something like that.
 
-<p>That leaves (2).  That might be useful if it actually set the document's
+That leaves (2).  That might be useful if it actually set the document's
 background color, but it seems like it sets table cell backgrounds sometimes
 instead, which is really confusing.
 
-<p>The path of least resistance seems to be to standardize this as meaning the
-same thing as hiliteColor, and make up new commands if we want to do things
-like set the document background color.  Feedback appreciated on this point.
-</div>
-
+The path of least resistance is to standardize this as meaning the same thing
+as hiliteColor, and make up new commands if we want to do things like set the
+document background color.  See hiliteColor for comments.
+-->
+<p><a href=#action>Action</a>:
+
+<ol>
+  <li>If <var title="">value</var> is not a valid CSS color, prepend "#" to it.
+
+  <li>If <var title="">value</var> is still not a valid CSS color, or if it is
+  currentColor, raise a <code class=external data-anolis-spec=domcore title=dom-DOMException-SYNTAX_ERR><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-syntax_err>SYNTAX_ERR</a></code> exception.
+
+  <li><a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>, then <a href=#set-the-value>set the
+  value</a> of each returned <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> to <var title="">value</var>.
+</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-value title="effective
+value">effective values</a>.  Otherwise false.
+
+<p><a href=#value>Value</a>: The <a href=#effective-value>effective 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>This 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=#relevant-css-property>Relevant CSS property</a>: "background-color"
 
 
 <h3 id=the-bold-command><span class=secno>7.9 </span><dfn>The <code title="">bold</code> command</dfn></h3>
--- a/implementation.js	Thu Jul 07 14:50:34 2011 -0600
+++ b/implementation.js	Fri Jul 08 11:21:25 2011 -0600
@@ -1560,8 +1560,9 @@
 		return node.getAttribute("href");
 	}
 
-	// "If command is "hiliteColor":"
-	if (command == "hilitecolor") {
+	// "If command is "backColor" or "hiliteColor":"
+	if (command == "backcolor"
+	|| command == "hilitecolor") {
 		// "While the computed value of "background-color" on node is any
 		// fully transparent value, and node's parent is an Element, set
 		// node to its parent."
@@ -1669,9 +1670,9 @@
 }
 
 function getSpecifiedValue(element, command) {
-	// "If command is "hiliteColor" and element's display property does not
-	// compute to "inline", return null."
-	if (command == "hilitecolor"
+	// "If command is "backColor" or "hiliteColor" and element's display
+	// property does not compute to "inline", return null."
+	if ((command == "backcolor" || command == "hilitecolor")
 	&& getComputedStyle(element).display != "inline") {
 		return null;
 	}
@@ -2506,8 +2507,61 @@
 //@}
 
 ///// The backColor command /////
-// Unimplemented
-//commands.backcolor = {};
+//@{
+commands.backcolor = {
+	// Copy-pasted, same as hiliteColor
+	action: function(value) {
+		// "If value is not a valid CSS color, prepend "#" to it."
+		//
+		// "If value is still not a valid CSS color, or if it is currentColor,
+		// raise a SYNTAX_ERR exception."
+		//
+		// Cheap hack for testing, no attempt to be comprehensive.
+		if (/^([0-9a-fA-F]{3}){1,2}$/.test(value)) {
+			value = "#" + value;
+		}
+		if (!/^#([0-9a-fA-F]{3}){1,2}$/.test(value)
+		&& !/^(rgba?|hsla?)\(.*\)$/.test(value)
+		// Not gonna list all the keywords, only the ones I use.
+		&& value != "red"
+		&& value != "cornsilk"
+		&& value != "transparent") {
+			throw "SYNTAX_ERR";
+		}
+
+		// "Decompose the active range, then set the value of each returned
+		// node to value."
+		var nodeList = decomposeRange(getActiveRange());
+		for (var i = 0; i < nodeList.length; i++) {
+			setNodeValue(nodeList[i], "backcolor", value);
+		}
+	}, indeterm: function() {
+		// "True if among editable Text nodes that are effectively contained in
+		// the active range, there are two that have distinct effective values.
+		// Otherwise false."
+		return getAllEffectivelyContainedNodes(getActiveRange(), function(node) {
+			return isEditable(node) && node.nodeType == Node.TEXT_NODE;
+		}).map(function(node) {
+			return getEffectiveValue(node, "backcolor");
+		}).filter(function(value, i, arr) {
+			return arr.slice(0, i).indexOf(value) == -1;
+		}).length >= 2;
+	}, value: function() {
+		// "The effective 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 computed value stuff is underdefined
+		// anyway).
+		var value = getEffectiveValue(getActiveRange().startContainer, "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"
+};
+//@}
 
 ///// The bold command /////
 //@{
@@ -2871,6 +2925,9 @@
 };
 //@}
 
+// "The backColor command must behave identically to the hiliteColor command."
+commands.backcolor = commands.hilitecolor;
+
 ///// The italic command /////
 //@{
 commands.italic = {
--- a/source.html	Thu Jul 07 14:50:34 2011 -0600
+++ b/source.html	Fri Jul 08 11:21:25 2011 -0600
@@ -409,7 +409,7 @@
 in that it will only run the command if it's enabled, but it doesn't make much
 sense to only have the command run if the start is editable.
 
-It's not clear to me what the point of this command is.  There's no way we're
+It's not clear to me what the point of this method is.  There's no way we're
 going to always return true if the command will do something and false if it
 won't.  I just stuck with a really conservative definition that happens to be
 convenient: if there's nothing selected, obviously nothing will work, and we
@@ -1107,7 +1107,7 @@
     <li>Return the [[attrvalue]] of <var>node</var>'s [[href]] attribute.
   </ol>
 
-  <li>If <var>command</var> is "hiliteColor":
+  <li>If <var>command</var> is "backColor" or "hiliteColor":
 
   <ol>
     <li>While the [[compval]] of "background-color" on <var>node</var> is
@@ -1179,8 +1179,8 @@
 different name.
 
 <ol>
-  <li>If <var>command</var> is "hiliteColor" and the [[element]]'s
-  display property does not compute to "inline", return null.
+  <li>If <var>command</var> is "backColor" or "hiliteColor" and the
+  [[element]]'s display property does not compute to "inline", return null.
 
   <li>If <var>command</var> is "createLink" or "unlink":
 
@@ -1996,28 +1996,24 @@
 
 <h3><dfn>The <code title>backColor</code> command</dfn></h3>
 <!-- @{ -->
-<p><span>Action</span>:
-
-<div class=XXX>
-<p>We have three behaviors to choose from for this one:
-
-<ol>
-  <li>Chrome 11 dev and IE 9 RC treat it the same as hiliteColor (although IE 9
-  RC doesn't support hiliteColor itself).
-
-  <li>Firefox 4 in non-CSS mode sets the bgcolor of the nearest td or body, or
-  something like that.  In testing, it seems to jump out of contenteditable
-  elements to style non-editable ancestors, which is alarming.
-
-  <li>Firefox 4 in CSS mode and Opera 11 set the background of the nearest
-  block container, although it doesn't seem to be very dependable (probably I
-  just don't get what exactlyit's doing).
-</ol>
-
-<p>(1) is obviously redundant, but has plurality support, so we could spec it
-that way if the other ways were useless.
-
-<p>(3) is incoherent from a user perspective.  For instance, if you try it on
+<!--
+We have three behaviors to choose from for this one:
+
+1) Chrome 11 dev and IE 9 RC treat it the same as hiliteColor (although IE 9 RC
+doesn't support hiliteColor itself).
+
+2) Firefox 4 in non-CSS mode sets the bgcolor of the nearest td or body, or
+something like that.  In testing, it seems to jump out of contenteditable
+elements to style non-editable ancestors, which is alarming.
+
+3) Firefox 4 in CSS mode and Opera 11 set the background of the nearest block
+container, although it doesn't seem to be very dependable (probably I just
+don't get what exactlyit's doing).
+
+(1) is obviously redundant, but has plurality support, so we could spec it that
+way if the other ways were useless.
+
+(3) is incoherent from a user perspective.  For instance, if you try it on
 paragraphs the background will have big gaps where the margins are.  If you try
 it on an inline element that's a child of the editing host, it will do nothing
 or apply the background to everything or such, even though such an inline
@@ -2026,15 +2022,38 @@
 elements all have no margins, or if we wrap things in a div if they have
 margins, or something like that.
 
-<p>That leaves (2).  That might be useful if it actually set the document's
+That leaves (2).  That might be useful if it actually set the document's
 background color, but it seems like it sets table cell backgrounds sometimes
 instead, which is really confusing.
 
-<p>The path of least resistance seems to be to standardize this as meaning the
-same thing as hiliteColor, and make up new commands if we want to do things
-like set the document background color.  Feedback appreciated on this point.
-</div>
-</dl>
+The path of least resistance is to standardize this as meaning the same thing
+as hiliteColor, and make up new commands if we want to do things like set the
+document background color.  See hiliteColor for comments.
+-->
+<p><span>Action</span>:
+
+<ol>
+  <li>If <var>value</var> is not a valid CSS color, prepend "#" to it.
+
+  <li>If <var>value</var> is still not a valid CSS color, or if it is
+  currentColor, raise a [[SYNTAX_ERR]] exception.
+
+  <li><span>Decompose</span> the <span>active range</span>, then <span>set the
+  value</span> of each returned [[node]] to <var>value</var>.
+</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
+value">effective values</span>.  Otherwise false.
+
+<p><span>Value</span>: The <span>effective value</span> of the <span>active
+range</span>'s [[startnode]].
+
+<p class=note>This 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>Relevant CSS property</span>: "background-color"
 <!-- @} -->
 
 <h3><dfn>The <code title>bold</code> command</dfn></h3>
--- a/tests.js	Thu Jul 07 14:50:34 2011 -0600
+++ b/tests.js	Fri Jul 08 11:21:25 2011 -0600
@@ -75,25 +75,7 @@
 // Now for the meat of the file.
 var tests = {
 	backcolor: [
-	//@{
-		'foo[]bar',
-		'<span>foo</span>{}<span>bar</span>',
-		'<span>foo[</span><span>]bar</span>',
-		'<p>foo[bar]baz',
-		'<p>foo]bar[baz',
-		'<div><p>foo[bar]baz</p></div>',
-
-		'<table><tbody><tr><td>foo<td>b[a]r<td>baz</table>',
-		'<table><tbody><tr data-start=1 data-end=2><td>foo<td>bar<td>baz</table>',
-		'<table><tbody><tr data-start=0 data-end=2><td>foo<td>bar<td>baz</table>',
-		'<table><tbody data-start=0 data-end=1><tr><td>foo<td>bar<td>baz</table>',
-		'<table data-start=0 data-end=1><tbody><tr><td>foo<td>bar<td>baz</table>',
-		'{<table><tr><td>foo<td>bar<td>baz</table>}',
-
-		'{<p><p> <p>foo</p>}',
-		'{<p>foo</p><p>bar</p>}',
-		'<p>[foo</p><p>bar]</p>',
-		'<p>foo[bar<i>baz]qoz</i>quz',
+	//@{ Same as hilitecolor (set below)
 	],
 	//@}
 	bold: [
@@ -1659,7 +1641,7 @@
 	],
 	//@}
 	insertlinebreak: [
-	//@{ Just the same as insertparagraph (set below).
+	//@{ Same as insertparagraph (set below)
 	],
 	//@}
 	insertorderedlist: [
@@ -3273,6 +3255,7 @@
 	usecss: ['foo[bar]baz'],
 	quasit: ['foo[bar]baz'],
 };
+tests.backcolor = tests.hilitecolor;
 tests.insertlinebreak = tests.insertparagraph;
 
 var defaultValues = {