--- a/autoimplementation.html Thu Jun 02 15:37:20 2011 -0600
+++ b/autoimplementation.html Fri Jun 03 13:08:06 2011 -0600
@@ -943,6 +943,22 @@
'<p>foo[bar<p><b>baz]quz</b>',
'<div><p>foo<p>[bar<p>baz]</div>',
+
+ 'foo[<br>]bar',
+ '<p>foo[</p><p>]bar</p>',
+ '<p>foo[</p><p>]bar<br>baz</p>',
+ 'foo[<p>]bar</p>',
+ 'foo[<p>]bar<br>baz</p>',
+ 'foo[<p>]bar</p>baz',
+ '<p>foo[</p>]bar',
+ '<p>foo[</p>]bar<br>baz',
+ '<p>foo[</p>]bar<p>baz</p>',
+ 'foo[<div><p>]bar</div>',
+ '<div><p>foo[</p></div>]bar',
+ 'foo[<div><p>]bar</p>baz</div>',
+ 'foo[<div>]bar<p>baz</p></div>',
+ '<div><p>foo</p>bar[</div>]baz',
+ '<div>foo<p>bar[</p></div>]baz',
],
insertorderedlist: [
'foo[]bar',
--- a/editcommands.html Thu Jun 02 15:37:20 2011 -0600
+++ b/editcommands.html Fri Jun 03 13:08:06 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-2-june-2011>Work in Progress — Last Update 2 June 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-—-last-update-3-june-2011>Work in Progress — Last Update 3 June 2011</h2>
<dl>
<dt>Editor
<dd>Aryeh Gregor <ayg+spec@aryeh.name>
@@ -758,6 +758,9 @@
<li>If <var title="">original parent</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>, remove it 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>.
+ <li>Otherwise, <a href=#remove-extraneous-line-breaks-before>remove extraneous line breaks before</a>
+ <var title="">original parent</var>.
+
<li>If <var title="">node list</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> is null,
<a href=#remove-extraneous-line-breaks-at-the-end-of>remove extraneous line breaks at the end of</a> <var title="">node
list</var>'s last 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>.
@@ -933,26 +936,22 @@
block element empty, when we really need to add 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> <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> no matter
what so it doesn't collapse.
+<p class=XXX>I'm uncertain about the use of prohibited paragraph children here.
+I'm using it mostly because it's convenient and seems relatively sensible. If
+we really want to use it, we probably want to change its name.
+
<ol>
<li>Let <var title="">range</var> be the <a href=#active-range>active range</a>.
<li>If <var title="">range</var> is null, abort these steps and do nothing.
- <li>If no <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> is <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in <var title="">range</var>, and
- either <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is not a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> or <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#comment>Comment</a></code> node
- or <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>,
- and either <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is not a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> or <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#comment>Comment</a></code>
- node or <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is 0, call <code class=external data-anolis-spec=domrange title=dom-Range-deleteContents><a href=http://html5.org/specs/dom-range.html#dom-range-deletecontents>deleteContents()</a></code> on <var title="">range</var>
- and abort these steps.
- <!-- This is precisely the case where deleteContents() will not alter the
- DOM, just collapse the selection. I think. -->
-
- <p class=XXX>Is it possible for subsequent steps to make the range's start go
- past its end or vice versa, or does this step successfully prevent that case?
+ <li>Let <var title="">start node</var>, <var title="">start offset</var>, <var title="">end node</var>,
+ and <var title="">end offset</var> be <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> and
+ <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>nodes</a> 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>.
<!-- Drill the range down to the lowest possible level, so we don't delete
more elements than necessary. -->
- <li>While the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> of <var title="">range</var> has at least one <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>:
+ <li>While <var title="">start node</var> has at least one <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>:
<!--
We don't want to keep going when we hit an element with no children, because
then we'd do something like
@@ -966,93 +965,181 @@
-->
<ol>
- <li>If <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>, and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'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 null, set
- <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> to (<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 <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, 1 +
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>) and continue this loop from the beginning.
+ <li>If <var title="">start offset</var> is <var title="">start node</var>'s
+ <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>, and <var title="">start node</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is <a href=#in-the-same-editing-host>in the same
+ editing host</a>, and <var title="">start node</var> is not a <a href=#prohibited-paragraph-child>prohibited
+ paragraph child</a>, set <var title="">start 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 <var title="">start node</var>, then set <var title="">start node</var> to its
+ <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> and continue this loop from the beginning.
<!--
For instance:
<b>foo[</b><i>bar]</i>
+ -> <b>foo{</b><i>bar]</i>
-> <b>foo</b>{<i>bar]</i>
Then the next step will make it <b>foo</b><i>[bar]</i>.
+
+ We don't want to do this for prohibited paragraph children, because that
+ would lead to something like
+
+ <p>foo[</p><p>]bar<p>
+
+ ultimately collapsing, which is wrong. Once we do the deletion, it needs
+ to wind up <p>foo[]bar</p>, whereas an actually collapsed selection should
+ do nothing.
-->
- <li>If <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>, break from this loop.
+ <li>If <var title="">start offset</var> is <var title="">start node</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>,
+ break from this loop.
<!-- This happens if the first step brought us all the way up to the root.
The step immediately after this loop will bring us back down again. -->
- <li>Let <var title="">reference node</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>child</a> of <var title="">range</var>'s
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> equal to its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a>.
+ <li>Let <var title="">reference node</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>child</a> of <var title="">start node</var>
+ with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> equal to <var title="">start offset</var>.
<li>If <var title="">reference node</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> with 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>,
break from this loop.
<!-- Don't descend into it, since then it won't get deleted even if it's
selected. -->
- <li>Set <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> to (<var title="">reference node</var>,
- 0).
+ <li>Set <var title="">start node</var> to <var title="">reference node</var> and <var title="">start
+ offset</var> to 0.
</ol>
- <!-- Corner case: maybe we went all the way up to the end of the root. -->
- <li>If <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of its
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, then while <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> 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>
- and its 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> 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> with 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>, set
- <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> to (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 <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>,
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of 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 <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>).
-
- <li>While the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> of <var title="">range</var> has at least one <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>:
+ <li>While <var title="">end node</var> has at least one <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>:
<ol>
- <li>If <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is 0, and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'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 null, set <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> to (<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 <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>) and continue this loop from the
- beginning.
-
- <li>If <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is 0, break from this loop.
-
- <li>Let <var title="">reference node</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>child</a> of <var title="">range</var>'s
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> equal to its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> minus one.
+ <li>If <var title="">end offset</var> is 0, and <var title="">end node</var>'s
+ <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is <a href=#in-the-same-editing-host>in the same editing host</a>, and <var title="">end
+ node</var> is not a <a href=#prohibited-paragraph-child>prohibited paragraph child</a>, set <var title="">end
+ 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 <var title="">end node</var>, then set <var title="">end
+ node</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> and continue this loop from the beginning.
+
+ <li>If <var title="">end offset</var> is 0, break from this loop.
+
+ <li>Let <var title="">reference node</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>child</a> of <var title="">end node</var>
+ with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> equal to <var title="">end offset</var> minus one.
<li>If <var title="">reference node</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> with 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>,
break from this loop.
- <li>Set <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> to (<var title="">reference node</var>,
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of <var title="">reference node</var>).
+ <li>Set <var title="">end node</var> to <var title="">reference node</var> and <var title="">end
+ offset</var> to the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of <var title="">reference node</var>.
</ol>
- <li>If <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is 0, then while <var title="">range</var>'s
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> 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> and its 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> 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>
- with 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>, set <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> to (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 <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, 0).
+ <li>If (<var title="">end node</var>, <var title="">end offset</var>) is <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-bp-before title=concept-bp-before>before</a> (<var title="">start
+ node</var>, <var title="">start offset</var>), call <code class=external data-anolis-spec=domrange title=dom-Range-deleteContents><a href=http://html5.org/specs/dom-range.html#dom-range-deletecontents>deleteContents()</a></code> on <var title="">range</var>
+ and abort these steps.
+
+ <li>Set <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> to (<var title="">start node</var>,
+ <var title="">start offset</var>) and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> to (<var title="">end node</var>,
+ <var title="">end offset</var>).
<li>Let <var title="">start block</var> be the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> of
<var title="">range</var>.
<li>While <var title="">start block</var> is not a <a href=#prohibited-paragraph-child>prohibited paragraph
- child</a>, set <var title="">start block</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
-
- <p class=XXX>I'm uncertain about the use of prohibited paragraph children
- here. I'm using it mostly because it's convenient and seems relatively
- sensible. If we really want to use it, we probably want to change its name.
+ child</a> 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 <a href=#in-the-same-editing-host>in the same editing host</a>, set
+ <var title="">start block</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
<li>Let <var title="">end block</var> be the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> of
<var title="">range</var>.
<li>While <var title="">end block</var> is not a <a href=#prohibited-paragraph-child>prohibited paragraph
- child</a>, set <var title="">end block</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+ child</a> 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 <a href=#in-the-same-editing-host>in the same editing host</a>, set
+ <var title="">end block</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
<li>Call <code class=external data-anolis-spec=domrange title=dom-Range-deleteContents><a href=http://html5.org/specs/dom-range.html#dom-range-deletecontents>deleteContents()</a></code> on <var title="">range</var>.
-
- <li>If <var title="">start block</var> 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 null, or <var title="">end
- block</var> 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 null, or <var title="">start block</var> 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> or <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 <var title="">end block</var>, abort these steps.
+ <!--
+ Now we need to merge blocks. The simplest case is something like
+
+ <p>fo[o</p><p>bar</p><p>b]az</p>
+ -> <p>fo</p>{}<p>az</p>
+ -> <p>fo{}az</p>
+
+ where neither block descends from the other. More complicated is something
+ like
+
+ foo[<p>]bar</p>
+ -> foo[]bar
+
+ or
+
+ <p>foo[</p>]bar
+ -> <p>foo[]bar</p>
+
+ where one descends from the other.
+ -->
+
+ <li>If <var title="">start block</var> is not <a href=#in-the-same-editing-host>in the same editing host</a> as
+ <var title="">end block</var>, or <var title="">start block</var> is neither an <a href=#editing-host>editing
+ host</a> nor a <a href=#prohibited-paragraph-child>prohibited paragraph child</a>, or <var title="">end
+ block</var> is neither an <a href=#editing-host>editing host</a> nor a <a href=#prohibited-paragraph-child>prohibited
+ paragraph child</a>, or <var title="">start block</var> and <var title="">end block</var>
+ are the same, abort these steps.
+
+ <li>If <var title="">start block</var> 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="">end block</var>:
+ <!-- Just repeatedly blow up the end block. -->
+
+ <ol>
+ <li>Let <var title="">reference node</var> be <var title="">end block</var>.
+
+ <li>While <var title="">reference node</var> is not a <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>, set <var title="">reference node</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+
+ <li>Set the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> of <var title="">range</var> to
+ (<var title="">start block</var>, <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of <var title="">reference node</var>).
+
+ <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>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>.
+
+ <li>While <var title="">children</var>'s last member is not 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>, and
+ <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> is an <a href=#inline-node>inline
+ 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>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>.
+
+ <li>If 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 <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>
+ equal to its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> 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> and is not the first member of
+ <var title="">children</var>, remove that <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code> 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>.
+
+ <li>Abort these steps.
+ </ol>
<li>Set the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> of <var title="">range</var> to
(<var title="">start block</var>, <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of <var title="">start block</var>).
+ <li>If <var title="">start block</var> is 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>descendant</a> of <var title="">end block</var>:
+ <!-- Pull in everything that comes after <var title>start block</var>, until we hit
+ a br or prohibited paragraph child. -->
+
+ <ol>
+ <li>Let <var title="">reference node</var> be <var title="">start block</var>.
+
+ <li>While <var title="">reference node</var> is not a <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>, set <var title="">reference node</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+
+ <li>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=#prohibited-paragraph-child>prohibited paragraph child</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>, <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
+ it 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>.
+
+ <li>Abort these steps.
+ </ol>
+
+ <!-- In the last case, just move all the children of the end block to the
+ start block, and then get rid of any elements we emptied that way. -->
<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>.
--- a/implementation.js Thu Jun 02 15:37:20 2011 -0600
+++ b/implementation.js Fri Jun 03 13:08:06 2011 -0600
@@ -593,6 +593,10 @@
// "If original parent has no children, remove it from its parent."
if (!originalParent.hasChildNodes()) {
originalParent.parentNode.removeChild(originalParent);
+
+ // "Otherwise, remove extraneous line breaks before original parent."
+ } else {
+ removeExtraneousLineBreaksBefore(originalParent);
}
// "If node list's last member's nextSibling is null, remove extraneous
@@ -772,43 +776,36 @@
return;
}
- // "If no node is contained in range, and either range's start node is not
- // a Text or Comment node or range's start offset is its start node's
- // length, and either range's end node is not a Text or Comment node or
- // range's end offset is 0, call deleteContents() on range and abort these
- // steps."
- if (!collectContainedNodes(range).length
- && ((range.startContainer.nodeType != Node.TEXT_NODE
- && range.startContainer.nodeType != Node.COMMENT_NODE)
- || range.startOffset == getNodeLength(range.startContainer))
- && ((range.endContainer.nodeType != Node.TEXT_NODE
- && range.endContainer.nodeType != Node.COMMENT_NODE)
- || range.endOffset == 0)) {
- range.deleteContents();
- return;
- }
-
- // "While the start node of range has at least one child:"
- while (range.startContainer.hasChildNodes()) {
- // "If range's start offset is its start node's length, and its start
- // node's parent is not null, set range's start to (parent of start
- // node, 1 + index of start node) and continue this loop from the
- // beginning."
- if (range.startOffset == getNodeLength(range.startContainer)
- && range.startContainer.parentNode) {
- range.setStart(range.startContainer.parentNode, 1 + getNodeIndex(range.startContainer));
+ // "Let start node, start offset, end node, and end offset be range's start
+ // and end nodes and offsets."
+ var startNode = range.startContainer;
+ var startOffset = range.startOffset;
+ var endNode = range.endContainer;
+ var endOffset = range.endOffset;
+
+ // "While start node has at least one child:"
+ while (startNode.hasChildNodes()) {
+ // "If start offset is start node's length, and start node's parent is
+ // in the same editing host, and start node is not a prohibited
+ // paragraph child, set start offset to one plus the index of start
+ // node, then set start node to its parent and continue this loop from
+ // the beginning."
+ if (startOffset == getNodeLength(startNode)
+ && inSameEditingHost(startNode, startNode.parentNode)
+ && !isProhibitedParagraphChild(startNode)) {
+ startOffset = 1 + getNodeIndex(startNode);
+ startNode = startNode.parentNode;
continue;
}
- // "If range's start offset is its start node's length, break from this
- // loop."
- if (range.startOffset == getNodeLength(range.startContainer)) {
+ // "If start offset is start node's length, break from this loop."
+ if (startOffset == getNodeLength(startNode)) {
break;
}
- // "Let reference node be the child of range's start node with index
- // equal to its start offset."
- var referenceNode = range.startContainer.childNodes[range.startOffset];
+ // "Let reference node be the child of start node with index equal to
+ // start offset."
+ var referenceNode = startNode.childNodes[startOffset];
// "If reference node is an Element with no children, break from this
// loop."
@@ -817,41 +814,33 @@
break;
}
- // "Set range's start to (reference node, 0)."
- range.setStart(referenceNode, 0);
- }
-
- // "If range's start offset is the length of its start node, then while
- // range's start node has children and its last child is not an Element
- // with no children, set range's start to (last child of start node, length
- // of last child of start node)."
- if (range.startOffset == getNodeLength(range.startContainer)) {
- while (range.startContainer.hasChildNodes()
- && (range.lastChild.nodeType != Node.ELEMENT_NODE
- || range.lastChild.hasChildNodes())) {
- range.setStart(range.startContainer.lastChild, getNodeLength(range.startContainer.lastChild));
- }
- }
-
- // "While the end node of range has at least one child:"
- while (range.endContainer.hasChildNodes()) {
- // "If range's end offset is 0, and its end node's parent is not null,
- // set range's end to (parent of end node, index of end node) and
+ // "Set start node to reference node and start offset to 0."
+ startNode = referenceNode;
+ startOffset = 0;
+ }
+
+ // "While end node has at least one child:"
+ while (endNode.hasChildNodes()) {
+ // "If end offset is 0, and end node's parent is in the same editing
+ // host, and end node is not a prohibited paragraph child, set end
+ // offset to the index of end node, then set end node to its parent and
// continue this loop from the beginning."
- if (range.endOffset == 0
- && range.endContainer.parentNode) {
- range.setEnd(range.endContainer.parentNode, getNodeIndex(range.endContainer));
+ if (endOffset == 0
+ && inSameEditingHost(endNode, endNode.parentNode)
+ && !isProhibitedParagraphChild(endNode)) {
+ endOffset = getNodeIndex(endNode);
+ endNode = endNode.parentNode;
continue;
}
- // "If range's end offset is 0, break from this loop."
- if (range.endOffset == 0) {
+ // "If end offset is 0, break from this loop."
+ if (endOffset == 0) {
break;
}
- // "Let reference node be the child of range's end node with index
- // equal to its end offset minus one."
- var referenceNode = range.endContainer.childNodes[range.endOffset - 1];
+ // "Let reference node be the child of end node with index equal to end
+ // offset minus one."
+ var referenceNode = endNode.childNodes[endOffset - 1];
// "If reference node is an Element with no children, break from this
// loop."
@@ -860,51 +849,113 @@
break;
}
- // "Set range's end to (reference node, length of reference node)."
- range.setEnd(referenceNode, getNodeLength(referenceNode));
- }
-
- // "If range's end offset is 0, then while range's end node has children
- // and its first child is not an Element with no children, set range's end
- // to (first child of end node, 0)."
- if (range.endOffset == 0) {
- while (range.endContainer.hasChildNodes()
- && (range.lastChild.nodeType != Node.ELEMENT_NODE
- || range.lastChild.hasChildNodes())) {
- range.setEnd(range.endContainer.firstChild, 0);
- }
- }
+ // "Set end node to reference node and end offset to the length of
+ // reference node."
+ endNode = referenceNode;
+ endOffset = getNodeLength(referenceNode);
+ }
+
+ // "If (end node, end offset) is before (start node, start offset), call
+ // deleteContents() on range and abort these steps."
+ var startPoint = document.createRange();
+ startPoint.setStart(startNode, startOffset);
+ var endPoint = document.createRange();
+ endPoint.setStart(endNode, endOffset);
+ if (startPoint.compareBoundaryPoints(Range.START_TO_START, endPoint) == 1) {
+ range.deleteContents();
+ return;
+ }
+
+ // "Set range's start to (start node, start offset) and its end to (end
+ // node, end offset)."
+ range.setStart(startNode, startOffset);
+ range.setEnd(endNode, endOffset);
// "Let start block be the start node of range."
var startBlock = range.startContainer;
- // "While start block is not a prohibited paragraph child, set start block
- // to its parent."
- while (!isProhibitedParagraphChild(startBlock)) {
+ // "While start block is not a prohibited paragraph child and its parent is
+ // in the same editing host, set start block to its parent."
+ while (!isProhibitedParagraphChild(startBlock)
+ && inSameEditingHost(startBlock, startBlock.parentNode)) {
startBlock = startBlock.parentNode;
}
// "Let end block be the end node of range."
var endBlock = range.endContainer;
- // "While end block is not a prohibited paragraph child, set end block to
- // its parent."
- while (!isProhibitedParagraphChild(endBlock)) {
+ // "While end block is not a prohibited paragraph child and its parent is
+ // in the same editing host, set end block to its parent."
+ while (!isProhibitedParagraphChild(endBlock)
+ && inSameEditingHost(endBlock, endBlock.parentNode)) {
endBlock = endBlock.parentNode;
}
// "Call deleteContents() on range."
range.deleteContents();
- // "If start block or its parent is null, or end block or its parent is
- // null, or start block is an ancestor or descendant of end block, abort
- // these steps."
- if (!startBlock
- || !startBlock.parentNode
- || !endBlock
- || !endBlock.parentNode
- || isAncestor(startBlock, endBlock)
- || isDescendant(startBlock, endBlock)) {
+ // "If start block is not in the same editing host as end block, or start
+ // block is neither an editing host nor a prohibited paragraph child, or
+ // end block is neither an editing host nor a prohibited paragraph child,
+ // or start block and end block are the same, abort these steps."
+ if (!inSameEditingHost(startBlock, endBlock)
+ || (!isEditingHost(startBlock) && !isProhibitedParagraphChild(startBlock))
+ || (!isEditingHost(endBlock) && !isProhibitedParagraphChild(endBlock))
+ || startBlock == endBlock) {
+ return;
+ }
+
+ // "If start block is an ancestor of end block:"
+ if (isAncestor(startBlock, endBlock)) {
+ // "Let reference node be end block."
+ var referenceNode = endBlock;
+
+ // "While reference node is not a child of start block, set reference
+ // node to its parent."
+ while (referenceNode.parentNode != startBlock) {
+ referenceNode = referenceNode.parentNode;
+ }
+
+ // "Set the start and end of range to (start block, index of reference
+ // node)."
+ range.setStart(startBlock, getNodeIndex(referenceNode));
+ range.setEnd(startBlock, getNodeIndex(referenceNode));
+
+ // "If end block's firstChild is not an inline node, abort these
+ // steps."
+ if (!isInlineNode(endBlock.firstChild)) {
+ return;
+ }
+
+ // "Let children be an array of nodes, initially empty."
+ var children = [];
+
+ // "Append the first child of end block to children."
+ children.push(endBlock.firstChild);
+
+ // "While children's last member is not a br, and children's last
+ // member's nextSibling is an inline node, append children's last
+ // member's nextSibling to children."
+ while (!isHtmlElement(children[children.length - 1], "br")
+ && isInlineNode(children[children.length - 1].nextSibling)) {
+ children.push(children[children.length - 1].nextSibling);
+ }
+
+ // "While children's first member's parent is not start block, split
+ // the parent of children."
+ while (children[0].parentNode != startBlock) {
+ splitParent(children);
+ }
+
+ // "If the child of range's start node with index equal to its start
+ // offset is a br and is not the first member of children, remove that
+ // br from its parent."
+ if (isHtmlElement(range.startContainer.childNodes[range.startOffset], "br")
+ && range.startContainer.childNodes[range.startOffset] != children[0]) {
+ range.startContainer.removeChild(range.startContainer.childNodes[range.startOffset]);
+ }
+
+ // "Abort these steps."
return;
}
@@ -913,6 +964,36 @@
range.setStart(startBlock, getNodeLength(startBlock));
range.setEnd(startBlock, getNodeLength(startBlock));
+ // "If start block is a descendant of end block:"
+ if (isDescendant(startBlock, endBlock)) {
+ // "Let reference node be start block."
+ var referenceNode = startBlock;
+
+ // "While reference node is not a child of end block, set reference
+ // node to its parent."
+ while (referenceNode.parentNode != endBlock) {
+ referenceNode = referenceNode.parentNode;
+ }
+
+ // "While the nextSibling of reference node is neither null nor a br
+ // nor a prohibited paragraph child, append the nextSibling of
+ // reference node as the last child of start block, preserving ranges."
+ while (referenceNode.nextSibling
+ && !isHtmlElement(referenceNode.nextSibling, "br")
+ && !isProhibitedParagraphChild(referenceNode.nextSibling)) {
+ movePreservingRanges(referenceNode.nextSibling, startBlock, -1);
+ }
+
+ // "If the nextSibling of reference node is a br, remove it from its
+ // parent."
+ if (isHtmlElement(referenceNode.nextSibling, "br")) {
+ referenceNode.parentNode.removeChild(referenceNode.nextSibling);
+ }
+
+ // "Abort these steps."
+ return;
+ }
+
// "While end block has children, append the first child of end block to
// start block, preserving ranges."
while (endBlock.hasChildNodes()) {
--- a/source.html Thu Jun 02 15:37:20 2011 -0600
+++ b/source.html Fri Jun 03 13:08:06 2011 -0600
@@ -714,6 +714,9 @@
<li>If <var>original parent</var> has no [[children]], remove it from its
[[parent]].
+ <li>Otherwise, <span>remove extraneous line breaks before</span>
+ <var>original parent</var>.
+
<li>If <var>node list</var>'s last member's [[nextsibling]] is null,
<span>remove extraneous line breaks at the end of</span> <var>node
list</var>'s last member's [[parent]].
@@ -894,28 +897,22 @@
block element empty, when we really need to add a [[br]] [[child]] no matter
what so it doesn't collapse.
+<p class=XXX>I'm uncertain about the use of prohibited paragraph children here.
+I'm using it mostly because it's convenient and seems relatively sensible. If
+we really want to use it, we probably want to change its name.
+
<ol>
<li>Let <var>range</var> be the <span>active range</span>.
<li>If <var>range</var> is null, abort these steps and do nothing.
- <li>If no [[node]] is [[contained]] in <var>range</var>, and
- either <var>range</var>'s [[startnode]] is not a [[text]] or [[comment]] node
- or <var>range</var>'s [[startoffset]] is its [[startnode]]'s [[nodelength]],
- and either <var>range</var>'s [[endnode]] is not a [[text]] or [[comment]]
- node or <var>range</var>'s [[endoffset]] is 0, call <code
- data-anolis-spec=domrange
- title=dom-Range-deleteContents>deleteContents()</code> on <var>range</var>
- and abort these steps.
- <!-- This is precisely the case where deleteContents() will not alter the
- DOM, just collapse the selection. I think. -->
-
- <p class=XXX>Is it possible for subsequent steps to make the range's start go
- past its end or vice versa, or does this step successfully prevent that case?
+ <li>Let <var>start node</var>, <var>start offset</var>, <var>end node</var>,
+ and <var>end offset</var> be <var>range</var>'s [[rangestart]] and
+ [[rangeend]] [[bpnodes]] and [[bpoffsets]].
<!-- Drill the range down to the lowest possible level, so we don't delete
more elements than necessary. -->
- <li>While the [[startnode]] of <var>range</var> has at least one [[child]]:
+ <li>While <var>start node</var> has at least one [[child]]:
<!--
We don't want to keep going when we hit an element with no children, because
then we'd do something like
@@ -929,94 +926,184 @@
-->
<ol>
- <li>If <var>range</var>'s [[startoffset]] is its [[startnode]]'s
- [[nodelength]], and its [[startnode]]'s [[parent]] is not null, set
- <var>range</var>'s [[rangestart]] to ([[parent]] of [[startnode]], 1 +
- [[index]] of [[startnode]]) and continue this loop from the beginning.
+ <li>If <var>start offset</var> is <var>start node</var>'s
+ [[nodelength]], and <var>start node</var>'s [[parent]] is <span>in the same
+ editing host</span>, and <var>start node</var> is not a <span>prohibited
+ paragraph child</span>, set <var>start offset</var> to one plus the
+ [[index]] of <var>start node</var>, then set <var>start node</var> to its
+ [[parent]] and continue this loop from the beginning.
<!--
For instance:
<b>foo[</b><i>bar]</i>
+ -> <b>foo{</b><i>bar]</i>
-> <b>foo</b>{<i>bar]</i>
Then the next step will make it <b>foo</b><i>[bar]</i>.
+
+ We don't want to do this for prohibited paragraph children, because that
+ would lead to something like
+
+ <p>foo[</p><p>]bar<p>
+
+ ultimately collapsing, which is wrong. Once we do the deletion, it needs
+ to wind up <p>foo[]bar</p>, whereas an actually collapsed selection should
+ do nothing.
-->
- <li>If <var>range</var>'s [[startoffset]] is its [[startnode]]'s
- [[nodelength]], break from this loop.
+ <li>If <var>start offset</var> is <var>start node</var>'s [[nodelength]],
+ break from this loop.
<!-- This happens if the first step brought us all the way up to the root.
The step immediately after this loop will bring us back down again. -->
- <li>Let <var>reference node</var> be the [[child]] of <var>range</var>'s
- [[startnode]] with [[index]] equal to its [[startoffset]].
+ <li>Let <var>reference node</var> be the [[child]] of <var>start node</var>
+ with [[index]] equal to <var>start offset</var>.
<li>If <var>reference node</var> is an [[element]] with no [[children]],
break from this loop.
<!-- Don't descend into it, since then it won't get deleted even if it's
selected. -->
- <li>Set <var>range</var>'s [[rangestart]] to (<var>reference node</var>,
- 0).
+ <li>Set <var>start node</var> to <var>reference node</var> and <var>start
+ offset</var> to 0.
</ol>
- <!-- Corner case: maybe we went all the way up to the end of the root. -->
- <li>If <var>range</var>'s [[startoffset]] is the [[nodelength]] of its
- [[startnode]], then while <var>range</var>'s [[startnode]] has [[children]]
- and its last [[child]] is not an [[element]] with no [[children]], set
- <var>range</var>'s [[rangestart]] to (last [[child]] of [[startnode]],
- [[nodelength]] of last [[child]] of [[startnode]]).
-
- <li>While the [[endnode]] of <var>range</var> has at least one [[child]]:
+ <li>While <var>end node</var> has at least one [[child]]:
<ol>
- <li>If <var>range</var>'s [[endoffset]] is 0, and its [[endnode]]'s
- [[parent]] is not null, set <var>range</var>'s [[rangeend]] to ([[parent]]
- of [[endnode]], [[index]] of [[endnode]]) and continue this loop from the
- beginning.
-
- <li>If <var>range</var>'s [[endoffset]] is 0, break from this loop.
-
- <li>Let <var>reference node</var> be the [[child]] of <var>range</var>'s
- [[endnode]] with [[index]] equal to its [[endoffset]] minus one.
+ <li>If <var>end offset</var> is 0, and <var>end node</var>'s
+ [[parent]] is <span>in the same editing host</span>, and <var>end
+ node</var> is not a <span>prohibited paragraph child</span>, set <var>end
+ offset</var> to the [[index]] of <var>end node</var>, then set <var>end
+ node</var> to its [[parent]] and continue this loop from the beginning.
+
+ <li>If <var>end offset</var> is 0, break from this loop.
+
+ <li>Let <var>reference node</var> be the [[child]] of <var>end node</var>
+ with [[index]] equal to <var>end offset</var> minus one.
<li>If <var>reference node</var> is an [[element]] with no [[children]],
break from this loop.
- <li>Set <var>range</var>'s [[rangeend]] to (<var>reference node</var>,
- [[nodelength]] of <var>reference node</var>).
+ <li>Set <var>end node</var> to <var>reference node</var> and <var>end
+ offset</var> to the [[nodelength]] of <var>reference node</var>.
</ol>
- <li>If <var>range</var>'s [[endoffset]] is 0, then while <var>range</var>'s
- [[endnode]] has [[children]] and its first [[child]] is not an [[element]]
- with no [[children]], set <var>range</var>'s [[rangeend]] to (first [[child]]
- of [[endnode]], 0).
+ <li>If (<var>end node</var>, <var>end offset</var>) is <span
+ data-anolis-spec=domrange title=concept-bp-before>before</span> (<var>start
+ node</var>, <var>start offset</var>), call <code data-anolis-spec=domrange
+ title=dom-Range-deleteContents>deleteContents()</code> on <var>range</var>
+ and abort these steps.
+
+ <li>Set <var>range</var>'s [[rangestart]] to (<var>start node</var>,
+ <var>start offset</var>) and its [[rangeend]] to (<var>end node</var>,
+ <var>end offset</var>).
<li>Let <var>start block</var> be the [[rangestart]] [[bpnode]] of
<var>range</var>.
<li>While <var>start block</var> is not a <span>prohibited paragraph
- child</span>, set <var>start block</var> to its [[parent]].
-
- <p class=XXX>I'm uncertain about the use of prohibited paragraph children
- here. I'm using it mostly because it's convenient and seems relatively
- sensible. If we really want to use it, we probably want to change its name.
+ child</span> and its [[parent]] is <span>in the same editing host</span>, set
+ <var>start block</var> to its [[parent]].
<li>Let <var>end block</var> be the [[rangeend]] [[bpnode]] of
<var>range</var>.
<li>While <var>end block</var> is not a <span>prohibited paragraph
- child</span>, set <var>end block</var> to its [[parent]].
+ child</span> and its [[parent]] is <span>in the same editing host</span>, set
+ <var>end block</var> to its [[parent]].
<li>Call <code data-anolis-spec=domrange
title=dom-Range-deleteContents>deleteContents()</code> on <var>range</var>.
-
- <li>If <var>start block</var> or its [[parent]] is null, or <var>end
- block</var> or its [[parent]] is null, or <var>start block</var> is an
- [[ancestor]] or [[descendant]] of <var>end block</var>, abort these steps.
+ <!--
+ Now we need to merge blocks. The simplest case is something like
+
+ <p>fo[o</p><p>bar</p><p>b]az</p>
+ -> <p>fo</p>{}<p>az</p>
+ -> <p>fo{}az</p>
+
+ where neither block descends from the other. More complicated is something
+ like
+
+ foo[<p>]bar</p>
+ -> foo[]bar
+
+ or
+
+ <p>foo[</p>]bar
+ -> <p>foo[]bar</p>
+
+ where one descends from the other.
+ -->
+
+ <li>If <var>start block</var> is not <span>in the same editing host</span> as
+ <var>end block</var>, or <var>start block</var> is neither an <span>editing
+ host</span> nor a <span>prohibited paragraph child</span>, or <var>end
+ block</var> is neither an <span>editing host</span> nor a <span>prohibited
+ paragraph child</span>, or <var>start block</var> and <var>end block</var>
+ are the same, abort these steps.
+
+ <li>If <var>start block</var> is an [[ancestor]] of <var>end block</var>:
+ <!-- Just repeatedly blow up the end block. -->
+
+ <ol>
+ <li>Let <var>reference node</var> be <var>end block</var>.
+
+ <li>While <var>reference node</var> is not a [[child]] of <var>start
+ block</var>, set <var>reference node</var> to its [[parent]].
+
+ <li>Set the [[rangestart]] and [[rangeend]] of <var>range</var> to
+ (<var>start block</var>, [[index]] of <var>reference node</var>).
+
+ <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>Append the first [[child]] of <var>end block</var> to
+ <var>children</var>.
+
+ <li>While <var>children</var>'s last member is not a [[br]], and
+ <var>children</var>'s last member's [[nextsibling]] is an <span>inline
+ node</span>, append <var>children</var>'s last member's [[nextsibling]] to
+ <var>children</var>.
+
+ <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>.
+
+ <li>If the [[child]] of <var>range</var>'s [[startnode]] with [[index]]
+ equal to its [[startoffset]] is a [[br]] and is not the first member of
+ <var>children</var>, remove that [[br]] from its [[parent]].
+
+ <li>Abort these steps.
+ </ol>
<li>Set the [[rangestart]] and [[rangeend]] of <var>range</var> to
(<var>start block</var>, [[nodelength]] of <var>start block</var>).
+ <li>If <var>start block</var> is a [[descendant]] of <var>end block</var>:
+ <!-- Pull in everything that comes after <var>start block</var>, until we hit
+ a br or prohibited paragraph child. -->
+
+ <ol>
+ <li>Let <var>reference node</var> be <var>start block</var>.
+
+ <li>While <var>reference node</var> is not a [[child]] of <var>end
+ block</var>, set <var>reference node</var> to its [[parent]].
+
+ <li>While the [[nextsibling]] of <var>reference node</var> is neither null
+ nor a [[br]] nor a <span>prohibited paragraph child</span>, append the
+ [[nextsibling]] of <var>reference 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
+ it from its [[parent]].
+
+ <li>Abort these steps.
+ </ol>
+
+ <!-- In the last case, just move all the children of the end block to the
+ start block, and then get rid of any elements we emptied that way. -->
<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>.