--- a/autoimplementation.html Wed May 25 13:54:18 2011 -0600
+++ b/autoimplementation.html Thu May 26 10:38:25 2011 -0600
@@ -873,8 +873,31 @@
'<span>foo[</span><span>]bar</span>',
["", 'foo[bar]baz'],
'foo[bar]baz',
+
+ 'foo<b>[bar]</b>baz',
'foo<b>{bar}</b>baz',
+ 'foo{<b>bar</b>}baz',
+ 'foo<span>[bar]</span>baz',
+ 'foo<span>{bar}</span>baz',
+ 'foo{<span>bar</span>}baz',
+ '<b>foo[bar</b><i>baz]quz</i>',
+ '<p>foo</p><p>[bar]</p><p>baz</p>',
+ '<p>foo</p><p>{bar}</p><p>baz</p>',
+ '<p>foo</p>{<p>bar</p>}<p>baz</p>',
+
'<p>foo[bar<p>baz]quz',
+ '<p>foo[bar<div>baz]quz</div>',
+ '<p>foo[bar<h1>baz]quz</h1>',
+ '<div>foo[bar</div><p>baz]quz',
+ '<blockquote>foo[bar</blockquote><pre>baz]quz</pre>',
+
+ '<p><b>foo[bar</b><p>baz]quz',
+ '<div><p>foo[bar</div><p>baz]quz',
+ '<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote',
+ '<p>foo[bar<p style=color:red>baz]quz',
+ '<p>foo[bar<p><b>baz]quz</b>',
+
+ '<div><p>foo<p>[bar<p>baz]</div>',
],
insertorderedlist: [
'foo[]bar',
--- a/editcommands.html Wed May 25 13:54:18 2011 -0600
+++ b/editcommands.html Thu May 26 10:38:25 2011 -0600
@@ -35,7 +35,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-25-may-2011>Work in Progress — Last Update 25 May 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-—-last-update-26-may-2011>Work in Progress — Last Update 26 May 2011</h2>
<dl>
<dt>Editor
<dd>Aryeh Gregor <ayg+spec@aryeh.name>
@@ -705,6 +705,141 @@
<li>Return <var title="">new parent</var>.
</ol>
+<p>To <dfn id=delete-the-selection>delete the selection</dfn>:
+
+<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?
+
+ <!-- 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>:
+ <!--
+ We don't want to keep going when we hit an element with no children, because
+ then we'd do something like
+
+ foo{<br />bar]
+ -> foo<br>{</br>bar]
+ -> foo<br />{bar]
+ -> foo<br />[bar]
+
+ and we deselected the <br>.
+ -->
+
+ <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.
+ <!--
+ For instance:
+
+ <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>.
+ -->
+
+ <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.
+ <!-- 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>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).
+ </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>:
+
+ <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="">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>).
+ </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>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 an <a href=#html-element>HTML element</a> or its
+ <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> is not a <a href=#prohibited-paragraph-children title="prohibited paragraph children">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.
+
+ <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 an <a href=#html-element>HTML element</a> or its
+ <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> is not a <a href=#prohibited-paragraph-children title="prohibited paragraph children">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>.
+
+ <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>.
+
+ <p class=XXX>This might blow up non-editable stuff.
+
+ <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.
+
+ <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>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>.
+
+ <li>While <var title="">end 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>, let <var title="">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 <var title="">end block</var>, then remove <var title="">end block</var> from
+ <var title="">parent</var>, then set <var title="">end block</var> to <var title="">parent</var>.
+</ol>
+
<p>To move 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> to a new location, <dfn id=preserving-ranges>preserving ranges</dfn>, remove
the <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> from its original <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> (if any), then insert it in the new
location. In doing so, however, ignore the regular <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#range-mutation-rules>range mutation rules</a>, and
@@ -1121,7 +1256,7 @@
<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-offset title=concept-boundary-point-offset>offset</a> of <var title="">cloned range</var> equals 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-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 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
- <var title="">clone 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 null, set the
+ <var title="">cloned 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 null, set 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> of <var title="">cloned range</var> 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>, 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-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>).
@@ -2244,7 +2379,7 @@
<li>Let <var title="">range</var> be the <a href=#active-range>active range</a>.
- <li>Run <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><a href=#delete-the-selection>Delete the selection</a>.
<li>Let <var title="">img</var> be 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("img")</a></code> on the
<a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>.
--- a/implementation.js Wed May 25 13:54:18 2011 -0600
+++ b/implementation.js Thu May 26 10:38:25 2011 -0600
@@ -302,8 +302,8 @@
}
/**
- * Return all editable nodes contained in range that the provided function
- * returns true for, omitting any with an ancestor already being returned.
+ * Return all nodes contained in range that the provided function returns true
+ * for, omitting any with an ancestor already being returned.
*/
function collectContainedNodes(range, condition) {
var node = range.startContainer;
@@ -332,7 +332,6 @@
var nodeList = [];
while (isBefore(node, stop)) {
if (isContained(node, range)
- && isEditable(node)
&& condition(node)) {
nodeList.push(node);
node = nextNodeDescendants(node);
@@ -659,6 +658,180 @@
return newParent;
}
+// "This is defined to be the first range in the Selection given by calling
+// getSelection() on the context object, or null if there is no such range."
+function getActiveRange() {
+ if (getSelection().rangeCount) {
+ return getSelection().getRangeAt(0);
+ }
+ return null;
+}
+
+function deleteSelection() {
+ // "Let range be the active range."
+ var range = globalRange;
+
+ // "If range is null, abort these steps and do nothing."
+ if (!range) {
+ 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, function() { return true }).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));
+ continue;
+ }
+
+ // "If range's start offset is its start node's length, break from this
+ // loop."
+ if (range.startOffset == getNodeLength(range.startContainer)) {
+ 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];
+
+ // "If reference node is an Element with no children, break from this
+ // loop."
+ if (referenceNode.nodeType == Node.ELEMENT_NODE
+ && !referenceNode.hasChildNodes()) {
+ 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
+ // continue this loop from the beginning."
+ if (range.endOffset == 0
+ && range.endContainer.parentNode) {
+ range.setEnd(range.endContainer.parentNode, getNodeIndex(range.endContainer));
+ continue;
+ }
+
+ // "If range's end offset is 0, break from this loop."
+ if (range.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];
+
+ // "If reference node is an Element with no children, break from this
+ // loop."
+ if (referenceNode.nodeType == Node.ELEMENT_NODE
+ && !referenceNode.hasChildNodes()) {
+ 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);
+ }
+ }
+
+ // "Let start block be the start node of range."
+ var startBlock = range.startContainer;
+
+ // "While start block is not an HTML element or its local name is not a
+ // prohibited paragraph child, set start block to its parent."
+ while (!isHtmlElement(startBlock, prohibitedParagraphChildren)) {
+ startBlock = startBlock.parentNode;
+ }
+
+ // "Let end block be the end node of range."
+ var endBlock = range.endContainer;
+
+ // "While end block is not an HTML element or its local name is not a
+ // prohibited paragraph child, set end block to its parent."
+ while (!isHtmlElement(endBlock, prohibitedParagraphChildren)) {
+ 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)) {
+ return;
+ }
+
+ // "Set the start and end of range to (start block, length of start
+ // block)."
+ range.setStart(startBlock, getNodeLength(startBlock));
+ range.setEnd(startBlock, getNodeLength(startBlock));
+
+ // "While end block has children, append the first child of end block to
+ // start block, preserving ranges."
+ while (endBlock.hasChildNodes()) {
+ movePreservingRanges(endBlock.firstChild, startBlock, -1);
+ }
+
+ // "While end block has no children, let parent be the parent of end block,
+ // then remove end block from parent, then set end block to parent."
+ while (!endBlock.hasChildNodes()) {
+ var parent_ = endBlock.parentNode;
+ parent_.removeChild(endBlock);
+ endBlock = parent_;
+ }
+}
+
function removeExtraneousLineBreaksBefore(node) {
// "If node is not an Element, or it is an inline node, do nothing and
// abort these steps."
@@ -2699,7 +2872,8 @@
// "dd", "dl", "dt", "footer", "header", "hgroup", "li", "nav", "ol",
// "section", "table", "tbody", "td", "th", "thead", "tr", or "ul"."
nodeList = collectContainedNodes(newRange, function(node) {
- return !isHtmlElement(node, ["ARTICLE", "ASIDE", "BLOCKQUOTE",
+ return isEditable(node)
+ && !isHtmlElement(node, ["ARTICLE", "ASIDE", "BLOCKQUOTE",
"CAPTION", "COL", "COLGROUP", "DD", "DL", "DT", "FOOTER",
"HEADER", "HGROUP", "LI", "NAV", "OL", "SECTION", "TABLE",
"TBODY", "TD", "TH", "THEAD", "TR", "UL"]);
@@ -2942,8 +3116,8 @@
return;
}
- // "Run deleteContents() on the range."
- range.deleteContents();
+ // "Delete the selection."
+ deleteSelection();
// "Let img be the result of calling createElement("img") on the
// context object."
--- a/preprocess Wed May 25 13:54:18 2011 -0600
+++ b/preprocess Thu May 26 10:38:25 2011 -0600
@@ -34,6 +34,8 @@
'documenttype': '<code data-anolis-spec=domcore>DocumentType</code>',
'element': '<code data-anolis-spec=domcore>Element</code>',
'em': '<code data-anolis-spec=html title="the em element">em</code>',
+ 'endnode': '<span data-anolis-spec=domrange title=concept-range-end>end</span> <span data-anolis-spec=domrange title=concept-boundary-point-node>node</span>',
+ 'endoffset': '<span data-anolis-spec=domrange title=concept-range-end>end</span> <span data-anolis-spec=domrange title=concept-boundary-point-offset>offset</span>',
'followingsibling': '<span data-anolis-spec=domcore title="concept-tree-following-sibling">following sibling</span>',
'font': '<code data-anolis-spec=html title=font>font</code>',
'fontcolor': '<code data-anolis-spec=html title=dom-font-color>color</code>',
@@ -69,6 +71,8 @@
'sibling': '<span data-anolis-spec=domcore title=concept-tree-sibling>sibling</span>',
'spacecharacter': '<span data-anolis-spec=domcore title="space character">space character</span>',
'span': '<code data-anolis-spec=html title="the span element">span</code>',
+ 'startnode': '<span data-anolis-spec=domrange title=concept-range-start>start</span> <span data-anolis-spec=domrange title=concept-boundary-point-node>node</span>',
+ 'startoffset': '<span data-anolis-spec=domrange title=concept-range-start>start</span> <span data-anolis-spec=domrange title=concept-boundary-point-offset>offset</span>',
'strike': '<code data-anolis-spec=html title="the strike element">strike</code>',
'strong': '<code data-anolis-spec=html title="the strong element">strong</code>',
'style': '<code data-anolis-spec=html title="the style attribute">style</code>',
--- a/source.html Wed May 25 13:54:18 2011 -0600
+++ b/source.html Thu May 26 10:38:25 2011 -0600
@@ -667,6 +667,144 @@
<li>Return <var>new parent</var>.
</ol>
+<p>To <dfn>delete the selection</dfn>:
+
+<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?
+
+ <!-- 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]]:
+ <!--
+ We don't want to keep going when we hit an element with no children, because
+ then we'd do something like
+
+ foo{<br />bar]
+ -> foo<br>{</br>bar]
+ -> foo<br />{bar]
+ -> foo<br />[bar]
+
+ and we deselected the <br>.
+ -->
+
+ <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.
+ <!--
+ For instance:
+
+ <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>.
+ -->
+
+ <li>If <var>range</var>'s [[startoffset]] is its [[startnode]]'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>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).
+ </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]]:
+
+ <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>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>).
+ </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>Let <var>start block</var> be the [[rangestart]] [[bpnode]] of
+ <var>range</var>.
+
+ <li>While <var>start block</var> is not an <span>HTML element</span> or its
+ [[localname]] is not a <span title="prohibited paragraph children">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.
+
+ <li>Let <var>end block</var> be the [[rangeend]] [[bpnode]] of
+ <var>range</var>.
+
+ <li>While <var>end block</var> is not an <span>HTML element</span> or its
+ [[localname]] is not a <span title="prohibited paragraph children">prohibited
+ paragraph child</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>.
+
+ <p class=XXX>This might blow up non-editable stuff.
+
+ <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.
+
+ <li>Set the [[rangestart]] and [[rangeend]] of <var>range</var> to
+ (<var>start block</var>, [[nodelength]] of <var>start block</var>).
+
+ <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>.
+
+ <li>While <var>end block</var> has no [[children]], let <var>parent</var> be
+ the [[parent]] of <var>end block</var>, then remove <var>end block</var> from
+ <var>parent</var>, then set <var>end block</var> to <var>parent</var>.
+</ol>
+
<p>To move a [[node]] to a new location, <dfn>preserving ranges</dfn>, remove
the [[node]] from its original [[parent]] (if any), then insert it in the new
location. In doing so, however, ignore the regular [[rangemutationrules]], and
@@ -1091,7 +1229,7 @@
<li>While the [[rangeend]] [[bpoffset]] of <var>cloned range</var> equals the
[[nodelength]] of its [[rangeend]] [[bpnode]], and the [[parent]] of
- <var>clone range</var>'s [[rangeend]] [[bpnode]] is not null, set the
+ <var>cloned range</var>'s [[rangeend]] [[bpnode]] is not null, set the
[[rangeend]] of <var>cloned range</var> to ([[parent]] of [[rangeend]]
[[bpnode]], 1 + [[index]] of [[rangeend]] [[bpnode]]).
@@ -2233,8 +2371,7 @@
<li>Let <var>range</var> be the <span>active range</span>.
- <li>Run <code data-anolis-spec=domrange
- title=dom-Range-deleteContents>deleteContents()</code> on <var>range</var>.
+ <li><span>Delete the selection</span>.
<li>Let <var>img</var> be the result of calling <code
data-anolis-spec=domcore