Start on the collapsed-selection case for delete
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Mon, 06 Jun 2011 16:11:16 -0600
changeset 237 1f3c9d03e7b4
parent 236 cd5324fd83c5
child 238 dfb268b4d33b
Start on the collapsed-selection case for delete
autoimplementation.html
editcommands.html
implementation.js
preprocess
source.html
--- a/autoimplementation.html	Mon Jun 06 15:21:45 2011 -0600
+++ b/autoimplementation.html	Mon Jun 06 16:11:16 2011 -0600
@@ -312,6 +312,9 @@
 		'<div>foo</div><div>[]bar</div>',
 		'<pre>foo</pre>[]bar',
 		'foo<br>[]bar',
+		'foo<br><b>[]bar</b>',
+		'foo<hr>[]bar',
+		'<p>foo<hr><p>[]bar',
 
 		'foo[bar]baz',
 
--- a/editcommands.html	Mon Jun 06 15:21:45 2011 -0600
+++ b/editcommands.html	Mon Jun 06 16:11:16 2011 -0600
@@ -2448,7 +2448,38 @@
   collapsed?  WebKit seems to do some normalization on the range before
   deciding whether it's collapsed, and that sounds like a good idea.
 
-  <li class=XXX>The stuff where we delete the previous character goes here.
+  <li>Let <var title="">node</var> and <var title="">offset</var> be the <a href=#active-range>active
+  range</a>'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> 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>offset</a>.
+
+  <!-- First go up as high as possible within the current block, then drill
+  down to the lowest possible level, in the hopes that we'll wind up at the end
+  of a text node, or maybe in a br or hr. -->
+  <li>While <var title="">offset</var> is zero and <var title="">node</var> is not a
+  <a href=#prohibited-paragraph-child>prohibited paragraph child</a>, set <var title="">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="">node</var>, then set <var title="">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 <var title="">node</var> has 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> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> <var title="">offset</var>
+  &minus; 1 and that <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 a <a href=#prohibited-paragraph-child>prohibited paragraph
+  child</a>, set <var title="">node</var> to that <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>, then set
+  <var title="">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="">node</var>.
+
+  <li>If <var title="">node</var> is 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> node and <var title="">offset</var> is not zero,
+  call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+  Then <a href=#delete-the-contents>delete the contents</a> of the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a>
+  (<var title="">node</var>, <var title="">offset</var> &minus; 1) 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>
+  (<var title="">node</var>, <var title="">offset</var>) and abort these steps.
+
+  <li>If <var title="">node</var> has 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> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> <var title="">offset</var>
+  &minus; 1 and that <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 an <code class=external data-anolis-spec=html title="the hr element"><a href=http://www.whatwg.org/html/#the-hr-element>hr</a></code>, set <var title="">node</var> to that
+  <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>If <var title="">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> or <code class=external data-anolis-spec=html title="the hr element"><a href=http://www.whatwg.org/html/#the-hr-element>hr</a></code>, call
+  <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">node</var>, 0)</a></code> on the <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.  Then <a href=#delete-the-contents>delete
+  the contents</a> of the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> with <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=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="">node</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="">node</var>) 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=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="">node</var>, 1 + <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="">node</var>) and abort these steps.
+
+  <li class=XXX>Lots more cases to handle.
 </ol>
 
 
--- a/implementation.js	Mon Jun 06 15:21:45 2011 -0600
+++ b/implementation.js	Mon Jun 06 16:11:16 2011 -0600
@@ -767,7 +767,19 @@
 	return null;
 }
 
