Improve insertOrderedList somewhat
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Mon, 09 May 2011 16:30:29 -0600
changeset 100 92484a18d548
parent 99 6f63f6aa573a
child 101 95523848c7f8
Improve insertOrderedList somewhat

Still more work to do.
autoimplementation.html
editcommands.html
implementation.js
preprocess
source.html
--- a/autoimplementation.html	Mon May 09 15:59:56 2011 -0600
+++ b/autoimplementation.html	Mon May 09 16:30:29 2011 -0600
@@ -625,33 +625,20 @@
 
 		'<p>foo<p>[bar]<p>baz',
 		'<p>foo<blockquote>[bar]</blockquote><p>baz',
-		'<ol><li>foo<li>[bar]<li>baz</ol>',
-		'<ul><li>foo<li>[bar]<li>baz</ul>',
 		'<dl><dt>foo<dd>[bar]<dt>baz<dd>quz</dl>',
 		'<dl><dt>foo<dd>bar<dt>[baz]<dd>quz</dl>',
 
 		'<p>foo<p>b[a]r<p>baz',
 		'<p>foo<blockquote>b[a]r</blockquote><p>baz',
-		'<ol><li>foo<li>b[a]r<li>baz</ol>',
-		'<ul><li>foo<li>b[a]r<li>baz</ul>',
 		'<dl><dt>foo<dd>b[a]r<dt>baz<dd>quz</dl>',
 		'<dl><dt>foo<dd>bar<dt>b[a]z<dd>quz</dl>',
 
 		'<p>[foo<p>bar]<p>baz',
 		'<p>[foo<blockquote>bar]</blockquote><p>baz',
-		'<ol><li>[foo<li>bar]<li>baz</ol>',
-		'<ul><li>[foo<li>bar]<li>baz</ul>',
 		'<dl><dt>[foo<dd>bar]<dt>baz<dd>quz</dl>',
 		'<dl><dt>foo<dd>[bar<dt>baz]<dd>quz</dl>',
 
 		'<p>[foo<blockquote><p>bar]<p>baz</blockquote>',
-		'<ol><li><ol><li>foo<li>[bar]</ol><li>baz</ol>',
-		'<ol><li><ul><li>foo<li>[bar]</ul><li>baz</ol>',
-		'<ul><li><ol><li>foo<li>[bar]</ol><li>baz</ul>',
-		'<ul><li><ul><li>foo<li>[bar]</ol><li>baz</ul>',
-
-		'<ol><li>foo</ol>[bar]',
-		'<ul><li>foo</ul>[bar]',
 
 		// Various <ol> stuff
 		'<ol><li>foo<li>[bar]<li>baz</ol>',
--- a/editcommands.html	Mon May 09 15:59:56 2011 -0600
+++ b/editcommands.html	Mon May 09 16:30:29 2011 -0600
@@ -544,14 +544,15 @@
 command.
 
 <p>When the user agent is 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>, it must 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>, then
-insert it in the new location.  In doing so, however, it must 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 instead follow these rules:
+ranges</dfn>, it must 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, it must 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 instead follow these rules:
 
 <ol>
   <li>Let <var title="">node</var> be the moved <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>, <var title="">old parent</var> and
-  <var title="">old index</var> be the old <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>, and <var title="">new
-  parent</var> and <var title="">new index</var> be the new <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>.
+  <var title="">old index</var> be the old <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> (which may be null) and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>,
+  and <var title="">new parent</var> and <var title="">new index</var> be the new <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> and
+  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>.
 
   <li>If a <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point title=concept-boundary-point>boundary point</a>'s <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 the same as or a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendant</a> of
   <var title="">node</var>, leave it unchanged, so it moves to the new location.  <!--
@@ -2688,25 +2689,36 @@
     <li>s. -->
 
     <ol>
