Spec queryCommandEnabled()
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Mon, 27 Jun 2011 15:19:45 -0600
changeset 326 96c10e10a216
parent 325 13272d002cb2
child 327 1458537e4a06
Spec queryCommandEnabled()

Not sure if it's good, as noted in comments.
editcommands.html
implementation.js
source.html
tests.js
--- a/editcommands.html	Mon Jun 27 14:27:27 2011 -0600
+++ b/editcommands.html	Mon Jun 27 15:19:45 2011 -0600
@@ -330,10 +330,9 @@
 and <var title="">value</var> parameters, even if specified, are ignored except where
 otherwise stated.
 
-<p>The <dfn id=querycommandenabled() title=queryCommandEnabled()><code>queryCommandEnabled(<var title="">command</var>)</code></dfn>
-method on the <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/html/#htmldocument>HTMLDocument</a></code> interface allows
-scripts to ask whether calling <code><a href=#execcommand()>execCommand()</a></code> would have any
-effect.
+<p class=XXX>The <dfn id=querycommandenabled() title=queryCommandEnabled()><code>queryCommandEnabled(<var title="">command</var>)</code></dfn>
+method on the <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/html/#htmldocument>HTMLDocument</a></code> interface does
+the same thing as <code><a href=#querycommandsupported()>queryCommandSupported()</a></code>.
 
 <p class=XXX>The <dfn id=querycommandindeterm() title=queryCommandIndeterm()><code>queryCommandIndeterm(<var title="">command</var>)</code></dfn>
 method on the <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/html/#htmldocument>HTMLDocument</a></code> interface is a
@@ -361,12 +360,11 @@
 specification.
 
 <p><a href=#command title=command>Commands</a> may have an associated
-<dfn id=action>action</dfn>, <dfn id=enabled-flag>enabled flag</dfn>, <dfn id=indeterminate-flag>indeterminate flag</dfn>,
-<dfn id=state>state</dfn>, <dfn id=value>value</dfn>, and/or <dfn id=relevant-css-property>relevant CSS property</dfn>.
-If not otherwise specified, the <a href=#action>action</a> for a <a href=#command>command</a>
-is to do nothing, the <a href=#enabled-flag>enabled flag</a> is true, the
-<a href=#indeterminate-flag>indeterminate flag</a> is false, the <a href=#state>state</a> is false, the
-<a href=#value>value</a> is the empty string, and the <a href=#relevant-css-property>relevant CSS
+<dfn id=action>action</dfn>, <dfn id=indeterminate-flag>indeterminate flag</dfn>, <dfn id=state>state</dfn>,
+<dfn id=value>value</dfn>, and/or <dfn id=relevant-css-property>relevant CSS property</dfn>.  If not otherwise
+specified, the <a href=#action>action</a> for a <a href=#command>command</a> is to do nothing,
+the <a href=#indeterminate-flag>indeterminate flag</a> is false, the <a href=#state>state</a> is false,
+the <a href=#value>value</a> is the empty string, and the <a href=#relevant-css-property>relevant CSS
 property</a> is null.
 <!--
 Requesting the state of an unknown command throws an exception in IE 9 RC and
@@ -391,7 +389,35 @@
 instructions as arguments.
 
 <p>When <code><a href=#querycommandenabled()>queryCommandEnabled()</a></code> is invoked, the user agent must
-return the <a href=#enabled-flag>enabled flag</a> for <var title="">command</var>.
+return the result of calling <code><a href=#querycommandsupported()>queryCommandSupported()</a></code> with the same
+arguments.
+
+<p class=XXX>This isn't how anyone behaves, but no one's behavior is very
+useful anyway.  For this to make sense would require a significant amount of
+work and it's not clear it's worth it at all.  See comment for details.
+<!--
+Testing with bold and formatBlock:
+
+IE9 seems to return false if there's no selection or it's entirely outside
+anything editable, but true if any part of the selection descends from anything
+editable, even if it's fully contained in something non-editable (provided it
+descends from something editable).
+
+Firefox 6.0a2 seems to always return true if there's anything editable on the
+page, and throw otherwise.  Opera 11.11 seems to always return true if there's
+anything editable on the page, and false otherwise.  Neither behavior makes
+much sense.
+
+Chrome 14 dev seems to do something like return true if every node effectively
+contained in the selection is editable, false otherwise.  This makes the most
+sense, but it's too narrow for us, because we take some action in many cases
+even if there's some non-editable stuff around.
+
+What we really want this to do is return true if we'd do something when you run
+the command, false otherwise.  This will actually vary by command, and is
+nontrivial, and I'm not sure what the use-case is.  So for now I'll go with
+Opera, but I'll return to it later.
+-->
 
 <p>When <code><a href=#querycommandindeterm()>queryCommandIndeterm()</a></code> is invoked, the user agent must
 return the <a href=#indeterminate-flag>indeterminate flag</a> for <var title="">command</var>.
