--- a/editcommands.html Mon Jul 11 13:58:51 2011 -0600
+++ b/editcommands.html Tue Jul 12 11:28:30 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-11-july-2011>Work in Progress — Last Update 11 July 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-—-last-update-12-july-2011>Work in Progress — Last Update 12 July 2011</h2>
<dl>
<dt>Editor
<dd>Aryeh Gregor <ayg+spec@aryeh.name>
@@ -328,6 +328,15 @@
especially since in many cases, the command's effect isn't currently
interoperable anyway. I'll switch them back to doing nothing if implementers
think this is a problem.
+
+ <li>The CSS styling flag is an issue. Currently authors are forced to turn
+ it entirely on or entirely off. If it's on, it produces stuff like <code title=""><span style=font-weight:bold></code> instead of <code title=""><b></code>, while if it's off, it produces stuff like <code title=""><font color=red></code> instead of <code title=""><span
+ style=color:red></code>. The issue is that authors might want a mix, like
+ making the markup as concise as possible while still conforming, and they
+ can't do that. Changing the flag on a per-command basis doesn't help because
+ of things like the "restore the values" algorithm, which might create several
+ different types of style at once and has to use the same styling flag for all
+ of them.
</ul>
<p class=XXX>A variety of other issues are also noted in the text, formatted
@@ -1521,6 +1530,65 @@
<a href=#preserving-ranges>preserving ranges</a>.
</ol>
+<p>To <dfn id=record-the-values>record the values</dfn> of 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> <var title="">node list</var>:
+
+<ol>
+ <li>Let <var title="">values</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>node</a>, <a href=#command>command</a>,
+ <a href=#specified-value>specified value</a>) triples, initially empty.
+
+ <li>For each <var title="">node</var> in <var title="">node list</var>, for each
+ <var title="">command</var> in the list "subscript", "bold", "fontName", "fontSize",
+ "foreColor", "hiliteColor", "italic", "strikethrough", and "underline" in
+ that order:
+ <!-- As with removeFormat, we put subscript first so it doesn't interfere
+ with fontSize, and omit superscript because it's redundant with subscript.
+ -->
+
+ <ol>
+ <li>Let <var title="">ancestor</var> equal <var title="">node</var>.
+
+ <li>If <var title="">ancestor</var> is not an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>, set it 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>While <var title="">ancestor</var> is an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code> and its <a href=#specified-value>specified
+ value</a> for <var title="">command</var> is null, set it 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 <var title="">ancestor</var> is an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>, add (<var title="">node</var>,
+ <var title="">command</var>, <var title="">ancestor</var>'s <a href=#specified-value>specified value</a> for
+ <var title="">command</var>) to <var title="">values</var>. Otherwise add (<var title="">node</var>,
+ <var title="">command</var>, null) to <var title="">values</var>.
+ </ol>
+
+ <li>Return <var title="">values</var>.
+</ol>
+
+<p>To <dfn id=restore-the-values>restore the values</dfn> specified by a list <var title="">values</var>
+returned by the <a href=#record-the-values>record the values</a> algorithm:
+
+<ol>
+ <li>For each (<var title="">node</var>, <var title="">command</var>, <var title="">value</var>) triple
+ in <var title="">values</var>:
+
+ <ol>
+ <li>Let <var title="">ancestor</var> equal <var title="">node</var>.
+
+ <li>If <var title="">ancestor</var> is not an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>, set it 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>While <var title="">ancestor</var> is an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code> and its <a href=#specified-value>specified
+ value</a> for <var title="">command</var> is null, set it 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 <var title="">value</var> is null and <var title="">ancestor</var> is an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>,
+ <a href=#push-down-values>push down values</a> on <var title="">node</var> for <var title="">command</var>,
+ with <var title="">new value</var> null.
+
+ <li>Otherwise, if <var title="">ancestor</var> is an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code> and its
+ <a href=#specified-value>specified value</a> for <var title="">command</var> is different from
+ <var title="">value</var>, or if <var title="">ancestor</var> is not an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code> and
+ <var title="">value</var> is not null, <a href=#force-the-value>force the value</a> of
+ <var title="">command</var> to <var title="">value</var> on <var title="">node</var>.
+ </ol>
+</ol>
+
+
<h3 id="clearing-an-element's-value"><span class=secno>7.3 </span>Clearing an element's value</h3>
@@ -3063,18 +3131,26 @@
"dt", or "dd".
<p>The <dfn id=default-single-line-container-name>default single-line container name</dfn> is "p".
-<!-- Possibly to be made configurable later. -->
+<!-- TODO V2: Make this configurable. -->
<h3 id=assorted-block-formatting-command-algorithms><span class=secno>8.2 </span>Assorted block formatting command algorithms</h3>
<p>To <dfn id=fix-disallowed-ancestors>fix disallowed ancestors</dfn> of <var title="">node</var>:
+<!-- TODO V2: When breaking a non-inline element out of an inline element, like
+p in b or whatever, it would make sense to re-wrap the contents in the inline
+tag. -->
<ol>
<li>If <var title="">node</var> is not <a href=#editable>editable</a>, abort these steps.
<li>If <var title="">node</var> is not an <a href=#allowed-child>allowed child</a> of 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> <a href=#in-the-same-editing-host>in the same editing host</a>:
+ <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> <a href=#in-the-same-editing-host>in the same editing host</a>, and is not 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> equal to the <a href=#default-single-line-container-name>default single-line
+ container name</a>:
+ <!-- The requirement about default containers is to prevent an infinite loop.
+ This case is really intended to handle stuff like list items or table cells
+ that wander outside their proper place. -->
<ol>
<li>If <var title="">node</var> is a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code>, <a href=#wrap>wrap</a> the
@@ -3101,9 +3177,14 @@
<li>Abort these steps.
</ol>
+ <li><a href=#record-the-values>Record the values</a> of the one-<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> list consisting of
+ <var title="">node</var>, and let <var title="">values</var> be the result.
+
<li>While <var title="">node</var> is not an <a href=#allowed-child>allowed child</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>, <a href=#split-the-parent>split the parent</a> of the one-<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> list consisting
of <var title="">node</var>.
+
+ <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
</ol>
<p>To <dfn id=normalize-sublists>normalize sublists</dfn> in a <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="">item</var>:
@@ -3730,7 +3811,7 @@
<li>If <var title="">end block</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-firstChild><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-firstchild>firstChild</a></code> is not an <a href=#inline-node>inline
node</a>, abort these steps.
- <li>Let <var title="">children</var> be an array 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>Let <var title="">children</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>Append the first <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 <var title="">end block</var> to
<var title="">children</var>.
@@ -3740,6 +3821,9 @@
node</a>, append <var title="">children</var>'s last member's <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> to
<var title="">children</var>.
+ <li><a href=#record-the-values>Record the values</a> of <var title="">children</var>, and let
+ <var title="">values</var> be the result.
+
<li>While <var title="">children</var>'s first member'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 <var title="">start
block</var>, <a href=#split-the-parent>split the parent</a> of <var title="">children</var>.
@@ -3765,9 +3849,21 @@
node</a> and <var title="">start block</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-lastChild><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-lastchild>lastChild</a></code> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, remove
<var title="">start block</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-lastChild><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-lastchild>lastChild</a></code> from it.
- <li>While the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of <var title="">reference node</var> is neither null
- nor a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code> nor a <a href=#block-node>block node</a>, append the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of
- <var title="">reference node</var> as the last <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 <var title="">start block</var>,
+ <li>Let <var title="">nodes to move</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>If <var title="">reference node</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> is neither null nor a
+ <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code> nor a <a href=#block-node>block node</a>, append it to <var title="">nodes to
+ move</var>.
+
+ <li>While <var title="">nodes to move</var> is nonempty and its last member's
+ <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> is neither null nor a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code> nor a <a href=#block-node>block node</a>,
+ append it to <var title="">nodes to move</var>.
+
+ <li><a href=#record-the-values>Record the values</a> of <var title="">nodes to move</var>, and let
+ <var title="">values</var> be the result.
+
+ <li>For each <var title="">node</var> in <var title="">nodes to move</var>, append
+ <var title="">node</var> as the last <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 <var title="">start block</var>,
<a href=#preserving-ranges>preserving ranges</a>.
<li>If the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of <var title="">reference node</var> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, remove
@@ -3786,6 +3882,9 @@
and <var title="">start block</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-lastChild><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-lastchild>lastChild</a></code> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, remove <var title="">start
block</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-lastChild><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-lastchild>lastChild</a></code> from it.
+ <li><a href=#record-the-values>Record the values</a> of <var title="">end block</var>'s <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>children</a>,
+ and let <var title="">values</var> be the result.
+
<li>While <var title="">end block</var> has <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>children</a>, append the first <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 <var title="">end block</var> to <var title="">start block</var>, <a href=#preserving-ranges>preserving
ranges</a>.
@@ -3795,6 +3894,8 @@
<var title="">parent</var>, then set <var title="">end block</var> to <var title="">parent</var>.
</ol>
+ <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
+
<li>If <var title="">start block</var> has no <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>children</a>, call
<code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a> and append the result as the
last <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 <var title="">start block</var>.
@@ -3806,13 +3907,6 @@
<p>To <dfn id=split-the-parent>split the parent</dfn> of a list <var title="">node list</var> of consecutive
<a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-sibling title=concept-tree-sibling>sibling</a> <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>:
-<p class=XXX>Pretty much any time we call this algorithm, it can cause trouble
-if the parent had styles, classes, etc. There's not going to be any general
-way to handle this, but we should at least try to handle the special case of
-inline styles, because Firefox does actually add them to arbitrary elements.
-Also, when splitting out of an inline parent, it might be good to wrap all the
-inline descendants in a clone of the former parent.
-
<ol>
<li>Let <var title="">original parent</var> be 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 the first member of
<var title="">node list</var>.
@@ -4342,26 +4436,6 @@
indentation element, as does the spec.
-->
- <div class=XXX>
- <p>We don't handle a case like
-
- </p><xmp><ol><ol style="color: red"><li>foo<li>bar</ol><li>baz</ol></xmp>
-
- <p>If the inner <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> is selected to be outdented, "foo" and "bar" will stop
- being red. It seems nontrivial to handle this case in general, since we
- can't group <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. If the list we're outdenting is a child of a non-list,
- then we can just change it to a div. Hopefully
- <a href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=13128">HTML bug
- 13128</a> will get fixed, in which case I can just use a div here too.
- </div>
- <!--
- Chrome 12 dev seems to special-case style attributes by converting them to
- the corresponding inline markup elements (at least in easy cases like color).
- For other attributes and non-WebKit browsers (IE9/FF4/O11.10), it looks like
- all the attributes are just removed. Maybe we should try to copy WebKit
- here.
- -->
-
<ol>
<li>Unset the <code class=external data-anolis-spec=html title=attr-ol-reversed><a href=http://www.whatwg.org/html/#attr-ol-reversed>reversed</a></code>, <code class=external data-anolis-spec=html title=attr-ol-start><a href=http://www.whatwg.org/html/#attr-ol-start>start</a></code>, and <code class=external data-anolis-spec=html title=attr-ol-type><a href=http://www.whatwg.org/html/#attr-ol-type>type</a></code> attributes of <var title="">node</var>, if any are
set.
@@ -4370,8 +4444,23 @@
<li>If <var title="">node</var> has attributes, 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 not 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>, <a href=#set-the-tag-name>set the tag name</a> of <var title="">node</var> to "div".
-
- <li>Otherwise remove <var title="">node</var>, <a href=#preserving-its-descendants>preserving its descendants</a>.
+ <!--
+ We can't turn it into a div if it's the child of an ol or ul, because
+ that's not currently allowed. TODO V2: change this if
+ http://www.w3.org/Bugs/Public/show_bug.cgi?id=13128 is fixed and we can
+ make it a div.
+ -->
+
+ <li>Otherwise:
+
+ <ol>
+ <li><a href=#record-the-values>Record the values</a> of <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-child title=concept-tree-child>children</a>, and
+ let <var title="">values</var> be the result.
+
+ <li>Remove <var title="">node</var>, <a href=#preserving-its-descendants>preserving its descendants</a>.
+
+ <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
+ </ol>
<li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of each member of
<var title="">children</var>.
@@ -4798,10 +4887,15 @@
<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>, remove the first member from <var title="">node
list</var> and append it to <var title="">sublist</var>.
+ <li><a href=#record-the-values>Record the values</a> of <var title="">sublist</var>, and let
+ <var title="">values</var> be the result.
+
<li><a href=#split-the-parent>Split the parent</a> of <var title="">sublist</var>.
<li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of each member of
<var title="">sublist</var>.
+
+ <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
</ol>
<li>Otherwise, while <var title="">node list</var> is not empty:
@@ -4822,8 +4916,9 @@
<li>If <var title="">sublist</var> contains more than one member, <a href=#wrap>wrap</a>
<var title="">sublist</var>, with <a href=#sibling-criteria>sibling criteria</a> matching nothing and
- <a href=#new-parent-instructions>new parent instructions</a> returning the result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement("li")</a></code> on the
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>. Let <var title="">node</var> be the result.
+ <a href=#new-parent-instructions>new parent instructions</a> returning the result of calling
+ <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement("li")</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>. Let <var title="">node</var> be
+ the result.
<li>Otherwise, let <var title="">node</var> be the sole member of
<var title="">sublist</var>.
@@ -4834,14 +4929,18 @@
<ol>
<li>Let <var title="">children</var> be 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>children</a> of <var title="">node</var>.
+ <li><a href=#record-the-values>Record the values</a> of <var title="">children</var>, and let
+ <var title="">values</var> be the result.
+
<li>Remove <var title="">node</var>, <a href=#preserving-its-descendants>preserving its descendants</a>.
<li><a href=#wrap>Wrap</a> <var title="">children</var>, with <a href=#sibling-criteria>sibling
criteria</a> matching any <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 <a href=#new-parent-instructions>new parent
- instructions</a> returning the result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement(<var title="">tag
- name</var>)</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>. Let <var title="">node</var> be the
- result.
+ <var title="">tag name</var> and <a href=#new-parent-instructions>new parent instructions</a> returning
+ the result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement(<var title="">tag name</var>)</a></code> on the
+ <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>. Let <var title="">node</var> be the result.
+
+ <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
<li>Prepend the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendants</a> of <var title="">node</var> that are <a href=#html-element title="HTML element">HTML elements</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> (if any) to <var title="">node list</var>.
@@ -4883,6 +4982,9 @@
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>:
<ol>
+ <li><a href=#record-the-values>Record the values</a> of the one-<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> list consisting of
+ <var title="">node</var>, and let <var title="">values</var> be the result.
+
<li><a href=#split-the-parent>Split the parent</a> of the one-<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> list consisting of
<var title="">node</var>.
@@ -4890,8 +4992,9 @@
<var title="">node</var>, with <a href=#sibling-criteria>sibling criteria</a> matching any
<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 with <a href=#new-parent-instructions>new parent instructions</a> returning the result of
- calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement(<var title="">tag
- name</var>)</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>.
+ calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement(<var title="">tag name</var>)</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>.
+
+ <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
<li>Prepend the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendants</a> of <var title="">node</var> that are <a href=#html-element title="HTML element">HTML elements</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> (if any) to <var title="">node list</var>.
@@ -5160,9 +5263,14 @@
<li><a href=#normalize-sublists>Normalize sublists</a> of each <var title="">item</var> in
<var title="">items</var>.
+ <li><a href=#record-the-values>Record the values</a> of the one-<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> list consisting of
+ <var title="">node</var>, and let <var title="">values</var> be the result.
+
<li><a href=#split-the-parent>Split the parent</a> of the one-<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> list consisting of
<var title="">node</var>.
+ <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
+
<li>If <var title="">node</var> is a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code>, and it is not an
<a href=#allowed-child>allowed child</a> of 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> <a href=#in-the-same-editing-host>in the same
editing host</a>, <a href=#set-the-tag-name>set the tag name</a> of <var title="">node</var> to
@@ -5438,6 +5546,9 @@
of "p" or a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code>, and <var title="">node</var> is not 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
a <a href=#prohibited-paragraph-child>prohibited paragraph child</a>.
+ <li><a href=#record-the-values>Record the values</a> of <var title="">node list</var>, and let
+ <var title="">values</var> be the result.
+
<li>For each <var title="">node</var> in <var title="">node list</var>, while <var title="">node</var>
is the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendant</a> of an <a href=#editable>editable</a> <a href=#html-element>HTML element</a>
<a href=#in-the-same-editing-host>in the same editing host</a>, which has <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> "address",
@@ -5458,6 +5569,8 @@
out of lists or tables or such if they happen to be nested in a <div>.
-->
+ <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
+
<!--
We have two different behaviors, one for div and p and one for everything
else. The basic difference is that for div and p, we assume that it should
@@ -5518,9 +5631,14 @@
<li>Let <var title="">sublist</var> be 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>children</a> of the first member of
<var title="">node list</var>.
+ <li><a href=#record-the-values>Record the values</a> of <var title="">sublist</var>, and let
+ <var title="">values</var> be the result.
+
<li>Remove the first member of <var title="">node list</var> from 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>,
<a href=#preserving-its-descendants>preserving its descendants</a>.
+ <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
+
<li>Remove the first member from <var title="">node list</var>.
</ol>
@@ -6777,37 +6895,33 @@
<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>:
-
- <ol>
- <li>If the last member of <var title="">node list</var> (if any) is 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>, or if <var title="">node</var> is not <a href=#editable>editable</a>,
- continue with the next <var title="">node</var>.
-
- <!--
- This step is kind of weird. For regular outdenting, we start at the inside
- and outdent going out, so that we remove the innermost indentation, on the
- theory that that will produce the cleanest markup (remove the most nodes).
- For lists, we remove the outermost indentation, because it makes a
- difference whether we remove inner or outer indentation, and logically we
- want to remove outer. E.g.,
-
- <ol><li>foo</li><ul><li>bar</li></ul></ol>
-
- should become
-
- foo<ul><li>bar</li></ul>
-
- not
-
- foo<ol><li>bar</li></ol>.
-
- But this is a bit weird and I'm wondering if it's really correct.
- -->
- <li>If <var title="">node</var> has no <a href=#editable>editable</a> <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendants</a>, or 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 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> whose <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>, append it to <var title="">node list</var>.
- </ol>
+ <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>,
+ 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>; and either <var title="">node</var> has no
+ <a href=#editable>editable</a> <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendants</a>, or 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 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> whose <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>.
+ <!--
+ This step is kind of weird. For regular outdenting, we start at the inside
+ and outdent going out, so that we remove the innermost indentation, on the
+ theory that that will produce the cleanest markup (remove the most nodes).
+ For lists, we remove the outermost indentation, because it makes a difference
+ whether we remove inner or outer indentation, and logically we want to remove
+ outer. E.g.,
+
+ <ol><li>foo</li><ul><li>bar</li></ul></ol>
+
+ should become
+
+ foo<ul><li>bar</li></ul>
+
+ not
+
+ foo<ol><li>bar</li></ol>.
+
+ But this is a bit weird and I'm wondering if it's really correct. TODO V2:
+ Reexamine this.
+ -->
<li>While <var title="">node list</var> is not empty:
@@ -6828,10 +6942,15 @@
list</var> is not 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>, remove the first member of <var title="">node
list</var> and append it to <var title="">sublist</var>.
+ <li><a href=#record-the-values>Record the values</a> of <var title="">sublist</var>, and let
+ <var title="">values</var> be the result.
+
<li><a href=#split-the-parent>Split the parent</a> of <var title="">sublist</var>.
<li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of each member of
<var title="">sublist</var>.
+
+ <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
</ol>
</ol>
--- a/implementation.js Mon Jul 11 13:58:51 2011 -0600
+++ b/implementation.js Tue Jul 12 11:28:30 2011 -0600
@@ -2054,6 +2054,91 @@
movePreservingRanges(node, candidate, -1);
}
+function recordValues(nodeList) {
+ // "Let values be a list of (node, command, specified value) triples,
+ // initially empty."
+ var values = [];
+
+ // "For each node in node list, for each command in the list "subscript",
+ // "bold", "fontName", "fontSize", "foreColor", "hiliteColor", "italic",
+ // "strikethrough", and "underline" in that order:"
+ nodeList.forEach(function(node) {
+ ["subscript", "bold", "fontname", "fontsize", "forecolor",
+ "hilitecolor", "italic", "strikethrough", "underline"].forEach(function(command) {
+ // "Let ancestor equal node."
+ var ancestor = node;
+
+ // "If ancestor is not an Element, set it to its parent."
+ if (ancestor.nodeType != Node.ELEMENT_NODE) {
+ ancestor = ancestor.parentNode;
+ }
+
+ // "While ancestor is an Element and its specified value for
+ // command is null, set it to its parent."
+ while (ancestor
+ && ancestor.nodeType == Node.ELEMENT_NODE
+ && getSpecifiedValue(ancestor, command) === null) {
+ ancestor = ancestor.parentNode;
+ }
+
+ // "If ancestor is an Element, add (node, command, ancestor's
+ // specified value for command) to values. Otherwise add (node,
+ // command, null) to values."
+ if (ancestor && ancestor.nodeType == Node.ELEMENT_NODE) {
+ values.push([node, command, getSpecifiedValue(ancestor, command)]);
+ } else {
+ values.push([node, command, null]);
+ }
+ });
+ });
+
+ // "Return values."
+ return values;
+}
+
+function restoreValues(values) {
+ // "For each (node, command, value) triple in values:"
+ values.forEach(function(triple) {
+ var node = triple[0];
+ var command = triple[1];
+ var value = triple[2];
+
+ // "Let ancestor equal node."
+ var ancestor = node;
+
+ // "If ancestor is not an Element, set it to its parent."
+ if (!ancestor || ancestor.nodeType != Node.ELEMENT_NODE) {
+ ancestor = ancestor.parentNode;
+ }
+
+ // "While ancestor is an Element and its specified value for command is
+ // null, set it to its parent."
+ while (ancestor
+ && ancestor.nodeType == Node.ELEMENT_NODE
+ && getSpecifiedValue(ancestor, command) === null) {
+ ancestor = ancestor.parentNode;
+ }
+
+ // "If value is null and ancestor is an Element, push down values on
+ // node for command, with new value null."
+ if (value === null
+ && ancestor
+ && ancestor.nodeType == Node.ELEMENT_NODE) {
+ pushDownValues(node, command, null);
+
+ // "Otherwise, if ancestor is an Element and its specified value for
+ // command is different from value, or if ancestor is not an Element
+ // and value is not null, force the value of command to value on node."
+ } else if ((ancestor
+ && ancestor.nodeType == Node.ELEMENT_NODE
+ && !valuesEqual(command, getSpecifiedValue(ancestor, command), value))
+ || ((!ancestor || ancestor.nodeType != Node.ELEMENT_NODE)
+ && value !== null)) {
+ forceValue(node, command, value);
+ }
+ });
+}
+
//@}
///// Clearing an element's value /////
@@ -3443,11 +3528,13 @@
}
// "If node is not an allowed child of any of its ancestors in the same
- // editing host:"
+ // editing host, and is not an HTML element with local name equal to the
+ // default single-line container name:"
if (getAncestors(node).every(function(ancestor) {
return !inSameEditingHost(node, ancestor)
|| !isAllowedChild(node, ancestor)
- })) {
+ })
+ && !isHtmlElement(node, defaultSingleLineContainerName)) {
// "If node is a dd or dt, wrap the one-node list consisting of node,
// with sibling criteria matching any dl with no attributes, and new
// parent instructions returning the result of calling
@@ -3483,11 +3570,18 @@
return;
}
+ // "Record the values of the one-node list consisting of node, and let
+ // values be the result."
+ var values = recordValues([node]);
+
// "While node is not an allowed child of its parent, split the parent of
// the one-node list consisting of node."
while (!isAllowedChild(node, node.parentNode)) {
splitParent([node]);
}
+
+ // "Restore the values from values."
+ restoreValues(values);
}
function normalizeSublists(item) {
@@ -4189,7 +4283,7 @@
return;
}
- // "Let children be an array of nodes, initially empty."
+ // "Let children be a list of nodes, initially empty."
var children = [];
// "Append the first child of end block to children."
@@ -4203,6 +4297,9 @@
children.push(children[children.length - 1].nextSibling);
}
+ // "Record the values of children, and let values be the result."
+ var values = recordValues(children);
+
// "While children's first member's parent is not start block, split
// the parent of children."
while (children[0].parentNode != startBlock) {
@@ -4239,14 +4336,35 @@
startBlock.removeChild(startBlock.lastChild);
}
- // "While the nextSibling of reference node is neither null nor a br
- // nor a block node, append the nextSibling of reference node as the
- // last child of start block, preserving ranges."
- while (referenceNode.nextSibling
+ // "Let nodes to move be a list of nodes, initially empty."
+ var nodesToMove = [];
+
+ // "If reference node's nextSibling is neither null nor a br nor a
+ // block node, append it to nodes to move."
+ if (referenceNode.nextSibling
&& !isHtmlElement(referenceNode.nextSibling, "br")
&& !isBlockNode(referenceNode.nextSibling)) {
- movePreservingRanges(referenceNode.nextSibling, startBlock, -1);
- }
+ nodesToMove.push(referenceNode.nextSibling);
+ }
+
+ // "While nodes to move is nonempty and its last member's nextSibling
+ // is neither null nor a br nor a block node, append it to nodes to
+ // move."
+ if (nodesToMove.length
+ && nodesToMove[nodesToMove.length - 1].nextSibling
+ && !isHtmlElement(nodesToMove[nodesToMove.length - 1].nextSibling, "br")
+ && !isBlockNode(nodesToMove[nodesToMove.length - 1].nextSibling)) {
+ nodesToMove.push(nodesToMove[nodesToMove.length - 1].nextSibling);
+ }
+
+ // "Record the values of nodes to move, and let values be the result."
+ var values = recordValues(nodesToMove);
+
+ // "For each node in nodes to move, append node as the last child of
+ // start block, preserving ranges."
+ nodesToMove.forEach(function(node) {
+ movePreservingRanges(node, startBlock, -1);
+ });
// "If the nextSibling of reference node is a br, remove it from its
// parent."
@@ -4268,6 +4386,10 @@
startBlock.removeChild(startBlock.lastChild);
}
+ // "Record the values of end block's children, and let values be the
+ // result."
+ var values = recordValues([].slice.call(endBlock.childNodes));
+
// "While end block has children, append the first child of end block
// to start block, preserving ranges."
while (endBlock.hasChildNodes()) {
@@ -4284,6 +4406,9 @@
}
}
+ // "Restore the values from values."
+ restoreValues(values);
+
// "If start block has no children, call createElement("br") on the context
// object and append the result as the last child of start block."
if (!startBlock.hasChildNodes()) {
@@ -4794,9 +4919,17 @@
&& !isHtmlElement(node.parentNode, ["OL", "UL"])) {
setTagName(node, "div");
- // "Otherwise remove node, preserving its descendants."
+ // "Otherwise:"
} else {
+ // "Record the values of node's children, and let values be the
+ // result."
+ var values = recordValues([].slice.call(node.childNodes));
+
+ // "Remove node, preserving its descendants."
removePreservingDescendants(node);
+
+ // "Restore the values from values."
+ restoreValues(values);
}
// "Fix disallowed ancestors of each member of children."
@@ -4877,24 +5010,13 @@
// "Let items be a list of all lis that are ancestor containers of the
// range's start and/or end node."
- //
- // Has to be in tree order, remember!
- var items = [];
- for (var node = range.endContainer; node != range.commonAncestorContainer; node = node.parentNode) {
- if (isHtmlElement(node, "LI")) {
- items.unshift(node);
- }
- }
- for (var node = range.startContainer; node != range.commonAncestorContainer; node = node.parentNode) {
- if (isHtmlElement(node, "LI")) {
- items.unshift(node);
- }
- }
- for (var node = range.commonAncestorContainer; node; node = node.parentNode) {
- if (isHtmlElement(node, "LI")) {
- items.unshift(node);
- }
- }
+ var items = getDescendants(document).filter(function(node) {
+ return isHtmlElement(node, "li")
+ && (isAncestor(node, range.startContainer)
+ || node == range.startContainer
+ || isAncestor(node, range.endContainer)
+ || node == range.endContainer);
+ });
// "For each item in items, normalize sublists of item."
for (var i = 0; i < items.length; i++) {
@@ -4905,28 +5027,19 @@
var newRange = blockExtend(range);
// "Let node list be a list of nodes, initially empty."
- var nodeList = [];
-
+ //
// "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 an 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."
- for (
- var node = newRange.startContainer;
- node != nextNodeDescendants(newRange.endContainer);
- node = nextNode(node)
- ) {
- if (isEditable(node)
- && isContained(node, newRange)
- && (!nodeList.length || !isAncestor(nodeList[nodeList.length - 1], node))
+ var nodeList = getContainedNodes(newRange, function(node) {
+ return isEditable(node)
&& !isIndentationElement(node)
&& (isHtmlElement(node, ["OL", "UL"])
|| isHtmlElement(node.parentNode, ["OL", "UL"])
- || isAllowedChild(node, "li"))) {
- nodeList.push(node);
- }
- }
+ || isAllowedChild(node, "li"));
+ });
// "If mode is "disable", then while node list is not empty:"
if (mode == "disable") {
@@ -4956,6 +5069,9 @@
sublist.push(nodeList.shift());
}
+ // "Record the values of sublist, and let values be the result."
+ var values = recordValues(sublist);
+
// "Split the parent of sublist."
splitParent(sublist);
@@ -4963,6 +5079,9 @@
for (var i = 0; i < sublist.length; i++) {
fixDisallowedAncestors(sublist[i]);
}
+
+ // "Restore the values from values."
+ restoreValues(values);
}
// "Otherwise, while node list is not empty:"
@@ -5009,6 +5128,10 @@
// "Let children be the children of node."
var children = [].slice.call(node.childNodes);
+ // "Record the values of children, and let values be the
+ // result."
+ var values = recordValues(children);
+
// "Remove node, preserving its descendants."
removePreservingDescendants(node);
@@ -5020,6 +5143,9 @@
function(node) { return isHtmlElement(node, tagName) },
function() { return document.createElement(tagName) });
+ // "Restore the values from values."
+ restoreValues(values);
+
// "Prepend the descendants of node that are HTML elements with
// local name other tag name (if any) to node list."
nodeList = [].slice.call(node.querySelectorAll(otherTagName)).concat(nodeList);
@@ -5037,6 +5163,10 @@
// "If node is the child of an HTML element with local name other
// tag name:"
if (isHtmlElement(node.parentNode, otherTagName)) {
+ // "Record the values of the one-node list consisting of node,
+ // and let values be the result."
+ var values = recordValues([node]);
+
// "Split the parent of the one-node list consisting of
// node."
splitParent([node]);
@@ -5049,6 +5179,9 @@
function(node) { return isHtmlElement(node, tagName) },
function() { return document.createElement(tagName) });
+ // "Restore the values from values."
+ restoreValues(values);
+
// "Prepend the descendants of node that are HTML elements with
// local name other tag name (if any) to node list."
nodeList = [].slice.call(node.querySelectorAll(otherTagName)).concat(nodeList);
@@ -5350,9 +5483,16 @@
normalizeSublists(items[i]);
}
+ // "Record the values of the one-node list consisting of node, and
+ // let values be the result."
+ var values = recordValues([node]);
+
// "Split the parent of the one-node list consisting of node."
splitParent([node]);
+ // "Restore the values from values."
+ restoreValues(values);
+
// "If node is a dd or dt, and it is not an allowed child of any of
// its ancestors in the same editing host, set the tag name of node
// to the default single-line container name and let node be the
@@ -5595,6 +5735,9 @@
&& !getDescendants(node).some(isProhibitedParagraphChild);
});
+ // "Record the values of node list, and let values be the result."
+ var values = recordValues(nodeList);
+
// "For each node in node list, while node is the descendant of an
// editable HTML element in the same editing host, which has local name
// "address", "dd", "div", "dt", "h1", "h2", "h3", "h4", "h5", "h6",
@@ -5613,6 +5756,9 @@
}
}
+ // "Restore the values from values."
+ restoreValues(values);
+
// "While node list is not empty:"
while (nodeList.length) {
var sublist;
@@ -5624,10 +5770,17 @@
// list."
sublist = [].slice.call(nodeList[0].childNodes);
+ // "Record the values of sublist, and let values be the
+ // result."
+ var values = recordValues(sublist);
+
// "Remove the first member of node list from its parent,
// preserving its descendants."
removePreservingDescendants(nodeList[0]);
+ // "Restore the values from values."
+ restoreValues(values);
+
// "Remove the first member from node list."
nodeList.shift();
@@ -6891,24 +7044,13 @@
action: function() {
// "Let items be a list of all lis that are ancestor containers of the
// active range's start and/or end node."
- //
- // Has to be in tree order, remember!
- var items = [];
- for (var node = getActiveRange().endContainer; node != getActiveRange().commonAncestorContainer; node = node.parentNode) {
- if (isHtmlElement(node, "LI")) {
- items.unshift(node);
- }
- }
- for (var node = getActiveRange().startContainer; node != getActiveRange().commonAncestorContainer; node = node.parentNode) {
- if (isHtmlElement(node, "LI")) {
- items.unshift(node);
- }
- }
- for (var node = getActiveRange().commonAncestorContainer; node; node = node.parentNode) {
- if (isHtmlElement(node, "LI")) {
- items.unshift(node);
- }
- }
+ var items = getDescendants(document).filter(function(node) {
+ return isHtmlElement(node, "li")
+ && (isAncestor(node, getActiveRange().startContainer)
+ || node == getActiveRange().startContainer
+ || isAncestor(node, getActiveRange().endContainer)
+ || node == getActiveRange().endContainer);
+ });
// "For each item in items, normalize sublists of item."
for (var i = 0; i < items.length; i++) {
@@ -6919,34 +7061,17 @@
var newRange = blockExtend(getActiveRange());
// "Let node list be a list of nodes, initially empty."
- var nodeList = [];
-
- // "For each node node contained in new range:"
- for (
- var node = newRange.startContainer;
- node != nextNodeDescendants(newRange.endContainer);
- node = nextNode(node)
- ) {
- if (!isContained(node, newRange)) {
- continue;
- }
-
- // "If the last member of node list (if any) is an ancestor of
- // node, or if node is not editable, continue with the next node."
- if ((nodeList.length && isAncestor(nodeList[nodeList.length - 1], node))
- || !isEditable(node)) {
- continue;
- }
-
- // "If node has no editable descendants, or is an ol or ul, or is
- // an li whose parent is an ol or ul, append it to node list."
- if (!hasEditableDescendants(node)
- || isHtmlElement(node, ["OL", "UL"])
- || (isHtmlElement(node, "LI")
- && isHtmlElement(node.parentNode, ["OL", "UL"]))) {
- nodeList.push(node);
- }
- }
+ //
+ // "For each node 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; and either node has no editable descendants, or is
+ // an ol or ul, or is an li whose parent is an ol or ul."
+ var nodeList = getContainedNodes(newRange, function(node) {
+ return isEditable(node)
+ && (!getDescendants(node).some(isEditable)
+ || isHtmlElement(node, ["ol", "ul"])
+ || (isHtmlElement(node, "li") && isHtmlElement(node.parentNode, ["ol", "ul"])));
+ });
// "While node list is not empty:"
while (nodeList.length) {
@@ -6980,13 +7105,17 @@
sublist.push(nodeList.shift());
}
+ // "Record the values of sublist, and let values be the result."
+ var values = recordValues(sublist);
+
// "Split the parent of sublist, with new parent null."
splitParent(sublist);
// "Fix disallowed ancestors of each member of sublist."
- for (var i = 0; i < sublist.length; i++) {
- fixDisallowedAncestors(sublist[i]);
- }
+ sublist.forEach(fixDisallowedAncestors);
+
+ // "Restore the values from values."
+ restoreValues(values);
}
}
};
--- a/source.html Mon Jul 11 13:58:51 2011 -0600
+++ b/source.html Tue Jul 12 11:28:30 2011 -0600
@@ -256,6 +256,18 @@
especially since in many cases, the command's effect isn't currently
interoperable anyway. I'll switch them back to doing nothing if implementers
think this is a problem.
+
+ <li>The CSS styling flag is an issue. Currently authors are forced to turn
+ it entirely on or entirely off. If it's on, it produces stuff like <code
+ title><span style=font-weight:bold></code> instead of <code
+ title><b></code>, while if it's off, it produces stuff like <code
+ title><font color=red></code> instead of <code title><span
+ style=color:red></code>. The issue is that authors might want a mix, like
+ making the markup as concise as possible while still conforming, and they
+ can't do that. Changing the flag on a per-command basis doesn't help because
+ of things like the "restore the values" algorithm, which might create several
+ different types of style at once and has to use the same styling flag for all
+ of them.
</ul>
<p class=XXX>A variety of other issues are also noted in the text, formatted
@@ -1474,6 +1486,65 @@
<li>Append the <var>node</var> as the last [[child]] of <var>candidate</var>,
<span>preserving ranges</span>.
</ol>
+
+<p>To <dfn>record the values</dfn> of a list of [[nodes]] <var>node list</var>:
+
+<ol>
+ <li>Let <var>values</var> be a list of ([[node]], <span>command</span>,
+ <span>specified value</span>) triples, initially empty.
+
+ <li>For each <var>node</var> in <var>node list</var>, for each
+ <var>command</var> in the list "subscript", "bold", "fontName", "fontSize",
+ "foreColor", "hiliteColor", "italic", "strikethrough", and "underline" in
+ that order:
+ <!-- As with removeFormat, we put subscript first so it doesn't interfere
+ with fontSize, and omit superscript because it's redundant with subscript.
+ -->
+
+ <ol>
+ <li>Let <var>ancestor</var> equal <var>node</var>.
+
+ <li>If <var>ancestor</var> is not an [[element]], set it to its [[parent]].
+
+ <li>While <var>ancestor</var> is an [[element]] and its <span>specified
+ value</span> for <var>command</var> is null, set it to its [[parent]].
+
+ <li>If <var>ancestor</var> is an [[element]], add (<var>node</var>,
+ <var>command</var>, <var>ancestor</var>'s <span>specified value</span> for
+ <var>command</var>) to <var>values</var>. Otherwise add (<var>node</var>,
+ <var>command</var>, null) to <var>values</var>.
+ </ol>
+
+ <li>Return <var>values</var>.
+</ol>
+
+<p>To <dfn>restore the values</dfn> specified by a list <var>values</var>
+returned by the <span>record the values</span> algorithm:
+
+<ol>
+ <li>For each (<var>node</var>, <var>command</var>, <var>value</var>) triple
+ in <var>values</var>:
+
+ <ol>
+ <li>Let <var>ancestor</var> equal <var>node</var>.
+
+ <li>If <var>ancestor</var> is not an [[element]], set it to its [[parent]].
+
+ <li>While <var>ancestor</var> is an [[element]] and its <span>specified
+ value</span> for <var>command</var> is null, set it to its [[parent]].
+
+ <li>If <var>value</var> is null and <var>ancestor</var> is an [[element]],
+ <span>push down values</span> on <var>node</var> for <var>command</var>,
+ with <var>new value</var> null.
+
+ <li>Otherwise, if <var>ancestor</var> is an [[element]] and its
+ <span>specified value</span> for <var>command</var> is different from
+ <var>value</var>, or if <var>ancestor</var> is not an [[element]] and
+ <var>value</var> is not null, <span>force the value</span> of
+ <var>command</var> to <var>value</var> on <var>node</var>.
+ </ol>
+</ol>
+
<!-- @} -->
<h3>Clearing an element's value</h3>
@@ -3039,18 +3110,26 @@
"dt", or "dd".
<p>The <dfn>default single-line container name</dfn> is "p".
-<!-- Possibly to be made configurable later. -->
+<!-- TODO V2: Make this configurable. -->
<!-- @} -->
<h3>Assorted block formatting command algorithms</h3>
<!-- @{ -->
<p>To <dfn>fix disallowed ancestors</dfn> of <var>node</var>:
+<!-- TODO V2: When breaking a non-inline element out of an inline element, like
+p in b or whatever, it would make sense to re-wrap the contents in the inline
+tag. -->
<ol>
<li>If <var>node</var> is not <span>editable</span>, abort these steps.
<li>If <var>node</var> is not an <span>allowed child</span> of any of its
- [[ancestors]] <span>in the same editing host</span>:
+ [[ancestors]] <span>in the same editing host</span>, and is not an <span>HTML
+ element</span> with [[localname]] equal to the <span>default single-line
+ container name</span>:
+ <!-- The requirement about default containers is to prevent an infinite loop.
+ This case is really intended to handle stuff like list items or table cells
+ that wander outside their proper place. -->
<ol>
<li>If <var>node</var> is a [[dd]] or [[dt]], <span>wrap</span> the
@@ -3077,9 +3156,14 @@
<li>Abort these steps.
</ol>
+ <li><span>Record the values</span> of the one-[[node]] list consisting of
+ <var>node</var>, and let <var>values</var> be the result.
+
<li>While <var>node</var> is not an <span>allowed child</span> of its
[[parent]], <span>split the parent</span> of the one-[[node]] list consisting
of <var>node</var>.
+
+ <li><span>Restore the values</span> from <var>values</var>.
</ol>
<p>To <dfn>normalize sublists</dfn> in a [[node]] <var>item</var>:
@@ -3709,7 +3793,7 @@
<li>If <var>end block</var>'s [[firstchild]] is not an <span>inline
node</span>, abort these steps.
- <li>Let <var>children</var> be an array of [[nodes]], initially empty.
+ <li>Let <var>children</var> be a list of [[nodes]], initially empty.
<li>Append the first [[child]] of <var>end block</var> to
<var>children</var>.
@@ -3719,6 +3803,9 @@
node</span>, append <var>children</var>'s last member's [[nextsibling]] to
<var>children</var>.
+ <li><span>Record the values</span> of <var>children</var>, and let
+ <var>values</var> be the result.
+
<li>While <var>children</var>'s first member's [[parent]] is not <var>start
block</var>, <span>split the parent</span> of <var>children</var>.
@@ -3744,9 +3831,21 @@
node</span> and <var>start block</var>'s [[lastchild]] is a [[br]], remove
<var>start block</var>'s [[lastchild]] from it.
- <li>While the [[nextsibling]] of <var>reference node</var> is neither null
- nor a [[br]] nor a <span>block node</span>, append the [[nextsibling]] of
- <var>reference node</var> as the last [[child]] of <var>start block</var>,
+ <li>Let <var>nodes to move</var> be a list of [[nodes]], initially empty.
+
+ <li>If <var>reference node</var>'s [[nextsibling]] is neither null nor a
+ [[br]] nor a <span>block node</span>, append it to <var>nodes to
+ move</var>.
+
+ <li>While <var>nodes to move</var> is nonempty and its last member's
+ [[nextsibling]] is neither null nor a [[br]] nor a <span>block node</span>,
+ append it to <var>nodes to move</var>.
+
+ <li><span>Record the values</span> of <var>nodes to move</var>, and let
+ <var>values</var> be the result.
+
+ <li>For each <var>node</var> in <var>nodes to move</var>, append
+ <var>node</var> as the last [[child]] of <var>start block</var>,
<span>preserving ranges</span>.
<li>If the [[nextsibling]] of <var>reference node</var> is a [[br]], remove
@@ -3765,6 +3864,9 @@
and <var>start block</var>'s [[lastchild]] is a [[br]], remove <var>start
block</var>'s [[lastchild]] from it.
+ <li><span>Record the values</span> of <var>end block</var>'s [[children]],
+ and let <var>values</var> be the result.
+
<li>While <var>end block</var> has [[children]], append the first [[child]]
of <var>end block</var> to <var>start block</var>, <span>preserving
ranges</span>.
@@ -3774,6 +3876,8 @@
<var>parent</var>, then set <var>end block</var> to <var>parent</var>.
</ol>
+ <li><span>Restore the values</span> from <var>values</var>.
+
<li>If <var>start block</var> has no [[children]], call
[[createelement|"br"]] on the [[contextobject]] and append the result as the
last [[child]] of <var>start block</var>.
@@ -3785,13 +3889,6 @@
<p>To <dfn>split the parent</dfn> of a list <var>node list</var> of consecutive
[[sibling]] [[nodes]]:
-<p class=XXX>Pretty much any time we call this algorithm, it can cause trouble
-if the parent had styles, classes, etc. There's not going to be any general
-way to handle this, but we should at least try to handle the special case of
-inline styles, because Firefox does actually add them to arbitrary elements.
-Also, when splitting out of an inline parent, it might be good to wrap all the
-inline descendants in a clone of the former parent.
-
<ol>
<li>Let <var>original parent</var> be the [[parent]] of the first member of
<var>node list</var>.
@@ -4326,26 +4423,6 @@
indentation element, as does the spec.
-->
- <div class=XXX>
- <p>We don't handle a case like
-
- <xmp><ol><ol style="color: red"><li>foo<li>bar</ol><li>baz</ol></xmp>
-
- <p>If the inner [[ol]] is selected to be outdented, "foo" and "bar" will stop
- being red. It seems nontrivial to handle this case in general, since we
- can't group [[li]]s. If the list we're outdenting is a child of a non-list,
- then we can just change it to a div. Hopefully
- <a href=http://www.w3.org/Bugs/Public/show_bug.cgi?id=13128>HTML bug
- 13128</a> will get fixed, in which case I can just use a div here too.
- </div>
- <!--
- Chrome 12 dev seems to special-case style attributes by converting them to
- the corresponding inline markup elements (at least in easy cases like color).
- For other attributes and non-WebKit browsers (IE9/FF4/O11.10), it looks like
- all the attributes are just removed. Maybe we should try to copy WebKit
- here.
- -->
-
<ol>
<li>Unset the <code data-anolis-spec=html
title=attr-ol-reversed>reversed</code>, <code data-anolis-spec=html
@@ -4357,8 +4434,23 @@
<li>If <var>node</var> has attributes, and its [[parent]] is not an [[ol]]
or [[ul]], <span>set the tag name</span> of <var>node</var> to "div".
-
- <li>Otherwise remove <var>node</var>, <span>preserving its descendants</span>.
+ <!--
+ We can't turn it into a div if it's the child of an ol or ul, because
+ that's not currently allowed. TODO V2: change this if
+ http://www.w3.org/Bugs/Public/show_bug.cgi?id=13128 is fixed and we can
+ make it a div.
+ -->
+
+ <li>Otherwise:
+
+ <ol>
+ <li><span>Record the values</span> of <var>node</var>'s [[children]], and
+ let <var>values</var> be the result.
+
+ <li>Remove <var>node</var>, <span>preserving its descendants</span>.
+
+ <li><span>Restore the values</span> from <var>values</var>.
+ </ol>
<li><span>Fix disallowed ancestors</span> of each member of
<var>children</var>.
@@ -4785,10 +4877,15 @@
[[localname]] <var>tag name</var>, remove the first member from <var>node
list</var> and append it to <var>sublist</var>.
+ <li><span>Record the values</span> of <var>sublist</var>, and let
+ <var>values</var> be the result.
+
<li><span>Split the parent</span> of <var>sublist</var>.
<li><span>Fix disallowed ancestors</span> of each member of
<var>sublist</var>.
+
+ <li><span>Restore the values</span> from <var>values</var>.
</ol>
<li>Otherwise, while <var>node list</var> is not empty:
@@ -4809,10 +4906,9 @@
<li>If <var>sublist</var> contains more than one member, <span>wrap</span>
<var>sublist</var>, with <span>sibling criteria</span> matching nothing and
- <span>new parent instructions</span> returning the result of calling <code
- data-anolis-spec=domcore
- title=dom-Document-createElement>createElement("li")</code> on the
- [[contextobject]]. Let <var>node</var> be the result.
+ <span>new parent instructions</span> returning the result of calling
+ [[createelement|"li"]] on the [[contextobject]]. Let <var>node</var> be
+ the result.
<li>Otherwise, let <var>node</var> be the sole member of
<var>sublist</var>.
@@ -4823,16 +4919,18 @@
<ol>
<li>Let <var>children</var> be the [[children]] of <var>node</var>.
+ <li><span>Record the values</span> of <var>children</var>, and let
+ <var>values</var> be the result.
+
<li>Remove <var>node</var>, <span>preserving its descendants</span>.
<li><span>Wrap</span> <var>children</var>, with <span>sibling
criteria</span> matching any <span>HTML element</span> with [[localname]]
- <var>tag name</var> and <span>new parent
- instructions</span> returning the result of calling <code
- data-anolis-spec=domcore
- title=dom-Document-createElement>createElement(<var>tag
- name</var>)</code> on the [[contextobject]]. Let <var>node</var> be the
- result.
+ <var>tag name</var> and <span>new parent instructions</span> returning
+ the result of calling [[createelement|<var>tag name</var>]] on the
+ [[contextobject]]. Let <var>node</var> be the result.
+
+ <li><span>Restore the values</span> from <var>values</var>.
<li>Prepend the [[descendants]] of <var>node</var> that are <span
title="HTML element">HTML elements</span> with [[localname]] <var>other
@@ -4875,6 +4973,9 @@
with [[localname]] <var>other tag name</var>:
<ol>
+ <li><span>Record the values</span> of the one-[[node]] list consisting of
+ <var>node</var>, and let <var>values</var> be the result.
+
<li><span>Split the parent</span> of the one-[[node]] list consisting of
<var>node</var>.
@@ -4882,9 +4983,9 @@
<var>node</var>, with <span>sibling criteria</span> matching any
<span>HTML element</span> with [[localname]] <var>tag name</var>,
and with <span>new parent instructions</span> returning the result of
- calling <code data-anolis-spec=domcore
- title=dom-Document-createElement>createElement(<var>tag
- name</var>)</code> on the [[contextobject]].
+ calling [[createelement|<var>tag name</var>]] on the [[contextobject]].
+
+ <li><span>Restore the values</span> from <var>values</var>.
<li>Prepend the [[descendants]] of <var>node</var> that are <span
title="HTML element">HTML elements</span> with [[localname]] <var>other
@@ -5159,9 +5260,14 @@
<li><span>Normalize sublists</span> of each <var>item</var> in
<var>items</var>.
+ <li><span>Record the values</span> of the one-[[node]] list consisting of
+ <var>node</var>, and let <var>values</var> be the result.
+
<li><span>Split the parent</span> of the one-[[node]] list consisting of
<var>node</var>.
+ <li><span>Restore the values</span> from <var>values</var>.
+
<li>If <var>node</var> is a [[dd]] or [[dt]], and it is not an
<span>allowed child</span> of any of its [[ancestors]] <span>in the same
editing host</span>, <span>set the tag name</span> of <var>node</var> to
@@ -5437,6 +5543,9 @@
of "p" or a [[dd]] or [[dt]], and <var>node</var> is not the [[ancestor]] of
a <span>prohibited paragraph child</span>.
+ <li><span>Record the values</span> of <var>node list</var>, and let
+ <var>values</var> be the result.
+
<li>For each <var>node</var> in <var>node list</var>, while <var>node</var>
is the [[descendant]] of an <span>editable</span> <span>HTML element</span>
<span>in the same editing host</span>, which has [[localname]] "address",
@@ -5457,6 +5566,8 @@
out of lists or tables or such if they happen to be nested in a <div>.
-->
+ <li><span>Restore the values</span> from <var>values</var>.
+
<!--
We have two different behaviors, one for div and p and one for everything
else. The basic difference is that for div and p, we assume that it should
@@ -5517,9 +5628,14 @@
<li>Let <var>sublist</var> be the [[children]] of the first member of
<var>node list</var>.
+ <li><span>Record the values</span> of <var>sublist</var>, and let
+ <var>values</var> be the result.
+
<li>Remove the first member of <var>node list</var> from its [[parent]],
<span>preserving its descendants</span>.
+ <li><span>Restore the values</span> from <var>values</var>.
+
<li>Remove the first member from <var>node list</var>.
</ol>
@@ -6791,37 +6907,33 @@
<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>:
-
- <ol>
- <li>If the last member of <var>node list</var> (if any) is an [[ancestor]]
- of <var>node</var>, or if <var>node</var> is not <span>editable</span>,
- continue with the next <var>node</var>.
-
- <!--
- This step is kind of weird. For regular outdenting, we start at the inside
- and outdent going out, so that we remove the innermost indentation, on the
- theory that that will produce the cleanest markup (remove the most nodes).
- For lists, we remove the outermost indentation, because it makes a
- difference whether we remove inner or outer indentation, and logically we
- want to remove outer. E.g.,
-
- <ol><li>foo</li><ul><li>bar</li></ul></ol>
-
- should become
-
- foo<ul><li>bar</li></ul>
-
- not
-
- foo<ol><li>bar</li></ol>.
-
- But this is a bit weird and I'm wondering if it's really correct.
- -->
- <li>If <var>node</var> has no <span>editable</span> [[descendants]], or is
- an [[ol]] or [[ul]], or is an [[li]] whose [[parent]] is an [[ol]] or
- [[ul]], append it to <var>node list</var>.
- </ol>
+ <li>For each [[node]] <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>; and either <var>node</var> has no
+ <span>editable</span> [[descendants]], or is an [[ol]] or [[ul]], or is an
+ [[li]] whose [[parent]] is an [[ol]] or [[ul]].
+ <!--
+ This step is kind of weird. For regular outdenting, we start at the inside
+ and outdent going out, so that we remove the innermost indentation, on the
+ theory that that will produce the cleanest markup (remove the most nodes).
+ For lists, we remove the outermost indentation, because it makes a difference
+ whether we remove inner or outer indentation, and logically we want to remove
+ outer. E.g.,
+
+ <ol><li>foo</li><ul><li>bar</li></ul></ol>
+
+ should become
+
+ foo<ul><li>bar</li></ul>
+
+ not
+
+ foo<ol><li>bar</li></ol>.
+
+ But this is a bit weird and I'm wondering if it's really correct. TODO V2:
+ Reexamine this.
+ -->
<li>While <var>node list</var> is not empty:
@@ -6842,10 +6954,15 @@
list</var> is not an [[ol]] or [[ul]], remove the first member of <var>node
list</var> and append it to <var>sublist</var>.
+ <li><span>Record the values</span> of <var>sublist</var>, and let
+ <var>values</var> be the result.
+
<li><span>Split the parent</span> of <var>sublist</var>.
<li><span>Fix disallowed ancestors</span> of each member of
<var>sublist</var>.
+
+ <li><span>Restore the values</span> from <var>values</var>.
</ol>
</ol>
<!-- @} -->
--- a/tests.js Mon Jul 11 13:58:51 2011 -0600
+++ b/tests.js Tue Jul 12 11:28:30 2011 -0600
@@ -433,6 +433,37 @@
'<div><div><p>foo</p></div></div><div><div><!--abc--><div>[]bar</div></div></div>',
'<div><div><p>foo</p></div></div><div><div><div><!--abc-->[]bar</div></div></div>',
+ // Styled stuff with collapsed selection
+ '<p style=color:red>foo<p>[]bar',
+ '<p style=color:red>foo<p style=color:blue>[]bar',
+ '<p>foo<p style=color:blue>[]bar',
+ '<p><font color=red>foo</font><p>[]bar',
+ '<p><font color=red>foo</font><p><font color=blue>[]bar</font>',
+ '<p>foo<p><font color=blue>[]bar</font>',
+ '<p><span style=color:red>foo</font><p>[]bar',
+ '<p><span style=color:red>foo</font><p><span style=color:blue>[]bar</font>',
+ '<p>foo<p><span style=color:blue>[]bar</font>',
+
+ '<p style=background-color:salmon>foo<p>[]bar',
+ '<p style=background-color:salmon>foo<p style=background-color:aqua>[]bar',
+ '<p>foo<p style=background-color:aqua>[]bar',
+ '<p><span style=background-color:salmon>foo</font><p>[]bar',
+ '<p><span style=background-color:salmon>foo</font><p><span style=background-color:aqua>[]bar</font>',
+ '<p>foo<p><span style=background-color:aqua>[]bar</font>',
+
+ '<p style=text-decoration:underline>foo<p>[]bar',
+ '<p style=text-decoration:underline>foo<p style=text-decoration:line-through>[]bar',
+ '<p>foo<p style=text-decoration:line-through>[]bar',
+ '<p><u>foo</u><p>[]bar',
+ '<p><u>foo</u><p><s>[]bar</s>',
+ '<p>foo<p><s>[]bar</s>',
+
+ '<p style=color:red>foo</p>[]bar',
+ 'foo<p style=color:blue>[]bar',
+ '<div style=color:red><p style=color:green>foo</div>[]bar',
+ '<div style=color:red><p style=color:green>foo</div><p style=color:blue>[]bar',
+ '<p style=color:red>foo<div style=color:blue><p style=color:green>[]bar',
+
// Uncollapsed selection
'foo[bar]baz',
@@ -1043,6 +1074,8 @@
'<p>[foo<h1>bar]</h1>',
'<h1>[foo</h1><h2>bar]</h2>',
'<div>[foo</div>bar]',
+
+ ['<p>', '<div style=color:red>[foo]</div>'],
],
//@}
forwarddelete: [
@@ -1198,6 +1231,37 @@
'<div><div><p>foo[]</p></div></div><div><div><!--abc--><div>bar</div></div></div>',
'<div><div><p>foo[]</p></div></div><div><div><div><!--abc-->bar</div></div></div>',
+ // Styled stuff with collapsed selection
+ '<p style=color:red>foo[]<p>bar',
+ '<p style=color:red>foo[]<p style=color:blue>bar',
+ '<p>foo[]<p style=color:blue>bar',
+ '<p><font color=red>foo[]</font><p>bar',
+ '<p><font color=red>foo[]</font><p><font color=blue>bar</font>',
+ '<p>foo[]<p><font color=blue>bar</font>',
+ '<p><span style=color:red>foo[]</font><p>bar',
+ '<p><span style=color:red>foo[]</font><p><span style=color:blue>bar</font>',
+ '<p>foo[]<p><span style=color:blue>bar</font>',
+
+ '<p style=background-color:salmon>foo[]<p>bar',
+ '<p style=background-color:salmon>foo[]<p style=background-color:aqua>bar',
+ '<p>foo[]<p style=background-color:aqua>bar',
+ '<p><span style=background-color:salmon>foo[]</font><p>bar',
+ '<p><span style=background-color:salmon>foo[]</font><p><span style=background-color:aqua>bar</font>',
+ '<p>foo[]<p><span style=background-color:aqua>bar</font>',
+
+ '<p style=text-decoration:underline>foo[]<p>bar',
+ '<p style=text-decoration:underline>foo[]<p style=text-decoration:line-through>bar',
+ '<p>foo[]<p style=text-decoration:line-through>bar',
+ '<p><u>foo[]</u><p>bar',
+ '<p><u>foo[]</u><p><s>bar</s>',
+ '<p>foo[]<p><s>bar</s>',
+
+ '<p style=color:red>foo[]</p>bar',
+ 'foo[]<p style=color:blue>bar',
+ '<div style=color:red><p style=color:green>foo[]</div>bar',
+ '<div style=color:red><p style=color:green>foo[]</div><p style=color:blue>bar',
+ '<p style=color:red>foo[]<div style=color:blue><p style=color:green>bar',
+
// Uncollapsed selection (should be same as delete command)
'foo[bar]baz',
@@ -1639,6 +1703,10 @@
['<nobr>abc</nobr>', '<nobr>f[o]o</nobr>'],
['<nobr>abc</nobr>', 'f[o]o'],
+
+ ['<p>abc', '<font color=red>foo[]bar</font>'],
+ ['<p>abc', '<span style=color:red>foo[]bar</span>'],
+ ['<p>abc', '<span style=font-variant:small-caps>foo[]bar</span>'],
],
//@}
insertimage: [