--- a/editcommands.html Tue Jun 28 15:39:29 2011 -0600
+++ b/editcommands.html Wed Jun 29 09:08:33 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-—-last-update-28-june-2011>Work in Progress — Last Update 28 June 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-—-last-update-29-june-2011>Work in Progress — Last Update 29 June 2011</h2>
<dl>
<dt>Editor
<dd>Aryeh Gregor <ayg+spec@aryeh.name>
@@ -339,7 +339,10 @@
scripts to determine whether the selection is in a mixed or indeterminate
state, like (for <a href=#the-bold-command>the <code title="">bold</code> command</a>) partly bold
and partly not. An editing toolbar with a "bold" button might show it
-differently if the selection is indeterminate.
+differently if the selection is indeterminate. As a rule, the current
+selection is indeterminate for a command if either the command has a state
+which is true for part of the selection but not the whole selection, or it has
+a value which is different for different parts of the selection.
<p>The <dfn id=querycommandstate() title=queryCommandState()><code>queryCommandState(<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
@@ -3197,6 +3200,52 @@
</ol>
</ol>
+<p>The <dfn id="selection's-list-state">selection's list state</dfn> is returned by the following
+algorithm:
+
+<ol>
+ <li><a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>, and let <var title="">new
+ range</var> be the result.
+
+ <li>Let <var title="">node list</var> be a list of <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>nodes</a>, initially empty.
+
+ <li>For each <var title="">node</var> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in <var title="">new range</var>, append
+ <var title="">node</var> to <var title="">node list</var> if the last member of <var title="">node
+ list</var> (if any) is not an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var>;
+ <var title="">node</var> is <a href=#editable>editable</a>; <var title="">node</var> is not a
+ <a href=#potential-indentation-element>potential indentation element</a>; and <var title="">node</var> is either an
+ <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, or the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, or an
+ <a href=#allowed-child>allowed child</a> of "li".
+
+ <li>If <var title="">node list</var> is empty, return "none".
+
+ <li>If every member of <var title="">node list</var> is either an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or the
+ <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code>, and none is a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code> or an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>,
+ return "ol".
+
+ <li>If every member of <var title="">node list</var> is either a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code> or the
+ <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, and none is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code>,
+ return "ul".
+ <!-- The previous two conditions are mutually exclusive, so the order is
+ actually irrelevant. Clearly they could only both hold if no member of node
+ list is an ol or ul, so if they both held, every member would have to be both
+ the child of an ol and the child of a ul. This is impossible unless the list
+ is empty, in which case we already aborted. -->
+
+ <li>If some member of <var title="">node list</var> is either an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or the
+ <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> or <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code>, and some member of <var title="">node
+ list</var> is either a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code> or the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> or <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>,
+ return "mixed".
+
+ <li>If some member of <var title="">node list</var> is either an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or the
+ <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> or <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code>, return "mixed ol".
+
+ <li>If some member of <var title="">node list</var> is either a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code> or the
+ <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> or <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, return "mixed ul".
+
+ <li>Return "none".
+</ol>
+
<p>The <dfn id=canonical-space-sequence>canonical space sequence</dfn> of length <var title="">n</var>, with boolean
flags <var title="">non-breaking start</var> and <var title="">non-breaking end</var>, is
returned by the following algorithm:
@@ -3546,7 +3595,7 @@
and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offsets</a> of <var title="">range</var>.
<li>If some <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#ancestor-container title="ancestor container">ancestor container</a> of <var title="">start node</var> is an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code>, set
- <var title="">start offset</var> to the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of the last such <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> in
+ <var title="">start offset</var> to the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of the first such <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> in
<a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#tree-order>tree order</a>, and set <var title="">start node</var> to that <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code>'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>.
<li>Repeat the following steps:
@@ -3579,7 +3628,7 @@
</ol>
<li>If some <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#ancestor-container title="ancestor container">ancestor container</a> of <var title="">end node</var> is an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code>, set
- <var title="">end offset</var> to one plus the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of the last such <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> in
+ <var title="">end offset</var> to one plus the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of the first such <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> in
<a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#tree-order>tree order</a>, and set <var title="">end node</var> to that <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code>'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>.
<li>Repeat the following steps:
@@ -4517,6 +4566,9 @@
or "ul"):
<ol>
+ <li>Let <var title="">mode</var> be "disable" if the <a href="#selection's-list-state">selection's list
+ state</a> is <var title="">tag name</var>, and "enable" otherwise.
+
<li>Let <var title="">other tag name</var> be "ol" if <var title="">tag name</var> is "ul", and
"ul" if <var title="">tag name</var> is "ol".
@@ -4557,11 +4609,8 @@
case.
-->
- <li>If every member of <var title="">node list</var> is equal to or the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of
- an <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">tag name</var>, and no
- member of <var title="">node list</var> is equal to or the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of an
- <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">other tag name</var>, then
- while <var title="">node list</var> is not empty:
+ <li>If <var title="">mode</var> is "disable", then while <var title="">node list</var> is not
+ empty:
<ol>
<li>Let <var title="">sublist</var> be an empty list of <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>nodes</a>.
@@ -5806,46 +5855,24 @@
<p><a href=#action>Action</a>: <a href=#toggle-lists>Toggle lists</a> with <var title="">tag name</var>
"ol".
-<p class=XXX>Consider defining indeterminate flag.
-<!-- Gecko sort of supports it, but unreliably, and no one else does. Ditto
-insertUnorderedList, obviously. -->
-
-<p><a href=#state>State</a>:
+<p><a href=#indeterminate-flag>Indeterminate flag</a>: True if the <a href="#selection's-list-state">selection's list
+state</a> is "mixed" or "mixed ol", false otherwise.
<!--
-Logically, this should return true if running the command would remove ordered
-lists, false if it would add them, just like for bold etc. So I copy-paste the
-logic from there. Note that when we actually run the command, we'll normalize
-sublists, but not just when we query. This probably doesn't make a difference,
-but I'm not totally sure.
-
+Firefox 6.0a2 sort of supports this, but it throws exceptions most of the
+time. It has the quirk that even if there are no ol's around, it will say it's
+indeterminate if there are some things that are ul's and some that are not
+lists at all, but this doesn't make sense and I don't duplicate it. No one
+else supports indeterminate for insert*List, but it makes sense if you support
+state.
+-->
+
+<p><a href=#state>State</a>: True if the <a href="#selection's-list-state">selection's list state</a> is "ol",
+false otherwise.
+<!--
IE9 throws exceptions in most cases, Firefox 6.0a2 in some cases as well, for
no apparent reason. Ignoring those, the spec basically matches all browsers,
except with a few weird random mismatches that looked like browser bugs to me.
-->
-<p class=XXX>Does the fact that we don't normalize sublists before running this
-mean that it might produce results that don't match the way the action will
-behave?
-
-<ol>
- <li><a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>, and let <var title="">new
- range</var> be the result.
-
- <li>Let <var title="">node list</var> be a list of <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>nodes</a>, initially empty.
-
- <li>For each <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <var title="">node</var> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in <var title="">new range</var>,
- if <var title="">node</var> is <a href=#editable>editable</a>; the last member of <var title="">node
- list</var> (if any) is not an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var>;
- <var title="">node</var> is not a <a href=#potential-indentation-element>potential indentation element</a>; and
- either <var title="">node</var> is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, or 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 an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code>
- or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, or it is an <a href=#allowed-child>allowed child</a> of "li"; then append
- <var title="">node</var> to <var title="">node list</var>.
-
- <li>If every member of <var title="">node list</var> is equal to or the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of
- an <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> "ol", and no member of
- <var title="">node list</var> is equal to or the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of an <a href=#html-element>HTML
- element</a> with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> "ul", then return true. Otherwise, return
- false.
-</ol>
<h3 id=the-insertparagraph-command><span class=secno>7.18 </span><dfn>The <code title="">insertParagraph</code> command</dfn></h3>
@@ -6292,32 +6319,11 @@
<p><a href=#action>Action</a>: <a href=#toggle-lists>Toggle lists</a> with <var title="">tag name</var>
"ul".
-<p><a href=#state>State</a>:
-<!-- See insertOrderedList for comments. -->
-<p class=XXX>Does the fact that we don't normalize sublists before running this
-mean that it might produce results that don't match the way the action will
-behave?
-
-<ol>
- <li><a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>, and let <var title="">new
- range</var> be the result.
-
- <li>Let <var title="">node list</var> be a list of <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>nodes</a>, initially empty.
-
- <li>For each <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <var title="">node</var> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in <var title="">new range</var>,
- if <var title="">node</var> is <a href=#editable>editable</a>; the last member of <var title="">node
- list</var> (if any) is not an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var>;
- <var title="">node</var> is not a <a href=#potential-indentation-element>potential indentation element</a>; and
- either <var title="">node</var> is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, or 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 an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code>
- or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, or it is an <a href=#allowed-child>allowed child</a> of "li"; then append
- <var title="">node</var> to <var title="">node list</var>.
-
- <li>If every member of <var title="">node list</var> is equal to or the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of
- an <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> "ul", and no member of
- <var title="">node list</var> is equal to or the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of an <a href=#html-element>HTML
- element</a> with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> "ol", then return true. Otherwise, return
- false.
-</ol>
+<p><a href=#indeterminate-flag>Indeterminate flag</a>: True if the <a href="#selection's-list-state">selection's list
+state</a> is "mixed" or "mixed ul", false otherwise.
+
+<p><a href=#state>State</a>: True if the <a href="#selection's-list-state">selection's list state</a> is "ul",
+false otherwise.
<h3 id=the-justifycenter-command><span class=secno>7.21 </span><dfn>The <code title="">justifyCenter</code> command</dfn></h3>
--- a/implementation.js Tue Jun 28 15:39:29 2011 -0600
+++ b/implementation.js Wed Jun 29 09:08:33 2011 -0600
@@ -3601,6 +3601,77 @@
}
}
+function getSelectionListState() {
+ // "Block-extend the active range, and let new range be the result."
+ var newRange = blockExtendRange(getActiveRange());
+
+ // "Let node list be a list of nodes, initially empty."
+ //
+ // "For each node contained in new range, append node to node list if the
+ // last member of node list (if any) is not an ancestor of node; node is
+ // editable; node is not a potential indentation element; and node is
+ // either an ol or ul, or the child of an ol or ul, or an allowed child of
+ // "li"."
+ var nodeList = collectContainedNodes(newRange, function(node) {
+ return isEditable(node)
+ && !isPotentialIndentationElement(node)
+ && (isHtmlElement(node, ["ol", "ul"])
+ || isHtmlElement(node.parentNode, ["ol", "ul"])
+ || isAllowedChild(node, "li"));
+ });
+
+ // "If node list is empty, return "none"."
+ if (!nodeList.length) {
+ return "none";
+ }
+
+ // "If every member of node list is either an ol or the child of an ol, and
+ // none is a ul or an ancestor of a ul, return "ol"."
+ if (nodeList.every(function(node) { return isHtmlElement(node, "ol") || isHtmlElement(node.parentNode, "ol") })
+ && !nodeList.some(function(node) { return isHtmlElement(node, "ul") || ("querySelector" in node && node.querySelector("ul")) })) {
+ return "ol";
+ }
+
+ // "If every member of node list is either a ul or the child of a ul, and
+ // none is an ol or an ancestor of an ol, return "ul"."
+ if (nodeList.every(function(node) { return isHtmlElement(node, "ul") || isHtmlElement(node.parentNode, "ul") })
+ && !nodeList.some(function(node) { return isHtmlElement(node, "ol") || ("querySelector" in node && node.querySelector("ol")) })) {
+ return "ul";
+ }
+
+ var hasOl = nodeList.some(function(node) {
+ return isHtmlElement(node, "ol")
+ || isHtmlElement(node.parentNode, "ol")
+ || ("querySelector" in node && node.querySelector("ol"));
+ });
+ var hasUl = nodeList.some(function(node) {
+ return isHtmlElement(node, "ul")
+ || isHtmlElement(node.parentNode, "ul")
+ || ("querySelector" in node && node.querySelector("ul"));
+ });
+ // "If some member of node list is either an ol or the child or ancestor of
+ // an ol, and some member of node list is either a ul or the child or
+ // ancestor of a ul, return "mixed"."
+ if (hasOl && hasUl) {
+ return "mixed";
+ }
+
+ // "If some member of node list is either an ol or the child or ancestor of
+ // an ol, return "mixed ol"."
+ if (hasOl) {
+ return "mixed ol";
+ }
+
+ // "If some member of node list is either a ul or the child or ancestor of
+ // a ul, return "mixed ul"."
+ if (hasUl) {
+ return "mixed ul";
+ }
+
+ // "Return "none"."
+ return "none";
+}
+
function canonicalSpaceSequence(n, nonBreakingStart, nonBreakingEnd) {
// "If n is zero, return the empty string."
if (n == 0) {
@@ -3967,7 +4038,7 @@
var endOffset = range.endOffset;
// "If some ancestor container of start node is an li, set start offset to
- // the index of the last such li in tree order, and set start node to that
+ // the index of the first such li in tree order, and set start node to that
// li's parent."
for (
var ancestorContainer = startNode;
@@ -3977,7 +4048,6 @@
if (isHtmlElement(ancestorContainer, "LI")) {
startOffset = getNodeIndex(ancestorContainer);
startNode = ancestorContainer.parentNode;
- break;
}
}
@@ -4016,7 +4086,7 @@
}
// "If some ancestor container of end node is an li, set end offset to one
- // plus the index of the last such li in tree order, and set end node to
+ // plus the index of the first such li in tree order, and set end node to
// that li's parent."
for (
var ancestorContainer = endNode;
@@ -4026,7 +4096,6 @@
if (isHtmlElement(ancestorContainer, "LI")) {
endOffset = 1 + getNodeIndex(ancestorContainer);
endNode = ancestorContainer.parentNode;
- break;
}
}
@@ -4689,6 +4758,10 @@
//@{
function toggleLists(tagName) {
+ // "Let mode be "disable" if the selection's list state is tag name, and
+ // "enable" otherwise."
+ var mode = getSelectionListState() == tagName ? "disable" : "enable";
+
var range = getActiveRange();
tagName = tagName.toUpperCase();
@@ -4749,12 +4822,8 @@
}
}
- // "If every member of node list is equal to or the child of an HTML
- // element with local name tag name, and no member of node list is equal to
- // or the ancestor of an HTML element with local name other tag name, then
- // while node list is not empty:"
- if (nodeList.every(function(node) { return isHtmlElement(node, tagName) || isHtmlElement(node.parentNode, tagName) })
- && !nodeList.some(function(node) { return isHtmlElement(node, otherTagName) || node.querySelector(otherTagName) })) {
+ // "If mode is "disable", then while node list is not empty:"
+ if (mode == "disable") {
while (nodeList.length) {
// "Let sublist be an empty list of nodes."
var sublist = [];
@@ -5983,35 +6052,11 @@
commands.insertorderedlist = {
// "Toggle lists with tag name "ol"."
action: function() { toggleLists("ol") },
- state: function() {
- // "Block-extend the active range, and let new range be the result."
- var newRange = blockExtendRange(getActiveRange());
-
- // "Let node list be a list of nodes, initially empty."
- //
- // "For each node node contained in new range, if node is editable; the
- // last member of node list (if any) is not an ancestor of node; node
- // is not a potential indentation element; and either node is an ol or
- // ul, or its parent is an ol or ul, or it is an allowed child of "li";
- // then append node to node list."
- var nodeList = collectContainedNodes(newRange, function(node) {
- return isEditable(node)
- && !isPotentialIndentationElement(node)
- && (isHtmlElement(node, ["ol", "ul"])
- || isHtmlElement(node.parentNode, ["ol", "ul"])
- || isAllowedChild(node, "li"));
- });
-
- // "If every member of node list is equal to or the child of an HTML
- // element with local name "ol", and no member of node list is equal to
- // or the ancestor of an HTML element with local name "ul", then return
- // true. Otherwise, return false."
- return nodeList.every(function(node) {
- return (isHtmlElement(node, "ol") || isHtmlElement(node.parentNode, "ol"))
- && !isHtmlElement(node, "ul")
- && !node.querySelector("ul");
- });
- },
+ // "True if the selection's list state is "mixed" or "mixed ol", false
+ // otherwise."
+ indeterm: function() { return /^mixed( ol)?$/.test(getSelectionListState()) },
+ // "True if the selection's list state is "ol", false otherwise."
+ state: function() { return getSelectionListState() == "ol" },
};
//@}
@@ -6393,35 +6438,11 @@
commands.insertunorderedlist = {
// "Toggle lists with tag name "ul"."
action: function() { toggleLists("ul") },
- state: function() {
- // "Block-extend the active range, and let new range be the result."
- var newRange = blockExtendRange(getActiveRange());
-
- // "Let node list be a list of nodes, initially empty."
- //
- // "For each node node contained in new range, if node is editable; the
- // last member of node list (if any) is not an ancestor of node; node
- // is not a potential indentation element; and either node is an ol or
- // ul, or its parent is an ol or ul, or it is an allowed child of "li";
- // then append node to node list."
- var nodeList = collectContainedNodes(newRange, function(node) {
- return isEditable(node)
- && !isPotentialIndentationElement(node)
- && (isHtmlElement(node, ["ol", "ul"])
- || isHtmlElement(node.parentNode, ["ol", "ul"])
- || isAllowedChild(node, "li"));
- });
-
- // "If every member of node list is equal to or the child of an HTML
- // element with local name "ul", and no member of node list is equal to
- // or the ancestor of an HTML element with local name "ol", then return
- // true. Otherwise, return false."
- return nodeList.every(function(node) {
- return (isHtmlElement(node, "ul") || isHtmlElement(node.parentNode, "ul"))
- && !isHtmlElement(node, "ol")
- && !node.querySelector("ol");
- });
- },
+ // "True if the selection's list state is "mixed" or "mixed ul", false
+ // otherwise."
+ indeterm: function() { return /^mixed( ul)?$/.test(getSelectionListState()) },
+ // "True if the selection's list state is "ul", false otherwise."
+ state: function() { return getSelectionListState() == "ul" },
};
//@}
--- a/source.html Tue Jun 28 15:39:29 2011 -0600
+++ b/source.html Wed Jun 29 09:08:33 2011 -0600
@@ -275,7 +275,10 @@
scripts to determine whether the selection is in a mixed or indeterminate
state, like (for <span>the <code title>bold</code> command</span>) partly bold
and partly not. An editing toolbar with a "bold" button might show it
-differently if the selection is indeterminate.
+differently if the selection is indeterminate. As a rule, the current
+selection is indeterminate for a command if either the command has a state
+which is true for part of the selection but not the whole selection, or it has
+a value which is different for different parts of the selection.
<p>The <dfn
title=queryCommandState()><code>queryCommandState(<var>command</var>)</code></dfn>
@@ -3182,6 +3185,52 @@
</ol>
</ol>
+<p>The <dfn>selection's list state</dfn> is returned by the following
+algorithm:
+
+<ol>
+ <li><span>Block-extend</span> the <span>active range</span>, and let <var>new
+ range</var> be the result.
+
+ <li>Let <var>node list</var> be a list of [[nodes]], initially empty.
+
+ <li>For each <var>node</var> [[contained]] in <var>new range</var>, append
+ <var>node</var> to <var>node list</var> if the last member of <var>node
+ list</var> (if any) is not an [[ancestor]] of <var>node</var>;
+ <var>node</var> is <span>editable</span>; <var>node</var> is not a
+ <span>potential indentation element</span>; and <var>node</var> is either an
+ [[ol]] or [[ul]], or the [[child]] of an [[ol]] or [[ul]], or an
+ <span>allowed child</span> of "li".
+
+ <li>If <var>node list</var> is empty, return "none".
+
+ <li>If every member of <var>node list</var> is either an [[ol]] or the
+ [[child]] of an [[ol]], and none is a [[ul]] or an [[ancestor]] of a [[ul]],
+ return "ol".
+
+ <li>If every member of <var>node list</var> is either a [[ul]] or the
+ [[child]] of a [[ul]], and none is an [[ol]] or an [[ancestor]] of an [[ol]],
+ return "ul".
+ <!-- The previous two conditions are mutually exclusive, so the order is
+ actually irrelevant. Clearly they could only both hold if no member of node
+ list is an ol or ul, so if they both held, every member would have to be both
+ the child of an ol and the child of a ul. This is impossible unless the list
+ is empty, in which case we already aborted. -->
+
+ <li>If some member of <var>node list</var> is either an [[ol]] or the
+ [[child]] or [[ancestor]] of an [[ol]], and some member of <var>node
+ list</var> is either a [[ul]] or the [[child]] or [[ancestor]] of a [[ul]],
+ return "mixed".
+
+ <li>If some member of <var>node list</var> is either an [[ol]] or the
+ [[child]] or [[ancestor]] of an [[ol]], return "mixed ol".
+
+ <li>If some member of <var>node list</var> is either a [[ul]] or the
+ [[child]] or [[ancestor]] of a [[ul]], return "mixed ul".
+
+ <li>Return "none".
+</ol>
+
<p>The <dfn>canonical space sequence</dfn> of length <var>n</var>, with boolean
flags <var>non-breaking start</var> and <var>non-breaking end</var>, is
returned by the following algorithm:
@@ -3531,7 +3580,7 @@
and [[bpoffsets]] of <var>range</var>.
<li>If some [[ancestorcontainer]] of <var>start node</var> is an [[li]], set
- <var>start offset</var> to the [[index]] of the last such [[li]] in
+ <var>start offset</var> to the [[index]] of the first such [[li]] in
[[treeorder]], and set <var>start node</var> to that [[li]]'s [[parent]].
<li>Repeat the following steps:
@@ -3564,7 +3613,7 @@
</ol>
<li>If some [[ancestorcontainer]] of <var>end node</var> is an [[li]], set
- <var>end offset</var> to one plus the [[index]] of the last such [[li]] in
+ <var>end offset</var> to one plus the [[index]] of the first such [[li]] in
[[treeorder]], and set <var>end node</var> to that [[li]]'s [[parent]].
<li>Repeat the following steps:
@@ -4506,6 +4555,9 @@
or "ul"):
<ol>
+ <li>Let <var>mode</var> be "disable" if the <span>selection's list
+ state</span> is <var>tag name</var>, and "enable" otherwise.
+
<li>Let <var>other tag name</var> be "ol" if <var>tag name</var> is "ul", and
"ul" if <var>tag name</var> is "ol".
@@ -4546,11 +4598,8 @@
case.
-->
- <li>If every member of <var>node list</var> is equal to or the [[child]] of
- an <span>HTML element</span> with [[localname]] <var>tag name</var>, and no
- member of <var>node list</var> is equal to or the [[ancestor]] of an
- <span>HTML element</span> with [[localname]] <var>other tag name</var>, then
- while <var>node list</var> is not empty:
+ <li>If <var>mode</var> is "disable", then while <var>node list</var> is not
+ empty:
<ol>
<li>Let <var>sublist</var> be an empty list of [[nodes]].
@@ -5818,46 +5867,24 @@
<p><span>Action</span>: <span>Toggle lists</span> with <var>tag name</var>
"ol".
-<p class=XXX>Consider defining indeterminate flag.
-<!-- Gecko sort of supports it, but unreliably, and no one else does. Ditto
-insertUnorderedList, obviously. -->
-
-<p><span>State</span>:
+<p><span>Indeterminate flag</span>: True if the <span>selection's list
+state</span> is "mixed" or "mixed ol", false otherwise.
<!--
-Logically, this should return true if running the command would remove ordered
-lists, false if it would add them, just like for bold etc. So I copy-paste the
-logic from there. Note that when we actually run the command, we'll normalize
-sublists, but not just when we query. This probably doesn't make a difference,
-but I'm not totally sure.
-
+Firefox 6.0a2 sort of supports this, but it throws exceptions most of the
+time. It has the quirk that even if there are no ol's around, it will say it's
+indeterminate if there are some things that are ul's and some that are not
+lists at all, but this doesn't make sense and I don't duplicate it. No one
+else supports indeterminate for insert*List, but it makes sense if you support
+state.
+-->
+
+<p><span>State</span>: True if the <span>selection's list state</span> is "ol",
+false otherwise.
+<!--
IE9 throws exceptions in most cases, Firefox 6.0a2 in some cases as well, for
no apparent reason. Ignoring those, the spec basically matches all browsers,
except with a few weird random mismatches that looked like browser bugs to me.
-->
-<p class=XXX>Does the fact that we don't normalize sublists before running this
-mean that it might produce results that don't match the way the action will
-behave?
-
-<ol>
- <li><span>Block-extend</span> the <span>active range</span>, and let <var>new
- range</var> be the result.
-
- <li>Let <var>node list</var> be a list of [[nodes]], initially empty.
-
- <li>For each [[node]] <var>node</var> [[contained]] in <var>new range</var>,
- if <var>node</var> is <span>editable</span>; the last member of <var>node
- list</var> (if any) is not an [[ancestor]] of <var>node</var>;
- <var>node</var> is not a <span>potential indentation element</span>; and
- either <var>node</var> is an [[ol]] or [[ul]], or its [[parent]] is an [[ol]]
- or [[ul]], or it is an <span>allowed child</span> of "li"; then append
- <var>node</var> to <var>node list</var>.
-
- <li>If every member of <var>node list</var> is equal to or the [[child]] of
- an <span>HTML element</span> with [[localname]] "ol", and no member of
- <var>node list</var> is equal to or the [[ancestor]] of an <span>HTML
- element</span> with [[localname]] "ul", then return true. Otherwise, return
- false.
-</ol>
<!-- @} -->
<h3><dfn>The <code title>insertParagraph</code> command</dfn></h3>
@@ -6312,32 +6339,11 @@
<p><span>Action</span>: <span>Toggle lists</span> with <var>tag name</var>
"ul".
-<p><span>State</span>:
-<!-- See insertOrderedList for comments. -->
-<p class=XXX>Does the fact that we don't normalize sublists before running this
-mean that it might produce results that don't match the way the action will
-behave?
-
-<ol>
- <li><span>Block-extend</span> the <span>active range</span>, and let <var>new
- range</var> be the result.
-
- <li>Let <var>node list</var> be a list of [[nodes]], initially empty.
-
- <li>For each [[node]] <var>node</var> [[contained]] in <var>new range</var>,
- if <var>node</var> is <span>editable</span>; the last member of <var>node
- list</var> (if any) is not an [[ancestor]] of <var>node</var>;
- <var>node</var> is not a <span>potential indentation element</span>; and
- either <var>node</var> is an [[ol]] or [[ul]], or its [[parent]] is an [[ol]]
- or [[ul]], or it is an <span>allowed child</span> of "li"; then append
- <var>node</var> to <var>node list</var>.
-
- <li>If every member of <var>node list</var> is equal to or the [[child]] of
- an <span>HTML element</span> with [[localname]] "ul", and no member of
- <var>node list</var> is equal to or the [[ancestor]] of an <span>HTML
- element</span> with [[localname]] "ol", then return true. Otherwise, return
- false.
-</ol>
+<p><span>Indeterminate flag</span>: True if the <span>selection's list
+state</span> is "mixed" or "mixed ul", false otherwise.
+
+<p><span>State</span>: True if the <span>selection's list state</span> is "ul",
+false otherwise.
<!-- @} -->
<h3><dfn>The <code title>justifyCenter</code> command</dfn></h3>