Crude, not-really-usable createLink
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Wed, 06 Apr 2011 14:00:50 -0600
changeset 44 87520fdd8938
parent 43 d6c648b8e769
child 45 b716a68f0a08
Crude, not-really-usable createLink

I need to generalize my markup algorithm to apply to things other than
just style.
autoimplementation.html
editcommands.html
implementation.js
preprocess
source.html
--- a/autoimplementation.html	Wed Apr 06 13:36:07 2011 -0600
+++ b/autoimplementation.html	Wed Apr 06 14:00:50 2011 -0600
@@ -38,6 +38,7 @@
 <ul>
 	<li><a href=#backcolor>backcolor</a>
 	<li><a href=#bold>bold</a>
+	<li><a href=#createlink>createlink</a>
 	<li><a href=#fontname>fontname</a>
 	<li><a href=#forecolor>forecolor</a>
 	<li><a href=#hilitecolor>hilitecolor</a>
@@ -76,6 +77,20 @@
 <button onclick="addTest('bold', document.querySelector('#bold input').value)">Add test</button>
 </div>
 
+<div id=createlink>
+<h1>createlink</h1>
+
+<button onclick="runTests('createlink')">Run tests</button>
+
+<p>Tests set the href to "http://www.google.com/".  <strong>Note:</strong> The
+spec has known errors and its output should probably be ignored.
+
+<table border=1><tr><th>Input <th>Spec <th>Browser <th>Same?</table>
+
+<p><label>Enter new test here: <input></label>
+<button onclick="addTest('createlink', document.querySelector('#createlink input').value)">Add test</button>
+</div>
+
 <div id=fontname>
 <h1>fontname</h1>
 
@@ -170,6 +185,7 @@
 var values = {
 	backcolor: "#FF8888",
 	bold: null,
+	createlink: "http://www.google.com/",
 	fontname: "sans-serif",
 	forecolor: "#FF0000",
 	hilitecolor: "#FF8888",
@@ -295,6 +311,42 @@
 
 		'<p style="font-weight: bold">foo[bar]baz</p>',
 	],
+	createlink: [
+		'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 href=http://www.google.com/>foobarbaz</a>}',
+		'<a href=http://www.google.com/>[foobarbaz]</a>',
+
+		'foo<a href=http://www.google.com/>[bar]</a>baz',
+		'foo[<a href=http://www.google.com/>bar</a>]baz',
+		'foo<a href=http://www.google.com/>[bar</a>baz]',
+		'[foo<a href=http://www.google.com/>bar]</a>baz',
+		'[foo<a href=http://www.google.com/>bar</a>baz]',
+
+		'<a href=http://google.com/>foo[bar]baz</a>',
+		'<a href=http://google.com/>foo[barbaz</a>}',
+		'{<a href=http://google.com/>foobar]baz</a>',
+		'{<a href=http://google.com/>foobarbaz</a>}',
+		'<a href=http://google.com/>[foobarbaz]</a>',
+
+		'foo<a href=http://google.com/>[bar]</a>baz',
+		'foo[<a href=http://google.com/>bar</a>]baz',
+		'foo<a href=http://google.com/>[bar</a>baz]',
+		'[foo<a href=http://google.com/>bar]</a>baz',
+		'[foo<a href=http://google.com/>bar</a>baz]',
+	],
 	fontname: [
 		'foo[bar]baz',
 		'foo]bar[baz',
@@ -685,7 +737,9 @@
 			document.execCommand("styleWithCSS", false, styleWithCss);
 		} catch (e) {}
 		document.execCommand(command, false, value);
-		addBrackets(getSelection().getRangeAt(0));
+		if (getSelection().rangeCount) {
+			addBrackets(getSelection().getRangeAt(0));
+		}
 		browserCell.lastChild.textContent = browserCell.firstChild.innerHTML;
 	} catch (e) {
 		browserCell.textContent = "Exception: " + e;
--- a/editcommands.html	Wed Apr 06 13:36:07 2011 -0600
+++ b/editcommands.html	Wed Apr 06 14:00:50 2011 -0600
@@ -1085,6 +1085,11 @@
 meanings, are as follows.  These values must be compared to the argument in an
 <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#ascii-case-insensitive>ASCII case-insensitive</a> manner.
 
+<!-- Notes on commands I've looked at but haven't bothered specifying yet:
+
+* decreaseFontSize, increaseFontSize: Only implemented in Gecko and Opera.
+-->
+
 <dl>
 <dt><code title=""><dfn id=command-backcolor title=command-backcolor>backColor</dfn></code>
 
@@ -1181,25 +1186,22 @@
     <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendants</a> of <var title="">node</var>, or <var title="">node</var> itself if it's 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.
 
-    <li>For each <var title="">text node</var> in <var title="">text nodes</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>:
+    <li>For each <var title="">text node</var> in <var title="">text nodes</var>:
 
     <ol>
       <li>Let <var title="">ancestor link</var> be the parent of <var title="">text
       node</var>.
 
-      <li>While <var title="">ancestor link</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", or it has no <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>While <var title="">ancestor link</var> 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 or has no <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:
 
       <ol>
         <li>If the parent of <var title="">ancestor link</var> is not an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>,
         set <var title="">ancestor link</var> to null and break from this loop.
 
-        <li>Otherwise, set <var title="">ancestor link</var> to its parent.
+        <li>Otherwise, set <var title="">ancestor link</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>.
       </ol>
 
-      <li>If <var title="">ancestor link</var> is not null, set its "href" attribute
+      <li>If <var title="">ancestor link</var> is not null, set its <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
       to <var title="">value</var> and continue with the next <var title="">text node</var>.
       <!-- There are three approaches here.  For instance, if you ask browsers
       to create a link to "http://example.org" on the "b" here:
@@ -1234,7 +1236,7 @@
       the previous sibling of <var title="">text node</var>.
 
       <li>Append <var title="">text node</var> to <var title="">new parent</var> as its last
-      child.
+      child, <a href=#preserving-ranges>preserving ranges</a>.
     </ol>
   </ol>
 </ol>
--- a/implementation.js	Wed Apr 06 13:36:07 2011 -0600
+++ b/implementation.js	Wed Apr 06 14:00:50 2011 -0600
@@ -1376,7 +1376,6 @@
 		}
 		break;
 
