--- a/autoimplementation.html Thu Apr 14 10:11:40 2011 -0600
+++ b/autoimplementation.html Thu Apr 28 12:49:11 2011 -0600
@@ -15,18 +15,39 @@
.line-through { text-decoration: line-through }
.underline-and-line-through { text-decoration: underline line-through }
#purple { color: purple }
-td > div:first-child {
+body > div > table > tbody > tr > td > div:first-child {
padding-bottom: 0.2em;
}
-td > div:last-child {
+body > div > table > tbody > tr > td > div:last-child {
padding-top: 0.2em;
border-top: 1px solid black;
}
/* https://bugs.webkit.org/show_bug.cgi?id=56670 */
dfn { font-style: italic }
+/* Opera has weird default blockquote style */
+blockquote { margin: 1em 40px }
+/* Let the rendered HTML line up so it's easier to compare whitespace */
+body > div > table > tbody > tr > td { vertical-align: top }
/* We don't want test cells to not wrap */
listing, plaintext, pre, xmp { white-space: pre-wrap }
img, video { width: 50px }
+body > div > table {
+ width: 100%;
+ table-layout: fixed;
+}
+body > div > table > tbody > tr > td,
+body > div > table > tbody > tr > th {
+ width: 30%;
+}
+body > div > table > tbody > tr > td:last-child,
+body > div > table > tbody > tr > th:last-child {
+ width: 10%;
+}
+body > div > table > tbody > tr > td:last-child {
+ text-align: center;
+ vertical-align: middle;
+ font-size: 3em;
+}
</style>
<p>Legend: {[ are the selection anchor, }] are the selection focus, {}
represent an element boundary point, [] represent a text node boundary point.
@@ -442,6 +463,9 @@
'<span>foo[</span><span>]bar</span><p>extra',
'foo[bar]baz<p>extra',
'<p dir=rtl>פו[בר]בז<p dir=rtl>נוםף',
+ '<p dir=rtl>פו[ברבז<p>Foobar]baz<p>Extra',
+ '<p>Foo[barbaz<p dir=rtl>פובר]בז<p>Extra',
+ '<div><p>Foo[barbaz<p dir=rtl>פובר]בז</div><p>Extra',
'foo]bar[baz<p>extra',
'{<p><p> <p>foo</p>}<p>extra',
'foo[bar<i>baz]qoz</i>quz<p>extra',
@@ -456,6 +480,9 @@
'<p>foo[bar]</p><p>baz</p><p>extra',
'<p>[foobar</p><p>ba]z</p><p>extra',
'foo[bar]<br>baz<p>extra',
+ 'foo[bar]<br><br><br><br>baz<p>extra',
+ 'foobar<br>[ba]z<p>extra',
+ 'foobar<br><br><br><br>[ba]z<p>extra',
'foo[bar<br>ba]z<p>extra',
// These mimic existing indentation in various browsers, to see how
@@ -1059,7 +1086,7 @@
var table = document.querySelectorAll("#" + command + " > table")[idx];
var tr = document.createElement("tr");
- table.appendChild(tr);
+ table.firstChild.appendChild(tr);
return tr;
}
@@ -1117,6 +1144,9 @@
specCell.lastChild.style.color = "red";
specCell.lastChild.style.fontWeight = "bold";
specCell.lastChild.textContent = "Note, exception: " + e;
+ if ("stack" in e) {
+ specCell.lastChild.textContent += " (stack: " + e.stack + ")";
+ }
}
var key = "execcommand-" + command
@@ -1127,10 +1157,10 @@
localStorage[key] = specCell.lastChild.textContent;
if (oldValue !== null && oldValue !== undefined && oldValue != specCell.lastChild.textContent) {
- specCell.appendChild(document.createElement("div"));
- specCell.lastChild.style.color = "red";
- specCell.lastChild.style.fontWeight = "bold";
- specCell.lastChild.textContent = "Note, last run produced different markup: " + oldValue;
+ specCell.lastChild.appendChild(document.createElement("div"));
+ specCell.lastChild.lastChild.style.color = "red";
+ specCell.lastChild.lastChild.style.fontWeight = "bold";
+ specCell.lastChild.lastChild.textContent = "Note, last run produced different markup: " + oldValue;
}
}
@@ -1189,6 +1219,9 @@
browserCell.lastChild.style.color = "red";
browserCell.lastChild.style.fontWeight = "bold";
browserCell.lastChild.textContent = "Exception: " + e;
+ if ("stack" in e) {
+ specCell.lastChild.textContent += " (stack: " + e.stack + ")";
+ }
if (testDiv && testDiv.parentNode != browserCell) {
browserCell.insertBefore(testDiv, browserCell.firstChild);
}
@@ -1201,16 +1234,21 @@
try {
// Ad hoc normalization to avoid basically spurious mismatches. For
// now this includes ignoring where the selection goes.
- var normalizedSpecCell = tr.childNodes[1].childNodes[1].textContent
+ var normalizedSpecCell = tr.childNodes[1].lastChild.firstChild.textContent
.replace(/[[\]{}]/g, "")
+ .replace(/ style="margin: 0 40px"/g, "")
.replace(/: /g, ":")
.replace(/;? ?"/g, '"')
.replace(/<(\/?)strong/g, '<$1b')
.replace(/<(\/?)strike/g, '<$1s')
.replace(/<(\/?)em/g, '<$1i')
.replace(/#[0-9a-fA-F]{6}/g, function(match) { return match.toUpperCase(); });
- var normalizedBrowserCell = tr.childNodes[2].childNodes[1].textContent
+ var normalizedBrowserCell = tr.childNodes[2].lastChild.firstChild.textContent
.replace(/[[\]{}]/g, "")
+ .replace(/ class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"/g, '')
+ .replace(/ style="margin-right: 0px;" dir="ltr"/g, '')
+ .replace(/ style="margin-left: 0px;" dir="rtl"/g, '')
+ .replace(/ style="margin-(left|right): 40px;"/g, '')
.replace(/: /g, ":")
.replace(/;? ?"/g, '"')
.replace(/<(\/?)strong/g, '<$1b')
@@ -1240,16 +1278,14 @@
tr.appendChild(sameCell);
// Insert zero-width spaces so IE doesn't stretch the screen
- try {
- tr.childNodes[2].childNodes[1].textContent =
- tr.childNodes[2].childNodes[1].textContent
- .replace(/</g, "\u200B<")
- .replace(/>/g, ">\u200B");
- tr.childNodes[1].childNodes[1].textContent =
- tr.childNodes[1].childNodes[1].textContent
- .replace(/</g, "\u200B<")
- .replace(/>/g, ">\u200B");
- } catch (e) {};
+ for (var i = 0; i <= 2; i++) {
+ try {
+ tr.childNodes[i].lastChild.firstChild.textContent =
+ tr.childNodes[i].lastChild.firstChild.textContent
+ .replace(/</g, "\u200B<")
+ .replace(/>/g, ">\u200B");
+ } catch (e) {};
+ }
}
function doTearDown(command) {
--- a/editcommands.html Thu Apr 14 10:11:40 2011 -0600
+++ b/editcommands.html Thu Apr 28 12:49:11 2011 -0600
@@ -27,7 +27,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-14-april-2011>Work in Progress — Last Update 14 April 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-—-last-update-28-april-2011>Work in Progress — Last Update 28 April 2011</h2>
<dl>
<dt>Editor
<dd>Aryeh Gregor <ayg+spec@aryeh.name>
@@ -1681,21 +1681,30 @@
<dd><strong>Relevant CSS Property</strong>: "background-color"
-<!--
-<dt><code title><dfn title=command-indent>indent</dfn></code>
--->
+<dt><code title=""><dfn id=command-indent title=command-indent>indent</dfn></code>
<!--
IE9: Outputs <blockquote style="margin-right: 0px" dir="ltr">, or when
- surrounding RTL blocks, <blockquote style="margin-left: 0px" dir="rtl">.
+ surrounding RTL blocks, <blockquote style="margin-left: 0px" dir="rtl">. The
+ direction seems to go by the end of the selection. The presence of the dir
+ attribute means that any contents that were inheriting a different dir from
+ an ancestor get their direction changed as a side effect, but if they
+ actually have the opposite dir specified, they won't appear to be indented.
+ It doesn't reset top or bottom margins on the blockquote, so it adds them.
+ If it's not wrapping a block element, like if it's only wrapping up until a
+ <br>, it adds a <p>.
Firefox 4.0: In styleWithCSS mode, adds style="margin-left: 40px" to the
appropriate block container (or margin-right if it's RTL). If there's no
- appropriate block container, adds a div. In non-styleWithCSS mode, uses
- <blockquote>, so it indents on both sides.
+ appropriate block container, adds a div. If multiple blocks are affected, it
+ goes by the direction of the block whose style it's changing, which winds up
+ being wrong for descendants with different direction. In non-styleWithCSS
+ mode, uses <blockquote>, so it indents on both sides and also adds top/bottom
+ margins.
Chrome 12 dev: Outputs <blockquote class="webkit-indent-blockquote"
style="margin: 0 0 0 40px; border: none; padding: 0px"> in both modes for
both LTR and RTL (which is broken for RTL, since it indents only on the
- right).
-Opera 11.00: Outputs <blockquote>, so it indents on both sides.
+ left).
+Opera 11.00: Outputs <blockquote>, so it indents on both sides and on the
+ top/bottom.
For repeated indentation, everyone except Opera that outputs <blockquote>s just
puts them at the outermost possible location, which works well. Opera puts
@@ -1707,15 +1716,21 @@
doesn't actually increase the indentation. However, if an element has an
explicit left margin (assuming LTR), it will increase the margin to 80px, so it
works with WebKit's blockquotes.
+
+
+We have two strategies for handling directionality: always indent on both sides
+(Firefox non-CSS, Opera) or try to figure out heuristically which side we want
+(IE, Firefox CSS). The latter approach is only possible by adding extra markup
+and complexity, so for now we'll take the easy way out and go with just
+indenting on both sides.
-->
-<!--
<dd><strong>Action</strong>:
<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 <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 the <span data-anolis-spec=domrange title=concept-range>range</span>.
+ <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 <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 the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a>.
<p class=XXX>Handle corner cases: endpoints are detached, documents, document
fragments, html/body, head or things in head . . .
@@ -1723,22 +1738,22 @@
<li>Repeat the following steps:
<ol>
- <li>If <var title>start node</var> is a <code data-anolis-spec=domcore>Text</code> or <code data-anolis-spec=domcore>Comment</code> node or
- <var title>start offset</var> is 0, set <var title>start offset</var> to the <span data-anolis-spec=domrange title=concept-indexof>index</span>
- of <var title>start node</var> and then set <var title>start node</var> to its
- <span data-anolis-spec=domcore title=concept-tree-parent>parent</span>.
-
- <li>Otherwise, if the <var title>start offset</var> is equal to the
- <span data-anolis-spec=domrange title=concept-node-length>length</span> of <var title>start node</var>, set <var title>start offset</var> to one
- plus the <span data-anolis-spec=domrange title=concept-indexof>index</span> of <var title>start node</var> and then set <var title>start
- node</var> to its <span data-anolis-spec=domcore title=concept-tree-parent>parent</span>.
-
- <li>Otherwise, if the <span data-anolis-spec=domcore title=concept-tree-child>child</span> of <var title>start node</var> with <span data-anolis-spec=domrange title=concept-indexof>index</span>
- <var title>start offset</var> minus one is a <code data-anolis-spec=domcore>Text</code> or <code data-anolis-spec=domcore>Comment</code> node, or an
- (insert definition here), subtract one from <var title>start offset</var>.
+ <li>If <var title="">start node</var> is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> or <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#comment>Comment</a></code> node or
+ <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</a>
+ of <var title="">start node</var> and then set <var title="">start node</var> to its
+ <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+
+ <li>Otherwise, if <var title="">start offset</var> is equal to the
+ <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of <var title="">start node</var>, 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</a> of <var title="">start node</var> and then set <var title="">start
+ node</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+
+ <li>Otherwise, if the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">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> minus one is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> or <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#comment>Comment</a></code> node, or an
+ (insert definition here), subtract one from <var title="">start offset</var>.
<p class=XXX>The definition should include all inline elements except
- <br>. As elsewhere, we have trouble with the exact definition because
+ <br>. As elsewhere, we have trouble with the exact definition because
HTML doesn't classify non-conforming elements, but those are common in
editing and need to be handled correctly.
@@ -1748,28 +1763,90 @@
<li>Repeat the following steps:
<ol>
- <li>If <var title>end node</var> is a <code data-anolis-spec=domcore>Text</code> or <code data-anolis-spec=domcore>Comment</code> node or <var title>end
- offset</var> is 0, set <var title>end offset</var> to the <span data-anolis-spec=domrange title=concept-indexof>index</span> of <var title>end
- node</var> and then set <var title>end node</var> to its <span data-anolis-spec=domcore title=concept-tree-parent>parent</span>.
-
- <li>Otherwise, if the <var title>end offset</var> is equal to 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</span>
- of <var title>end node</var> and then set <var title>end node</var> to its <span data-anolis-spec=domcore title=concept-tree-parent>parent</span>.
-
- <li>Otherwise, if the <span data-anolis-spec=domcore title=concept-tree-child>child</span> of <var title>end node</var> with <span data-anolis-spec=domrange title=concept-indexof>index</span>
- <var title>end offset</var> plus one is a <code data-anolis-spec=domcore>Text</code> or <code data-anolis-spec=domcore>Comment</code> node, or an
- (insert definition here), add one to <var title>end offset</var>.
+ <li>If <var title="">end offset</var> is 0, 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</a> of <var title="">end node</var> and then set <var title="">end node</var> to its
+ <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+
+ <li>Otherwise, if <var title="">end node</var> is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> or <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#comment>Comment</a></code> node or
+ <var title="">end offset</var> is equal to the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of <var title="">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</a> of <var title="">end
+ node</var> and then set <var title="">end node</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+
+ <li>Otherwise, if the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">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> is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> or <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#comment>Comment</a></code> node, or an (insert
+ definition here), add one to <var title="">end offset</var>.
<p class=XXX>Same definition as before.
+ <li>Otherwise, if the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">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> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, remove it from its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> and break
+ from this loop.
+ <!-- If the first line box in a block box starts with a non-preserved line
+ break, the line break will create an empty line box. If the line line box
+ in a block box ends with a non-preserved line break, however, it will not
+ create an extra line box. This means that if you have foo<br>bar, there
+ will be no empty line in between, but if you change it to
+ <div>foo</div><br>bar, you've created an extra line. Chrome 12 dev thus
+ deletes a <br> that immediately follows a <blockquote> it creates. Firefox
+ 4.0 and Opera 11.00 instead just includes it in the blockquote, so it has
+ no effect. The issue doesn't come up for IE9, since it indents the whole
+ block and doesn't treat <br> differently from other inline elements. I
+ follow WebKit because it produces slightly neater markup. -->
+
<li>Otherwise, break from this loop.
</ol>
+
+ <li>Let <var title="">new range</var> be a new <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> whose <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> are <var title="">start node</var>,
+ <var title="">start offset</var>, <var title="">end node</var>, and <var title="">end offset</var>.
+
+ <li>Let <var title="">node list</var> be all <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>nodes</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in <var title="">new
+ range</var>, omitting any that cannot be the child of a <code class=external data-anolis-spec=html title="the blockquote element"><a href=http://www.whatwg.org/html/#the-blockquote-element>blockquote</a></code> and
+ omitting any with an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> already in <var title="">node list</var>.
+
+ <li>For each <var title="">node</var> in <var title="">node list</var>:
+
+ <ol>
+ <li>If the <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code> of <var title="">node</var> is an <a href=#html-element>HTML
+ element</a>; its "display" property computes to "block"; its
+ "margin-left" and "margin-right" properties compute to "40px"; and its
+ "margin-top" and "margin-bottom" properties compute to "0"; then append
+ <var title="">node</var> as the last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of its <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code>,
+ <a href=#preserving-ranges>preserving ranges</a>, and continue with the next <var title="">node</var>.
+
+ <li>Let <var title="">tag</var> be "div" if the <a href=#css-styling-flag>CSS styling flag</a> is
+ true, otherwise "blockquote".
+ <!-- Firefox 4.0 is the only tested browser that respects the CSS styling
+ flag for indent at all. For indent, as for inline markup commands like
+ bold, it will modify the inline style of existing elements if available,
+ and only create spans/divs if there are no existing elements where it could
+ add the style instead. For indent as for other commands, I follow WebKit
+ and always create an extra element, to ensure consistency between CSS and
+ non-CSS modes. -->
+
+ <li>Let <var title="">new parent</var> be the result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement(<var title="">tag</var>)</a></code> on
+ the <code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">node</var>.
+
+ <li>Insert <var title="">new parent</var> into <var title="">node</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>
+ immediately before <var title="">node</var>.
+
+ <li>Set the CSS property "margin" of <var title="">new parent</var> to "0 40px".
+
+ <p class=XXX>This indents on both sides, so we don't have to worry about
+ directionality. Preferably we should indent only on the start side, but
+ that requires care to get right in mixed-direction cases. Even once
+ browsers start to support margin-start and so on, we can't use them because
+ a) we have to work okay in legacy browsers and b) it doesn't help if a
+ nested block has different direction (so should be indented the other way).
+
+ <li>Append <var title="">node</var> as the last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">new parent</var>,
+ <a href=#preserving-ranges>preserving ranges</a>.
+ </ol>
</ol>
<dd><strong>State</strong>:
<dd><strong>Value</strong>:
--->
<dt><code title=""><dfn id=command-inserthorizontalrule title=command-inserthorizontalrule>insertHorizontalRule</dfn></code>
--- a/implementation.js Thu Apr 14 10:11:40 2011 -0600
+++ b/implementation.js Thu Apr 28 12:49:11 2011 -0600
@@ -1896,7 +1896,7 @@
// "medium", "large", "x-large", "xx-large", "xxx-large", and is not a
// valid CSS absolute length, then do nothing and abort these steps."
//
- // More cheap hacks to skip of valid CSS absolute length checks.
+ // More cheap hacks to skip valid CSS absolute length checks.
if (["xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "xxx-large"].indexOf(value) == -1
&& !/^[0-9]+(\.[0-9]+)?(cm|mm|in|pt|pc)$/.test(value)) {
return;
@@ -1938,6 +1938,155 @@
}
break;
+ case "indent":
+ // "Let start node, start offset, end node, and end offset be the start
+ // and end nodes and offsets of the range."
+ var startNode = range.startContainer;
+ var startOffset = range.startOffset;
+ var endNode = range.endContainer;
+ var endOffset = range.endOffset;
+
+ // "Repeat the following steps:"
+ while (true) {
+ // "If start node is a Text or Comment node or start offset is 0,
+ // set start offset to the index of start node and then set start
+ // node to its parent."
+ if (startNode.nodeType == Node.TEXT_NODE
+ || startNode.nodeType == Node.COMMENT_NODE
+ || startOffset == 0) {
+ startOffset = getNodeIndex(startNode);
+ startNode = startNode.parentNode;
+
+ // "Otherwise, if start offset is equal to the length of start
+ // node, set start offset to one plus the index of start node and
+ // then set start node to its parent."
+ } else if (startOffset == getNodeLength(startNode)) {
+ startOffset = 1 + getNodeIndex(startNode);
+ startNode = startNode.parentNode;
+
+ // "Otherwise, if the child of start node with index start offset
+ // minus one is a Text or Comment node, or an (insert definition
+ // here), subtract one from start offset."
+ } else if (startNode.childNodes[startOffset - 1].nodeType == Node.TEXT_NODE
+ || startNode.childNodes[startOffset - 1].nodeType == Node.COMMENT_NODE
+ || ["B", "I", "SPAN"].indexOf(startNode.childNodes[startOffset - 1].tagName) != -1) {
+ startOffset--;
+
+ // "Otherwise, break from this loop."
+ } else {
+ break;
+ }
+ }
+
+ // "Repeat the following steps:"
+ while (true) {
+ // "If end offset is 0, set end offset to the index of end node and
+ // then set end node to its parent."
+ if (endOffset == 0) {
+ endOffset = getNodeIndex(endNode);
+ endNode = endNode.parentNode;
+
+ // "Otherwise, if end node is a Text or Comment node or end offset
+ // is equal to the length of end node, set end offset to one plus
+ // the index of end node and then set end node to its parent."
+ } else if (endNode.nodeType == Node.TEXT_NODE
+ || endNode.nodeType == Node.COMMENT_NODE
+ || endOffset == getNodeLength(endNode)) {
+ endOffset = 1 + getNodeIndex(endNode);
+ endNode = endNode.parentNode;
+
+ // "Otherwise, if the child of end node with index end offset is a
+ // Text or Comment node, or an (insert definition here), add one to
+ // end offset."
+ } else if (endNode.childNodes[endOffset].nodeType == Node.TEXT_NODE
+ || endNode.childNodes[endOffset].nodeType == Node.COMMENT_NODE
+ || ["B", "I", "SPAN"].indexOf(endNode.childNodes[endOffset].tagName) != -1) {
+ endOffset++;
+
+ // "Otherwise, if the child of end node with index end offset is a br,
+ // remove it from its parent and break from this loop."
+ } else if (isHtmlElement(endNode.childNodes[endOffset])
+ && endNode.childNodes[endOffset].tagName == "BR") {
+ endNode.removeChild(endNode.childNodes[endOffset]);
+ break;
+
+ // "Otherwise, break from this loop."
+ } else {
+ break;
+ }
+ }
+
+ // "Let new range be a new range whose start and end nodes and offsets
+ // are start node, start offset, end node, and end offset."
+ var newRange = startNode.ownerDocument.createRange();
+ newRange.setStart(startNode, startOffset);
+ newRange.setEnd(endNode, endOffset);
+
+ // "Let node list be all nodes contained in new range, omitting any
+ // that cannot be the child of a blockquote and omitting any with an
+ // ancestor already in node list."
+ var nodeList = [];
+ for (var node = newRange.startContainer; node != nextNodeDescendants(newRange.endContainer); node = nextNode(node)) {
+ if (!isContained(node, newRange)) {
+ continue;
+ }
+
+ if (node.nodeType == Node.ELEMENT_NODE
+ && ["TBODY", "THEAD", "TR", "TH", "TD"].indexOf(node.tagName) != -1) {
+ continue;
+ }
+
+ if (nodeList.length
+ && isAncestor(nodeList[nodeList.length - 1], node)) {
+ continue;
+ }
+
+ nodeList.push(node);
+ }
+
+ // "For each node in node list:"
+ for (var i = 0; i < nodeList.length; i++) {
+ var node = nodeList[i];
+
+ // "If the previousSibling of node is an HTML element; its
+ // "display" property computes to "block"; its "margin-left" and
+ // "margin-right" properties compute to "40px"; and its
+ // "margin-top" and "margin-bottom" properties compute to "0"; then
+ // append node as the last child of its previousSibling, preserving
+ // ranges, and continue with the next node."
+ if (isHtmlElement(node.previousSibling)) {
+ var style = getComputedStyle(node.previousSibling);
+ if (style.display == "block"
+ && style.marginLeft == "40px"
+ && style.marginRight == "40px"
+ && style.marginTop == "0px"
+ && style.marginBottom == "0px") {
+ movePreservingRanges(node, node.previousSibling, node.previousSibling.childNodes.length);
+ continue;
+ }
+ }
+
+ // "Let tag be "div" if the CSS styling flag is true, otherwise
+ // "blockquote"."
+ var tag = cssStylingFlag ? "div" : "blockquote";
+
+ // "Let new parent be the result of calling createElement(tag) on
+ // the ownerDocument of node."
+ var newParent = node.ownerDocument.createElement(tag);
+
+ // "Insert new parent into node's parent immediately before node."
+ node.parentNode.insertBefore(newParent, node);
+
+ // "Set the CSS property "margin" of new parent to "0 40px"."
+ newParent.setAttribute("style", "margin: 0 40px");
+
+ // "Append node as the last child of new parent, preserving
+ // ranges."
+ movePreservingRanges(node, newParent, 0);
+ }
+
+ break;
+
case "inserthorizontalrule":
// "Run deleteContents() on the range."
range.deleteContents();
--- a/preprocess Thu Apr 14 10:11:40 2011 -0600
+++ b/preprocess Thu Apr 28 12:49:11 2011 -0600
@@ -11,6 +11,8 @@
'attrlocalname': '<span data-anolis-spec=domcore title=concept-attr-local-name>local name</span>',
'attrvalue': '<span data-anolis-spec=domcore title=concept-attr-value>value</span>',
'b': '<code data-anolis-spec=html title="the b element">b</code>',
+ 'blockquote': '<code data-anolis-spec=html title="the blockquote element">blockquote</code>',
+ 'br': '<code data-anolis-spec=html title="the br element">br</code>',
'boundarypoint': '<span data-anolis-spec=domrange title=concept-boundary-point>boundary point</span>',
'bpnode': '<span data-anolis-spec=domrange title=concept-boundary-point-node>node</span>',
'bpoffset': '<span data-anolis-spec=domrange title=concept-boundary-point-offset>offset</span>',
--- a/source.html Thu Apr 14 10:11:40 2011 -0600
+++ b/source.html Thu Apr 28 12:49:11 2011 -0600
@@ -1697,21 +1697,30 @@
<dd><strong>Relevant CSS Property</strong>: "background-color"
-<!--
<dt><code title><dfn title=command-indent>indent</dfn></code>
--->
<!--
IE9: Outputs <blockquote style="margin-right: 0px" dir="ltr">, or when
- surrounding RTL blocks, <blockquote style="margin-left: 0px" dir="rtl">.
+ surrounding RTL blocks, <blockquote style="margin-left: 0px" dir="rtl">. The
+ direction seems to go by the end of the selection. The presence of the dir
+ attribute means that any contents that were inheriting a different dir from
+ an ancestor get their direction changed as a side effect, but if they
+ actually have the opposite dir specified, they won't appear to be indented.
+ It doesn't reset top or bottom margins on the blockquote, so it adds them.
+ If it's not wrapping a block element, like if it's only wrapping up until a
+ <br>, it adds a <p>.
Firefox 4.0: In styleWithCSS mode, adds style="margin-left: 40px" to the
appropriate block container (or margin-right if it's RTL). If there's no
- appropriate block container, adds a div. In non-styleWithCSS mode, uses
- <blockquote>, so it indents on both sides.
+ appropriate block container, adds a div. If multiple blocks are affected, it
+ goes by the direction of the block whose style it's changing, which winds up
+ being wrong for descendants with different direction. In non-styleWithCSS
+ mode, uses <blockquote>, so it indents on both sides and also adds top/bottom
+ margins.
Chrome 12 dev: Outputs <blockquote class="webkit-indent-blockquote"
style="margin: 0 0 0 40px; border: none; padding: 0px"> in both modes for
both LTR and RTL (which is broken for RTL, since it indents only on the
- right).
-Opera 11.00: Outputs <blockquote>, so it indents on both sides.
+ left).
+Opera 11.00: Outputs <blockquote>, so it indents on both sides and on the
+ top/bottom.
For repeated indentation, everyone except Opera that outputs <blockquote>s just
puts them at the outermost possible location, which works well. Opera puts
@@ -1723,9 +1732,15 @@
doesn't actually increase the indentation. However, if an element has an
explicit left margin (assuming LTR), it will increase the margin to 80px, so it
works with WebKit's blockquotes.
+
+
+We have two strategies for handling directionality: always indent on both sides
+(Firefox non-CSS, Opera) or try to figure out heuristically which side we want
+(IE, Firefox CSS). The latter approach is only possible by adding extra markup
+and complexity, so for now we'll take the easy way out and go with just
+indenting on both sides.
-->
-<!--
<dd><strong>Action</strong>:
<ol>
@@ -1744,7 +1759,7 @@
of <var>start node</var> and then set <var>start node</var> to its
[[parent]].
- <li>Otherwise, if the <var>start offset</var> is equal to the
+ <li>Otherwise, if <var>start offset</var> is equal to the
[[nodelength]] of <var>start node</var>, set <var>start offset</var> to one
plus the [[index]] of <var>start node</var> and then set <var>start
node</var> to its [[parent]].
@@ -1764,28 +1779,92 @@
<li>Repeat the following steps:
<ol>
- <li>If <var>end node</var> is a [[text]] or [[comment]] node or <var>end
- offset</var> is 0, set <var>end offset</var> to the [[index]] of <var>end
+ <li>If <var>end offset</var> is 0, set <var>end offset</var> to the
+ [[index]] of <var>end node</var> and then set <var>end node</var> to its
+ [[parent]].
+
+ <li>Otherwise, if <var>end node</var> is a [[text]] or [[comment]] node or
+ <var>end offset</var> is equal to the [[nodelength]] of <var>end
+ node</var>, set <var>end offset</var> to one plus the [[index]] of <var>end
node</var> and then set <var>end node</var> to its [[parent]].
- <li>Otherwise, if the <var>end offset</var> is equal to the [[nodelength]]
- of <var>end node</var>, set <var>end offset</var> to one plus the [[index]]
- of <var>end node</var> and then set <var>end node</var> to its [[parent]].
-
<li>Otherwise, if the [[child]] of <var>end node</var> with [[index]]
- <var>end offset</var> plus one is a [[text]] or [[comment]] node, or an
- (insert definition here), add one to <var>end offset</var>.
+ <var>end offset</var> is a [[text]] or [[comment]] node, or an (insert
+ definition here), add one to <var>end offset</var>.
<p class=XXX>Same definition as before.
+ <li>Otherwise, if the [[child]] of <var>end node</var> with [[index]]
+ <var>end offset</var> is a [[br]], remove it from its [[parent]] and break
+ from this loop.
+ <!-- If the first line box in a block box starts with a non-preserved line
+ break, the line break will create an empty line box. If the line line box
+ in a block box ends with a non-preserved line break, however, it will not
+ create an extra line box. This means that if you have foo<br>bar, there
+ will be no empty line in between, but if you change it to
+ <div>foo</div><br>bar, you've created an extra line. Chrome 12 dev thus
+ deletes a <br> that immediately follows a <blockquote> it creates. Firefox
+ 4.0 and Opera 11.00 instead just includes it in the blockquote, so it has
+ no effect. The issue doesn't come up for IE9, since it indents the whole
+ block and doesn't treat <br> differently from other inline elements. I
+ follow WebKit because it produces slightly neater markup. -->
+
<li>Otherwise, break from this loop.
</ol>
+
+ <li>Let <var>new range</var> be a new [[range]] whose [[rangestart]] and
+ [[rangeend]] [[bpnodes]] and [[bpoffsets]] are <var>start node</var>,
+ <var>start offset</var>, <var>end node</var>, and <var>end offset</var>.
+
+ <li>Let <var>node list</var> be all [[nodes]] [[contained]] in <var>new
+ range</var>, omitting any that cannot be the child of a [[blockquote]] and
+ omitting any with an [[ancestor]] already in <var>node list</var>.
+
+ <li>For each <var>node</var> in <var>node list</var>:
+
+ <ol>
+ <li>If the [[previoussibling]] of <var>node</var> is an <span>HTML
+ element</span>; its "display" property computes to "block"; its
+ "margin-left" and "margin-right" properties compute to "40px"; and its
+ "margin-top" and "margin-bottom" properties compute to "0"; then append
+ <var>node</var> as the last [[child]] of its [[previoussibling]],
+ <span>preserving ranges</span>, and continue with the next <var>node</var>.
+
+ <li>Let <var>tag</var> be "div" if the <span>CSS styling flag</span> is
+ true, otherwise "blockquote".
+ <!-- Firefox 4.0 is the only tested browser that respects the CSS styling
+ flag for indent at all. For indent, as for inline markup commands like
+ bold, it will modify the inline style of existing elements if available,
+ and only create spans/divs if there are no existing elements where it could
+ add the style instead. For indent as for other commands, I follow WebKit
+ and always create an extra element, to ensure consistency between CSS and
+ non-CSS modes. -->
+
+ <li>Let <var>new parent</var> be the result of calling <code
+ data-anolis-spec=domcore
+ title=dom-Document-createElement>createElement(<var>tag</var>)</code> on
+ the [[ownerdocument]] of <var>node</var>.
+
+ <li>Insert <var>new parent</var> into <var>node</var>'s [[parent]]
+ immediately before <var>node</var>.
+
+ <li>Set the CSS property "margin" of <var>new parent</var> to "0 40px".
+
+ <p class=XXX>This indents on both sides, so we don't have to worry about
+ directionality. Preferably we should indent only on the start side, but
+ that requires care to get right in mixed-direction cases. Even once
+ browsers start to support margin-start and so on, we can't use them because
+ a) we have to work okay in legacy browsers and b) it doesn't help if a
+ nested block has different direction (so should be indented the other way).
+
+ <li>Append <var>node</var> as the last [[child]] of <var>new parent</var>,
+ <span>preserving ranges</span>.
+ </ol>
</ol>
<dd><strong>State</strong>:
<dd><strong>Value</strong>:
--->
<dt><code title><dfn title=command-inserthorizontalrule>insertHorizontalRule</dfn></code>