Basically working unlink command
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Thu, 07 Apr 2011 14:14:37 -0600
changeset 48 7f271e7fde68
parent 47 cb313cb44512
child 49 c2df7ab3cca1
Basically working unlink command
autoimplementation.html
editcommands.html
implementation.js
source.html
--- a/autoimplementation.html	Thu Apr 07 13:58:56 2011 -0600
+++ b/autoimplementation.html	Thu Apr 07 14:14:37 2011 -0600
@@ -617,17 +617,6 @@
 		'<p style="text-decoration: underline">foo[bar]baz</p>',
 	],
 	unlink: [
-		'foo[bar]baz',
-		'foo]bar[baz',
-		'{<p><p> <p>foo</p>}',
-
-		'<table><tbody><tr><td>foo<td>b[a]r<td>baz</table>',
-		'<table><tbody><tr data-start=1 data-end=2><td>foo<td>bar<td>baz</table>',
-		'<table><tbody><tr data-start=0 data-end=2><td>foo<td>bar<td>baz</table>',
-		'<table><tbody data-start=0 data-end=1><tr><td>foo<td>bar<td>baz</table>',
-		'<table data-start=0 data-end=1><tbody><tr><td>foo<td>bar<td>baz</table>',
-		'{<table><tr><td>foo<td>bar<td>baz</table>}',
-
 		'<a href=http://www.google.com/>foo[bar]baz</a>',
 		'<a href=http://www.google.com/>foo[barbaz</a>}',
 		'{<a href=http://www.google.com/>foobar]baz</a>',
--- a/editcommands.html	Thu Apr 07 13:58:56 2011 -0600
+++ b/editcommands.html	Thu Apr 07 14:14:37 2011 -0600
@@ -230,7 +230,7 @@
   <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, return the <a href=#effective-value>effective
   value</a> of its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> for <var title="">command</var>.
 
-  <li>If <var title="">command</var> is "createLink":
+  <li>If <var title="">command</var> is "createLink" or "unlink":
 
   <ol>
     <li>While <var title="">node</var> is not null, and is not an <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/html/#the-a-element>a</a></code> element that has
@@ -304,7 +304,7 @@
   <li>If <var title="">command</var> is "hiliteColor" and the <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>'s
   display property does not compute to "inline", return null.
 
-  <li>If <var title="">command</var> is "createLink":
+  <li>If <var title="">command</var> is "createLink" or "unlink":
 
   <ol>
     <li>If <var title="">element</var> is an <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/html/#the-a-element>a</a></code> element and has an <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/html/#attr-hyperlink-href>href</a></code>
@@ -564,7 +564,7 @@
   </ol>
 
   <li>If <var title="">element</var> is an <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/html/#the-a-element>a</a></code> element and <var title="">command</var> is
-  "createLink", unset the <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/html/#attr-hyperlink-href>href</a></code> property of <var title="">element</var>.
+  "createLink" or "unlink", unset the <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/html/#attr-hyperlink-href>href</a></code> property of <var title="">element</var>.
 
   <li>If <var title="">element</var>'s <a href=#specified-value>specified value</a> for
   <var title="">command</var> is null, return the empty list.
@@ -650,8 +650,10 @@
   <var title="">command</var> on the last member of <var title="">ancestor list</var>.
 
   <!-- We can only remove specified values, so if the value isn't specified,
-  give up. -->
-  <li>If <var title="">propagated value</var> is null, abort this algorithm.
+  give up.  Unless we're actually trying to push down a null specified value,
+  like for unlink. -->
+  <li>If <var title="">propagated value</var> is null and is not equal to <var title="">new
+  value</var>, abort this algorithm.
 
   <!-- If we go all the way up to the root and still don't have the desired
   value, pushing down values is pointless.  It will create extra markup for no
@@ -712,6 +714,8 @@
 <ol>
   <li>If <var title="">node</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is null, abort this algorithm.
 
+  <li>If <var title="">new value</var> is null, abort this algorithm.
+
   <li>If <var title="">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>, <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code>, <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#comment>Comment</a></code>, or
   <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#processinginstruction>ProcessingInstruction</a></code> node, and is not an <a href=#unwrappable-element>unwrappable
   element</a>:
@@ -881,8 +885,8 @@
     of <var title="">new parent</var> to <var title="">new value</var>.
   </ol>
 
-  <li>If <var title="">command</var> is "createLink", let <var title="">new parent</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("a")</a></code> on the
+  <li>If <var title="">command</var> is "createLink" or "unlink", let <var title="">new
+  parent</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("a")</a></code> on the
   <code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">node</var>, then set the <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/html/#attr-hyperlink-href>href</a></code> attribute of
   <var title="">new parent</var> to <var title="">new value</var>.
 
@@ -1528,45 +1532,10 @@
 
 <dt><code title=""><dfn id=command-unlink title=command-unlink>unlink</dfn></code>
 
-<dd><strong>Action</strong>: The user agent must execute the following
-steps:
-<!-- IE 9 RC unlinks the whole link you're pointing at.  Others just unlink
-your selection, which does nothing if you have nothing selected.
-Unfortunately, everyone but IE winds up doing some DOM surgery here in some
-cases, creating and splitting elements in some cases. -->
-
-<p class=XXX>This is based on what IE does.  Other browsers only unlink the
-selected portion, which might be more user-friendly but involves chopping up
-and reorganizing the DOM.  Revisit this later to see if it's reasonable to spec
-what the other browsers do instead.
-
-<ol>
-  <li>Let <var title="">links</var> be a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-collection title=concept-collection>collection</a> rooted at the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a>'s
-  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-root title=concept-range-root>root</a>, whose filter matches only <a href=#html-element title="HTML element">HTML
-  elements</a> with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> "a", that have an <a href=#html-attribute>HTML
-  attribute</a> with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-attr-local-name title=concept-attr-local-name>local name</a> "href".
-
-  <li>Let <var title="">selected</var> be a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-collection title=concept-collection>collection</a> rooted at the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a>'s
-  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-root title=concept-range-root>root</a>, whose filter matches only <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> that are <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in
-  the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> and <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> nodes that are <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#partially-contained>partially contained</a> in the
-  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a>.
-
-  <li>For each <var title="">link</var> in <var title="">links</var>, in <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#tree-order>tree order</a>:
-
-  <ol>
-    <li>If <var title="">link</var> is not in <var title="">selected</var> and is not an
-    <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of any <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> in <var title="">selected</var>, continue with the next
-    <var title="">link</var>.
-
-    <li>While <var title="">link</var> has children, insert <var title="">link</var>'s first
-    child into its parent as <var title="">link</var>'s previous sibling.
-
-    <li>Remove <var title="">link</var>.
-
-    <p class=XXX>This means it disappears even if it had an id, class, etc.
-    Maybe not what we want?
-  </ol>
-</ol>
+<dd><strong>Action</strong>: <a href=#decompose>Decompose</a> the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a>, and
+<a href=#set-the-value>set the value</a> of each returned <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 null.
+<!-- IE 9 RC unlinks the whole link you're pointing at.  We follow the other
+browsers, which operate more consistently with other commands. -->
 
 <dd><strong>State</strong>: Always false.
 
--- a/implementation.js	Thu Apr 07 13:58:56 2011 -0600
+++ b/implementation.js	Thu Apr 07 14:14:37 2011 -0600
@@ -299,8 +299,8 @@
 		return getEffectiveValue(node.parentNode, command);
 	}
 