-      <li>While <var title="">node list</var> is not empty, and the first member of
-      <var title="">node list</var> is the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last member of
-      <var title="">sublist</var>, and the last member of <var title="">sublist</var> and first
-      member of <var title="">node list</var> are both <a href=#inline-node title="inline node">inline
-      nodes</a> that are not <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>s, remove the first member from <var title="">node
-      list</var> and append it to <var title="">sublist</var>.
-
-      <li>Let <var title="">li</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("li")</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 the first member of <var title="">sublist</var>.
+      <li>If the first member of <var title="">sublist</var> is a <code class=external data-anolis-spec=html title="the p element"><a href=http://www.whatwg.org/html/#the-p-element>p</a></code> or <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> or
+      <code class=external data-anolis-spec=html title="the div element"><a href=http://www.whatwg.org/html/#the-div-element>div</a></code>, <a href=#set-the-tag-name>set the tag name</a> of the first member of
+      <var title="">sublist</var> to "li", and let <var title="">li</var> be the result.  Remove
+      the first member of <var title="">sublist</var>, and append <var title="">li</var> to
+      <var title="">sublist</var>.
+
+      <li>Otherwise:
+
+      <ol>
+        <li>While <var title="">node list</var> is not empty, and the first member of
+        <var title="">node list</var> is the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last member of
+        <var title="">sublist</var>, and the last member of <var title="">sublist</var> and first
+        member of <var title="">node list</var> are both <a href=#inline-node title="inline
+        node">inline nodes</a> that are not <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>s, remove the first member
+        from <var title="">node list</var> and append it to <var title="">sublist</var>.
+
+        <li>Let <var title="">li</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("li")</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 the first member of <var title="">sublist</var>.
+      </ol>
 
       <li>If the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last member of <var title="">sublist</var> is an
       <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code>:
 
       <ol>
         <li>Insert <var title="">li</var> as 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 the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code>
-        of the last member of <var title="">sublist</var>.
-
-        <li>If the first member of <var title="">sublist</var> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, remove it
-        from <var title="">sublist</var>.
+        of the last member of <var title="">sublist</var>, <a href=#preserving-ranges>preserving
+        ranges</a>.
+
+        <li>If the first member of <var title="">sublist</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 li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code>,
+        remove it from <var title="">sublist</var>.
 
         <li>For each <var title="">node</var> in <var title="">sublist</var> <em>in reverse
         order</em>, insert <var title="">node</var> as 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
@@ -2726,10 +2738,11 @@
         <var title="">sublist</var> immediately before the first member of
         <var title="">sublist</var>.
 
-        <li>Append <var title="">li</var> as the last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">ol</var>.
-
-        <li>If the first member of <var title="">sublist</var> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, remove it
-        from <var title="">sublist</var>.
+        <li>Append <var title="">li</var> as the last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">ol</var>,
+        <a href=#preserving-ranges>preserving ranges</a>.
+
+        <li>If the first member of <var title="">sublist</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 li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code>,
+        remove it from <var title="">sublist</var>.
 
         <li>For each <var title="">node</var> in <var title="">sublist</var>, append
         <var title="">node</var> as the last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">li</var>,