--- a/implementation.js	Mon Jun 27 14:27:27 2011 -0600
+++ b/implementation.js	Mon Jun 27 15:19:45 2011 -0600
@@ -515,7 +515,7 @@
 
 	// "If the active range is null, all commands must behave as though they
 	// were not defined except those in the miscellaneous commands section."
-	if (!globalRange && command != "selectall" && command != "stylewithcss" && command != "usecss") {
+	if (!globalRange && ["copy", "cut", "paste", "selectall", "stylewithcss", "usecss"].indexOf(command) == -1) {
 		return false;
 	}
 
@@ -532,20 +532,13 @@
 	if (setupEditCommandMethod(command, range)) {
 		commands[command].action(value);
 	}
-
-	globalRange = null;
+	// else do nothing
 }
 
 function myQueryCommandEnabled(command, range) {
-	command = command.toLowerCase();
-
-	if (setupEditCommandMethod(command, range)) {
-		return commands[command].enabled();
-	} else {
-		return false;
-	}
-
-	globalRange = null;
+	// "When queryCommandEnabled() is invoked, the user agent must return the
+	// result of calling queryCommandSupported() with the same arguments."
+	return myQueryCommandSupported(command, range);
 }
 
 function myQueryCommandIndeterm(command, range) {
@@ -554,10 +547,11 @@
 	if (setupEditCommandMethod(command, range)) {
 		return commands[command].indeterm();
 	} else {
+		// "If not otherwise specified, the action for a command is to do
+		// nothing, the indeterminate flag is false, the state is false, the
+		// value is the empty string, and the relevant CSS property is null."
 		return false;
 	}
-
-	globalRange = null;
 }
 
 function myQueryCommandState(command, range) {
@@ -567,12 +561,15 @@
 		return commands[command].state();
 	} else {
 		// "If not otherwise specified, the action for a command is to do
-		// nothing, the state is false, the value is the empty string, and the
-		// relevant CSS property is null."
+		// nothing, the indeterminate flag is false, the state is false, the
+		// value is the empty string, and the relevant CSS property is null."
 		return false;
 	}
-
-	globalRange = null;
+}
+
+function myQueryCommandSupported(command, range) {
+	command = command.toLowerCase();
+	return setupEditCommandMethod(command, range);
 }
 
 function myQueryCommandValue(command, range) {
@@ -582,12 +579,10 @@
 		return commands[command].value();
 	} else {
 		// "If not otherwise specified, the action for a command is to do
-		// nothing, the state is false, the value is the empty string, and the
-		// relevant CSS property is null."
+		// nothing, the indeterminate flag is false, the state is false, the
+		// value is the empty string, and the relevant CSS property is null."
 		return "";
 	}