-	// "If command is "createLink":"
-	if (command == "createlink") {
+	// "If command is "createLink" or "unlink":"
+	if (command == "createlink" || command == "unlink") {
 		// "While node is not null, and is not an a element that has an href
 		// attribute, set node to its parent."
 		while (node
@@ -428,8 +428,8 @@
 		return null;
 	}
 
-	// "If command is "createLink":"
-	if (command == "createlink") {
+	// "If command is "createLink" or "unlink":"
+	if (command == "createlink" || command == "unlink") {
 		// "If element is an a element and has an href attribute, return the
 		// value of that attribute."
 		if (isHtmlElement(element)
@@ -878,11 +878,11 @@
 		}
 	}
 
-	// "If element is an a element and command is "createLink", unset the href
-	// property of element."
+	// "If element is an a element and command is "createLink" or "unlink",
+	// unset the href property of element."
 	if (isHtmlElement(element)
 	&& element.tagName == "A"
-	&& command == "createlink") {
+	&& (command == "createlink" || command == "unlink")) {
 		element.removeAttribute("href");
 	}
 
@@ -954,8 +954,9 @@
 	// member of ancestor list."
 	var propagatedValue = getSpecifiedValue(ancestorList[ancestorList.length - 1], command);
 
-	// "If propagated value is null, abort this algorithm."
-	if (propagatedValue === null) {
+	// "If propagated value is null and is not equal to new value, abort this
+	// algorithm."
+	if (propagatedValue === null && propagatedValue != newValue) {
 		return;
 	}
 
@@ -1021,6 +1022,11 @@
 		return;
 	}
 
+	// "If new value is null, abort this algorithm."
+	if (newValue === null) {
+		return;
+	}
+
 	// "If node is an Element, Text, Comment, or ProcessingInstruction node,
 	// and is not an unwrappable element:"
 	if ((node.nodeType == Node.ELEMENT_NODE
@@ -1234,10 +1240,10 @@
 		}
 	}
 
-	// "If command is "createLink", let new parent be the result of calling
-	// createElement("a") on the ownerDocument of node, then set the href
-	// attribute of new parent to new value."
-	if (command == "createlink") {
+	// "If command is "createLink" or "unlink", let new parent be the result of
+	// calling createElement("a") on the ownerDocument of node, then set the
+	// href attribute of new parent to new value."
+	if (command == "createlink" || command == "unlink") {
 		newParent = node.ownerDocument.createElement("a");
 		newParent.setAttribute("href", newValue);
 	}
@@ -1567,6 +1573,15 @@
 		}
 		break;
 
+		case "unlink":
+		// "Decompose the range, and set the value of each returned node to
+		// null."
+		var nodeList = decomposeRange(range);
+		for (var i = 0; i < nodeList.length; i++) {
+			setNodeValue(nodeList[i], command, null);
+		}
+		break;
+
 		case "usecss":
 		// "Convert value to a boolean according to the algorithm in WebIDL,
 		// and set the CSS styling flag to the negation of the result."
--- a/source.html	Thu Apr 07 13:58:56 2011 -0600
+++ b/source.html	Thu Apr 07 14:14:37 2011 -0600
@@ -219,7 +219,7 @@
   <li>If <var>node</var> is a [[text]] node, return the <span>effective
   value</span> of its [[parent]] for <var>command</var>.
 
-  <li>If <var>command</var> is "createLink":
+  <li>If <var>command</var> is "createLink" or "unlink":
 
   <ol>
     <li>While <var>node</var> is not null, and is not an [[a]] element that has
@@ -293,7 +293,7 @@
   <li>If <var>command</var> is "hiliteColor" and the [[element]]'s
   display property does not compute to "inline", return null.
 
-  <li>If <var>command</var> is "createLink":
+  <li>If <var>command</var> is "createLink" or "unlink":
 
   <ol>
     <li>If <var>element</var> is an [[a]] element and has an [[href]]
@@ -557,7 +557,7 @@
   </ol>
 
   <li>If <var>element</var> is an [[a]] element and <var>command</var> is
-  "createLink", unset the [[href]] property of <var>element</var>.
+  "createLink" or "unlink", unset the [[href]] property of <var>element</var>.
 
   <li>If <var>element</var>'s <span>specified value</span> for
   <var>command</var> is null, return the empty list.
@@ -643,8 +643,10 @@
   <var>command</var> on the last member of <var>ancestor list</var>.
 
   <!-- We can only remove specified values, so if the value isn't specified,
-  give up. -->
-  <li>If <var>propagated value</var> is null, abort this algorithm.
+  give up.  Unless we're actually trying to push down a null specified value,
+  like for unlink. -->
+  <li>If <var>propagated value</var> is null and is not equal to <var>new
+  value</var>, abort this algorithm.
 
   <!-- If we go all the way up to the root and still don't have the desired
   value, pushing down values is pointless.  It will create extra markup for no
@@ -706,6 +708,8 @@
 <ol>
   <li>If <var>node</var>'s [[parent]] is null, abort this algorithm.
 
+  <li>If <var>new value</var> is null, abort this algorithm.
+
   <li>If <var>node</var> is an [[element]], [[text]], [[comment]], or
   [[processinginstruction]] node, and is not an <span>unwrappable
   element</span>:
@@ -884,8 +888,8 @@
     of <var>new parent</var> to <var>new value</var>.
   </ol>
 
-  <li>If <var>command</var> is "createLink", let <var>new parent</var> be the
-  result of calling <code data-anolis-spec=domcore
+  <li>If <var>command</var> is "createLink" or "unlink", let <var>new
+  parent</var> be the result of calling <code data-anolis-spec=domcore
   title=dom-Document-createElement>createElement("a")</code> on the
   [[ownerdocument]] of <var>node</var>, then set the [[href]] attribute of
   <var>new parent</var> to <var>new value</var>.
@@ -1549,45 +1553,10 @@
 
 <dt><code title><dfn title=command-unlink>unlink</dfn></code>
 
-<dd><strong>Action</strong>: The user agent must execute the following
-steps:
-<!-- IE 9 RC unlinks the whole link you're pointing at.  Others just unlink
-your selection, which does nothing if you have nothing selected.
-Unfortunately, everyone but IE winds up doing some DOM surgery here in some
-cases, creating and splitting elements in some cases. -->
-
-<p class=XXX>This is based on what IE does.  Other browsers only unlink the
-selected portion, which might be more user-friendly but involves chopping up
-and reorganizing the DOM.  Revisit this later to see if it's reasonable to spec
-what the other browsers do instead.
-
-<ol>
-  <li>Let <var>links</var> be a [[collection]] rooted at the [[range]]'s
-  [[rangeroot]], whose filter matches only <span title="HTML element">HTML
-  elements</span> with [[localname]] "a", that have an <span>HTML
-  attribute</span> with [[attrlocalname]] "href".
-
-  <li>Let <var>selected</var> be a [[collection]] rooted at the [[range]]'s
-  [[rangeroot]], whose filter matches only [[nodes]] that are [[contained]] in
-  the [[range]] and [[text]] nodes that are [[partiallycontained]] in the
-  [[range]].
-
-  <li>For each <var>link</var> in <var>links</var>, in [[treeorder]]:
-
-  <ol>
-    <li>If <var>link</var> is not in <var>selected</var> and is not an
-    [[ancestor]] of any [[node]] in <var>selected</var>, continue with the next
-    <var>link</var>.
-
-    <li>While <var>link</var> has children, insert <var>link</var>'s first
-    child into its parent as <var>link</var>'s previous sibling.
-
-    <li>Remove <var>link</var>.
-
-    <p class=XXX>This means it disappears even if it had an id, class, etc.
-    Maybe not what we want?
-  </ol>
-</ol>
+<dd><strong>Action</strong>: <span>Decompose</span> the [[range]], and
+<span>set the value</span> of each returned [[node]] to null.
+<!-- IE 9 RC unlinks the whole link you're pointing at.  We follow the other
+browsers, which operate more consistently with other commands. -->
 
 <dd><strong>State</strong>: Always false.