--- a/implementation.js	Mon May 09 15:59:56 2011 -0600
+++ b/implementation.js	Mon May 09 16:30:29 2011 -0600
@@ -172,6 +172,11 @@
 
 // Functions for stuff in DOM Range
 function getNodeIndex(node) {
+	if (!node.parentNode) {
+		// No preceding siblings, so . . .
+		return 0;
+	}
+
 	var ret = 0;
 	// These are no-ops to avoid a completely ridiculous bug in IE where
 	// sometimes a node is not actually equal to any of its parents' children.
@@ -995,12 +1000,13 @@
 
 function movePreservingRanges(node, newParent, newIndex) {
 	// "When the user agent is to move a Node to a new location, preserving
-	// ranges, it must remove the Node from its original parent, then insert it
-	// in the new location. In doing so, however, it must ignore the regular
-	// range mutation rules, and instead follow these rules:"
+	// ranges, it must remove the Node from its original parent (if any), then
+	// insert it in the new location. In doing so, however, it must ignore the
+	// regular range mutation rules, and instead follow these rules:"
 
 	// "Let node be the moved Node, old parent and old index be the old parent
-	// and index, and new parent and new index be the new parent and index."
+	// (which may be null) and index, and new parent and new index be the new
+	// parent and index."
 	var oldParent = node.parentNode;
 	var oldIndex = getNodeIndex(node);
 
@@ -2626,33 +2632,49 @@
 				}
 			// "Otherwise:"
 			} else {
-				// "While node list is not empty, and the first member of node
-				// list is the nextSibling of the last member of sublist, and
-				// the last member of sublist and first member of node list are
-				// both inline nodes that are not brs, remove the first member
-				// from node list and append it to sublist."
-				while (nodeList.length
-				&& nodeList[0] == sublist[sublist.length -1].nextSibling
-				&& isInlineNode(nodeList[0])
-				&& isInlineNode(sublist[sublist.length -1])
-				&& !isHtmlElement(nodeList[0], "BR")
-				&& !isHtmlElement(sublist[sublist.length -1], "BR")) {
-					sublist.push(nodeList.shift());
+				// "If the first member of sublist is a p or li or div, set the
+				// tag name of the first member of sublist to "li", and let li
+				// be the result.  Remove the first member of sublist, and
+				// append li to sublist."
+				var li;
+				if (isHtmlElement(sublist[0], "P")
+				|| isHtmlElement(sublist[0], "LI")
+				|| isHtmlElement(sublist[0], "DIV")) {
+					li = setTagName(sublist[0], "LI");
+					sublist = [li];
+
+				// "Otherwise:"
+				} else {
+					// "While node list is not empty, and the first member of
+					// node list is the nextSibling of the last member of
+					// sublist, and the last member of sublist and first member
+					// of node list are both inline nodes that are not brs,
+					// remove the first member from node list and append it to
+					// sublist."
+					while (nodeList.length
+					&& nodeList[0] == sublist[sublist.length -1].nextSibling
+					&& isInlineNode(nodeList[0])
+					&& isInlineNode(sublist[sublist.length -1])
+					&& !isHtmlElement(nodeList[0], "BR")
+					&& !isHtmlElement(sublist[sublist.length -1], "BR")) {
+						sublist.push(nodeList.shift());
+					}
+
+					// "Let li be the result of calling createElement("li") on
+					// the ownerDocument of the first member of sublist."
+					var li = sublist[0].ownerDocument.createElement("li");
 				}
 
-				// "Let li be the result of calling createElement("li") on the
-				// ownerDocument of the first member of sublist."
-				var li = sublist[0].ownerDocument.createElement("li");
-
 				// "If the nextSibling of the last member of sublist is an ol:"
 				if (isHtmlElement(sublist[sublist.length - 1].nextSibling, "OL")) {
 					// "Insert li as the first child of the nextSibling of the
-					// last member of sublist."
-					sublist[sublist.length - 1].nextSibling.insertBefore(li, sublist[sublist.length - 1].nextSibling.firstChild);
-
-					// "If the first member of sublist is a br, remove it from
-					// sublist."
-					if (isHtmlElement(sublist[0], "BR")) {
+					// last member of sublist, preserving ranges."
+					movePreservingRanges(li, sublist[sublist.length - 1].nextSibling, 0);
+
+					// "If the first member of sublist is a br or li, remove it
+					// from sublist."
+					if (isHtmlElement(sublist[0], "BR")
+					|| isHtmlElement(sublist[0], "LI")) {
 						sublist.shift();
 					}
 
@@ -2677,12 +2699,13 @@
 						sublist[0].parentNode.insertBefore(ol, sublist[0]);
 					}
 
-					// "Append li as the last child of ol."
-					ol.appendChild(li);
-
-					// "If the first member of sublist is a br, remove it from
-					// sublist."
-					if (isHtmlElement(sublist[0], "BR")) {
+					// "Append li as the last child of ol, preserving ranges."
+					movePreservingRanges(li, ol, ol.childNodes.length);
+
+					// "If the first member of sublist is a br or li, remove it
+					// from sublist."
+					if (isHtmlElement(sublist[0], "BR")
+					|| isHtmlElement(sublist[0], "LI")) {
 						sublist.shift();
 					}
 
--- a/preprocess	Mon May 09 15:59:56 2011 -0600
+++ b/preprocess	Mon May 09 16:30:29 2011 -0600
@@ -50,6 +50,7 @@
     'nodelength': '<span data-anolis-spec=domrange title=concept-node-length>length</span>',
     'ol': '<code data-anolis-spec=html title="the ol element">ol</code>',
     'ownerdocument': '<code data-anolis-spec=domcore title=dom-Node-ownerDocument>ownerDocument</code>',
+    'p': '<code data-anolis-spec=html title="the p element">p</code>',
     'parent': '<span data-anolis-spec=domcore title=concept-tree-parent>parent</span>',
     'partiallycontained': '<span data-anolis-spec=domrange>partially contained</span>',
     'phrasingcontent': '<span data-anolis-spec=html>phrasing content</span>',
--- a/source.html	Mon May 09 15:59:56 2011 -0600
+++ b/source.html	Mon May 09 16:30:29 2011 -0600
@@ -535,14 +535,15 @@
 command.
 
 <p>When the user agent is to move a [[node]] to a new location, <dfn>preserving
-ranges</dfn>, it must remove the [[node]] from its original [[parent]], then
-insert it in the new location.  In doing so, however, it must ignore the
-regular [[rangemutationrules]], and instead follow these rules:
+ranges</dfn>, it must remove the [[node]] from its original [[parent]] (if
+any), then insert it in the new location.  In doing so, however, it must ignore
+the regular [[rangemutationrules]], and instead follow these rules:
 
 <ol>
   <li>Let <var>node</var> be the moved [[node]], <var>old parent</var> and
-  <var>old index</var> be the old [[parent]] and [[index]], and <var>new
-  parent</var> and <var>new index</var> be the new [[parent]] and [[index]].
+  <var>old index</var> be the old [[parent]] (which may be null) and [[index]],
+  and <var>new parent</var> and <var>new index</var> be the new [[parent]] and
+  [[index]].
 
   <li>If a [[boundarypoint]]'s [[bpnode]] is the same as or a [[descendant]] of
   <var>node</var>, leave it unchanged, so it moves to the new location.  <!--
@@ -2733,27 +2734,38 @@
     <li>s. -->
 
     <ol>
-      <li>While <var>node list</var> is not empty, and the first member of
-      <var>node list</var> is the [[nextsibling]] of the last member of
-      <var>sublist</var>, and the last member of <var>sublist</var> and first
-      member of <var>node list</var> are both <span title="inline node">inline
-      nodes</span> that are not [[br]]s, remove the first member from <var>node
-      list</var> and append it to <var>sublist</var>.
-
-      <li>Let <var>li</var> be the result of calling <code
-      data-anolis-spec=domcore
-      title=dom-Document-createElement>createElement("li")</code> on the
-      [[ownerdocument]] of the first member of <var>sublist</var>.
+      <li>If the first member of <var>sublist</var> is a [[p]] or [[li]] or
+      [[div]], <span>set the tag name</span> of the first member of
+      <var>sublist</var> to "li", and let <var>li</var> be the result.  Remove
+      the first member of <var>sublist</var>, and append <var>li</var> to
+      <var>sublist</var>.
+
+      <li>Otherwise:
+
+      <ol>
+        <li>While <var>node list</var> is not empty, and the first member of
+        <var>node list</var> is the [[nextsibling]] of the last member of
+        <var>sublist</var>, and the last member of <var>sublist</var> and first
+        member of <var>node list</var> are both <span title="inline
+        node">inline nodes</span> that are not [[br]]s, remove the first member
+        from <var>node list</var> and append it to <var>sublist</var>.
+
+        <li>Let <var>li</var> be the result of calling <code
+        data-anolis-spec=domcore
+        title=dom-Document-createElement>createElement("li")</code> on the
+        [[ownerdocument]] of the first member of <var>sublist</var>.
+      </ol>
 
       <li>If the [[nextsibling]] of the last member of <var>sublist</var> is an
       [[ol]]:
 
       <ol>
         <li>Insert <var>li</var> as the first [[child]] of the [[nextsibling]]
-        of the last member of <var>sublist</var>.
-
-        <li>If the first member of <var>sublist</var> is a [[br]], remove it
-        from <var>sublist</var>.
+        of the last member of <var>sublist</var>, <span>preserving
+        ranges</span>.
+
+        <li>If the first member of <var>sublist</var> is a [[br]] or [[li]],
+        remove it from <var>sublist</var>.
 
         <li>For each <var>node</var> in <var>sublist</var> <em>in reverse
         order</em>, insert <var>node</var> as the first [[child]] of
@@ -2774,10 +2786,11 @@
         <var>sublist</var> immediately before the first member of
         <var>sublist</var>.
 
-        <li>Append <var>li</var> as the last [[child]] of <var>ol</var>.
-
-        <li>If the first member of <var>sublist</var> is a [[br]], remove it
-        from <var>sublist</var>.
+        <li>Append <var>li</var> as the last [[child]] of <var>ol</var>,
+        <span>preserving ranges</span>.
+
+        <li>If the first member of <var>sublist</var> is a [[br]] or [[li]],
+        remove it from <var>sublist</var>.
 
         <li>For each <var>node</var> in <var>sublist</var>, append
         <var>node</var> as the last [[child]] of <var>li</var>,