--- a/editcommands.html Fri Feb 11 09:48:42 2011 -0700
+++ b/editcommands.html Thu Feb 17 15:06:13 2011 -0700
@@ -19,7 +19,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-11-february-2011>Work in Progress — Last Update 11 February 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-—-last-update-17-february-2011>Work in Progress — Last Update 17 February 2011</h2>
<dl>
<dt>Editor
<dd>Aryeh Gregor <ayg+spec@aryeh.name>
@@ -36,8 +36,10 @@
<ol class=toc>
<li><a class=no-num href=#table-of-contents>Table of contents</a></li>
<li><a href=#introduction><span class=secno>1 </span>Introduction</a></li>
- <li><a href=#definitions><span class=secno>2 </span>Definitions</a></li>
- <li><a href=#commands><span class=secno>3 </span>Commands</a></li>
+ <li><a href=#issues><span class=secno>2 </span>Issues</a></li>
+ <li><a href=#definitions><span class=secno>3 </span>Definitions</a></li>
+ <li><a href=#styling-a-range><span class=secno>4 </span>Styling a Range</a></li>
+ <li><a href=#commands><span class=secno>5 </span>Commands</a></li>
<li><a class=no-num href=#references>References</a></ol>
<!--end-toc-->
@@ -55,154 +57,491 @@
included in HTML comments so as not to distract the reader.
-<h2 id=definitions><span class=secno>2 </span>Definitions</h2>
-<p>When a user agent is to <dfn id=split-text-node title=split-text-node>split a <code class=external data-anolis-spec=domcore>Text</code> node</dfn> <var title="">node</var>, it must
-run the following steps:
-
-<ol>
- <li>Let <var title="">prefix</var> be the substring of <var title="">node</var>'s
- <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-characterdata-data><code class=external data-anolis-spec=domcore title=dom-CharacterData-data>data</code></a>
- of length <var title="">offset</var> beginning at offset 0.
-
- <li>Let <var title="">prefix node</var> be a new <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node whose <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-characterdata-data><code class=external data-anolis-spec=domcore title=dom-CharacterData-data>data</code></a> is equal to
- <var title="">prefix</var> and whose <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument><code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument>ownerDocument</code></a> is equal to <var title="">node</var>'s.
-
- <li>Insert <var title="">prefix node</var> in <var title="">node</var>'s parent as
- the previous sibling of <var title="">node</var>.
+<h2 id=issues><span class=secno>2 </span>Issues</h2>
- <li>Let <var title="">suffix</var> be the substring of <var title="">node</var>'s
- <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-characterdata-data><code class=external data-anolis-spec=domcore title=dom-CharacterData-data>data</code></a>
- beginning at offset <var title="">offset</var> and continuing to the end of the
- string.
+<ul>
+ <li><p>Need to make CSS terminology more precise, about setting/unsetting CSS
+ properties. The intent is to modify the style attribute, CSSOM-style.
- <li>Let <var title="">suffix node</var> be a new <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node whose <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-characterdata-data><code class=external data-anolis-spec=domcore title=dom-CharacterData-data>data</code></a> is equal to
- <var title="">suffix</var> and whose <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument><code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument>ownerDocument</code></a> is equal to <var title="">node</var>'s.
-
- <li>Insert <var title="">suffix node</var> in <var title="">node</var>'s parent as
- the previous sibling of <var title="">node</var>.
+ <li><p>Some of the DOM stuff might benefit from more precision. E.g., is
+ there a precise algorithm for what it means to append a node someplace, if
+ that node is already somewhere in the DOM? What does that do if it's
+ selected, it has state (like a video or animated image), etc.?
+</ul>
- <li>Delete <var title="">node</var> from its parent.
- <li>Return (<var title="">prefix node</var>, <var title="">suffix node</var>).
-</ol>
+<h2 id=definitions><span class=secno>3 </span>Definitions</h2>
-<p>When a user agent is to <dfn id=wrap-range-in-tag title=wrap-range-in-tag>wrap a <code class=external data-anolis-spec=domrange>Range</code> <var title="">range</var> in a tag <var title="">tag</var></dfn>, it must run the following steps:
+<p>A <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> is an <dfn id=html-element-with-name>HTML element
+with name</dfn> <var title="">name</var> if it is an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a>, its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-namespace title=concept-element-namespace>namespace</a> is the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#html-namespace>HTML namespace</a>, and 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
+<var title="">name</var>.
+
+
+<h2 id=styling-a-range><span class=secno>4 </span>Styling a Range</h2>
+<p>When a user agent is to <dfn id=style-a-range>style a <code class=external data-anolis-spec=domrange>Range</code></dfn> <var title="">range</var>, it must
+run the following steps. There are three inputs: a CSS property name <var title="">property name</var>, a new value <var title="">property value</var>, and a
+nonempty list of strings <var title="">tag list</var>.
<p class=XXX>This is totally made up and I have no idea yet if it matches
browsers and/or is even vaguely coherent.
<ol>
- <li>Let <var title="">start node</var>, <var title="">start offset</var>, <var title="">end node</var>, and <var title="">end offset</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> 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=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>nodes</a> and
+ <li><p>Let <var title="">start node</var>, <var title="">start offset</var>, <var title="">end node</var>, and <var title="">end offset</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> 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=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>nodes</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>offsets</a> of <var title="">range</var>,
respectively.
- <li>Let <var title="">document</var> be the <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument><code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument>ownerDocument</code></a> of <var title="">start
+ <li><p>Let <var title="">document</var> be the <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument><code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument>ownerDocument</code></a> of <var title="">start
node</var>.
- <li>If <var title="">start node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a>, <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#processinginstruction><code class=external data-anolis-spec=domcore>ProcessingInstruction</code></a>, or <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#comment><code class=external data-anolis-spec=domcore>Comment</code></a>, and it has no parent, abort these
- steps.
+ <li><p>If <var title="">start node</var> or <var title="">end node</var> is not an
+ <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a>, <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a>, <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#processinginstruction><code class=external data-anolis-spec=domcore>ProcessingInstruction</code></a>, or <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#comment><code class=external data-anolis-spec=domcore>Comment</code></a> node, or is not an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> and has no parent, abort
+ these steps.
+
+ <p class=XXX>Figure out something sensible here.
+
+ <li><p>If <var title="">start node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node and <var title="">start offset</var>
+ is neither 0 nor 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="">start node</var>, run
+ <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-text-splittext><code class=external data-anolis-spec=domcore title=dom-Text-splitText>splitText(<var title="">start offset</var>)</code></a> on <var title="">start node</var> and set <var title="">start node</var> to the returned node. Set <var title="">start
+ offset</var> to 0.
+
+ <li><p>If <var title="">end node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node and <var title="">end offset</var> is
+ neither 0 nor 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="">end node</var>, run
+ <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-text-splittext><code class=external data-anolis-spec=domcore title=dom-Text-splitText>splitText(<var title="">end offset</var>)</code></a> on <var title="">end node</var> and set <var title="">end node</var> to the previous sibling of the returned node. Set <var title="">end 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 the new <var title="">end node</var>.
+
+<!-- Original declarative definition
+ <li><p>Let <var title>node list</var> be the list of <code
+ data-anolis-spec=domcore>Node</code>s <var title>node</var> in <var
+ title>document</var> satisfying all of the following conditions:
+
+ <ul>
+ <li><p>In <span data-anolis-spec=domcore>tree order</span>, <var
+ title>node</var> is after the child of <var title>start node</var> with
+ <span data-anolis-spec=domrange title=concept-indexof>index</span> <var
+ title>start offset</var> (or after <var title>start node</var> itself, if
+ <var title>start node</var> is not an <code
+ data-anolis-spec=domcore>Element</code>).
+
+ <li><p>In <span data-anolis-spec=domcore>tree order</span>, <var
+ title>node</var> is before the child of <var title>end node</var> with
+ <span data-anolis-spec=domrange title=concept-indexof>index</span> <var
+ title>end offset</var> (or before <var title>end node</var> itself, if <var
+ title>end node</var> is not an <code
+ data-anolis-spec=domcore>Element</code>).
+
+ <li><p><var title>node</var> is not a <span data-anolis-spec=domcore
+ title=concept-descendant-node>descendant</span> of any other <code
+ data-anolis-spec=domcore>Node</code> that satisfies the previous two
+ conditions.
+ </ul>
+
+ <li><p>If <var title>start node</var> is a <code
+ data-anolis-spec=domcore>Text</code> node and <var title>start offset</var>
+ is 0, add <var title>start node</var> to <var title>node list</var>.
+
+ <li><p>If <var title>end node</var> is a <code
+ data-anolis-spec=domcore>Text</code> node and <var title>end offset</var> is
+ the <span data-anolis-spec=domrange title=concept-node-length>length</span>
+ of <var title>end node</var>, add <var title>end node</var> to <var
+ title>node list</var>.
+
+ <li><p>If there is some <code data-anolis-spec=domcore>Element</code> that is
+ not in <var title>node list</var> but which has one or more children, and its
+ children are all in <var title>node list</var>, add that <code
+ data-anolis-spec=domcore>Element</code> to <var title>node list</var> and
+ remove all its children from <var title>node list</var>. Repeat until there
+ is no such <code data-anolis-spec=domcore>Element</code>.
+ -->
+
+ <li><p>Let <var title="">node list</var> be an empty list of <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a>s.
+
+ <li><p>If <var title="">start node</var> is an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> with at least one child, let <var title="">node</var> be the first <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a>
+ after the child of <var title="">start node</var> 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="">start
+ offset</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><p>Otherwise, if <var title="">start node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node and <var title="">start offset</var>
+ is 0, or if <var title="">start node</var> is an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> with no children, let <var title="">node</var> be <var title="">start node</var>.
+
+ <li><p>Otherwise, let <var title="">node</var> be the first <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> after <var title="">start node</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><p>If <var title="">end node</var> is an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> with at least one child, let <var title="">end</var> be the first <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a>
+ before the child of <var title="">end node</var> 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="">end
+ offset</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> (or, if
+ <var title="">end offset</var> is <var title="">end node</var>'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>, let <var title="">end</var> be the last child of <var title="">end node</var>).
+
+ <li><p>Otherwise, if <var title="">end node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node and <var title="">end offset</var> is
+ its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>,
+ or if <var title="">end node</var> is an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> with no children, let <var title="">end</var> be <var title="">end node</var>.
+
+ <li><p>Otherwise, let <var title="">end</var> be the last <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> before <var title="">end node</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><p>While <var title="">node</var> is not after <var title="">end</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>Append <var title="">node</var> to <var title="">node list</var>.
+
+ <li>Set <var title="">node</var> to the first <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> 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> that is after <var title="">node</var> and (if applicable) all
+ its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-descendant-node title=concept-descendant-node>descendants</a>. If no such <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> exists, break out of these substeps.
+ </ol>
+
+ <!-- Condense the node list for extra tidiness. -->
+ <li><p>Let <var title="">node</var> be the first <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> in <var title="">node list</var>.
+
+ <li><p>Repeat:
+
+ <ol>
+ <li><p>If <var title="">node</var> has a parent, and its parent is an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a>, and all the children of <var title="">node</var>'s parent are contained in <var title="">node list</var>, add
+ <var title="">node</var>'s parent to <var title="">node list</var> immediately
+ before <var title="">node</var>, then remove all children of <var title="">node</var>'s parent from <var title="">node list</var>. Set <var title="">node</var> to <var title="">node</var>'s parent and continue these
+ substeps from the beginning.
+
+ <li><p>If <var title="">node</var> is the last <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> in <var title="">node list</var>, break
+ out of these substeps.
+
+ <li><p>Set <var title="">node</var> to the next <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> in <var title="">node list</var>.
+ </ol>
+
+ <li><p>For each <var title="">node</var> in <var title="">node list</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><p>If <var title="">node</var> is an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a>:
+
+ <ol>
+ <li><p>If <var title="">node</var> is an <a href=#html-element-with-name>HTML element with name</a>
+ in <var title="">tag list</var>, unset the CSS property <var title="">property
+ name</var> of <var title="">node</var>. Otherwise, set the CSS property
+ <var title="">property name</var> of <var title="">node</var> to <var title="">property value</var>.
+
+ <li><p>For each <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-descendant-node title=concept-descendant-node>descendant</a> <var title="">descendant</var> of <var title="">node</var> that is an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a>:
+
+ <ol>
+ <li><p>If either
+
+ <ul>
+ <li><p><var title="">descendant</var> is an <a href=#html-element-with-name>HTML element with
+ name</a> either "span" or in <var title="">tag list</var>, and it has
+ only a single attribute, and that attribute is named "style", and
+ that style attribute sets only the CSS property <var title="">property
+ name</var>; or
+
+ <li><p><var title="">descendant</var> is an <a href=#html-element-with-name>HTML element with
+ name</a> in <var title="">tag list</var> and it has no attributes,
+ </ul>
+
+ <p>then append all of <var title="">descendant</var>'s children to the
+ parent of <var title="">descendant</var> in order immediately before <var title="">descendant</var>, and remove <var title="">descendant</var>.
+ Continue with the next descendant.
+
+ <li><p>Unset the CSS property <var title="">property name</var> of <var title="">descendant</var>.
+ <!-- Only WebKit appears to do this, but it makes sense. Otherwise
+ things like <span style=font-weight:normal> won't disappear when you
+ apply bold. (Same applies to the places below where we unset the CSS
+ property here.) -->
+
+ <li><p>If <var title="">descendant</var> is an <a href=#html-element-with-name>HTML element with
+ name</a> in <var title="">tag list</var>, let <var title="">new
+ descendant</var> be a new <a href=#html-element-with-name>HTML element with name</a> "span",
+ with the same attributes and <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument><code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument>ownerDocument</code></a> as <var title="">descendant</var>. Append <var title="">new descendant</var> to <var title="">descendant</var>'s parent as the previous sibling of <var title="">descendant</var>, then append all of <var title="">descendant</var>'s children to <var title="">new descendant</var> in
+ order, then remove <var title="">descendant</var>.
+ </ol>
+ </ol>
+
+ <li><p>Otherwise:
+
+ <ol>
+ <li><p>If <var title="">node</var> is not the first child of its parent,
+ and its previous sibling is an <a href=#html-element-with-name>HTML element with name</a> equal
+ to the first string in <var title="">tag list</var>, append <var title="">node</var> to <var title="">node</var>'s previous sibling as the last
+ child. Continue with the next <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a>
+ in <var title="">node list</var>.
+ <!-- Thus we merge things together a bit. This could probably use more
+ thought. -->
+
+ <li><p>If <var title="">node</var> is not a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node, or if its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-characterdata-data title=dom-CharacterData-data>data</a> is a
+ sequence of zero or more <a class=external data-anolis-spec=html href=http://www.whatwg.org/html/#space-character title="space
+ character">space characters</a>, continue with the next <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> in <var title="">node list</var>.
+ <!-- This avoids wrapping whitespace-only text nodes, which agrees with
+ Gecko and WebKit. IE9 and Opera wrap the whitespace-only text nodes,
+ which seems pointless. -->
+
+ <li><p>Let <var title="">new parent</var> be a new <a href=#html-element-with-name>HTML element with
+ name</a> equal to the first string in <var title="">tag list</var>, with
+ no attributes, and <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument><code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument>ownerDocument</code></a> set to <var title="">document</var>.
+
+ <li><p>Append <var title="">new parent</var> to <var title="">node</var>'s
+ parent as the previous sibling of <var title="">node</var>.
+
+ <li><p>Append <var title="">node</var> to <var title="">new parent</var> as
+ its last child.
+ </ol>
+ </ol>
+</ol>
+
+<!-- Out of IE9, Gecko, WebKit, and Opera, when asked to (e.g.) bold an
+element, IE9 and WebKit and Opera wrap various descendants in <b> or <strong>;
+Gecko just adds a style attribute. The latter is simpler, particularly because
+you then don't have to worry about making sure you only insert your tags in a
+valid place (which you have to so that text/html serialization is possible, if
+nothing else). I originally specced the former approach, retained here in case
+I want to switch back:
+
+<p>When a user agent is to <dfn title=wrap-range-in-tag>wrap a <code
+data-anolis-spec=domrange>Range</code> <var title>range</var> in a tag <var
+title>tag</var></dfn>, treating <var title>tag list</var> as equivalent and
+overriding CSS <var title>property</var>, it must run the following steps:
+
+<p class=XXX>This is totally made up and I have no idea yet if it matches
+browsers and/or is even vaguely coherent.
+
+<ol>
+ <li><p>Let <var title>start node</var>, <var title>start offset</var>, <var
+ title>end node</var>, and <var title>end offset</var> be the <span
+ data-anolis-spec=domrange title=concept-range-start>start</span> and <span
+ data-anolis-spec=domrange title=concept-range-end>end</span> <span
+ data-anolis-spec=domrange title=concept-boundary-point-node>nodes</span> and
+ <span data-anolis-spec=domrange
+ title=concept-boundary-point-offset>offsets</span> of <var title>range</var>,
+ respectively.
+
+ <li><p>Let <var title>document</var> be the <code data-anolis-spec=domcore
+ title=dom-Node-ownerDocument>ownerDocument</code> of <var title>start
+ node</var>.
+
+ <li><p>If <var title>start node</var> is a <code
+ data-anolis-spec=domcore>Text</code>, <code
+ data-anolis-spec=domcore>ProcessingInstruction</code>, or <code
+ data-anolis-spec=domcore>Comment</code> node, and it has no parent, abort
+ these steps.
<p class=XXX>Figure out something sensible here. Doesn't make sense except
in IE, since other browsers fail if it's not contentEditable. What does IE
do? What do we expect?
- <li>If <var title="">start node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node and <var title="">start offset</var>
- is neither 0 nor 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="">start node</var>, <a href=#split-text-node title=split-text-node>split <var title="">start node</var></a> and set <var title="">start node</var> to the second returned node. Set <var title="">start
+ <li><p>If <var title>start node</var> is a <code
+ data-anolis-spec=domcore>Text</code> node and <var title>start offset</var>
+ is neither 0 nor the <span data-anolis-spec=domrange
+ title=concept-node-length>length</span> of <var title>start node</var>, run
+ <code data-anolis-spec=domcore title=dom-Text-splitText>splitText(<var
+ title>start offset</var>)</code> on <var title>start node</var> and set <var
+ title>start node</var> to the returned node. Set <var title>start
offset</var> to 0.
- <li>If <var title="">start node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node and <var title="">start offset</var>
- is 0, set <var title="">start 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 of</a> <var title="">start node</var> in its parent, then set <var title="">start node</var> to
+ <li><p>If <var title>start node</var> is a <code
+ data-anolis-spec=domcore>Text</code> node and <var title>start offset</var>
+ is 0, set <var title>start offset</var> to the <span
+ data-anolis-spec=domrange title=concept-indexof>index of</span> <var
+ title>start node</var> in its parent, then set <var title>start node</var> to
its parent.
- <li>If <var title="">start node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node and <var title="">start offset</var>
- 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 <var title="">start node</var>, or if
- <var title="">start node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#comment><code class=external data-anolis-spec=domcore>Comment</code></a> or <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#processinginstruction><code class=external data-anolis-spec=domcore>ProcessingInstruction</code></a>, set <var title="">start
- offset</var> to one plus the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index of</a> <var title="">start node</var> in its
- parent, then set <var title="">start node</var> to its parent.
+ <li><p>If <var title>start node</var> is a <code
+ data-anolis-spec=domcore>Text</code>, <code
+ data-anolis-spec=domcore>Comment</code>, or <code
+ data-anolis-spec=domcore>ProcessingInstruction</code> node, set <var
+ title>start offset</var> to one plus the <span data-anolis-spec=domrange
+ title=concept-indexof>index of</span> <var title>start node</var> in its
+ parent, then set <var title>start node</var> to its parent.
- <li>If <var title="">end node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node and <var title="">end offset</var> is
- neither 0 nor 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="">end node</var>, <a href=#split-text-node title=split-text-node>split <var title="">end node</var></a> and set <var title="">end node</var> to the first returned node. Set <var title="">end
- 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 the new <var title="">end node</var>.
+ <li><p>If <var title>end node</var> is a <code
+ data-anolis-spec=domcore>Text</code> node and <var title>end offset</var> is
+ neither 0 nor the <span data-anolis-spec=domrange
+ title=concept-node-length>length</span> of <var title>end node</var>, run
+ <code data-anolis-spec=domcore title=dom-Text-splitText>splitText(<var
+ title>end offset</var>)</code> on <var title>end node</var> and set <var
+ title>end node</var> to the previous sibling of the returned node. Set <var
+ title>end offset</var> to the <span data-anolis-spec=domrange
+ title=concept-node-length>length</span> of the new <var title>end node</var>.
- <li>If <var title="">end node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node and <var title="">end offset</var> 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 <var title="">end node</var>, set <var title="">end offset</var> to one plus the
- <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index of</a> <var title="">end node</var> in its parent, then set <var title="">end node</var> to its
+ <li><p>If <var title>end node</var> is a <code
+ data-anolis-spec=domcore>Text</code> node and <var title>end offset</var> is
+ the <span data-anolis-spec=domrange title=concept-node-length>length</span>
+ of <var title>end node</var>, set <var title>end offset</var> to one plus the
+ <span data-anolis-spec=domrange title=concept-indexof>index of</span> <var
+ title>end node</var> in its parent, then set <var title>end node</var> to its
parent.
- <li>If <var title="">end node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node and <var title="">end offset</var> is
- 0, or if <var title="">end node</var> is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#comment><code class=external data-anolis-spec=domcore>Comment</code></a> or <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#processinginstruction><code class=external data-anolis-spec=domcore>ProcessingInstruction</code></a>, set <var title="">end
- 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 of</a> <var title="">end node</var> in its
- parent, then set <var title="">end node</var> to its parent.
+ <li><p>If <var title>end node</var> is a <code
+ data-anolis-spec=domcore>Text</code>, <code
+ data-anolis-spec=domcore>Comment</code>, or <code
+ data-anolis-spec=domcore>ProcessingInstruction</code> node, set <var
+ title>end offset</var> to the <span data-anolis-spec=domrange
+ title=concept-indexof>index of</span> <var title>end node</var> in its
+ parent, then set <var title>end node</var> to its parent.
- <p class=note>The previous several steps have ensured that <var title="">start
- node</var> and <var title="">end node</var> are not <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a>, <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#comment><code class=external data-anolis-spec=domcore>Comment</code></a>, or <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#processinginstruction><code class=external data-anolis-spec=domcore>ProcessingInstruction</code></a> nodes, so <var title="">start offset</var> and <var title="">end offset</var> now represent node
+ <p class=note>The previous several steps have ensured that <var title>start
+ node</var> and <var title>end node</var> are not <code
+ data-anolis-spec=domcore>Text</code>, <code
+ data-anolis-spec=domcore>Comment</code>, or <code
+ data-anolis-spec=domcore>ProcessingInstruction</code> nodes, so <var
+ title>start offset</var> and <var title>end offset</var> now represent node
offsets instead of character offsets.
- <li>Let <var title="">node</var> equal <var title="">start node</var> and let <var title="">offset</var> equal <var title="">start offset</var>.
-
- <li>Repeat the following steps until aborted:
- <ol>
- <li><i id=wrap-algorithm-start title="">Start</i>: If <var title="">node</var> is
- after <var title="">end node</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>, or if <var title="">node</var> equals <var title="">end node</var>
- and <var title="">offset</var> is greater than or equal to <var title="">end
- offset</var>, abort this subalgorithm.
-
- <li>Let <var title="">element</var> be a new <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> with no attributes, <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-namespace title=concept-element-namespace>namespace</a>
- set to the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#html-namespace>HTML namespace</a>, <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>
- set to <var title="">tag</var>, and <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument><code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument>ownerDocument</code></a> set to <var title="">document</var>.
-
- <li>While <var title="">node</var> has a child 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>, and that child is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node whose <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-characterdata-data><code class=external data-anolis-spec=domcore title=dom-CharacterData-data>data</code></a> is only
- <a class=external data-anolis-spec=html href=http://www.whatwg.org/html/#space-character title="space character">space characters</a>
- or that child is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#comment><code class=external data-anolis-spec=domcore>Comment</code></a> or that
- child is a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#processinginstruction><code class=external data-anolis-spec=domcore>ProcessingInstruction</code></a>,
- increment <var title="">offset</var>.
- <!-- This avoids wrapping whitespace-only text nodes, which agrees with
- WebKit. IE9 wraps the whitespace-only text nodes, and Gecko tries to do
- something crazy like add CSS attributes instead of elements. -->
+ <li><p>Let <var title>node</var> equal <var title>start node</var> and let <var
+ title>offset</var> equal <var title>start offset</var>.
- <li>If <var title="">offset</var> is equal to <var title="">node</var>'s number
- of children, let <var title="">node</var> equal the first <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> in <var title="">document</var> that is
- after all of <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-descendant-node title=concept-descendant-node>descendants</a> 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>, and let <var title="">offset</var>
- equal zero. Continue from <i title=""><a href=#wrap-algorithm-start>start</a></i>.
+ <li><p>Repeat the following steps until aborted:
+ <ol>
+ <li><p><i title id=wrap-algorithm-start>Start</i>: If <var title>node</var> is
+ after <var title>end node</var> in <span data-anolis-spec=domcore>tree
+ order</span>, or if <var title>node</var> equals <var title>end node</var>
+ and <var title>offset</var> is greater than or equal to <var title>end
+ offset</var>, abort this subalgorithm.
- <li>Let <var title="">child</var> be the child of <var title="">node</var> 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>.
+ <li><p>Let <var title>element</var> be a new <code
+ data-anolis-spec=domcore>Element</code> with no attributes, <span
+ data-anolis-spec=domcore title=concept-element-namespace>namespace</span>
+ set to the <span data-anolis-spec=domcore>HTML namespace</span>, <span
+ data-anolis-spec=domcore title=concept-element-local-name>local name</span>
+ set to <var title>tag</var>, and <code data-anolis-spec=domcore
+ title=dom-Node-ownerDocument>ownerDocument</code> set to <var
+ title>document</var>.
- <li>If <var title="">child</var> is an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> which is not part of the <a class=external data-anolis-spec=html href=http://www.whatwg.org/html/#content-models title="content models">content model</a> of <var title="">element</var>:
-
- <ol>
- <li>Create a new <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></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="">child</var>, 0), <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="">child</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="">child</var>), and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-root title=concept-range-root>root</a> the same as <var title="">range</var>'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>.
+ <li><p>While <var title>node</var> has a child with <span
+ data-anolis-spec=domrange title=concept-indexof>index</span> <var
+ title>offset</var>, and that child meets one of the following conditions,
+ take the described action (if any) and increment <var title>offset</var>:
+
+ <dl class=switch>
+ <dt>The child is a <code data-anolis-spec=domcore>Text</code> node whose
+ <code data-anolis-spec=domcore title=dom-CharacterData-data>data</code>
+ consists of zero or more <span data-anolis-spec=html title="space
+ character">space characters</span>
+ <!- - This avoids wrapping whitespace-only text nodes, which agrees with
+ WebKit. IE9 wraps the whitespace-only text nodes, and Gecko tries to do
+ something crazy like add CSS attributes instead of elements. - ->
+ <dt>The child is a <code data-anolis-spec=domcore>Comment</code>, <code
+ data-anolis-spec=domcore>ProcessingInstruction</code>, or <code
+ data-anolis-spec=domcore>DocumentType</code>
+ <dd>No action.
+
+ <dt>The child is an <code data-anolis-spec=domcore>Element</code> whose
+ <span data-anolis-spec=domcore
+ title=concept-element-namespace>namespace</span> is the <span
+ data-anolis-spec=domcore>HTML namespace</span> and whose <span
+ data-anolis-spec=domcore title=concept-element-local-name>local
+ name</span> is <var title>tag</var>
+ <dd><span>Unset the CSS property</span> <var title>property</var> on each
+ <span data-anolis-spec=domcore
+ title=concept-descendant-node>descendant</span> of the child.
+ <!- - Only WebKit appears to do this, but it makes sense. Otherwise
+ things like <span style=font-weight:normal> won't disappear when you
+ apply bold. (Same applies to the places below where we unset the CSS
+ property here.) - ->
+ </dl>
+
+ <li><p>If <var title>offset</var> is equal to <var title>node</var>'s <span
+ data-anolis-spec=domrange title=concept-node-length>length</span>:
+
+ <ol>
+ <li><p>If <var title>node</var> is the last <code
+ data-anolis-spec=domcore>Node</code> in <var title>document</var>, abort
+ this subalgorithm (the one that begins with <i title><a
+ href=wrap-algorithm-start>start</a></i>).
+
+ <li><p>Let <var title>node</var> equal the first <code
+ data-anolis-spec=domcore>Node</code> in <var title>document</var> that is
+ after all of <var title>node</var>'s <span data-anolis-spec=domcore
+ title=concept-descendant-node>descendants</span> in <span
+ data-anolis-spec=domcore>tree order</span>.
- <li><a href=#wrap-range-in-tag title=wrap-range-in-tag>Wrap that <code class=external data-anolis-spec=domrange>Range</code> in <var title="">tag</var></a>.
-
- <li>Increment <var title="">offset</var>.
-
- <li>Continue from <i title=""><a href=#wrap-algorithm-start>start</a></i>.
- </ol>
+ <li><p>Let <var title>offset</var> equal zero.
+
+ <li><p>Continue from <i title><a
+ href=#wrap-algorithm-start>start</a></i>.
+ </ol>
- <li>Append <var title="">element</var> to <var title="">node</var> as the
- previous sibling of <var title="">child</var>.
+ <li><p>Let <var title>child</var> be the child of <var title>node</var> with
+ <span data-anolis-spec=domrange title=concept-indexof>index</span> <var
+ title>offset</var>.
- <li>While the child of <var title="">node</var> has a child 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>, and while that child is not an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> or is an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> but is part of the <a class=external data-anolis-spec=html href=http://www.whatwg.org/html/#content-models title="content models">content model</a> of <var title="">element</var>, change that child's parent to <var title="">element</var>
- and increment <var title="">offset</var>.
+ <p class=note><var title>child</var> will always be either an <code
+ data-anolis-spec=domcore>Element</code> or a <code
+ data-anolis-spec=domcore>Text</code> node.
- <p class=XXX>What exactly does it mean to change the child's parent? E.g.,
- what happens if this occurs to a video that's playing? Is there a precise
- spec somewhere?
+ <li><p>If <var title>child</var> is an <code
+ data-anolis-spec=domcore>Element</code> which is not part of the <span
+ data-anolis-spec=html title="content models">content model</span> of <var
+ title>element</var>:
+
+ <ol>
+ <li><p>Create a new <code data-anolis-spec=domrange>Range</code> with <span
+ data-anolis-spec=domrange title=concept-range-start>start</span> (<var
+ title>child</var>, 0), <span data-anolis-spec=domrange
+ title=concept-range-end>end</span> (<var title>child</var>, <span
+ data-anolis-spec=domrange title=concept-node-length>length</span> of <Var
+ title>child</var>), and <span data-anolis-spec=domrange
+ title=concept-range-root>root</span> the same as <var title>range</var>'s
+ <span data-anolis-spec=domrange title=concept-range-root>root</span>.
+
+ <li><p><span title=wrap-range-in-tag>Wrap that <code
+ data-anolis-spec=domrange>Range</code> in <var title>tag</var></span>,
+ treating <var title>tag list</var> as equivalent and overriding CSS <var
+ title>property</var>.
+ </ol>
+
+ <li><p>Otherwise, if <var title>child</var> is an <code
+ data-anolis-spec=domcore>Element</code> whose <span
+ data-anolis-spec=domcore title=concept-element-namespace>namespace</span>
+ is the <span data-anolis-spec=domcore>HTML namespace</span> and whose <span
+ data-anolis-spec=domcore title=concept-element-local-name>local name</span>
+ is <var title>tag</var> or is in <var title>tag list</var>, change <var
+ title>child</var>'s <span data-anolis-spec=domcore
+ title=concept-element-local-name>local name</span> to <var title>tag</var>
+ and <span>unset the CSS property</span> <var title>property</var> on each
+ of its <span data-anolis-spec=domcore
+ title=concept-descendant-node>descendants</span>.
+
+ <li><p>Otherwise:
+
+ <p class=note><var title>child</var> is a <code
+ data-anolis-spec=domcore>Text</code> node or an <code
+ data-anolis-spec=domcore>Element</code> that is part of the <span
+ data-anolis-spec=html title="content models">content model</span> of <var
+ title>element</var>.
+
+ <ol>
+ <li><p>Append <var title>element</var> to <var title>node</var> as the
+ previous sibling of <var title>child</var>.
+
+ <li><p>While <var title>node</var> has a child with <span
+ data-anolis-spec=domrange title=concept-indexof>index</span> <var
+ title>offset</var> + 1, and while that child is not an <code
+ data-anolis-spec=domcore>Element</code> or is an <code
+ data-anolis-spec=domcore>Element</code> but is part of the <span
+ data-anolis-spec=html title="content models">content model</span> of <var
+ title>element</var>, append that child to <var title>element</var>.
+
+ <p class=note>Since the next sibling of <var title>element</var> is being
+ reparented on each iteration of the loop, the same <var
+ title>offset</var> will point to a new node every time.
+
+ <li><p><span>Unset the CSS property</span> <var title>property</var> on
+ each of <var title>element</var>'s descendants.
+ </ol>
+
+ <li><p>Increment <var title>offset</var>.
+
+ <p class=XXX>There appears to be no precise definition of what it means to
+ append an existing element to another one. Is it just obvious? Should Web
+ DOM Core be clearer?
</ol>
</ol>
+-->
-
-<h2 id=commands><span class=secno>3 </span>Commands</h2>
+<h2 id=commands><span class=secno>5 </span>Commands</h2>
<dl>
<dt><code title=""><dfn id=command-bold title=command-bold>bold</dfn></code>
-<dd>The user agent must <a href=#wrap-range-in-tag title=wrap-range-in-tag>wrap each <code class=external data-anolis-spec=domrange>Range</code></a> of the current <a href=http://html5.org/specs/dom-range.html#selection><code class=external data-anolis-spec=domrange>Selection</code></a> in a "b" tag.
+<dd>The user agent must <a href=#style-a-range title="style a range">style each <code class=external data-anolis-spec=domrange>Range</code></a> of the current <a href=http://html5.org/specs/dom-range.html#selection><code class=external data-anolis-spec=domrange>Selection</code></a> with <var title="">property name</var>
+"font-weight", <var title="">property value</var> "bold", and <var title="">tag
+list</var> ["b", "strong"].
<p class=XXX>Be clearer. What's the "current Selection", and what does it mean
to wrap "each Range"? What if there are overlapping Ranges?
+
+<p class=XXX>Obviously this doesn't yet even attempt to include the case where
+it's already bold and the bold has to be removed.
</dl>
--- a/source.html Fri Feb 11 09:48:42 2011 -0700
+++ b/source.html Thu Feb 17 15:06:13 2011 -0700
@@ -48,55 +48,42 @@
included in HTML comments so as not to distract the reader.
-<h2>Definitions</h2>
-<p>When a user agent is to <dfn title=split-text-node>split a <code
-data-anolis-spec=domcore>Text</code> node</dfn> <var title>node</var>, it must
-run the following steps:
-
-<ol>
- <li>Let <var title>prefix</var> be the substring of <var title>node</var>'s
- <code data-anolis-spec=domcore title=dom-CharacterData-data>data</code>
- of length <var title>offset</var> beginning at offset 0.
-
- <li>Let <var title>prefix node</var> be a new <code
- data-anolis-spec=domcore>Text</code> node whose <code
- data-anolis-spec=domcore title=dom-CharacterData-data>data</code> is equal to
- <var title>prefix</var> and whose <code data-anolis-spec=domcore
- title=dom-Node-ownerDocument>ownerDocument</code> is equal to <var
- title>node</var>'s.
-
- <li>Insert <var title>prefix node</var> in <var title>node</var>'s parent as
- the previous sibling of <var title>node</var>.
+<h2>Issues</h2>
- <li>Let <var title>suffix</var> be the substring of <var title>node</var>'s
- <code data-anolis-spec=domcore title=dom-CharacterData-data>data</code>
- beginning at offset <var title>offset</var> and continuing to the end of the
- string.
+<ul>
+ <li><p>Need to make CSS terminology more precise, about setting/unsetting CSS
+ properties. The intent is to modify the style attribute, CSSOM-style.
- <li>Let <var title>suffix node</var> be a new <code
- data-anolis-spec=domcore>Text</code> node whose <code
- data-anolis-spec=domcore title=dom-CharacterData-data>data</code> is equal to
- <var title>suffix</var> and whose <code data-anolis-spec=domcore
- title=dom-Node-ownerDocument>ownerDocument</code> is equal to <var
- title>node</var>'s.
-
- <li>Insert <var title>suffix node</var> in <var title>node</var>'s parent as
- the previous sibling of <var title>node</var>.
+ <li><p>Some of the DOM stuff might benefit from more precision. E.g., is
+ there a precise algorithm for what it means to append a node someplace, if
+ that node is already somewhere in the DOM? What does that do if it's
+ selected, it has state (like a video or animated image), etc.?
+</ul>
- <li>Delete <var title>node</var> from its parent.
- <li>Return (<var title>prefix node</var>, <var title>suffix node</var>).
-</ol>
+<h2>Definitions</h2>
-<p>When a user agent is to <dfn title=wrap-range-in-tag>wrap a <code
-data-anolis-spec=domrange>Range</code> <var title>range</var> in a tag <var
-title>tag</var></dfn>, it must run the following steps:
+<p>A <code data-anolis-spec=domcore>Node</code> is an <dfn>HTML element
+with name</dfn> <var title>name</var> if it is an <code
+data-anolis-spec=domcore>Element</code>, its <span data-anolis-spec=domcore
+title=concept-element-namespace>namespace</span> is the <span
+data-anolis-spec=domcore>HTML namespace</span>, and its <span
+data-anolis-spec=domcore title=concept-element-local-name>local name</span> is
+<var title>name</var>.
+
+
+<h2>Styling a Range</h2>
+<p>When a user agent is to <dfn>style a <code
+data-anolis-spec=domrange>Range</code></dfn> <var title>range</var>, it must
+run the following steps. There are three inputs: a CSS property name <var
+title>property name</var>, a new value <var title>property value</var>, and a
+nonempty list of strings <var title>tag list</var>.
<p class=XXX>This is totally made up and I have no idea yet if it matches
browsers and/or is even vaguely coherent.
<ol>
- <li>Let <var title>start node</var>, <var title>start offset</var>, <var
+ <li><p>Let <var title>start node</var>, <var title>start offset</var>, <var
title>end node</var>, and <var title>end offset</var> be the <span
data-anolis-spec=domrange title=concept-range-start>start</span> and <span
data-anolis-spec=domrange title=concept-range-end>end</span> <span
@@ -105,56 +92,332 @@
title=concept-boundary-point-offset>offsets</span> of <var title>range</var>,
respectively.
- <li>Let <var title>document</var> be the <code data-anolis-spec=domcore
+ <li><p>Let <var title>document</var> be the <code data-anolis-spec=domcore
title=dom-Node-ownerDocument>ownerDocument</code> of <var title>start
node</var>.
- <li>If <var title>start node</var> is a <code
+ <li><p>If <var title>start node</var> or <var title>end node</var> is not an
+ <code data-anolis-spec=domcore>Element</code>, <code
data-anolis-spec=domcore>Text</code>, <code
data-anolis-spec=domcore>ProcessingInstruction</code>, or <code
- data-anolis-spec=domcore>Comment</code>, and it has no parent, abort these
- steps.
+ data-anolis-spec=domcore>Comment</code> node, or is not an <code
+ data-anolis-spec=domcore>Element</code> and has no parent, abort
+ these steps.
+
+ <p class=XXX>Figure out something sensible here.
+
+ <li><p>If <var title>start node</var> is a <code
+ data-anolis-spec=domcore>Text</code> node and <var title>start offset</var>
+ is neither 0 nor the <span data-anolis-spec=domrange
+ title=concept-node-length>length</span> of <var title>start node</var>, run
+ <code data-anolis-spec=domcore title=dom-Text-splitText>splitText(<var
+ title>start offset</var>)</code> on <var title>start node</var> and set <var
+ title>start node</var> to the returned node. Set <var title>start
+ offset</var> to 0.
+
+ <li><p>If <var title>end node</var> is a <code
+ data-anolis-spec=domcore>Text</code> node and <var title>end offset</var> is
+ neither 0 nor the <span data-anolis-spec=domrange
+ title=concept-node-length>length</span> of <var title>end node</var>, run
+ <code data-anolis-spec=domcore title=dom-Text-splitText>splitText(<var
+ title>end offset</var>)</code> on <var title>end node</var> and set <var
+ title>end node</var> to the previous sibling of the returned node. Set <var
+ title>end offset</var> to the <span data-anolis-spec=domrange
+ title=concept-node-length>length</span> of the new <var title>end node</var>.
+
+<!-- Original declarative definition
+ <li><p>Let <var title>node list</var> be the list of <code
+ data-anolis-spec=domcore>Node</code>s <var title>node</var> in <var
+ title>document</var> satisfying all of the following conditions:
+
+ <ul>
+ <li><p>In <span data-anolis-spec=domcore>tree order</span>, <var
+ title>node</var> is after the child of <var title>start node</var> with
+ <span data-anolis-spec=domrange title=concept-indexof>index</span> <var
+ title>start offset</var> (or after <var title>start node</var> itself, if
+ <var title>start node</var> is not an <code
+ data-anolis-spec=domcore>Element</code>).
+
+ <li><p>In <span data-anolis-spec=domcore>tree order</span>, <var
+ title>node</var> is before the child of <var title>end node</var> with
+ <span data-anolis-spec=domrange title=concept-indexof>index</span> <var
+ title>end offset</var> (or before <var title>end node</var> itself, if <var
+ title>end node</var> is not an <code
+ data-anolis-spec=domcore>Element</code>).
+
+ <li><p><var title>node</var> is not a <span data-anolis-spec=domcore
+ title=concept-descendant-node>descendant</span> of any other <code
+ data-anolis-spec=domcore>Node</code> that satisfies the previous two
+ conditions.
+ </ul>
+
+ <li><p>If <var title>start node</var> is a <code
+ data-anolis-spec=domcore>Text</code> node and <var title>start offset</var>
+ is 0, add <var title>start node</var> to <var title>node list</var>.
+
+ <li><p>If <var title>end node</var> is a <code
+ data-anolis-spec=domcore>Text</code> node and <var title>end offset</var> is
+ the <span data-anolis-spec=domrange title=concept-node-length>length</span>
+ of <var title>end node</var>, add <var title>end node</var> to <var
+ title>node list</var>.
+
+ <li><p>If there is some <code data-anolis-spec=domcore>Element</code> that is
+ not in <var title>node list</var> but which has one or more children, and its
+ children are all in <var title>node list</var>, add that <code
+ data-anolis-spec=domcore>Element</code> to <var title>node list</var> and
+ remove all its children from <var title>node list</var>. Repeat until there
+ is no such <code data-anolis-spec=domcore>Element</code>.
+ -->
+
+ <li><p>Let <var title>node list</var> be an empty list of <code
+ data-anolis-spec=domcore>Node</code>s.
+
+ <li><p>If <var title>start node</var> is an <code
+ data-anolis-spec=domcore>Element</code> with at least one child, let <var
+ title>node</var> be the first <code data-anolis-spec=domcore>Node</code>
+ after the child of <var title>start node</var> with <span
+ data-anolis-spec=domrange title=concept-indexof>index</span> <var title>start
+ offset</var>, in <span data-anolis-spec=domcore>tree order</span>.
+
+ <li><p>Otherwise, if <var title>start node</var> is a <code
+ data-anolis-spec=domcore>Text</code> node and <var title>start offset</var>
+ is 0, or if <var title>start node</var> is an <code
+ data-anolis-spec=domcore>Element</code> with no children, let <var
+ title>node</var> be <var title>start node</var>.
+
+ <li><p>Otherwise, let <var title>node</var> be the first <code
+ data-anolis-spec=domcore>Node</code> after <var title>start node</var> in
+ <span data-anolis-spec=domcore>tree order</span>.
+
+ <li><p>If <var title>end node</var> is an <code
+ data-anolis-spec=domcore>Element</code> with at least one child, let <var
+ title>end</var> be the first <code data-anolis-spec=domcore>Node</code>
+ before the child of <var title>end node</var> with <span
+ data-anolis-spec=domrange title=concept-indexof>index</span> <var title>end
+ offset</var>, in <span data-anolis-spec=domcore>tree order</span> (or, if
+ <var title>end offset</var> is <var title>end node</var>'s <span
+ data-anolis-spec=domrange title=concept-node-length>length</span>, let <var
+ title>end</var> be the last child of <var title>end node</var>).
+
+ <li><p>Otherwise, if <var title>end node</var> is a <code
+ data-anolis-spec=domcore>Text</code> node and <var title>end offset</var> is
+ its <span data-anolis-spec=domrange title=concept-node-length>length</span>,
+ or if <var title>end node</var> is an <code
+ data-anolis-spec=domcore>Element</code> with no children, let <var
+ title>end</var> be <var title>end node</var>.
+
+ <li><p>Otherwise, let <var title>end</var> be the last <code
+ data-anolis-spec=domcore>Node</code> before <var title>end node</var> in
+ <span data-anolis-spec=domcore>tree order</span>.
+
+ <li><p>While <var title>node</var> is not after <var title>end</var> in
+ <span data-anolis-spec=domcore>tree order</span>:
+
+ <ol>
+ <li>Append <var title>node</var> to <var title>node list</var>.
+
+ <li>Set <var title>node</var> to the first <code
+ data-anolis-spec=domcore>Node</code> in <span data-anolis-spec=domcore>tree
+ order</span> that is after <var title>node</var> and (if applicable) all
+ its <span data-anolis-spec=domcore
+ title=concept-descendant-node>descendants</span>. If no such <code
+ data-anolis-spec=domcore>Node</code> exists, break out of these substeps.
+ </ol>
+
+ <!-- Condense the node list for extra tidiness. -->
+ <li><p>Let <var title>node</var> be the first <code
+ data-anolis-spec=domcore>Node</code> in <var title>node list</var>.
+
+ <li><p>Repeat:
+
+ <ol>
+ <li><p>If <var title>node</var> has a parent, and its parent is an <code
+ data-anolis-spec=domcore>Element</code>, and all the children of <var
+ title>node</var>'s parent are contained in <var title>node list</var>, add
+ <var title>node</var>'s parent to <var title>node list</var> immediately
+ before <var title>node</var>, then remove all children of <var
+ title>node</var>'s parent from <var title>node list</var>. Set <var
+ title>node</var> to <var title>node</var>'s parent and continue these
+ substeps from the beginning.
+
+ <li><p>If <var title>node</var> is the last <code
+ data-anolis-spec=domcore>Node</code> in <var title>node list</var>, break
+ out of these substeps.
+
+ <li><p>Set <var title>node</var> to the next <code
+ data-anolis-spec=domcore>Node</code> in <var title>node list</var>.
+ </ol>
+
+ <li><p>For each <var title>node</var> in <var title>node list</var>, in <span
+ data-anolis-spec=domcore>tree order</span>:
+
+ <ol>
+ <li><p>If <var title>node</var> is an <code
+ data-anolis-spec=domcore>Element</code>:
+
+ <ol>
+ <li><p>If <var title>node</var> is an <span>HTML element with name</span>
+ in <var title>tag list</var>, unset the CSS property <var title>property
+ name</var> of <var title>node</var>. Otherwise, set the CSS property
+ <var title>property name</var> of <var title>node</var> to <var
+ title>property value</var>.
+
+ <li><p>For each <span data-anolis-spec=domcore
+ title=concept-descendant-node>descendant</span> <var
+ title>descendant</var> of <var title>node</var> that is an <code
+ data-anolis-spec=domcore>Element</code>:
+
+ <ol>
+ <li><p>If either
+
+ <ul>
+ <li><p><var title>descendant</var> is an <span>HTML element with
+ name</span> either "span" or in <var title>tag list</var>, and it has
+ only a single attribute, and that attribute is named "style", and
+ that style attribute sets only the CSS property <var title>property
+ name</var>; or
+
+ <li><p><var title>descendant</var> is an <span>HTML element with
+ name</span> in <var title>tag list</var> and it has no attributes,
+ </ul>
+
+ <p>then append all of <var title>descendant</var>'s children to the
+ parent of <var title>descendant</var> in order immediately before <var
+ title>descendant</var>, and remove <var title>descendant</var>.
+ Continue with the next descendant.
+
+ <li><p>Unset the CSS property <var title>property name</var> of <var
+ title>descendant</var>.
+ <!-- Only WebKit appears to do this, but it makes sense. Otherwise
+ things like <span style=font-weight:normal> won't disappear when you
+ apply bold. (Same applies to the places below where we unset the CSS
+ property here.) -->
+
+ <li><p>If <var title>descendant</var> is an <span>HTML element with
+ name</span> in <var title>tag list</var>, let <var title>new
+ descendant</var> be a new <span>HTML element with name</span> "span",
+ with the same attributes and <code data-anolis-spec=domcore
+ title=dom-Node-ownerDocument>ownerDocument</code> as <var
+ title>descendant</var>. Append <var title>new descendant</var> to <var
+ title>descendant</var>'s parent as the previous sibling of <var
+ title>descendant</var>, then append all of <var
+ title>descendant</var>'s children to <var title>new descendant</var> in
+ order, then remove <var title>descendant</var>.
+ </ol>
+ </ol>
+
+ <li><p>Otherwise:
+
+ <ol>
+ <li><p>If <var title>node</var> is not the first child of its parent,
+ and its previous sibling is an <span>HTML element with name</span> equal
+ to the first string in <var title>tag list</var>, append <var
+ title>node</var> to <var title>node</var>'s previous sibling as the last
+ child. Continue with the next <code data-anolis-spec=domcore>Node</code>
+ in <var title>node list</var>.
+ <!-- Thus we merge things together a bit. This could probably use more
+ thought. -->
+
+ <li><p>If <var title>node</var> is not a <code
+ data-anolis-spec=domcore>Text</code> node, or if its <span
+ data-anolis-spec=domcore title=dom-CharacterData-data>data</span> is a
+ sequence of zero or more <span data-anolis-spec=html title="space
+ character">space characters</span>, continue with the next <code
+ data-anolis-spec=domcore>Node</code> in <var title>node list</var>.
+ <!-- This avoids wrapping whitespace-only text nodes, which agrees with
+ Gecko and WebKit. IE9 and Opera wrap the whitespace-only text nodes,
+ which seems pointless. -->
+
+ <li><p>Let <var title>new parent</var> be a new <span>HTML element with
+ name</span> equal to the first string in <var title>tag list</var>, with
+ no attributes, and <code data-anolis-spec=domcore
+ title=dom-Node-ownerDocument>ownerDocument</code> set to <var
+ title>document</var>.
+
+ <li><p>Append <var title>new parent</var> to <var title>node</var>'s
+ parent as the previous sibling of <var title>node</var>.
+
+ <li><p>Append <var title>node</var> to <var title>new parent</var> as
+ its last child.
+ </ol>
+ </ol>
+</ol>
+
+<!-- Out of IE9, Gecko, WebKit, and Opera, when asked to (e.g.) bold an
+element, IE9 and WebKit and Opera wrap various descendants in <b> or <strong>;
+Gecko just adds a style attribute. The latter is simpler, particularly because
+you then don't have to worry about making sure you only insert your tags in a
+valid place (which you have to so that text/html serialization is possible, if
+nothing else). I originally specced the former approach, retained here in case
+I want to switch back:
+
+<p>When a user agent is to <dfn title=wrap-range-in-tag>wrap a <code
+data-anolis-spec=domrange>Range</code> <var title>range</var> in a tag <var
+title>tag</var></dfn>, treating <var title>tag list</var> as equivalent and
+overriding CSS <var title>property</var>, it must run the following steps:
+
+<p class=XXX>This is totally made up and I have no idea yet if it matches
+browsers and/or is even vaguely coherent.
+
+<ol>
+ <li><p>Let <var title>start node</var>, <var title>start offset</var>, <var
+ title>end node</var>, and <var title>end offset</var> be the <span
+ data-anolis-spec=domrange title=concept-range-start>start</span> and <span
+ data-anolis-spec=domrange title=concept-range-end>end</span> <span
+ data-anolis-spec=domrange title=concept-boundary-point-node>nodes</span> and
+ <span data-anolis-spec=domrange
+ title=concept-boundary-point-offset>offsets</span> of <var title>range</var>,
+ respectively.
+
+ <li><p>Let <var title>document</var> be the <code data-anolis-spec=domcore
+ title=dom-Node-ownerDocument>ownerDocument</code> of <var title>start
+ node</var>.
+
+ <li><p>If <var title>start node</var> is a <code
+ data-anolis-spec=domcore>Text</code>, <code
+ data-anolis-spec=domcore>ProcessingInstruction</code>, or <code
+ data-anolis-spec=domcore>Comment</code> node, and it has no parent, abort
+ these steps.
<p class=XXX>Figure out something sensible here. Doesn't make sense except
in IE, since other browsers fail if it's not contentEditable. What does IE
do? What do we expect?
- <li>If <var title>start node</var> is a <code
+ <li><p>If <var title>start node</var> is a <code
data-anolis-spec=domcore>Text</code> node and <var title>start offset</var>
is neither 0 nor the <span data-anolis-spec=domrange
- title=concept-node-length>length</span> of <var title>start node</var>, <span
- title=split-text-node>split <var title>start node</var></span> and set <var
- title>start node</var> to the second returned node. Set <var title>start
+ title=concept-node-length>length</span> of <var title>start node</var>, run
+ <code data-anolis-spec=domcore title=dom-Text-splitText>splitText(<var
+ title>start offset</var>)</code> on <var title>start node</var> and set <var
+ title>start node</var> to the returned node. Set <var title>start
offset</var> to 0.
- <li>If <var title>start node</var> is a <code
+ <li><p>If <var title>start node</var> is a <code
data-anolis-spec=domcore>Text</code> node and <var title>start offset</var>
is 0, set <var title>start offset</var> to the <span
data-anolis-spec=domrange title=concept-indexof>index of</span> <var
title>start node</var> in its parent, then set <var title>start node</var> to
its parent.
- <li>If <var title>start node</var> is a <code
- data-anolis-spec=domcore>Text</code> node and <var title>start offset</var>
- is the <span data-anolis-spec=domrange
- title=concept-node-length>length</span> of <var title>start node</var>, or if
- <var title>start node</var> is a <code
- data-anolis-spec=domcore>Comment</code> or <code
- data-anolis-spec=domcore>ProcessingInstruction</code>, set <var title>start
- offset</var> to one plus the <span data-anolis-spec=domrange
+ <li><p>If <var title>start node</var> is a <code
+ data-anolis-spec=domcore>Text</code>, <code
+ data-anolis-spec=domcore>Comment</code>, or <code
+ data-anolis-spec=domcore>ProcessingInstruction</code> node, set <var
+ title>start offset</var> to one plus the <span data-anolis-spec=domrange
title=concept-indexof>index of</span> <var title>start node</var> in its
parent, then set <var title>start node</var> to its parent.
- <li>If <var title>end node</var> is a <code
+ <li><p>If <var title>end node</var> is a <code
data-anolis-spec=domcore>Text</code> node and <var title>end offset</var> is
neither 0 nor the <span data-anolis-spec=domrange
- title=concept-node-length>length</span> of <var title>end node</var>, <span
- title=split-text-node>split <var title>end node</var></span> and set <var
- title>end node</var> to the first returned node. Set <var title>end
- offset</var> to the <span data-anolis-spec=domrange
+ title=concept-node-length>length</span> of <var title>end node</var>, run
+ <code data-anolis-spec=domcore title=dom-Text-splitText>splitText(<var
+ title>end offset</var>)</code> on <var title>end node</var> and set <var
+ title>end node</var> to the previous sibling of the returned node. Set <var
+ title>end offset</var> to the <span data-anolis-spec=domrange
title=concept-node-length>length</span> of the new <var title>end node</var>.
- <li>If <var title>end node</var> is a <code
+ <li><p>If <var title>end node</var> is a <code
data-anolis-spec=domcore>Text</code> node and <var title>end offset</var> is
the <span data-anolis-spec=domrange title=concept-node-length>length</span>
of <var title>end node</var>, set <var title>end offset</var> to one plus the
@@ -162,12 +425,11 @@
title>end node</var> in its parent, then set <var title>end node</var> to its
parent.
- <li>If <var title>end node</var> is a <code
- data-anolis-spec=domcore>Text</code> node and <var title>end offset</var> is
- 0, or if <var title>end node</var> is a <code
- data-anolis-spec=domcore>Comment</code> or <code
- data-anolis-spec=domcore>ProcessingInstruction</code>, set <var title>end
- offset</var> to the <span data-anolis-spec=domrange
+ <li><p>If <var title>end node</var> is a <code
+ data-anolis-spec=domcore>Text</code>, <code
+ data-anolis-spec=domcore>Comment</code>, or <code
+ data-anolis-spec=domcore>ProcessingInstruction</code> node, set <var
+ title>end offset</var> to the <span data-anolis-spec=domrange
title=concept-indexof>index of</span> <var title>end node</var> in its
parent, then set <var title>end node</var> to its parent.
@@ -179,103 +441,172 @@
title>start offset</var> and <var title>end offset</var> now represent node
offsets instead of character offsets.
- <li>Let <var title>node</var> equal <var title>start node</var> and let <var
+ <li><p>Let <var title>node</var> equal <var title>start node</var> and let <var
title>offset</var> equal <var title>start offset</var>.
- <li>Repeat the following steps until aborted:
+ <li><p>Repeat the following steps until aborted:
<ol>
- <li><i title id=wrap-algorithm-start>Start</i>: If <var title>node</var> is
- after <var title>end node</var> in <span data-anolis-spec=domcore>tree
- order</span>, or if <var title>node</var> equals <var title>end node</var>
- and <var title>offset</var> is greater than or equal to <var title>end
- offset</var>, abort this subalgorithm.
-
- <li>Let <var title>element</var> be a new <code
- data-anolis-spec=domcore>Element</code> with no attributes, <span
- data-anolis-spec=domcore title=concept-element-namespace>namespace</span>
- set to the <span data-anolis-spec=domcore>HTML namespace</span>, <span
- data-anolis-spec=domcore title=concept-element-local-name>local name</span>
- set to <var title>tag</var>, and <code data-anolis-spec=domcore
- title=dom-Node-ownerDocument>ownerDocument</code> set to <var
- title>document</var>.
-
- <li>While <var title>node</var> has a child with <span
- data-anolis-spec=domrange title=concept-indexof>index</span> <var
- title>offset</var>, and that child is a <code
- data-anolis-spec=domcore>Text</code> node whose <code
- data-anolis-spec=domcore title=dom-CharacterData-data>data</code> is only
- <span data-anolis-spec=html title="space character">space characters</span>
- or that child is a <code data-anolis-spec=domcore>Comment</code> or that
- child is a <code data-anolis-spec=domcore>ProcessingInstruction</code>,
- increment <var title>offset</var>.
- <!-- This avoids wrapping whitespace-only text nodes, which agrees with
- WebKit. IE9 wraps the whitespace-only text nodes, and Gecko tries to do
- something crazy like add CSS attributes instead of elements. -->
-
- <li>If <var title>offset</var> is equal to <var title>node</var>'s number
- of children, let <var title>node</var> equal the first <code
- data-anolis-spec=domcore>Node</code> in <var title>document</var> that is
- after all of <var title>node</var>'s <span data-anolis-spec=domcore
- title=concept-descendant-node>descendants</span> in <span
- data-anolis-spec=domcore>tree order</span>, and let <var title>offset</var>
- equal zero. Continue from <i title><a
- href=#wrap-algorithm-start>start</a></i>.
+ <li><p><i title id=wrap-algorithm-start>Start</i>: If <var title>node</var> is
+ after <var title>end node</var> in <span data-anolis-spec=domcore>tree
+ order</span>, or if <var title>node</var> equals <var title>end node</var>
+ and <var title>offset</var> is greater than or equal to <var title>end
+ offset</var>, abort this subalgorithm.
- <li>Let <var title>child</var> be the child of <var title>node</var> with
- <span data-anolis-spec=domrange title=concept-indexof>index</span> <var
- title>offset</var>.
+ <li><p>Let <var title>element</var> be a new <code
+ data-anolis-spec=domcore>Element</code> with no attributes, <span
+ data-anolis-spec=domcore title=concept-element-namespace>namespace</span>
+ set to the <span data-anolis-spec=domcore>HTML namespace</span>, <span
+ data-anolis-spec=domcore title=concept-element-local-name>local name</span>
+ set to <var title>tag</var>, and <code data-anolis-spec=domcore
+ title=dom-Node-ownerDocument>ownerDocument</code> set to <var
+ title>document</var>.
- <li>If <var title>child</var> is an <code
- data-anolis-spec=domcore>Element</code> which is not part of the <span
- data-anolis-spec=html title="content models">content model</span> of <var
- title>element</var>:
-
- <ol>
- <li>Create a new <code data-anolis-spec=domrange>Range</code> with <span
- data-anolis-spec=domrange title=concept-range-start>start</span> (<var
- title>child</var>, 0), <span data-anolis-spec=domrange
- title=concept-range-end>end</span> (<var title>child</var>, <span
- data-anolis-spec=domrange title=concept-node-length>length</span> of <Var
- title>child</var>), and <span data-anolis-spec=domrange
- title=concept-range-root>root</span> the same as <var title>range</var>'s
- <span data-anolis-spec=domrange title=concept-range-root>root</span>.
+ <li><p>While <var title>node</var> has a child with <span
+ data-anolis-spec=domrange title=concept-indexof>index</span> <var
+ title>offset</var>, and that child meets one of the following conditions,
+ take the described action (if any) and increment <var title>offset</var>:
+
+ <dl class=switch>
+ <dt>The child is a <code data-anolis-spec=domcore>Text</code> node whose
+ <code data-anolis-spec=domcore title=dom-CharacterData-data>data</code>
+ consists of zero or more <span data-anolis-spec=html title="space
+ character">space characters</span>
+ <!- - This avoids wrapping whitespace-only text nodes, which agrees with
+ WebKit. IE9 wraps the whitespace-only text nodes, and Gecko tries to do
+ something crazy like add CSS attributes instead of elements. - ->
+ <dt>The child is a <code data-anolis-spec=domcore>Comment</code>, <code
+ data-anolis-spec=domcore>ProcessingInstruction</code>, or <code
+ data-anolis-spec=domcore>DocumentType</code>
+ <dd>No action.
+
+ <dt>The child is an <code data-anolis-spec=domcore>Element</code> whose
+ <span data-anolis-spec=domcore
+ title=concept-element-namespace>namespace</span> is the <span
+ data-anolis-spec=domcore>HTML namespace</span> and whose <span
+ data-anolis-spec=domcore title=concept-element-local-name>local
+ name</span> is <var title>tag</var>
+ <dd><span>Unset the CSS property</span> <var title>property</var> on each
+ <span data-anolis-spec=domcore
+ title=concept-descendant-node>descendant</span> of the child.
+ <!- - Only WebKit appears to do this, but it makes sense. Otherwise
+ things like <span style=font-weight:normal> won't disappear when you
+ apply bold. (Same applies to the places below where we unset the CSS
+ property here.) - ->
+ </dl>
+
+ <li><p>If <var title>offset</var> is equal to <var title>node</var>'s <span
+ data-anolis-spec=domrange title=concept-node-length>length</span>:
+
+ <ol>
+ <li><p>If <var title>node</var> is the last <code
+ data-anolis-spec=domcore>Node</code> in <var title>document</var>, abort
+ this subalgorithm (the one that begins with <i title><a
+ href=wrap-algorithm-start>start</a></i>).
+
+ <li><p>Let <var title>node</var> equal the first <code
+ data-anolis-spec=domcore>Node</code> in <var title>document</var> that is
+ after all of <var title>node</var>'s <span data-anolis-spec=domcore
+ title=concept-descendant-node>descendants</span> in <span
+ data-anolis-spec=domcore>tree order</span>.
- <li><span title=wrap-range-in-tag>Wrap that <code
- data-anolis-spec=domrange>Range</code> in <var title>tag</var></span>.
-
- <li>Increment <var title>offset</var>.
-
- <li>Continue from <i title><a href=#wrap-algorithm-start>start</a></i>.
- </ol>
-
- <li>Append <var title>element</var> to <var title>node</var> as the
- previous sibling of <var title>child</var>.
+ <li><p>Let <var title>offset</var> equal zero.
+
+ <li><p>Continue from <i title><a
+ href=#wrap-algorithm-start>start</a></i>.
+ </ol>
- <li>While the child of <var title>node</var> has a child with <span
- data-anolis-spec=domrange title=concept-indexof>index</span> <var
- title>offset</var>, and while that child is not an <code
- data-anolis-spec=domcore>Element</code> or is an <code
- data-anolis-spec=domcore>Element</code> but is part of the <span
- data-anolis-spec=html title="content models">content model</span> of <var
- title>element</var>, change that child's parent to <var title>element</var>
- and increment <var title>offset</var>.
+ <li><p>Let <var title>child</var> be the child of <var title>node</var> with
+ <span data-anolis-spec=domrange title=concept-indexof>index</span> <var
+ title>offset</var>.
- <p class=XXX>What exactly does it mean to change the child's parent? E.g.,
- what happens if this occurs to a video that's playing? Is there a precise
- spec somewhere?
+ <p class=note><var title>child</var> will always be either an <code
+ data-anolis-spec=domcore>Element</code> or a <code
+ data-anolis-spec=domcore>Text</code> node.
+
+ <li><p>If <var title>child</var> is an <code
+ data-anolis-spec=domcore>Element</code> which is not part of the <span
+ data-anolis-spec=html title="content models">content model</span> of <var
+ title>element</var>:
+
+ <ol>
+ <li><p>Create a new <code data-anolis-spec=domrange>Range</code> with <span
+ data-anolis-spec=domrange title=concept-range-start>start</span> (<var
+ title>child</var>, 0), <span data-anolis-spec=domrange
+ title=concept-range-end>end</span> (<var title>child</var>, <span
+ data-anolis-spec=domrange title=concept-node-length>length</span> of <Var
+ title>child</var>), and <span data-anolis-spec=domrange
+ title=concept-range-root>root</span> the same as <var title>range</var>'s
+ <span data-anolis-spec=domrange title=concept-range-root>root</span>.
+
+ <li><p><span title=wrap-range-in-tag>Wrap that <code
+ data-anolis-spec=domrange>Range</code> in <var title>tag</var></span>,
+ treating <var title>tag list</var> as equivalent and overriding CSS <var
+ title>property</var>.
+ </ol>
+
+ <li><p>Otherwise, if <var title>child</var> is an <code
+ data-anolis-spec=domcore>Element</code> whose <span
+ data-anolis-spec=domcore title=concept-element-namespace>namespace</span>
+ is the <span data-anolis-spec=domcore>HTML namespace</span> and whose <span
+ data-anolis-spec=domcore title=concept-element-local-name>local name</span>
+ is <var title>tag</var> or is in <var title>tag list</var>, change <var
+ title>child</var>'s <span data-anolis-spec=domcore
+ title=concept-element-local-name>local name</span> to <var title>tag</var>
+ and <span>unset the CSS property</span> <var title>property</var> on each
+ of its <span data-anolis-spec=domcore
+ title=concept-descendant-node>descendants</span>.
+
+ <li><p>Otherwise:
+
+ <p class=note><var title>child</var> is a <code
+ data-anolis-spec=domcore>Text</code> node or an <code
+ data-anolis-spec=domcore>Element</code> that is part of the <span
+ data-anolis-spec=html title="content models">content model</span> of <var
+ title>element</var>.
+
+ <ol>
+ <li><p>Append <var title>element</var> to <var title>node</var> as the
+ previous sibling of <var title>child</var>.
+
+ <li><p>While <var title>node</var> has a child with <span
+ data-anolis-spec=domrange title=concept-indexof>index</span> <var
+ title>offset</var> + 1, and while that child is not an <code
+ data-anolis-spec=domcore>Element</code> or is an <code
+ data-anolis-spec=domcore>Element</code> but is part of the <span
+ data-anolis-spec=html title="content models">content model</span> of <var
+ title>element</var>, append that child to <var title>element</var>.
+
+ <p class=note>Since the next sibling of <var title>element</var> is being
+ reparented on each iteration of the loop, the same <var
+ title>offset</var> will point to a new node every time.
+
+ <li><p><span>Unset the CSS property</span> <var title>property</var> on
+ each of <var title>element</var>'s descendants.
+ </ol>
+
+ <li><p>Increment <var title>offset</var>.
+
+ <p class=XXX>There appears to be no precise definition of what it means to
+ append an existing element to another one. Is it just obvious? Should Web
+ DOM Core be clearer?
</ol>
</ol>
-
+-->
<h2>Commands</h2>
<dl>
<dt><code title><dfn title=command-bold>bold</dfn></code>
-<dd>The user agent must <span title=wrap-range-in-tag>wrap each <code
+<dd>The user agent must <span title="style a range">style each <code
data-anolis-spec=domrange>Range</code></span> of the current <code
-data-anolis-spec=domrange>Selection</code> in a "b" tag.
+data-anolis-spec=domrange>Selection</code> with <var title>property name</var>
+"font-weight", <var title>property value</var> "bold", and <var title>tag
+list</var> ["b", "strong"].
<p class=XXX>Be clearer. What's the "current Selection", and what does it mean
to wrap "each Range"? What if there are overlapping Ranges?
+
+<p class=XXX>Obviously this doesn't yet even attempt to include the case where
+it's already bold and the bold has to be removed.
</dl>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bold.html Thu Feb 17 15:06:13 2011 -0700
@@ -0,0 +1,256 @@
+<!doctype html>
+<title>execCommand("bold") tests</title>
+<div id=log></div>
+<div contenteditable=true id=test>
+ <br> <br>
+ Some simple text<br>
+ <span>Some more text</span><br>
+ <b>Some more text</b><br>
+ <strong>Some more text</strong><br>
+ <span style=font-weight:bold>Some more text</span><br>
+ <span style=font-weight:bolder>Some more text</span><br>
+ <span style=font-weight:lighter>Some more text</span><br>
+ <span style=font-weight:900>Some more text</span><br>
+ <span style=font-weight:100>Some more text</span><br>
+ <i>Some more text</i><br>
+ <span style=font-style:italic>Some more text</span><br>
+ <span style=font-style:italic;font-weight:bold>Some more text</span><br>
+ <em style=font-weight:bold>Some more text</em><br>
+ <b>Some <span style=font-weight:light>more <b>te<span style=font-weight:bold>xt<strong>!</strong></span></b></span></b><br>
+ <p>Some simple text
+ <p><span>Some more text</span>
+ <p><b>Some more text</b>
+ <p><strong>Some more text</strong>
+ <p><span style=font-weight:bold>Some more text</span>
+ <p><span style=font-weight:bolder>Some more text</span>
+ <p><span style=font-weight:lighter>Some more text</span>
+ <p><span style=font-weight:900>Some more text</span>
+ <p><span style=font-weight:100>Some more text</span>
+ <p><i>Some more text</i>
+ <p><span style=font-style:italic>Some more text</span>
+ <p><span style=font-style:italic;font-weight:bold>Some more text</span>
+ <p><em style=font-weight:bold>Some more text</em>
+ <p><b>Some <span style=font-weight:light>more <b>te<span style=font-weight:bold>xt<strong>!</strong></span></b></span></b>
+</div>
+<script src=support/testharness.js></script>
+<script src=support/testharnessreport.js></script>
+<script>
+"use strict";
+
+var htmlNamespace = "http://www.w3.org/1999/xhtml";
+
+function indexOf(node) {
+ var ret = 0;
+ while (node != node.parentNode.childNodes[ret]) {
+ ret++;
+ }
+ return ret;
+}
+
+function nextNode(node) {
+ if (node.hasChildNodes()) {
+ return node.firstChild;
+ }
+ return nextNodeDescendants(node);
+}
+
+function previousNode(node) {
+ if (node.previousSibling) {
+ node = node.previousSibling;
+ while (node.hasChildNodes()) {
+ node = node.lastChild;
+ }
+ return node;
+ }
+ if (node.parentElement) {
+ return node.parentElement;
+ }
+ return null;
+}
+
+function nextNodeDescendants(node) {
+ while (node && !node.nextSibling) {
+ node = node.parentElement;
+ }
+ if (!node) {
+ return null;
+ }
+ return node.nextSibling;
+}
+
+function convertProperty(propertyName) {
+ // Hack for now
+ return "font-weight";
+}
+
+function styleRange(range, propertyName, propertyValue, tagList) {
+ var startNode = range.startContainer;
+ var startOffset = range.startOffset;
+ var endNode = range.endContainer;
+ var endOffset = range.endOffset;
+
+ var doc = startNode.ownerDocument;
+
+ // Skip the sanity check about node types/detached non-elements
+
+ if (startNode.nodeType == Node.TEXT_NODE
+ && startOffset != 0
+ && startOffset != startNode.data.length) {
+ startNode = startNode.splitText(startOffset);
+ startOffset = 0;
+ }
+
+ if (endNode.nodeType == Node.TEXT_NODE
+ && endOffset != 0
+ && endOffset != endNode.data.length) {
+ endNode = endNode.splitText(endOffset).previousSibling;
+ endOffset = endNode.data.length;
+ }
+
+ var nodeList = [];
+
+ var node;
+ if (startNode.nodeType == Node.ELEMENT_NODE
+ && startNode.hasChildNodes()) {
+ node = nextNode(startNode.childNodes[startOffset]);
+ } else if (
+ (startNode.nodeType == Node.TEXT_NODE && startOffset == 0)
+ || (startNode.nodeType == Node.ELEMENT_NODE && !startNode.hasChildNodes())
+ ) {
+ node = startNode;
+ } else {
+ node = nextNode(startNode);
+ }
+
+ var end;
+ if (endNode.nodeType == Node.ELEMENT_NODE
+ && endNode.hasChildNodes()) {
+ if (endOffset == endNode.childNodes.length) {
+ end = endNode.lastChild;
+ } else {
+ end = previousNode(endNode.childNodes[endOffset]);
+ }
+ } else if (
+ (endNode.nodeType == Node.TEXT_NODE && endOffset == endNode.data.length)
+ || (endNode.nodeType == Node.ELEMENT_NODE && !endNode.hasChildNodes())
+ ) {
+ end = endNode;
+ } else {
+ end = previousNode(endNode);
+ }
+
+ while (node && !(end.compareDocumentPosition(node) & 4)) {
+ nodeList.push(node);
+ node = nextNodeDescendants(node);
+ }
+
+ // FIXME what if nodeList.length == 0?
+ for (var i = 0; i < nodeList.length; i++) {
+ node = nodeList[i];
+ if (node.parentElement) {
+ var replace = true;
+ for (var j = 0; j < node.parentElement.childNodes.length; j++) {
+ if (node.parentElement.childNodes[j] != nodeList[i + j]) {
+ replace = false;
+ break;
+ }
+ }
+ if (replace) {
+ nodeList = nodeList.slice(0, i)
+ .concat(node.parentElement)
+ .concat(nodeList.slice(i + j));
+ continue;
+ }
+ }
+ }
+
+ for (var i = 0; i < nodeList.length; i++) {
+ node = nodeList[i];
+ if (node.nodeType == Node.ELEMENT_NODE) {
+ if (node.namespaceURI == htmlNamespace
+ && tagList.indexOf(node.tagName.toLowerCase()) != -1) {
+ node.style[propertyName] = '';
+ } else {
+ node.style[propertyName] = propertyValue;
+ }
+
+ var desc = nextNode(node);
+ var stop = nextNodeDescendants(node);
+ while (true) {
+ if (desc == stop) {
+ break;
+ }
+
+ if (desc.nodeType != Node.ELEMENT_NODE) {
+ desc = nextNode(desc);
+ continue;
+ }
+
+ if (
+ (desc.namespaceURI == htmlNamespace
+ && (desc.nodeName == "SPAN" || tagList.indexOf(desc.nodeName.toLowerCase()) != -1)
+ && desc.attributes.length == 1
+ //&& desc.attributes[0].namespaceURI == htmlNamespace
+ && desc.attributes[0].localName == "style"
+ && desc.style.length == 1
+ && desc.style.item(0) == convertProperty(propertyName)
+ )
+ ||
+ (desc.namespaceURI == htmlNamespace
+ && tagList.indexOf(desc.nodeName.toLowerCase()) != -1
+ && desc.attributes.length == 0)
+ ) {
+ var oldDesc = desc;
+ desc = nextNode(desc);
+ while (oldDesc.hasChildNodes()) {
+ oldDesc.parentNode.insertBefore(oldDesc.childNodes[0], oldDesc);
+ }
+ oldDesc.parentNode.removeChild(oldDesc);
+ continue;
+ }
+ desc.style[propertyName] = '';
+ if (desc.getAttribute("style") == "") {
+ desc.removeAttribute("style");
+ }
+ if (desc.namespaceURI == htmlNamespace
+ && tagList.indexOf(desc.tagName.toLowerCase()) != -1) {
+ var newDesc = doc.createElement("span");
+ for (var j = 0; j < desc.attributes.length; j++) {
+ // Sick of playing the namespace game, assume
+ // everything is in HTML.
+ newDesc.setAttribute(desc.attributes[j].localName, desc.attributes[j].value);
+ }
+ desc.parentNode.insertBefore(newDesc, desc);
+ while (desc.hasChildNodes()) {
+ newDesc.appendChild(desc.childNodes[0]);
+ }
+ desc.parentNode.removeChild(desc);
+ }
+ desc = nextNode(desc);
+ }
+ continue;
+ }
+
+ if (node.previousSibling
+ && node.previousSibling.nodeType == Node.ELEMENT_NODE
+ && node.previousSibling.namespaceURI == htmlNamespace
+ && node.previousSibling.tagName == tagList[0].toUpperCase()) {
+ node.previousSibling.appendChild(node);
+ continue;
+ }
+
+ if (node.nodeType != Node.TEXT_NODE
+ || /^[ \t\n\f\r]*$/.test(node.data)) {
+ continue;
+ }
+
+ var newParent = doc.createElement(tagList[0]);
+ node.parentNode.insertBefore(newParent, node);
+ newParent.appendChild(node);
+ }
+}
+
+var range = document.createRange();
+range.selectNodeContents(document.getElementsByTagName("div")[1]);
+styleRange(range, "fontWeight", "bold", ["b", "strong"]);
+</script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/editcommands.html Thu Feb 17 15:06:13 2011 -0700
@@ -0,0 +1,40 @@
+<!doctype html>
+<title>execCommand() tests</title>
+<div contenteditable=true>
+ <br> <br>
+ Some simple text<br>
+ <span>Some more text</span><br>
+ <b>Some more text</b><br>
+ <strong>Some more text</strong><br>
+ <span style=font-weight:bold>Some more text</span><br>
+ <span style=font-weight:bolder>Some more text</span><br>
+ <span style=font-weight:lighter>Some more text</span><br>
+ <span style=font-weight:900>Some more text</span><br>
+ <span style=font-weight:100>Some more text</span><br>
+ <i>Some more text</i><br>
+ <span style=font-style:italic>Some more text</span><br>
+ <span style=font-style:italic;font-weight:bold>Some more text</span><br>
+ <em style=font-weight:bold>Some more text</em><br>
+ <b>Some <span style=font-weight:light>more <b>te<span style=font-weight:bold>xt<strong>!</strong></span></b></span></b><br>
+ <p>Some simple text
+ <p><span>Some more text</span>
+ <p><b>Some more text</b>
+ <p><strong>Some more text</strong>
+ <p><span style=font-weight:bold>Some more text</span>
+ <p><span style=font-weight:bolder>Some more text</span>
+ <p><span style=font-weight:lighter>Some more text</span>
+ <p><span style=font-weight:900>Some more text</span>
+ <p><span style=font-weight:100>Some more text</span>
+ <p><i>Some more text</i>
+ <p><span style=font-style:italic>Some more text</span>
+ <p><span style=font-style:italic;font-weight:bold>Some more text</span>
+ <p><em style=font-weight:bold>Some more text</em>
+ <p><b>Some <span style=font-weight:light>more <b>te<span style=font-weight:bold>xt<strong>!</strong></span></b></span></b>
+</div>
+<script>
+var selection = getSelection();
+selection.selectAllChildren(document.querySelector("div"));
+document.execCommand("bold", false, null);
+//document.execCommand("bold", false, null);
+selection.removeAllRanges();
+</script>
--- a/xrefs.json Fri Feb 11 09:48:42 2011 -0700
+++ b/xrefs.json Thu Feb 17 15:06:13 2011 -0700
@@ -1,5 +1,5 @@
{
"command-bold": "command-bold",
- "split-text-node": "split-text-node",
- "wrap-range-in-tag": "wrap-range-in-tag"
+ "html element with name": "html-element-with-name",
+ "style a range": "style-a-range"
}