-function deleteContents(range) {
+function deleteContents(node1, offset1, node2, offset2) {
+	var range;
+
+	// We allow passing four arguments instead of one, in which case they're
+	// the start and end points of the range.
+	if (typeof offset1 == "undefined") {
+		range = node1;
+	} else {
+		range = document.createRange();
+		range.setStart(arguments[0], arguments[1]);
+		range.setEnd(arguments[2], arguments[3]);
+	}
+
 	// "If range is null, abort these steps and do nothing."
 	if (!range) {
 		return;
@@ -3114,6 +3126,59 @@
 			deleteContents(range);
 			return;
 		}
+
+		// "Let node and offset be the active range's start node and offset."
+		var node = range.startContainer;
+		var offset = range.startOffset;
+
+		// "While offset is zero and node is not a prohibited paragraph child,
+		// set offset to the index of node, then set node to its parent."
+		while (offset == 0
+		&& !isProhibitedParagraphChild(node)) {
+			offset = getNodeIndex(node);
+			node = node.parentNode;
+		}
+
+		// "While node has a child with index offset − 1 and that child is not
+		// a prohibited paragraph child, set node to that child, then set
+		// offset to the length of node."
+		while (0 <= offset - 1
+		&& offset - 1 < node.childNodes.length
+		&& !isProhibitedParagraphChild(node.childNodes[offset - 1])) {
+			node = node.childNodes[offset - 1];
+			offset = getNodeLength(node);
+		}
+
+		// "If node is a Text node and offset is not zero, call collapse(node,
+		// offset) on the Selection. Then delete the contents of the range with
+		// start (node, offset − 1) and end (node, offset) and abort these
+		// steps."
+		if (node.nodeType == Node.TEXT_NODE
+		&& offset != 0) {
+			range.setStart(node, offset);
+			range.setEnd(node, offset);
+			deleteContents(node, offset - 1, node, offset);
+			return;
+		}
+
+		// "If node has a child with index offset − 1 and that child is an hr,
+		// set node to that child."
+		if (0 <= offset -1
+		&& offset - 1 < node.childNodes.length
+		&& isHtmlElement(node.childNodes[offset - 1], "hr")) {
+			node = node.childNodes[offset - 1];
+		}
+
+		// "If node is a br or hr, call collapse(node, 0) on the Selection.
+		// Then delete the contents of the range with start (parent of node,
+		// index of node) and end (parent of node, 1 + index of node) and abort
+		// these steps."
+		if (isHtmlElement(node, ["br", "hr"])) {
+			range.setStart(node, 0);
+			range.setEnd(node, 0);
+			deleteContents(node.parentNode, getNodeIndex(node), node.parentNode, 1 + getNodeIndex(node));
+			return;
+		}
 		break;
 
 		case "fontname":
--- a/preprocess	Mon Jun 06 15:21:45 2011 -0600
+++ b/preprocess	Mon Jun 06 16:11:16 2011 -0600
@@ -48,6 +48,7 @@
     'getselection': '<code data-anolis-spec=domrange title=dom-Document-getSelection>getSelection()</code>',
     'htmldocument': '<code data-anolis-spec=html>HTMLDocument</code>',
     'htmlnamespace': '<span data-anolis-spec=domcore>HTML namespace</span>',
+    'hr': '<code data-anolis-spec=html title="the hr element">hr</code>',
     'href': '<code data-anolis-spec=html title=attr-hyperlink-href>href</code>',
     'i': '<code data-anolis-spec=html title="the i element">i</code>',
     'index': '<span data-anolis-spec=domrange title=concept-indexof>index</span>',
@@ -112,6 +113,7 @@
     'createelement': '<code data-anolis-spec=domcore title=dom-Document-createElement>createElement(\\1)</code>',
     'deletedata': '<code data-anolis-spec=domcore title=dom-CharacterData-deleteData>deleteData(\\1)</code>',
     'insertnode': '<code data-anolis-spec=domrange title=dom-Range-insertNode>insertNode(\\1)</code>',
+    'selcollapse': '<code data-anolis-spec=domrange title=dom-Selection-collapse>collapse(\\1)</code>',
 }
 
 for key in fnreplace:
--- a/source.html	Mon Jun 06 15:21:45 2011 -0600
+++ b/source.html	Mon Jun 06 16:11:16 2011 -0600
@@ -2429,7 +2429,38 @@
   collapsed?  WebKit seems to do some normalization on the range before
   deciding whether it's collapsed, and that sounds like a good idea.
 
-  <li class=XXX>The stuff where we delete the previous character goes here.
+  <li>Let <var>node</var> and <var>offset</var> be the <span>active
+  range</span>'s [[rangestart]] [[bpnode]] and [[bpoffset]].
+
+  <!-- First go up as high as possible within the current block, then drill
+  down to the lowest possible level, in the hopes that we'll wind up at the end
+  of a text node, or maybe in a br or hr. -->
+  <li>While <var>offset</var> is zero and <var>node</var> is not a
+  <span>prohibited paragraph child</span>, set <var>offset</var> to the
+  [[index]] of <var>node</var>, then set <var>node</var> to its [[parent]].
+
+  <li>While <var>node</var> has a [[child]] with [[index]] <var>offset</var>
+  &minus; 1 and that [[child]] is not a <span>prohibited paragraph
+  child</span>, set <var>node</var> to that [[child]], then set
+  <var>offset</var> to the [[nodelength]] of <var>node</var>.
+
+  <li>If <var>node</var> is a [[text]] node and <var>offset</var> is not zero,
+  call [[selcollapse|<var>node</var>, <var>offset</var>]] on the [[selection]].
+  Then <span>delete the contents</span> of the [[range]] with [[rangestart]]
+  (<var>node</var>, <var>offset</var> &minus; 1) and [[rangeend]]
+  (<var>node</var>, <var>offset</var>) and abort these steps.
+
+  <li>If <var>node</var> has a [[child]] with [[index]] <var>offset</var>
+  &minus; 1 and that [[child]] is an [[hr]], set <var>node</var> to that
+  [[child]].
+
+  <li>If <var>node</var> is a [[br]] or [[hr]], call
+  [[selcollapse|<var>node</var>, 0]] on the [[selection]].  Then <span>delete
+  the contents</span> of the [[range]] with [[rangestart]] ([[parent]] of
+  <var>node</var>, [[index]] of <var>node</var>) and [[rangeend]] ([[parent]]
+  of <var>node</var>, 1 + [[index]] of <var>node</var>) and abort these steps.
+
+  <li class=XXX>Lots more cases to handle.
 </ol>