-		/*
 		case "createlink":
 		// "If value is the empty string, do nothing."
 		if (value === "") {
@@ -1405,16 +1404,15 @@
 				}
 			}
 
-			// "For each text node in text nodes, in tree order:"
+			// "For each text node in text nodes:"
 			for (var j = 0; j < textNodes.length; j++) {
 				var textNode = textNodes[j];
 
 				// "Let ancestor link be the parent of text node."
 				var ancestorLink = textNode.parentNode;
 
-				// "While ancestor link is not an HTML element, or its local
-				// name is not "a", or it has no HTML attribute with local name
-				// "href":"
+				// "While ancestor link is not an a element or has no href
+				// attribute:"
 				while (!isHtmlNamespace(ancestorLink.namespaceURI)
 				|| ancestorLink.nodeType != Node.ELEMENT_NODE
 				|| ancestorLink.tagName != "A"
@@ -1431,28 +1429,30 @@
 					ancestorLink = ancestorLink.parentNode;
 				}
 
-				// "If ancestor link is not null, set its "href" attribute to
+				// "If ancestor link is not null, set its href attribute to
 				// value and continue with the next text node."
 				if (ancestorLink) {
 					ancestorLink.setAttribute("href", value);
 					continue;
 				}
 
-				// "Let new parent be a new HTML element with local name "a",
-				// the same ownerDocument as text node, and a single HTML
-				// attribute with local name "href" and value value."
+				// "Let new parent be the result of calling createElement("a")
+				// on the ownerDocument of text node."
 				var newParent = textNode.ownerDocument.createElement("a");
+
+				// "Call setAttribute("href", value) on new parent."
 				newParent.setAttribute("href", value);
 
 				// "Insert new parent into text node's parent as the previous
 				// sibling of text node."
 				textNode.parentNode.insertBefore(newParent, textNode);
 
-				// "Append text node to new parent as its last child."
-				newParent.appendChild(textNode);
+				// "Append text node to new parent as its last child,
+				// preserving ranges."
+				movePreservingRanges(textNode, newParent, 0);
 			}
 		}
-		*/
+		break;
 
 		case "fontname":
 		// "Decompose the Range, then style each returned Node with property
--- a/preprocess	Wed Apr 06 13:36:07 2011 -0600
+++ b/preprocess	Wed Apr 06 14:00:50 2011 -0600
@@ -31,6 +31,7 @@
     'fontsize': '<code data-anolis-spec=html title=dom-font-size>size</code>',
     'getselection': '<code data-anolis-spec=domrange title=dom-Document-getSelection>getSelection()</code>',
     'htmlnamespace': '<span data-anolis-spec=domcore>HTML namespace</span>',
+    '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>',
     'localname': '<span data-anolis-spec=domcore title=concept-element-local-name>local name</span>',
--- a/source.html	Wed Apr 06 13:36:07 2011 -0600
+++ b/source.html	Wed Apr 06 14:00:50 2011 -0600
@@ -1098,6 +1098,11 @@
 meanings, are as follows.  These values must be compared to the argument in an
 <span data-anolis-spec=domcore>ASCII case-insensitive</span> manner.
 
+<!-- Notes on commands I've looked at but haven't bothered specifying yet:
+
+* decreaseFontSize, increaseFontSize: Only implemented in Gecko and Opera.
+-->
+
 <dl>
 <dt><code title><dfn title=command-backcolor>backColor</dfn></code>
 
@@ -1195,25 +1200,23 @@
     [[descendants]] of <var>node</var>, or <var>node</var> itself if it's a
     [[text]] node.
 
-    <li>For each <var>text node</var> in <var>text nodes</var>, in
-    [[treeorder]]:
+    <li>For each <var>text node</var> in <var>text nodes</var>:
 
     <ol>
       <li>Let <var>ancestor link</var> be the parent of <var>text
       node</var>.
 
-      <li>While <var>ancestor link</var> is not an <span>HTML
-      element</span>, or its [[localname]] is not "a", or it has no <span>HTML
-      attribute</span> with [[attrlocalname]] "href":
+      <li>While <var>ancestor link</var> is not an <code data-anolis-spec=html
+      title="the a element">a</code> element or has no [[href]] attribute:
 
       <ol>
         <li>If the parent of <var>ancestor link</var> is not an [[element]],
         set <var>ancestor link</var> to null and break from this loop.
 
-        <li>Otherwise, set <var>ancestor link</var> to its parent.
+        <li>Otherwise, set <var>ancestor link</var> to its [[parent]].
       </ol>
 
-      <li>If <var>ancestor link</var> is not null, set its "href" attribute
+      <li>If <var>ancestor link</var> is not null, set its [[href]] attribute
       to <var>value</var> and continue with the next <var>text node</var>.
       <!-- There are three approaches here.  For instance, if you ask browsers
       to create a link to "http://example.org" on the "b" here:
@@ -1251,7 +1254,7 @@
       the previous sibling of <var>text node</var>.
 
       <li>Append <var>text node</var> to <var>new parent</var> as its last
-      child.
+      child, <span>preserving ranges</span>.
     </ol>
   </ol>
 </ol>