-
-	globalRange = null;
 }
 
 /**
@@ -6441,10 +6436,11 @@
 
 // Done with command setup
 
-// "Commands may have an associated action, state, value, and/or relevant CSS
-// property. If not otherwise specified, the action for a command is to do
-// nothing, the state is false, the value is the empty string, and the relevant
-// CSS property is null."
+// "Commands may have an associated action, indeterminate flag, state, value,
+// and/or relevant CSS property. If not otherwise specified, the action for a
+// command is to do nothing, the indeterminate flag is false, the state is
+// false, the value is the empty string, and the relevant CSS property is
+// null."
 //
 // Don't dump the "command" variable into the global scope, it can cause bugs
 // because we have lots of local "command"s.
@@ -6453,9 +6449,6 @@
 		if (!("action" in commands[command])) {
 			commands[command].action = function() {};
 		}
-		if (!("enabled" in commands[command])) {
-			commands[command].enabled = function() { return true };
-		}
 		if (!("indeterm" in commands[command])) {
 			commands[command].indeterm = function() { return false };
 		}
--- a/source.html	Mon Jun 27 14:27:27 2011 -0600
+++ b/source.html	Mon Jun 27 15:19:45 2011 -0600
@@ -264,11 +264,10 @@
 and <var>value</var> parameters, even if specified, are ignored except where
 otherwise stated.
 
-<p>The <dfn
+<p class=XXX>The <dfn
 title=queryCommandEnabled()><code>queryCommandEnabled(<var>command</var>)</code></dfn>
-method on the <code data-anolis-spec=html>HTMLDocument</code> interface allows
-scripts to ask whether calling <code>execCommand()</code> would have any
-effect.
+method on the <code data-anolis-spec=html>HTMLDocument</code> interface does
+the same thing as <code>queryCommandSupported()</code>.
 
 <p class=XXX>The <dfn
 title=queryCommandIndeterm()><code>queryCommandIndeterm(<var>command</var>)</code></dfn>
@@ -301,12 +300,11 @@
 specification.
 
 <p><span title=command>Commands</span> may have an associated
-<dfn>action</dfn>, <dfn>enabled flag</dfn>, <dfn>indeterminate flag</dfn>,
-<dfn>state</dfn>, <dfn>value</dfn>, and/or <dfn>relevant CSS property</dfn>.
-If not otherwise specified, the <span>action</span> for a <span>command</span>
-is to do nothing, the <span>enabled flag</span> is true, the
-<span>indeterminate flag</span> is false, the <span>state</span> is false, the
-<span>value</span> is the empty string, and the <span>relevant CSS
+<dfn>action</dfn>, <dfn>indeterminate flag</dfn>, <dfn>state</dfn>,
+<dfn>value</dfn>, and/or <dfn>relevant CSS property</dfn>.  If not otherwise
+specified, the <span>action</span> for a <span>command</span> is to do nothing,
+the <span>indeterminate flag</span> is false, the <span>state</span> is false,
+the <span>value</span> is the empty string, and the <span>relevant CSS
 property</span> is null.
 <!--
 Requesting the state of an unknown command throws an exception in IE 9 RC and
@@ -331,7 +329,35 @@
 instructions as arguments.
 
 <p>When <code>queryCommandEnabled()</code> is invoked, the user agent must
-return the <span>enabled flag</span> for <var>command</var>.
+return the result of calling <code>queryCommandSupported()</code> with the same
+arguments.
+
+<p class=XXX>This isn't how anyone behaves, but no one's behavior is very
+useful anyway.  For this to make sense would require a significant amount of
+work and it's not clear it's worth it at all.  See comment for details.
+<!--
+Testing with bold and formatBlock:
+
+IE9 seems to return false if there's no selection or it's entirely outside
+anything editable, but true if any part of the selection descends from anything
+editable, even if it's fully contained in something non-editable (provided it
+descends from something editable).
+
+Firefox 6.0a2 seems to always return true if there's anything editable on the
+page, and throw otherwise.  Opera 11.11 seems to always return true if there's
+anything editable on the page, and false otherwise.  Neither behavior makes
+much sense.
+
+Chrome 14 dev seems to do something like return true if every node effectively
+contained in the selection is editable, false otherwise.  This makes the most
+sense, but it's too narrow for us, because we take some action in many cases
+even if there's some non-editable stuff around.
+
+What we really want this to do is return true if we'd do something when you run
+the command, false otherwise.  This will actually vary by command, and is
+nontrivial, and I'm not sure what the use-case is.  So for now I'll go with
+Opera, but I'll return to it later.
+-->
 
 <p>When <code>queryCommandIndeterm()</code> is invoked, the user agent must
 return the <span>indeterminate flag</span> for <var>command</var>.
--- a/tests.js	Mon Jun 27 14:27:27 2011 -0600
+++ b/tests.js	Mon Jun 27 15:19:45 2011 -0600
@@ -3057,7 +3057,13 @@
 		'[foo<a name=foo>bar</a>baz]',
 	],
 	//@}
-	quasit: [],
+	copy: ['foo[bar]baz'],
+	cut: ['foo[bar]baz'],
+	paste: ['foo[bar]baz'],
+	selectall: ['foo[bar]baz'],
+	stylewithcss: ['foo[bar]baz'],
+	usecss: ['foo[bar]baz'],
+	quasit: ['foo[bar]baz'],
 };
 tests.insertlinebreak = tests.insertparagraph;