--- a/editing.html Tue Aug 02 14:29:11 2011 -0600
+++ b/editing.html Tue Aug 02 14:59:25 2011 -0600
@@ -187,10 +187,10 @@
<p>Where the reasoning behind the specification is of interest, such as when
major preexisting rendering engines are known not to match it, the reasoning is
-included in HTML comments so as not to distract the reader. If you have
-questions about why the specification says something, check for comments in the
-source first. They're sometimes longer than the specification text itself, and
-commonly record what the major browsers do and other essential information.
+available by clicking the "comments" button on the right (requires JavaScript).
+If you have questions about why the specification says something, check the
+comments first. They're sometimes longer than the specification text itself,
+and commonly record what the major browsers do and other essential information.
<p>The principles I've used for writing this specification so far are:
@@ -312,87 +312,97 @@
<p class=XXX>A variety of other issues are also noted in the text, formatted
like this. Feedback would be appreciated on all of them.
-<p>Things that would be useful to address for the future but aren't important
-to fix right now are in comments prefixed with "TODO".
-
-<!--
-TODO:
-
-* Scour browser bug trackers to try spotting issues I haven't thought of.
-
-* The wording I use for DOM stuff is not maximally precise. Really I want DOM
- Core to define nice concepts that I can xref, like "insert a node". I
+<div class=comments>
+<p>TODO:
+
+<ul>
+ <li>Scour browser bug trackers to try spotting issues I haven't thought of.
+
+ <li>The wording I use for DOM stuff is not maximally precise. Really I want
+ DOM Core to define nice concepts that I can xref, like "insert a node". I
don't want to have to explicitly refer to DOM methods like insertBefore()
every time I want to move things.
-* JavaScript can modify the DOM synchronously in some cases, such as DOM
+ <li>JavaScript can modify the DOM synchronously in some cases, such as DOM
mutation events and onunload when moving around iframes and objects. This
has to be dealt with somehow. (Pointed out by Ryosuke Niwa of WebKit:
- http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-March/030730.html
- http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-March/030751.html)
-
-* What happens if you do something like delete a selection or insert text or
+ <a href=http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-March/030730.html>1</a>
+ <a href=http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-March/030751.html>2</a>)
+
+ <li>What happens if you do something like delete a selection or insert text or
whatnot in the middle of a surrogate pair? This could make the content not
serialize through a character encoding change.
-* Probably need to record and restore overrides in some more places.
-
-* Some more thought needs to go into what happens to the selection when you
+ <li>Probably need to record and restore overrides in some more places.
+
+ <li>Some more thought needs to go into what happens to the selection when you
mutate the DOM. In some cases the results are pretty arbitrary. It might
make sense to do some kind of normalization.
-* I'm sloppy about handling things like nodes that don't descend from a
+ <li>I'm sloppy about handling things like nodes that don't descend from a
Document, comments that are children of a Document, that sort of thing. Not
essential for prototyping, but needs to be cleaned up eventually. Mostly we
should be able to avoid the problems by requiring that everything be
editable, since that immediately means it has to descend from an element or
Document (and cannot be parentless itself).
-* I need to pay more attention to invisible nodes. These will have no visual
+ <li>I need to pay more attention to invisible nodes. These will have no visual
effect, but they'll make many algorithms behave differently: decomposing a
range, block-extending, etc. Also, need to improve the definition to include
things like whitespace-only nodes.
-* Have to make sure that in all the places where we set a selection, it's
+ <li>Have to make sure that in all the places where we set a selection, it's
valid.
-* Redefine things in terms of ranges, not selections.
-
-* Allow some type of switch to affect non-editable regions too, perhaps on a
+ <li>Redefine things in terms of ranges, not selections.
+
+ <li>Allow some type of switch to affect non-editable regions too, perhaps on a
per-command basis.
--->
-
-<!--
-TODO: Things that are only implemented by a couple of browsers and may or may
-not be useful to spec:
-
-* decreaseFontSize, increaseFontSize: Only implemented in Gecko and Opera.
-* contentReadOnly, enableInlineTableEditing, enableObjectResizing, heading,
+</ul>
+
+<p>Also TODO: Things that are only implemented by a couple of browsers and may
+or may not be useful to spec:
+
+<ul>
+ <li>decreaseFontSize, increaseFontSize: Only implemented in Gecko and Opera.
+
+ <li>contentReadOnly, enableInlineTableEditing, enableObjectResizing, heading,
insertBrOnReturn: MDC docs say not implemented in IE (didn't test).
-* readOnly: MDC docs say it's a deprecated equivalent of contentReadOnly, so
- presumably like useCSS but less popular.
-* 2D-Position, absolutePosition, clearAuthenticationCache, createBookmark,
+
+ <li>readOnly: MDC docs say it's a deprecated equivalent of contentReadOnly,
+ so presumably like useCSS but less popular.
+
+ <li>2D-Position, absolutePosition, clearAuthenticationCache, createBookmark,
insertButton, insertFieldset, insertIframe, insertInput*, insertMarquee,
insertSelectDropdown, insertSelectListbox, insertTextarea, liveResize,
multipleSelection, overwrite, print, refresh, saveAs, unbookmark: Mentioned
in MSDN docs but not MDC, so presumably IE-only. Some of these seem
inappropriate or useless, others will bear investigation.
-* findString, fontSizeDelta, insertNewlineInQuotedContent, justifyNone, print,
- transpose: There's code for these in WebKit,
+
+ <li>findString, fontSizeDelta, insertNewlineInQuotedContent, justifyNone,
+ print, transpose: There's code for these in WebKit,
Source/WebCore/editing/EditorCommand.cpp, but I didn't see them mentioned
elsewhere. Some might be worth adding.
-* unselect: Seems to not be implemented by Gecko or Opera, and IE behaves
+
+ <li>unselect: Seems to not be implemented by Gecko or Opera, and IE behaves
oddly: it seems to collapse the selection instead of removing it. Will only
implement if there seems to be demand; it's redundant to
Selection.removeAllRanges() anyway.
-
-Things I haven't looked at that multiple browsers implement:
-
-* redo, undo: Needs review of the Google work on this; will probably be
+</ul>
+
+<p>Things I haven't looked at that multiple browsers implement:
+
+<ul>
+ <li>redo, undo: Needs review of the Google work on this; will probably be
quite complicated.
-
-Also need to look at contenteditable=plaintext-only.
--->
+</ul>
+
+<p>Also need to look at contenteditable=plaintext-only.
+</div>
+
+<p>Things that would be useful to address for the future but aren't important
+to fix right now are in comments prefixed with "TODO".
+
<h2 id=commands><span class=secno>3 </span>Commands</h2>
@@ -7130,50 +7140,57 @@
<p><a href=#action>Action</a>:
<ol>
- <li>If <var title="">value</var> is the empty string, abort these steps and do
+ <li>
+ <p class=comments>Similar logic to createLink, except even more compelling,
+ since an HTML document linking to itself as an image is just silly. In fact,
+ the current HTML spec instructs UAs to not even try displaying the image, and
+ just fail immediately if the URL is empty. Firefox 4b11 silently does
+ nothing on an empty string, but the other three browsers I tested stick in
+ the <img> anyway.
+
+ <p>If <var title="">value</var> is the empty string, abort these steps and do
nothing.
- <!-- Similar logic to createLink, except even more compelling, since an HTML
- document linking to itself as an image is just silly. In fact, the current
- HTML spec instructs UAs to not even try displaying the image, and just fail
- immediately if the URL is empty. Firefox 4b11 silently does nothing on an
- empty string, but the other three browsers I tested stick in the <img>
- anyway. -->
<li>Let <var title="">range</var> be the <a href=#active-range>active range</a>.
- <li><a href=#delete-the-contents>Delete the contents</a> of <var title="">range</var>, with <var title="">strip
+ <li>
+ <p class=comments>Firefox 7.0a2 seems to strip the wrapper or not depending
+ on the exact positioning of the selection: <b>{foo}</b> yes,
+ <b>[foo]</b> no. Chrome 14 dev seems to strip the wrapper regardless.
+ Opera 11.50 seems to keep the wrapper, but place the image outside it. I
+ didn't get IE to cooperate with my tests. I chose to leave wrappers across
+ the board because they might be meaningful: e.g., a background-color when the
+ image is small or not fully opaque.
+
+ <p><a href=#delete-the-contents>Delete the contents</a> of <var title="">range</var>, with <var title="">strip
wrappers</var> false.
- <!--
- Firefox 7.0a2 seems to strip the wrapper or not depending on the exact
- positioning of the selection: <b>{foo}</b> yes, <b>[foo]</b> no. Chrome 14
- dev seems to strip the wrapper regardless. Opera 11.50 seems to keep the
- wrapper, but place the image outside it. I didn't get IE to cooperate with
- my tests. I chose to leave wrappers across the board because they might be
- meaningful: e.g., a background-color when the image is small or not fully
- opaque.
- -->
<li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a> is neither
<a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>, abort these steps.
- <li>If <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a> is a <a href=#block-node>block node</a> whose
+ <li>
+ <p class=comments>Same logic as with insertHTML.
+
+ <p>If <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a> is a <a href=#block-node>block node</a> whose
sole <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> 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>, and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is 0, remove its
<a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a>'s <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> from it.
- <!-- Same logic as with insertHTML. -->
<li>Let <var title="">img</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("img")</a></code> on
the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>.
- <li>Run <code class=external data-anolis-spec=domcore title=dom-Element-setAttribute><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-element-setattribute>setAttribute("src", <var title="">value</var>)</a></code> on <var title="">img</var>.
- <!-- No alt text, so it's probably invalid. This matches all browsers. -->
-
- <li>Run <code class=external data-anolis-spec=domrange title=dom-Range-insertNode><a href=http://html5.org/specs/dom-range.html#dom-range-insertnode>insertNode(<var title="">img</var>)</a></code> on <var title="">range</var>.
- <!--
- This winds up putting it at the original start point of the active range, as
- currently specced. This matches IE9 and Firefox 5.0a2. Chrome 13 dev puts
- it at the end point, and Opera 11.11 puts it in between (where the range
- would collapse if you called deleteContents()).
- -->
+ <li>
+ <p class=comments>No alt text, so it's probably invalid. This matches all
+ browsers.
+
+ <p>Run <code class=external data-anolis-spec=domcore title=dom-Element-setAttribute><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-element-setattribute>setAttribute("src", <var title="">value</var>)</a></code> on <var title="">img</var>.
+
+ <li>
+ <p class=comments>This winds up putting it at the original start point of the
+ active range, as currently specced. This matches IE9 and Firefox 5.0a2.
+ Chrome 13 dev puts it at the end point, and Opera 11.11 puts it in between
+ (where the range would collapse if you called deleteContents()).
+
+ <p>Run <code class=external data-anolis-spec=domrange title=dom-Range-insertNode><a href=http://html5.org/specs/dom-range.html#dom-range-insertnode>insertNode(<var title="">img</var>)</a></code> on <var title="">range</var>.
<li>Let <var title="">selection</var> be the result of calling <code class=external data-anolis-spec=domrange title=dom-Document-getSelection><a href=http://html5.org/specs/dom-range.html#dom-document-getselection>getSelection()</a></code> on the
<a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>.
@@ -7186,48 +7203,53 @@
<h3 id=the-insertlinebreak-command><span class=secno>8.18 </span><dfn>The <code title="">insertLineBreak</code> command</dfn></h3>
-<p><a href=#action>Action</a>:
-
-<!--
-Only implemented in WebKit (Chrome 14 dev). Other tests are entirely manual.
+<div class=comments>
+<p>Only implemented in WebKit (Chrome 14 dev). Other tests are entirely
+manual (i.e., actually hitting Shift-Enter instead of running a command).
There's a surprisingly large amount of interop.
-IE9 is tripped up by <xmp>, and also often doesn't add an extra <br> when the
-one it just inserted is extraneous.
-
-Firefox 6.0a2 doesn't notice if you're trying to put the <br> in a bad place,
-which can result in unserializable DOMs.
-
-Chrome 14 dev inserts a literal linebreak for pre and xmp and maybe other
+<p>IE9 is tripped up by <xmp>, and also often doesn't add an extra <br>
+when the one it just inserted is extraneous.
+
+<p>Firefox 6.0a2 doesn't notice if you're trying to put the <br> in a bad
+place, which can result in unserializable DOMs.
+
+<p>Chrome 14 dev inserts a literal linebreak for pre and xmp and maybe other
similar elements. This doesn't seem very useful, so I don't bother.
-Opera 11.11 isn't heedful of <xmp>, and treats <pre> somewhat oddly.
--->
+<p>Opera 11.11 isn't heedful of <xmp>, and treats <pre> somewhat oddly.
+</div>
+
+<p><a href=#action>Action</a>:
<ol>
- <li><a href=#delete-the-contents>Delete the contents</a> of the <a href=#active-range>active range</a>, with
+ <li>
+ <p class=comments>IE9 doesn't strip wrappers (IE10PP2 didn't work in tests).
+ Firefox 7.0a2 strips wrappers inconsistently depending on the exact selection
+ endpoints. Chrome 14 dev strips wrappers but recreates any styles using new
+ wrappers. Opera 11.50 strips all wrappers.
+
+ <p><a href=#delete-the-contents>Delete the contents</a> of the <a href=#active-range>active range</a>, with
<var title="">strip wrappers</var> false.
- <!--
- IE9 doesn't strip wrappers (IE10PP2 didn't work in tests). Firefox 7.0a2
- strips wrappers inconsistently depending on the exact selection endpoints.
- Chrome 14 dev strips wrappers but recreates any styles using new wrappers.
- Opera 11.50 strips all wrappers.
- -->
<li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a> is neither
<a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>, abort these steps.
- <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a> is an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>, and
+ <li>
+ <p class=comments>script, xmp, table, . . .
+
+ <p>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a> is an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>, and
"br" is not an <a href=#allowed-child>allowed child</a> of it, abort these steps.
- <!-- script, xmp, table, . . . -->
<li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a> is not an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>,
and "br" is not an <a href=#allowed-child>allowed child</a> of the <a href=#active-range>active
range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a>'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>, abort these steps.
- <!-- We don't want to call insertNode at the start or end of a text node,
- because that will leave an empty text node. -->
- <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a> is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node and
+ <li>
+ <p class=comments>We don't want to call insertNode at the start or end of a
+ text node, because that will leave an empty text node.
+
+ <p>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a> is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node and
its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is zero, set the <a href=#active-range>active range</a>'s
<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> to (<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> of <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a>, <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of
<a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a>).
@@ -7258,46 +7280,47 @@
<p><a href=#action>Action</a>: <a href=#toggle-lists>Toggle lists</a> with <var title="">tag name</var>
"ol".
+<p class=comments>Firefox 6.0a2 sort of supports this, but it throws exceptions
+most of the time. It has the quirk that even if there are no ol's around, it
+will say it's indeterminate if there are some things that are ul's and some
+that are not lists at all, but this doesn't make sense and I don't duplicate
+it. No one else supports indeterminate for insert*List, but it makes sense if
+you support state.
+
<p><a href=#indeterminate>Indeterminate</a>: True if the <a href="#selection's-list-state">selection's list state</a>
is "mixed" or "mixed ol", false otherwise.
-<!--
-Firefox 6.0a2 sort of supports this, but it throws exceptions most of the
-time. It has the quirk that even if there are no ol's around, it will say it's
-indeterminate if there are some things that are ul's and some that are not
-lists at all, but this doesn't make sense and I don't duplicate it. No one
-else supports indeterminate for insert*List, but it makes sense if you support
-state.
--->
+
+<p class=comments>IE9 throws exceptions in most cases, Firefox 6.0a2 in some
+cases as well, for no apparent reason. Ignoring those, the spec basically
+matches all browsers, except with a few weird random mismatches that looked
+like browser bugs to me.
<p><a href=#state>State</a>: True if the <a href="#selection's-list-state">selection's list state</a> is "ol",
false otherwise.
-<!--
-IE9 throws exceptions in most cases, Firefox 6.0a2 in some cases as well, for
-no apparent reason. Ignoring those, the spec basically matches all browsers,
-except with a few weird random mismatches that looked like browser bugs to me.
--->
<h3 id=the-insertparagraph-command><span class=secno>8.20 </span><dfn>The <code title="">insertParagraph</code> command</dfn></h3>
-<!--
-There are three major behaviors here. Firefox 5.0a2 behaves identically to
+<div class=comments>
+<p>There are three major behaviors here. Firefox 5.0a2 behaves identically to
execCommand("formatBlock", false, "p"), which is not really useful. IE9
actually just overwrites the selection with an empty paragraph element, which
seems not very useful either. Chrome 13 dev and Opera 11.10 behave basically
the same as if the user hit the Return key. This latter behavior seems much
more useful, even though it's horribly misnamed, so it's what I'll spec.
-
-(Actually, Opera doesn't behave quite the same for insertParagraph and line
+Comments about IE/Firefox are based on manual tests, where I hit Enter instead
+of running commands.
+
+<p>(Actually, Opera doesn't behave quite the same for insertParagraph and line
breaks. But it's pretty close, and I expect the differences are bugs.)
-Then, of course, we have several flavors of line-breaking behavior to choose
-from. Firefox prefers <br>s, unless it's in the middle of a <p> or something.
-Opera and IE like <p>. Chrome prefers <div>. And there are lots of subtleties
-besides. I go with IE/Opera-style behavior, as discussed in this thread:
-
-http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2011-May/031577.html
--->
+<p>Then, of course, we have several flavors of line-breaking behavior to choose
+from. Firefox prefers <br>s, unless it's in the middle of a <p> or
+something. Opera and IE like <p>. Chrome prefers <div>. And there are
+lots of subtleties besides. I go with IE/Opera-style behavior, as discussed in
+<a href=http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2011-May/031577.html>a
+whatwg thread</a>.
+</div>
<p><a href=#action>Action</a>:
@@ -7334,10 +7357,12 @@
the same editing host</a> as <var title="">node</var>, set <var title="">container</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>If <var title="">container</var> is not <a href=#editable>editable</a> or not <a href=#in-the-same-editing-host>in the
+ <li>
+ <p class=comments>We add the default wrapper in this case.
+
+ <p>If <var title="">container</var> is not <a href=#editable>editable</a> or not <a href=#in-the-same-editing-host>in the
same editing host</a> as <var title="">node</var> or is not a <a href=#single-line-container>single-line
container</a>:
- <!-- Add the default wrapper. -->
<ol>
<li>Let <var title="">tag</var> be the <a href=#default-single-line-container-name>default single-line container
@@ -7355,12 +7380,14 @@
<li>If <var title="">node list</var> is empty:
<ol>
- <!-- Ideally, we should normalize things so that the cursor is never in a
- weird place after deletion, but let's be safe and bail out if we do hit
- this scenario. It's not clear if we need this line in the long term, but
- at the time of this writing there's at least one corner case where
- deleting can leave the cursor inside a <tr>. -->
- <li>If <var title="">tag</var> is not an <a href=#allowed-child>allowed child</a> of
+ <li>
+ <p class=comments>Ideally, we should normalize things so that the cursor
+ is never in a weird place after deletion, but let's be safe and bail out
+ if we do hit this scenario. It's not clear if we need this line in the
+ long term, but at the time of this writing there's at least one corner
+ case where deleting can leave the cursor inside a <tr>.
+
+ <p>If <var title="">tag</var> is not an <a href=#allowed-child>allowed child</a> of
<var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a>, abort these steps.
<li>Set <var title="">container</var> to the result of calling
@@ -7377,14 +7404,14 @@
<li>Abort these steps.
</ol>
- <li>While the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last member of <var title="">node list</var> is
+ <li>
+ <p class=comments>TODO: It is not at all obvious that this is the correct
+ list of nodes in all cases. It should probably work because of how the
+ block-extend algorithm works, but further thought would be good.
+
+ <p>While the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last member of <var title="">node list</var> is
not null and is an <a href=#allowed-child>allowed child</a> of "p", append it to
<var title="">node list</var>.
- <!--
- TODO: It is not at all obvious that this is the correct list of nodes in
- all cases. It should probably work because of how the block-extend
- algorithm works, but further thought would be good.
- -->
<li><a href=#wrap>Wrap</a> <var title="">node list</var>, with <a href=#sibling-criteria>sibling
criteria</a> matching nothing and <a href=#new-parent-instructions>new parent instructions</a>
@@ -7392,28 +7419,30 @@
<a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>. Set <var title="">container</var> to the result.
</ol>
- <li>If <var title="">container</var>'s <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 "address", "listing", or
- "pre":
- <!--
- IE9 and Chrome 13 dev just break <pre> up into multiple <pre>s. Firefox
- 5.0a2 and Opera 11.10 insert a <br> instead, treating it differently from
- <p>. The latter makes more sense. What might make the most sense is to just
- insert an actual newline character, though, since this is a pre after all
- . . .
-
- IE9 and Chrome 13 dev also break <address> up into multiple <address>es.
- Firefox 5.0a2 inserts <br> instead. Opera 11.10 nests <p>s inside. I don't
- like Opera's behavior, because it means we nest formatBlock candidates inside
- one another, so I'll go with Firefox.
-
- listing and xmp work the same as pre in all browsers. For Firefox and Opera,
- this results in trying to put a br inside an xmp, so I go with IE/Chrome for
- xmp.
-
- TODO: In cases where hitting enter in a header doesn't break out of the
+ <li>
+ <div class=comments>
+ <p>IE9 and Chrome 13 dev just break <pre> up into multiple <pre>s.
+ Firefox 5.0a2 and Opera 11.10 insert a <br> instead, treating it
+ differently from <p>. The latter makes more sense. What might make the
+ most sense is to just insert an actual newline character, though, since this
+ is a pre after all . . .
+
+ <p>IE9 and Chrome 13 dev also break <address> up into multiple
+ <address>es. Firefox 5.0a2 inserts <br> instead. Opera 11.10 nests
+ <p>s inside. I don't like Opera's behavior, because it means we nest
+ formatBlock candidates inside one another, so I'll go with Firefox.
+
+ <p>listing and xmp work the same as pre in all browsers. For Firefox and
+ Opera, this results in trying to put a br inside an xmp, so I go with
+ IE/Chrome for xmp.
+
+ <p>TODO: In cases where hitting enter in a header doesn't break out of the
header, we should probably follow this code path too, instead of creating an
adjoining header. No browser does this, though, so we don't.
- -->
+ </div>
+
+ <p>If <var title="">container</var>'s <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 "address", "listing", or
+ "pre":
<ol>
<li>Let <var title="">br</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("br")</a></code> on
@@ -7424,22 +7453,26 @@
<li>Increment <var title="">range</var>'s <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-offset title=concept-boundary-point-offset>offsets</a>.
- <li>If <var title="">br</var> is the last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendant</a> of <var title="">container</var>,
+ <li>
+ <p class=comments>Necessary because adding a br to the end of a block
+ element does nothing if there wasn't one there already. A single newline
+ immediately preceding a block boundary does nothing.
+
+ <p>If <var title="">br</var> is the last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendant</a> of <var title="">container</var>,
let <var title="">br</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("br")</a></code> on the
<a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>, then call <code class=external data-anolis-spec=domrange title=dom-Range-insertNode><a href=http://html5.org/specs/dom-range.html#dom-range-insertnode>insertNode(<var title="">br</var>)</a></code> on
<var title="">range</var>.
- <!-- Necessary because adding a br to the end of a block element does
- nothing if there wasn't one there already. A single newline immediately
- preceding a block boundary does nothing. -->
<li>Abort these steps.
</ol>
- <li>If <var title="">container</var>'s <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 "li", "dt", or "dd"; and
+ <li>
+ <p class=comments>Including dt/dd here follows Firefox 5.0a2, as with the
+ special dt/dd handling below.
+
+ <p>If <var title="">container</var>'s <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 "li", "dt", or "dd"; and
either it has no <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>children</a> or it has a single <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> and that <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>
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>:
- <!-- Including dt/dd here follows Firefox 5.0a2, as with the special dt/dd
- handling below. -->
<ol>
<li><a href=#split-the-parent>Split the parent</a> of the one-<a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> list consisting of
@@ -7449,17 +7482,17 @@
<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("br")</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a> and append the result 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="">container</var>.
- <li>If <var title="">container</var> is a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code>, and it is not an
+ <li>
+ <p class=comments>Annoying hack to prevent the dl from being re-added when
+ fixing disallowed ancestors. In most cases we want a wrapper dl added, but
+ in two cases (delete and insertParagraph) we're actually trying to outdent
+ the list item. TODO: there might be a better way to do this.
+
+ <p>If <var title="">container</var> is a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code>, and it is not an
<a href=#allowed-child>allowed child</a> of any of its <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>ancestors</a> <a href=#in-the-same-editing-host>in the same
editing host</a>, <a href=#set-the-tag-name>set the tag name</a> of <var title="">container</var>
to the <a href=#default-single-line-container-name>default single-line container name</a> and let
<var title="">container</var> be the result.
- <!--
- Annoying hack to prevent the dl from being re-added when fixing disallowed
- ancestors. In most cases we want a wrapper dl added, but in two cases
- (delete and insertParagraph) we're actually trying to outdent the list
- item. There might be a better way to do this.
- -->
<li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of <var title="">container</var>.
@@ -7470,11 +7503,13 @@
the same as <var title="">range</var>'s, and whose <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> is
(<var title="">container</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="">container</var>).
- <!-- We don't want the start to be just inside a node, because if it is,
- we'll leave behind an empty element either in the new or old container.
- Clearly we don't want the start point to get any higher than the container
- itself, though. -->
- <li>While <var title="">new line range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is zero and its
+ <li>
+ <p class=comments>We don't want the start to be just inside a node, because
+ if it is, we'll leave behind an empty element either in the new or old
+ container. Clearly we don't want the start point to get any higher than the
+ container itself, though.
+
+ <p>While <var title="">new line range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is zero and its
<a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a> is not <var title="">container</var>, set its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> to
(<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> of <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a>, <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a>).
@@ -7486,22 +7521,27 @@
<li>Let <var title="">end of line</var> be true if <var title="">new line range</var> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained title=contained>contains</a> either nothing or a
single <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, and false otherwise.
- <li>If the <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> of <var title="">container</var> is "h1", "h2", "h3", "h4",
+ <li>
+ <p class=comments>IE9 makes a new header if there's a trailing <br>.
+ Firefox 5.0a2, Chrome 13 dev, and Opera 11.10 do not, and I follow them,
+ since it makes more sense (such a <br> is invisible).
+
+ <p>If the <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> of <var title="">container</var> is "h1", "h2", "h3", "h4",
"h5", or "h6", and <var title="">end of line</var> is true, let <var title="">new container
name</var> be the <a href=#default-single-line-container-name>default single-line container name</a>.
- <!-- IE9 makes a new header if there's a trailing <br>. Firefox 5.0a2,
- Chrome 13 dev, and Opera 11.10 do not, and I follow them, since it makes more
- sense (such a <br> is invisible). -->
-
- <li>Otherwise, if the <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> of <var title="">container</var> is "dt" and
+
+ <li>
+ <p class=comments>This step and the next follow Firefox 5.0a2. IE9 and
+ Chrome 13 dev act as though these two lines were not present (they clone the
+ existing element). Opera 11.10 nests a <p> inside. Firefox is the most
+ useful, assuming a definition list somehow winds up inside the content (like
+ via formatBlock).
+
+ <p>Otherwise, if the <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> of <var title="">container</var> is "dt" and
<var title="">end of line</var> is true, let <var title="">new container name</var> be "dd".
<li>Otherwise, if the <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> of <var title="">container</var> is "dd" and
<var title="">end of line</var> is true, let <var title="">new container name</var> be "dt".
- <!-- These two follow Firefox 5.0a2. IE9 and Chrome 13 dev act as though
- these two lines were not present (they clone the existing element). Opera
- 11.10 nests a <p> inside. Firefox is the most useful, assuming a definition
- list somehow winds up inside the content. -->
<li>Otherwise, let <var title="">new container name</var> be the <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> of
<var title="">container</var>.
@@ -7519,14 +7559,15 @@
<li>Let <var title="">contained nodes</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
line range</var>.
- <li>Let <var title="">frag</var> be the result of calling <code class=external data-anolis-spec=domrange title=dom-Range-extractContents><a href=http://html5.org/specs/dom-range.html#dom-range-extractcontents>extractContents()</a></code> on
+ <li>
+ <p class=comments>TODO: This blows up any ranges (other than the selection,
+ which we reset), and can alter non-editable nodes, and maybe other bad stuff.
+ May or may not be the best solution. The intermediate fragment is also
+ possibly black-box detectable by DOM mutation events, but I like to pretend
+ those don't exist.
+
+ <p>Let <var title="">frag</var> be the result of calling <code class=external data-anolis-spec=domrange title=dom-Range-extractContents><a href=http://html5.org/specs/dom-range.html#dom-range-extractcontents>extractContents()</a></code> on
<var title="">new line range</var>.
- <!--
- TODO: This blows up any ranges (other than the selection, which we reset),
- and can alter non-editable nodes, and maybe other bad stuff. May or may not
- be the best solution. The intermediate fragment is also probably black-box
- detectable by DOM mutation events, but I like to pretend those don't exist.
- -->
<li>Unset the <code class=external data-anolis-spec=html title="the id attribute"><a href=http://www.whatwg.org/html/#the-id-attribute>id</a></code> attribute (if any) of each <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code> <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendant</a> of
<var title="">frag</var> that is not in <var title="">contained nodes</var>.
@@ -7537,13 +7578,16 @@
<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("br")</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>, and append the result 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="">container</var>.
- <li>If <var title="">new container</var> has no <a href=#visible>visible</a> <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>children</a>,
+ <li>
+ <p class=comments>These two steps follow Firefox 5.0a2, Chrome 13 dev, and
+ Opera 11.10. IE9 instead inserts an &nbsp; which magically does not
+ appear in innerHTML. In all cases, the reason is that an empty block box in
+ CSS will have zero height, so the user won't be able to put the selection
+ cursor inside it.
+
+ <p>If <var title="">new container</var> has no <a href=#visible>visible</a> <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>children</a>,
call <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("br")</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>, and append the result
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 container</var>.
- <!-- These two steps follow Firefox 5.0a2, Chrome 13 dev, and Opera 11.10.
- IE9 instead inserts an which magically does not appear in innerHTML.
- In all cases, the reason is that an empty block box in CSS will have zero
- height, so the user won't be able to put the selection cursor inside it. -->
<li>Set 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> of <var title="">range</var> to (<var title="">new container</var>,
0).
@@ -7552,23 +7596,24 @@
<h3 id=the-inserttext-command><span class=secno>8.21 </span><dfn>The <code title="">insertText</code> command</dfn></h3>
-<!--
-Supported only by WebKit. Tests in other browsers were manual. In the manual
-tests, where the value was always "a", IE9 and Firefox 5.0a2 match the spec
-exactly as far as I can tell; Chrome 14 dev and Opera 11.11 might match it in
-theory, but normalize the selection first, so they don't match it in practice.
--->
-<p><a href=#action>Action</a>:
-
-<!--
-Non-breaking space fun! The issue: if the user hits space twice, they expect
-it to create two spaces, not collapse. Also, if they're at the beginning or
-end of a line and hit space, again, they expect it not to collapse. Since we
-don't want to require that all contenteditable element contents always be used
-only with white-space: pre-wrap, we need to convert to and from non-breaking
-spaces.
-
-But there's a catch: you can't just make spaces non-breaking willy-nilly,
+<div class=comments>
+<p>Supported only by WebKit. Tests in other browsers were manual.
+
+<p>TODO: This doesn't work well if the input contains things that aren't
+supposed to appear in HTML, like carriage returns or nulls. Nor is it going to
+work well if the current cursor position is in between two halves of a non-BMP
+character. This will result in unserializability. The current spec disregards
+this, as Chrome 14 dev does. (It's not relevant to other browsers, since they
+don't support this as a command.)
+
+<p>Important issue: non-breaking space fun! The issue: if the user hits space
+twice, they expect it to create two spaces, not collapse. Also, if they're at
+the beginning or end of a line and hit space, again, they expect it not to
+collapse. Since we don't want to require that all contenteditable element
+contents always be used only with white-space: pre-wrap, we need to convert to
+and from non-breaking spaces.
+
+<p>But there's a catch: you can't just make spaces non-breaking willy-nilly,
because that doesn't just stop the space from collapsing, it also prevents
breaking. (Chrome 14 dev actually cheats here: in contenteditable, it doesn't
collapse nbsp, but breaks after it like a regular space.) The upshot of this
@@ -7578,91 +7623,92 @@
goals when there are an even number of spaces to display is left as an exercise
for the reader.
-Browsers vary greatly in how they handle all this, of course!
-
-The basic philosophy of IE9 is that if you're inserting a space, and one or
+<p>Browsers vary greatly in how they handle all this, of course!
+
+<p>The basic philosophy of IE9 is that if you're inserting a space, and one or
both of the neighboring characters is a space, change the neighboring
characters to non-breaking spaces. This breaks if one of the neighboring
characters is part of a run of collapsed whitespace: "foo []bar" becomes "foo
- []bar", which converts one visible space to three.
-
-Firefox 6.0a2 will sometimes convert the space you're inserting to an nbsp,
+&nbsp; []bar", which converts one visible space to three.
+
+<p>Firefox 6.0a2 will sometimes convert the space you're inserting to an nbsp,
sometimes convert neighboring spaces to nbsps, and sometimes convert
neighboring nbsps to spaces. I cannot discern any clear reason to when it
chooses what, except that it seems to prefer runs of nbsp's followed by a
single space (although not always). I didn't find any outright bugs, except
the inevitable ones like nbsp's sometimes being right after letters.
-Chrome 14 dev tries to normalize everything to look like " ...",
-alternating with space then nbsp. Unfortunately, it does so buggily, because
-it converts collapsed spaces to nbsp's, so inserting a space before " " makes
-it into " ", which changes one visible space to four (or
-arbitrarily many).
-
-Opera 11.11 has varying behavior, like Firefox and Chrome. Like Firefox, I
+<p>Chrome 14 dev tries to normalize everything to look like " &nbsp;
+&nbsp; ...", alternating with space then nbsp. Unfortunately, it does so
+buggily, because it converts collapsed spaces to nbsp's, so inserting a space
+before " " makes it into " &nbsp; &nbsp;", which changes one visible
+space to four (or arbitrarily many).
+
+<p>Opera 11.11 has varying behavior, like Firefox and Chrome. Like Firefox, I
didn't discern an obvious pattern.
-This was discussed: http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-June/032187.html
-
-Unfortunately, we're stuck with this nbsp stuff, because of 1) legacy reasons,
-2) mail clients might not support CSS equivalents, 3) authors might not know to
-apply any CSS to wherever the content is eventually used. The behavior I
-decided on to minimize the evil is as follows:
-
-* If the first and last spaces are in non-collapsing positions, two spaces is
- nbsp+space, three is space+nbsp+space, four or more is space+nbsp followed by
- the pattern for two less.
-* If the first space has to be an nbsp so it doesn't collapse, three is instead
- nbsp+nbsp+space, four or more is nbsp+space followed by the pattern for two
- less.
-* If the last space has to be nbsp, two is space+nbsp, three is
+<p>This was all <a href=http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-June/032187.html>discussed</a>.
+
+<p>Unfortunately, we're stuck with this nbsp stuff, because of 1) legacy
+reasons, 2) mail clients might not support CSS equivalents, 3) authors might
+not know to apply any CSS to wherever the content is eventually used. The
+behavior I decided on to minimize the evil is as follows:
+
+<ul>
+ <li>If the first and last spaces are in non-collapsing positions, two spaces
+ is nbsp+space, three is space+nbsp+space, four or more is space+nbsp followed
+ by the pattern for two less.
+
+ <li>If the first space has to be an nbsp so it doesn't collapse, three is
+ instead nbsp+nbsp+space, four or more is nbsp+space followed by the pattern
+ for two less.
+
+ <li>If the last space has to be nbsp, two is space+nbsp, three is
space+nbsp+nbsp, four or more is space+nbsp followed by the pattern for two
less.
-* If the first and last space must both be nbsp, two is nbsp+nbsp, three is
+
+ <li>If the first and last space must both be nbsp, two is nbsp+nbsp, three is
nbsp+space+nbsp, four or more nbsp+space followed by the pattern for two
less.
-
-This avoids nbsp at the end of a run except where it's needed, so words won't
-appear indented if they wrap to the next line. It avoids more than two nbsp's
-in a row, so there won't be huge chunks of space that get wrapped all at once.
-And it avoids nbsp at the beginning of a run except where it's needed or
+</ul>
+
+<p>This avoids nbsp at the end of a run except where it's needed, so words
+won't appear indented if they wrap to the next line. It avoids more than two
+nbsp's in a row, so there won't be huge chunks of space that get wrapped all at
+once. And it avoids nbsp at the beginning of a run except where it's needed or
if there are only two spaces in the run, so words won't have to wrap
unnecessarily.
-This is still a huge headache, though.
--->
-
-<!--
-TODO: This doesn't work well if the input contains things that aren't supposed
-to appear in HTML, like carriage returns or nulls. Nor is it going to work
-well if the current cursor position is in between two halves of a non-BMP
-character. This will result in unserializability. The current spec disregards
-this, as Chrome 14 dev does.
--->
+<p>This is still a huge headache, though.
+</div>
+
+<p><a href=#action>Action</a>:
<ol>
- <li><a href=#delete-the-contents>Delete the contents</a> of the <a href=#active-range>active range</a>, with
- <var title="">strip wrappers</var> false.
- <!--
- Chrome 14 dev does the deletion even if the value is empty. Of course, other
- browsers don't expose this as an execCommand(), so no one else has any
+ <li>
+ <div class=comments>
+ <p>Chrome 14 dev does the deletion even if the value is empty. Of course,
+ other browsers don't expose this as an execCommand(), so no one else has any
defined behavior in this case at all, so I follow Chrome.
- IE9, Firefox 7.0a2, Chrome 14 dev, and Opera 11.50 all don't strip wrappers,
- except that as usual, Gecko does if you select the whole wrapper, like
- {<b>foo</b>}. Also, Chrome 14 dev seems to strip the wrapper and try
- recreating the style in cases like <b>[foo</b>bar], where it starts in a
- wrapper but ends after it; this doesn't always work so well, so I don't do
- it. Firefox 7.0a2 also has the deletion set overrides for indeterminate
- state commands, so if you run insertText on [foo<b>bar</b>baz] it will make
- the result bold.
-
- These things don't make any sense to me, so I don't do them. I set overrides
- based on the first editable text node in the range when deleting; preserve
- any wrappers at the start of the range; and restore the overrides in case
- preserving the wrappers isn't enough (like if they weren't set by deletion at
- all). This behavior seems to closely match IE9.
- -->
+ <p>IE9, Firefox 7.0a2, Chrome 14 dev, and Opera 11.50 all don't strip
+ wrappers, except that as usual, Gecko does if you select the whole wrapper,
+ like {<b>foo</b>}. Also, Chrome 14 dev seems to strip the wrapper and
+ try recreating the style in cases like <b>[foo</b>bar], where it starts
+ in a wrapper but ends after it; this doesn't always work so well, so I don't
+ do it. Firefox 7.0a2 also has the deletion set overrides for indeterminate
+ state commands, so if you run insertText on [foo<b>bar</b>baz] it will
+ make the result bold.
+
+ <p>These things don't make any sense to me, so I don't do them. I set
+ overrides based on the first editable text node in the range when deleting;
+ preserve any wrappers at the start of the range; and restore the overrides in
+ case preserving the wrappers isn't enough (like if they weren't set by
+ deletion at all). This behavior seems to closely match IE9.
+ </div>
+
+ <p><a href=#delete-the-contents>Delete the contents</a> of the <a href=#active-range>active range</a>, with
+ <var title="">strip wrappers</var> false.
<li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</a> is neither
<a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>, abort these steps.
@@ -7679,25 +7725,27 @@
<li>If <var title="">value</var> is the empty string, abort these steps.
- <li>If <var title="">value</var> is a newline (U+00A0), take the <a href=#action>action</a>
+ <li>
+ <p class=comments>TODO: WebKit also does magic for tabs, wrapping them in a
+ whitespace-preserving span. Should we?
+
+ <p>If <var title="">value</var> is a newline (U+00A0), take the <a href=#action>action</a>
for <a href=#the-insertparagraph-command>the <code title="">insertParagraph</code> command</a> and abort
these steps.
- <!-- TODO: WebKit also does magic for tabs, wrapping them in a
- whitespace-preserving span. Should we? -->
<li>Let <var title="">node</var> and <var title="">offset</var> be the <a href=#active-range>active
range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</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>node</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>offset</a>.
- <!--
- Just to be tidy, add to an existing text node if there is one. Firefox 5.0a2
- only adds to an existing one if the range is in a text node. IE9, Chrome 14
- dev, and Opera 11.11 also add to an existing text node if the range is in an
- element adjacent to a text node. If there are two text nodes and it's in
- between, like foo{}bar, IE and Opera add to the first, Chrome adds to the
- second, although it probably doesn't matter in practice exactly which we
- choose.
- -->
- <li>If <var title="">node</var> has a <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> whose <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> is <var title="">offset</var>
+ <li>
+ <p class=comments>Just to be tidy, add to an existing text node if there is
+ one. Firefox 5.0a2 only adds to an existing one if the range is in a text
+ node. IE9, Chrome 14 dev, and Opera 11.11 also add to an existing text node
+ if the range is in an element adjacent to a text node. If there are two text
+ nodes and it's in between, like foo{}bar, IE and Opera add to the first,
+ Chrome adds to the second, although it probably doesn't matter in practice
+ exactly which we choose.
+
+ <p>If <var title="">node</var> has a <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> whose <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> is <var title="">offset</var>
− 1, and that <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> is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node, set <var title="">node</var> to that
<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>, then set <var title="">offset</var> to <var title="">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>.
@@ -7705,12 +7753,15 @@
and that <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> is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node, set <var title="">node</var> to that <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>,
then set <var title="">offset</var> to zero.
- <li>If <var title="">value</var> is a space (U+0020), and either <var title="">node</var> is an
+ <li>
+ <p class=comments><var title="">value</var> may change back to a space when we
+ canonicalize, even if this step is triggered.
+
+ <p>If <var title="">value</var> is a space (U+0020), and either <var title="">node</var> is an
<code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code> whose <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> for "white-space" is neither "pre" nor
"pre-wrap" or <var title="">node</var> is not an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code> but 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> is an
<code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code> whose <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> for "white-space" is neither "pre" nor
"pre-wrap", set <var title="">value</var> to a non-breaking space (U+00A0).
- <!-- This may change to a space when we canonicalize. -->
<li><a href=#record-current-overrides>Record current overrides</a>, and let <var title="">overrides</var> be
the result.
@@ -7731,9 +7782,11 @@
<li>Otherwise:
<ol>
- <!-- If some text is inserted into <p><br></p> or similar, we no longer need
- the <br>. -->
- <li>If <var title="">node</var> has only one <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>, which is a <a href=#collapsed-line-break>collapsed
+ <li>
+ <p class=comments>If some text is inserted into <p><br></p> or
+ similar, we no longer need the <br>.
+
+ <p>If <var title="">node</var> has only one <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>, which is a <a href=#collapsed-line-break>collapsed
line break</a>, remove its <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> from it.
<li>Let <var title="">text</var> be the result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createTextNode><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createtextnode>createTextNode(<var title="">value</var>)</a></code> on
@@ -7762,6 +7815,8 @@
<h3 id=the-insertunorderedlist-command><span class=secno>8.22 </span><dfn>The <code title="">insertUnorderedList</code> command</dfn></h3>
+<p class=comments>See comments for <a href=#the-insertorderedlist-command>insertOrderedList</a>.
+
<p><a href=#action>Action</a>: <a href=#toggle-lists>Toggle lists</a> with <var title="">tag name</var>
"ul".
@@ -7777,64 +7832,66 @@
<p><a href=#action>Action</a>: <a href=#justify-the-selection>Justify the selection</a> with
<var title="">alignment</var> "center".
+<div class=comments>
+<p>This roughly matches Chrome 14 dev, although not exactly. Firefox 6.0a2
+always returns false.
+
+<p>As a general rule, ignoring nodes with children saves us from treating
+<div align=left><div align=center>foo</div></div> as though it's
+indeterminate. Chrome 14 dev seems to only pay attention to text nodes,
+instead, or something like that. At any rate, it fails on images. Firefox
+6.0a2 (for state and value) gets tripped up by examples like the one given.
+
+<p>If we ever support centering of tables and similar, we'd want to pay
+attention even to some nodes that do have children.
+</div>
+
<p><a href=#indeterminate>Indeterminate</a>: <a href=#block-extend>Block-extend</a> the <a href=#active-range>active
range</a>. Return true if among <a href=#visible>visible</a> <a href=#editable>editable</a>
<a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>nodes</a> that are <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in the result and have no <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>children</a>, at
least one has <a href=#alignment-value>alignment value</a> "center" and at least one does not.
Otherwise return false.
-<!--
-This roughly matches Chrome 14 dev, although not exactly. Firefox 6.0a2 always
-returns false.
-
-As a general rule, ignoring nodes with children saves us from treating <div
-align=left><div align=center>foo</div></div> as though it's indeterminate.
-Chrome 14 dev seems to only pay attention to text nodes, instead, or something
-like that. At any rate, it fails on images. Firefox 6.0a2 (for state and
-value) gets tripped up by examples like the one given.
-
-If we ever support centering of tables and similar, we'd want to pay attention
-even to some nodes that do have children.
--->
+
+<div class=comments>
+<p>IE9 throws exceptions in almost every case when querying the state of
+justify*, and Opera 11.11 returns false in every case except some seemingly
+random crazy ones.
+
+<p>Firefox 6.0a2 returns true for the state of justify* if anything in the
+range has the right alignment, not if everything does. This isn't consistent
+with how state works for the inline commands, nor with WebKit.
+
+<p>Chrome 14 dev counts text-align on inline elements, which is wrong, because
+the property has no effect. It also counts it on non-editable elements, which
+is wrong, because then the state for justify* wouldn't necessarily be true
+after executing it. (Chrome actually does align the non-editable elements, but
+that's just a bug.) Chrome further returns false for justify* if the
+justification is just the default inherited justification, e.g., left for LTR.
+This doesn't seem to make sense either.
+
+<p>State is kind of redundant here, because it's true if and only if
+indeterminate is false and the value is equal to the desired value. However,
+I'll support it anyway, since Gecko/WebKit do.
+</div>
<p><a href=#state>State</a>: <a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>.
Return true if there is at least one <a href=#visible>visible</a> <a href=#editable>editable</a>
<a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> that is <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in the result and has no <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>children</a>, and all
such <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> have <a href=#alignment-value>alignment value</a> "center". Otherwise return
false.
-<!--
-IE9 throws exceptions in almost every case when querying the state of justify*,
-and Opera 11.11 returns false in every case except some seemingly random crazy
-ones.
-
-Firefox 6.0a2 returns true for the state of justify* if anything in the range
-has the right alignment, not if everything does. This isn't consistent with
-how state works for the inline commands, nor with WebKit.
-
-Chrome 14 dev counts text-align on inline elements, which is wrong, because the
-property has no effect. It also counts it on non-editable elements, which is
-wrong, because then the state for justify* wouldn't necessarily be true after
-executing it. (Chrome actually does align the non-editable elements, but
-that's just a bug.) Chrome further returns false for justify* if the
-justification is just the default inherited justification, e.g., left for LTR.
-This doesn't seem to make sense either.
-
-State is kind of redundant here, because it's true if and only if indeterminate
-is false and the value is equal to the desired value. However, I'll support it
-anyway, since Gecko/WebKit do.
--->
+
+<p class=comments>Not bidi-safe, but it's a pretty marginal corner case where
+it fails. Firefox 6.0a2 behaves weirdly here: it keys off the start node of
+the active range, even if that's not contained. Thus {<div
+align=center>foo</div>} has value "left" and indeterminate false, which
+would suggest that the whole selection is aligned left, but that's not the
+case. Chrome 14 dev returns the state cast to a string, as usual. Opera 11.11
+always returns the empty string.
<p><a href=#value>Value</a>: <a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>,
and return the <a href=#alignment-value>alignment value</a> of the first <a href=#visible>visible</a>
<a href=#editable>editable</a> <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> that is <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in the result and has no
<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>children</a>. If there is no such <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a>, return "left".
-<!--
-Not bidi-safe, but it's a pretty marginal corner case. Firefox 6.0a2 behaves
-weirdly here: it keys off the start node of the active range, even if that's
-not contained. Thus {<div align=center>foo</div>} has value "left" and
-indeterminate false, which would suggest that the whole selection is aligned
-left, but that's not the case. Chrome 14 dev returns the state cast to a
-string, as usual. Opera 11.11 always returns the empty string.
--->
<h3 id=the-justifyfull-command><span class=secno>8.24 </span><dfn>The <code title="">justifyFull</code> command</dfn></h3>
@@ -7915,43 +7972,47 @@
<a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#ancestor-container title="ancestor container">ancestor containers</a> of the <a href=#active-range>active range</a>'s <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/or <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>node</a>.
- <li>For each <var title="">item</var> in <var title="">items</var>, <a href=#normalize-sublists>normalize
+ <li>
+ <p class=comments>TODO: This overnormalizes, but it seems like the simplest
+ solution for now.
+
+ <p>For each <var title="">item</var> in <var title="">items</var>, <a href=#normalize-sublists>normalize
sublists</a> of <var title="">item</var>.
- <!-- This overnormalizes, but it seems like the simplest solution for now.
- -->
<li><a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>, and let <var title="">new
range</var> be the result.
<li>Let <var title="">node list</var> be a list of <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>, initially empty.
- <li>For each <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <var title="">node</var> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in <var title="">new range</var>,
+ <li>
+ <div class=comments>
+ <p>This step is kind of weird. For regular outdenting, we start at the
+ inside and outdent going out, so that we remove the innermost indentation, on
+ the theory that that will produce the cleanest markup (remove the most
+ nodes). For lists, we remove the outermost indentation, because it makes a
+ difference whether we remove inner or outer indentation, and logically we
+ want to remove outer. E.g.,
+
+ <pre><ol><li>foo</li><ul><li>bar</li></ul></ol></pre>
+
+ <p>should become
+
+ <pre>foo<ul><li>bar</li></ul></pre>
+
+ <p>not
+
+ <pre>foo<ol><li>bar</li></ol>.</pre>
+
+ <p>But this is a bit weird and I'm wondering if it's really correct. TODO:
+ Reexamine this.
+ </div>
+
+ <p>For each <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <var title="">node</var> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in <var title="">new range</var>,
append <var title="">node</var> to <var title="">node list</var> if the last member of
<var title="">node list</var> (if any) is not an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var>;
<var title="">node</var> is <a href=#editable>editable</a>; and either <var title="">node</var> has no
<a href=#editable>editable</a> <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendants</a>, or is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, or is an
<code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> whose <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>.
- <!--
- This step is kind of weird. For regular outdenting, we start at the inside
- and outdent going out, so that we remove the innermost indentation, on the
- theory that that will produce the cleanest markup (remove the most nodes).
- For lists, we remove the outermost indentation, because it makes a difference
- whether we remove inner or outer indentation, and logically we want to remove
- outer. E.g.,
-
- <ol><li>foo</li><ul><li>bar</li></ul></ol>
-
- should become
-
- foo<ul><li>bar</li></ul>
-
- not
-
- foo<ol><li>bar</li></ol>.
-
- But this is a bit weird and I'm wondering if it's really correct. TODO:
- Reexamine this.
- -->
<li>While <var title="">node list</var> is not empty:
@@ -7989,17 +8050,12 @@
<h3 id=the-copy-command><span class=secno>9.1 </span><dfn>The <code title="">copy</code> command</dfn></h3>
-<!--
-IE9 supports copy/cut/paste with a security warning. Firefox reportedly only
-supports it if you set a pref. I didn't find info on other browsers, but in my
-tests it didn't do anything. I'm not going to try speccing it unless
-implementers are interested in working out the security problems and trying to
-get interop. It seems like as of June 2011, everyone just uses Flash for this:
-
-http://code.google.com/p/zeroclipboard/
-
-So it would be nice if we could work out a more secure standardized substitute.
--->
+<p class=comments>IE9 supports copy/cut/paste with a security warning. Firefox
+reportedly only supports it if you set a pref. I didn't find info on other
+browsers, but in my tests it didn't do anything. I'm not going to try speccing
+it unless implementers are interested in working out the security problems and
+trying to get interop. It seems like as of June 2011, everyone just <a href=http://code.google.com/p/zeroclipboard/>uses Flash for this</a>. So it
+would be nice if we could work out a more secure standardized substitute.
<p><a href=#action>Action</a>: The user agent must either copy the current selection
to the clipboard as though the user had requested it, or raise a
@@ -8011,23 +8067,22 @@
because sites could abuse it to confuse and annoy the user by overwriting the
clipboard with extremely long, obscene, or otherwise objectionable content.
+<p class=comments>The idea is sites might catch the SECURITY_ERR and treat it
+differently from NOT_SUPPORTED_ERR, like encouraging users to reconfigure their
+browser. However, browsers might not want to encourage authors to tell users
+to reconfigure their browser insecurely.
+
<p>User agents may choose not to <a href=#supported title=supported>support</a> this
<a href=#command>command</a> at all. If a user agent will only honor the
<a href=#command>command</a> for some whitelisted sites depending on configuration, it
may either raise a <code class=external data-anolis-spec=domcore title=dom-DOMException-SECURITY_ERR><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-security_err>SECURITY_ERR</a></code> for non-whitelisted sites, or it may act as
though the <a href=#command>command</a> is <a href=#supported title=supported>unsupported</a> on
those sites.
-<!--
-The idea is sites might catch the SECURITY_ERR and treat it differently from
-NOT_SUPPORTED_ERR, like encouraging users to reconfigure their browser.
-However, browsers might not want to encourage authors to tell users to
-reconfigure their browser insecurely.
--->
<h3 id=the-cut-command><span class=secno>9.2 </span><dfn>The <code title="">cut</code> command</dfn></h3>
-<!-- See comment for copy -->
+<p class=comments>See comment for <a href=#the-copy-command>copy</a>.
<p><a href=#action>Action</a>: The user agent must either copy the current selection
to the clipboard and then delete it, as though the user had requested it, or
@@ -8049,7 +8104,7 @@
<h3 id=the-paste-command><span class=secno>9.3 </span><dfn>The <code title="">paste</code> command</dfn></h3>
-<!-- See comment for copy -->
+<p class=comments>See comment for <a href=#the-copy-command>copy</a>.
<p><a href=#action>Action</a>: The user agent must either <a href=#delete-the-contents>delete the
contents</a> of the <a href=#active-range>active range</a> and then paste the clipboard's
@@ -8071,44 +8126,51 @@
<h3 id=the-selectall-command><span class=secno>9.4 </span><dfn>The <code title="">selectAll</code> command</dfn></h3>
-<!--
-Tested using roughly this:
-
-http://software.hixie.ch/utilities/js/live-dom-viewer/saved/1018
-
-IE9: A bit confusing. The gist seems to be that it does selectAllChildren() on
-the body, except sometimes it doesn't.
-
-Firefox 5.0a2: Throws an exception if nothing in the document is editable,
-which apparently it always does for execCommand(). If there's a body, it does
-selectAllChildren() on that, and otherwise it does selectAllChildren() on the
-root element. If there's no root element, throws an exception.
-
-Chrome 13 dev: If there's no root element, removes the selection. If there's
-a root element but no body, collapses the selection at (document, 0). If
-there's a body, it selects all the contents of the body, although that doesn't
-mean the resulting anchor or focus actually are the body node (they're usually
-text nodes). But it seems to *avoid* selecting contenteditable stuff: if all
-the visible things in the body are contenteditable, it removes all ranges from
-the selection, and if some are, it freaks out and behaves oddly. But
-designMode doesn't trouble it.
-
-Opera 11.11: Was characteristically uncooperative in my tests, and I didn't try
-to investigate further.
-
-The behavior here is relatively simple and largely matches implementations.
--->
+<div class=comments>
+<p>Tested using roughly <a href=http://software.hixie.ch/utilities/js/live-dom-viewer/saved/1018>this</a>.
+
+<dl>
+ <dt>IE9
+ <dd>A bit confusing. The gist seems to be that it does selectAllChildren()
+ on the body, except sometimes it doesn't.
+
+ <dt>Firefox 5.0a2
+ <dd>Throws an exception if nothing in the document is editable, which
+ apparently it always does for execCommand(). If there's a body, it does
+ selectAllChildren() on that, and otherwise it does selectAllChildren() on the
+ root element. If there's no root element, throws an exception.
+
+ <dt>Chrome 13 dev
+ <dd>If there's no root element, removes the selection. If there's a root
+ element but no body, collapses the selection at (document, 0). If there's a
+ body, it selects all the contents of the body, although that doesn't mean the
+ resulting anchor or focus actually are the body node (they're usually text
+ nodes). But it seems to *avoid* selecting contenteditable stuff: if all the
+ visible things in the body are contenteditable, it removes all ranges from
+ the selection, and if some are, it freaks out and behaves oddly. But
+ designMode doesn't trouble it.
+
+ <dt>Opera 11.11
+ <dd>Was characteristically uncooperative in my tests, and I didn't try to
+ investigate further.
+</dl>
+
+<p>The behavior here is relatively simple and largely matches implementations.
+</div>
<p><a href=#action>Action</a>:
<ol>
- <li>Let <var title="">target</var> be <a class=external data-anolis-spec=html href=http://www.whatwg.org/html/#the-body-element-0 title=the-body-element-0>the body element</a> of the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>.
- <!-- TODO: Is this right even for framesets? -->
-
- <li>If <var title="">target</var> is null, let <var title="">target</var> be the
+ <li>
+ <p class=comments>TODO: Is this right even for framesets?
+
+ <p>Let <var title="">target</var> be <a class=external data-anolis-spec=html href=http://www.whatwg.org/html/#the-body-element-0 title=the-body-element-0>the body element</a> of the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>.
+
+ <p class=comments>TODO: Is this right even for documents whose root element
+ is not an HTML element?
+
+ <p>If <var title="">target</var> is null, let <var title="">target</var> be the
<a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domcore title=dom-Document-documentElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-documentelement>documentElement</a></code>.
- <!-- TODO: Is this right even for documents whose root element is not an HTML
- element? -->
<li>If <var title="">target</var> is null, call <code class=external data-anolis-spec=domrange title=dom-Document-getSelection><a href=http://html5.org/specs/dom-range.html#dom-document-getselection>getSelection()</a></code> on the
<a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>, and call <code class=external data-anolis-spec=domrange title=dom-Selection-removeAllRanges><a href=http://html5.org/specs/dom-range.html#dom-selection-removeallranges>removeAllRanges()</a></code> on the result.
@@ -8120,40 +8182,43 @@
<h3 id=the-stylewithcss-command><span class=secno>9.5 </span><dfn>The <code title="">styleWithCSS</code> command</dfn></h3>
-<!-- IE9 and Opera 11.00 don't support this command. By and large, they act
-the way Gecko and WebKit do when styleWithCSS is off. Gecko invented it, and
-WebKit also supports it:
-
-https://bugs.webkit.org/show_bug.cgi?id=13490
-
-The default in Firefox 4.0 is off, while all other browsers behave like the
-default is on (and IE/Opera give no way to turn it off), so I default it to on.
--->
+<div class=comments>
+<p>IE9 and Opera 11.00 don't support this command. By and large, they act the
+way Gecko and WebKit do when styleWithCSS is off. Gecko invented it, and
+WebKit also <a href="https://bugs.webkit.org/show_bug.cgi?id=13490">supports</a>
+it. The default in Firefox 4.0 is off, while all other browsers behave like
+the default is on (and IE/Opera give no way to turn it off), so I default it to
+on.
+
+<p>Handling of <var title="">value</var> matches Firefox 5.0a2. Chrome 13 dev treats
+the case-sensitive string "true" as true, the case-sensitive string "false" as
+false, and does nothing for any other string. I went with Gecko because this
+way there are only two possible effects, not three, which makes it easier to
+reason about and debug. Also, Gecko made up the command, so this is probably
+more web-compatible. Cursory searches of Google Code and GitHub suggest that
+authors almost always pass a boolean as the third argument when using
+styleWithCSS, in which case the two behaviors work the same.
+</div>
<p><a href=#action>Action</a>: If <var title="">value</var> is an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#ascii-case-insensitive>ASCII case-insensitive</a> match for the string
"false", set the <a href=#css-styling-flag>CSS styling flag</a> to false. Otherwise, set the
<a href=#css-styling-flag>CSS styling flag</a> to true.
-<!-- This matches Firefox 5.0a2. Chrome 13 dev treats the case-sensitive
-string "true" as true, the case-sensitive string "false" as false, and does
-nothing for any other string. I went with Gecko because this way there are
-only two possible effects, not three, which makes it easier to reason about and
-debug. Also, Gecko made up the command and has larger market share, so this is
-probably more web-compatible. Cursory searches of Google Code and GitHub
-suggest that authors almost always pass a boolean as the third argument when
-using styleWithCSS, in which case the two behaviors work the same. -->
+
+<p class=comments>This follows Chrome 13 dev. Firefox 5.0a2 doesn't support
+queryCommandState() for styleWithCSS.
<p><a href=#state>State</a>: True if the <a href=#css-styling-flag>CSS styling flag</a> is true,
otherwise false.
-<!-- This follows Chrome 13 dev. Firefox 5.0a2 doesn't support
-queryCommandState() for styleWithCSS. -->
<h3 id=the-usecss-command><span class=secno>9.6 </span><dfn>The <code title="">useCSS</code> command</dfn></h3>
-<!-- Supported by Firefox 4.0, but not IE9 or Opera 11.00 (which don't support
-styleWithCSS either), nor by Chrome 12 dev (which does support styleWithCSS.
-useCSS was the original feature in Mozilla 1.3, but the meaning is backward, so
-Gecko added styleWithCSS as a replacement. -->
+<p class=comments>Supported by Firefox 4.0, but not IE9 or Opera 11.00 (which
+don't support styleWithCSS either), nor by Chrome 12 dev (which does support
+styleWithCSS). useCSS was the original feature in Mozilla 1.3, but the meaning
+is backward, so Gecko added styleWithCSS as a replacement. No state is
+defined, since only Gecko supports useCss at all, and as of Firefox 6.0a2, it
+doesn't support queryCommandState() for it.
<p><a href=#action>Action</a>: If <var title="">value</var> is an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#ascii-case-insensitive>ASCII case-insensitive</a> match for the string
"false", set the <a href=#css-styling-flag>CSS styling flag</a> to true. Otherwise, set the
@@ -8169,9 +8234,6 @@
it. It would be great if Gecko would agree to drop support, so that we could
get rid of it.
-<!-- No state defined, since only Gecko supports useCss at all, and as of
-Firefox 6.0a2, it doesn't support queryCommandState() for it. -->
-
<h2 id=additional-requirements><span class=secno>10 </span>Additional requirements</h2>
--- a/source.html Tue Aug 02 14:29:11 2011 -0600
+++ b/source.html Tue Aug 02 14:59:25 2011 -0600
@@ -112,10 +112,10 @@
<p>Where the reasoning behind the specification is of interest, such as when
major preexisting rendering engines are known not to match it, the reasoning is
-included in HTML comments so as not to distract the reader. If you have
-questions about why the specification says something, check for comments in the
-source first. They're sometimes longer than the specification text itself, and
-commonly record what the major browsers do and other essential information.
+available by clicking the "comments" button on the right (requires JavaScript).
+If you have questions about why the specification says something, check the
+comments first. They're sometimes longer than the specification text itself,
+and commonly record what the major browsers do and other essential information.
<p>The principles I've used for writing this specification so far are:
@@ -242,87 +242,97 @@
<p class=XXX>A variety of other issues are also noted in the text, formatted
like this. Feedback would be appreciated on all of them.
-<p>Things that would be useful to address for the future but aren't important
-to fix right now are in comments prefixed with "TODO".
-
-<!--
-TODO:
-
-* Scour browser bug trackers to try spotting issues I haven't thought of.
-
-* The wording I use for DOM stuff is not maximally precise. Really I want DOM
- Core to define nice concepts that I can xref, like "insert a node". I
+<div class=comments>
+<p>TODO:
+
+<ul>
+ <li>Scour browser bug trackers to try spotting issues I haven't thought of.
+
+ <li>The wording I use for DOM stuff is not maximally precise. Really I want
+ DOM Core to define nice concepts that I can xref, like "insert a node". I
don't want to have to explicitly refer to DOM methods like insertBefore()
every time I want to move things.
-* JavaScript can modify the DOM synchronously in some cases, such as DOM
+ <li>JavaScript can modify the DOM synchronously in some cases, such as DOM
mutation events and onunload when moving around iframes and objects. This
has to be dealt with somehow. (Pointed out by Ryosuke Niwa of WebKit:
- http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-March/030730.html
- http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-March/030751.html)
-
-* What happens if you do something like delete a selection or insert text or
+ <a href=http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-March/030730.html>1</a>
+ <a href=http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-March/030751.html>2</a>)
+
+ <li>What happens if you do something like delete a selection or insert text or
whatnot in the middle of a surrogate pair? This could make the content not
serialize through a character encoding change.
-* Probably need to record and restore overrides in some more places.
-
-* Some more thought needs to go into what happens to the selection when you
+ <li>Probably need to record and restore overrides in some more places.
+
+ <li>Some more thought needs to go into what happens to the selection when you
mutate the DOM. In some cases the results are pretty arbitrary. It might
make sense to do some kind of normalization.
-* I'm sloppy about handling things like nodes that don't descend from a
+ <li>I'm sloppy about handling things like nodes that don't descend from a
Document, comments that are children of a Document, that sort of thing. Not
essential for prototyping, but needs to be cleaned up eventually. Mostly we
should be able to avoid the problems by requiring that everything be
editable, since that immediately means it has to descend from an element or
Document (and cannot be parentless itself).
-* I need to pay more attention to invisible nodes. These will have no visual
+ <li>I need to pay more attention to invisible nodes. These will have no visual
effect, but they'll make many algorithms behave differently: decomposing a
range, block-extending, etc. Also, need to improve the definition to include
things like whitespace-only nodes.
-* Have to make sure that in all the places where we set a selection, it's
+ <li>Have to make sure that in all the places where we set a selection, it's
valid.
-* Redefine things in terms of ranges, not selections.
-
-* Allow some type of switch to affect non-editable regions too, perhaps on a
+ <li>Redefine things in terms of ranges, not selections.
+
+ <li>Allow some type of switch to affect non-editable regions too, perhaps on a
per-command basis.
--->
-
-<!--
-TODO: Things that are only implemented by a couple of browsers and may or may
-not be useful to spec:
-
-* decreaseFontSize, increaseFontSize: Only implemented in Gecko and Opera.
-* contentReadOnly, enableInlineTableEditing, enableObjectResizing, heading,
+</ul>
+
+<p>Also TODO: Things that are only implemented by a couple of browsers and may
+or may not be useful to spec:
+
+<ul>
+ <li>decreaseFontSize, increaseFontSize: Only implemented in Gecko and Opera.
+
+ <li>contentReadOnly, enableInlineTableEditing, enableObjectResizing, heading,
insertBrOnReturn: MDC docs say not implemented in IE (didn't test).
-* readOnly: MDC docs say it's a deprecated equivalent of contentReadOnly, so
- presumably like useCSS but less popular.
-* 2D-Position, absolutePosition, clearAuthenticationCache, createBookmark,
+
+ <li>readOnly: MDC docs say it's a deprecated equivalent of contentReadOnly,
+ so presumably like useCSS but less popular.
+
+ <li>2D-Position, absolutePosition, clearAuthenticationCache, createBookmark,
insertButton, insertFieldset, insertIframe, insertInput*, insertMarquee,
insertSelectDropdown, insertSelectListbox, insertTextarea, liveResize,
multipleSelection, overwrite, print, refresh, saveAs, unbookmark: Mentioned
in MSDN docs but not MDC, so presumably IE-only. Some of these seem
inappropriate or useless, others will bear investigation.
-* findString, fontSizeDelta, insertNewlineInQuotedContent, justifyNone, print,
- transpose: There's code for these in WebKit,
+
+ <li>findString, fontSizeDelta, insertNewlineInQuotedContent, justifyNone,
+ print, transpose: There's code for these in WebKit,
Source/WebCore/editing/EditorCommand.cpp, but I didn't see them mentioned
elsewhere. Some might be worth adding.
-* unselect: Seems to not be implemented by Gecko or Opera, and IE behaves
+
+ <li>unselect: Seems to not be implemented by Gecko or Opera, and IE behaves
oddly: it seems to collapse the selection instead of removing it. Will only
implement if there seems to be demand; it's redundant to
Selection.removeAllRanges() anyway.
-
-Things I haven't looked at that multiple browsers implement:
-
-* redo, undo: Needs review of the Google work on this; will probably be
+</ul>
+
+<p>Things I haven't looked at that multiple browsers implement:
+
+<ul>
+ <li>redo, undo: Needs review of the Google work on this; will probably be
quite complicated.
-
-Also need to look at contenteditable=plaintext-only.
--->
+</ul>
+
+<p>Also need to look at contenteditable=plaintext-only.
+</div>
+
+<p>Things that would be useful to address for the future but aren't important
+to fix right now are in comments prefixed with "TODO".
+
<!-- @} -->
<h2>Commands</h2>
@@ -7169,50 +7179,57 @@
<p><span>Action</span>:
<ol>
- <li>If <var>value</var> is the empty string, abort these steps and do
+ <li>
+ <p class=comments>Similar logic to createLink, except even more compelling,
+ since an HTML document linking to itself as an image is just silly. In fact,
+ the current HTML spec instructs UAs to not even try displaying the image, and
+ just fail immediately if the URL is empty. Firefox 4b11 silently does
+ nothing on an empty string, but the other three browsers I tested stick in
+ the <img> anyway.
+
+ <p>If <var>value</var> is the empty string, abort these steps and do
nothing.
- <!-- Similar logic to createLink, except even more compelling, since an HTML
- document linking to itself as an image is just silly. In fact, the current
- HTML spec instructs UAs to not even try displaying the image, and just fail
- immediately if the URL is empty. Firefox 4b11 silently does nothing on an
- empty string, but the other three browsers I tested stick in the <img>
- anyway. -->
<li>Let <var>range</var> be the <span>active range</span>.
- <li><span>Delete the contents</span> of <var>range</var>, with <var>strip
+ <li>
+ <p class=comments>Firefox 7.0a2 seems to strip the wrapper or not depending
+ on the exact positioning of the selection: <b>{foo}</b> yes,
+ <b>[foo]</b> no. Chrome 14 dev seems to strip the wrapper regardless.
+ Opera 11.50 seems to keep the wrapper, but place the image outside it. I
+ didn't get IE to cooperate with my tests. I chose to leave wrappers across
+ the board because they might be meaningful: e.g., a background-color when the
+ image is small or not fully opaque.
+
+ <p><span>Delete the contents</span> of <var>range</var>, with <var>strip
wrappers</var> false.
- <!--
- Firefox 7.0a2 seems to strip the wrapper or not depending on the exact
- positioning of the selection: <b>{foo}</b> yes, <b>[foo]</b> no. Chrome 14
- dev seems to strip the wrapper regardless. Opera 11.50 seems to keep the
- wrapper, but place the image outside it. I didn't get IE to cooperate with
- my tests. I chose to leave wrappers across the board because they might be
- meaningful: e.g., a background-color when the image is small or not fully
- opaque.
- -->
<li>If the <span>active range</span>'s [[startnode]] is neither
<span>editable</span> nor an <span>editing host</span>, abort these steps.
- <li>If <var>range</var>'s [[startnode]] is a <span>block node</span> whose
+ <li>
+ <p class=comments>Same logic as with insertHTML.
+
+ <p>If <var>range</var>'s [[startnode]] is a <span>block node</span> whose
sole [[child]] is a [[br]], and its [[startoffset]] is 0, remove its
[[startnode]]'s [[child]] from it.
- <!-- Same logic as with insertHTML. -->
<li>Let <var>img</var> be the result of calling [[createelement|"img"]] on
the [[contextobject]].
- <li>Run [[setattribute|"src", <var>value</var>]] on <var>img</var>.
- <!-- No alt text, so it's probably invalid. This matches all browsers. -->
-
- <li>Run [[insertnode|<var>img</var>]] on <var>range</var>.
- <!--
- This winds up putting it at the original start point of the active range, as
- currently specced. This matches IE9 and Firefox 5.0a2. Chrome 13 dev puts
- it at the end point, and Opera 11.11 puts it in between (where the range
- would collapse if you called deleteContents()).
- -->
+ <li>
+ <p class=comments>No alt text, so it's probably invalid. This matches all
+ browsers.
+
+ <p>Run [[setattribute|"src", <var>value</var>]] on <var>img</var>.
+
+ <li>
+ <p class=comments>This winds up putting it at the original start point of the
+ active range, as currently specced. This matches IE9 and Firefox 5.0a2.
+ Chrome 13 dev puts it at the end point, and Opera 11.11 puts it in between
+ (where the range would collapse if you called deleteContents()).
+
+ <p>Run [[insertnode|<var>img</var>]] on <var>range</var>.
<li>Let <var>selection</var> be the result of calling [[getselection]] on the
[[contextobject]].
@@ -7225,48 +7242,53 @@
<!-- @} -->
<h3><dfn>The <code title>insertLineBreak</code> command</dfn></h3>
<!-- @{ -->
-<p><span>Action</span>:
-
-<!--
-Only implemented in WebKit (Chrome 14 dev). Other tests are entirely manual.
+<div class=comments>
+<p>Only implemented in WebKit (Chrome 14 dev). Other tests are entirely
+manual (i.e., actually hitting Shift-Enter instead of running a command).
There's a surprisingly large amount of interop.
-IE9 is tripped up by <xmp>, and also often doesn't add an extra <br> when the
-one it just inserted is extraneous.
-
-Firefox 6.0a2 doesn't notice if you're trying to put the <br> in a bad place,
-which can result in unserializable DOMs.
-
-Chrome 14 dev inserts a literal linebreak for pre and xmp and maybe other
+<p>IE9 is tripped up by <xmp>, and also often doesn't add an extra <br>
+when the one it just inserted is extraneous.
+
+<p>Firefox 6.0a2 doesn't notice if you're trying to put the <br> in a bad
+place, which can result in unserializable DOMs.
+
+<p>Chrome 14 dev inserts a literal linebreak for pre and xmp and maybe other
similar elements. This doesn't seem very useful, so I don't bother.
-Opera 11.11 isn't heedful of <xmp>, and treats <pre> somewhat oddly.
--->
+<p>Opera 11.11 isn't heedful of <xmp>, and treats <pre> somewhat oddly.
+</div>
+
+<p><span>Action</span>:
<ol>
- <li><span>Delete the contents</span> of the <span>active range</span>, with
+ <li>
+ <p class=comments>IE9 doesn't strip wrappers (IE10PP2 didn't work in tests).
+ Firefox 7.0a2 strips wrappers inconsistently depending on the exact selection
+ endpoints. Chrome 14 dev strips wrappers but recreates any styles using new
+ wrappers. Opera 11.50 strips all wrappers.
+
+ <p><span>Delete the contents</span> of the <span>active range</span>, with
<var>strip wrappers</var> false.
- <!--
- IE9 doesn't strip wrappers (IE10PP2 didn't work in tests). Firefox 7.0a2
- strips wrappers inconsistently depending on the exact selection endpoints.
- Chrome 14 dev strips wrappers but recreates any styles using new wrappers.
- Opera 11.50 strips all wrappers.
- -->
<li>If the <span>active range</span>'s [[startnode]] is neither
<span>editable</span> nor an <span>editing host</span>, abort these steps.
- <li>If the <span>active range</span>'s [[startnode]] is an [[element]], and
+ <li>
+ <p class=comments>script, xmp, table, . . .
+
+ <p>If the <span>active range</span>'s [[startnode]] is an [[element]], and
"br" is not an <span>allowed child</span> of it, abort these steps.
- <!-- script, xmp, table, . . . -->
<li>If the <span>active range</span>'s [[startnode]] is not an [[element]],
and "br" is not an <span>allowed child</span> of the <span>active
range</span>'s [[startnode]]'s [[parent]], abort these steps.
- <!-- We don't want to call insertNode at the start or end of a text node,
- because that will leave an empty text node. -->
- <li>If the <span>active range</span>'s [[startnode]] is a [[text]] node and
+ <li>
+ <p class=comments>We don't want to call insertNode at the start or end of a
+ text node, because that will leave an empty text node.
+
+ <p>If the <span>active range</span>'s [[startnode]] is a [[text]] node and
its [[startoffset]] is zero, set the <span>active range</span>'s
[[rangestart]] and [[rangeend]] to ([[parent]] of [[startnode]], [[index]] of
[[startnode]]).
@@ -7297,46 +7319,47 @@
<p><span>Action</span>: <span>Toggle lists</span> with <var>tag name</var>
"ol".
+<p class=comments>Firefox 6.0a2 sort of supports this, but it throws exceptions
+most of the time. It has the quirk that even if there are no ol's around, it
+will say it's indeterminate if there are some things that are ul's and some
+that are not lists at all, but this doesn't make sense and I don't duplicate
+it. No one else supports indeterminate for insert*List, but it makes sense if
+you support state.
+
<p><span>Indeterminate</span>: True if the <span>selection's list state</span>
is "mixed" or "mixed ol", false otherwise.
-<!--
-Firefox 6.0a2 sort of supports this, but it throws exceptions most of the
-time. It has the quirk that even if there are no ol's around, it will say it's
-indeterminate if there are some things that are ul's and some that are not
-lists at all, but this doesn't make sense and I don't duplicate it. No one
-else supports indeterminate for insert*List, but it makes sense if you support
-state.
--->
+
+<p class=comments>IE9 throws exceptions in most cases, Firefox 6.0a2 in some
+cases as well, for no apparent reason. Ignoring those, the spec basically
+matches all browsers, except with a few weird random mismatches that looked
+like browser bugs to me.
<p><span>State</span>: True if the <span>selection's list state</span> is "ol",
false otherwise.
-<!--
-IE9 throws exceptions in most cases, Firefox 6.0a2 in some cases as well, for
-no apparent reason. Ignoring those, the spec basically matches all browsers,
-except with a few weird random mismatches that looked like browser bugs to me.
--->
<!-- @} -->
<h3><dfn>The <code title>insertParagraph</code> command</dfn></h3>
<!-- @{ -->
-<!--
-There are three major behaviors here. Firefox 5.0a2 behaves identically to
+<div class=comments>
+<p>There are three major behaviors here. Firefox 5.0a2 behaves identically to
execCommand("formatBlock", false, "p"), which is not really useful. IE9
actually just overwrites the selection with an empty paragraph element, which
seems not very useful either. Chrome 13 dev and Opera 11.10 behave basically
the same as if the user hit the Return key. This latter behavior seems much
more useful, even though it's horribly misnamed, so it's what I'll spec.
-
-(Actually, Opera doesn't behave quite the same for insertParagraph and line
+Comments about IE/Firefox are based on manual tests, where I hit Enter instead
+of running commands.
+
+<p>(Actually, Opera doesn't behave quite the same for insertParagraph and line
breaks. But it's pretty close, and I expect the differences are bugs.)
-Then, of course, we have several flavors of line-breaking behavior to choose
-from. Firefox prefers <br>s, unless it's in the middle of a <p> or something.
-Opera and IE like <p>. Chrome prefers <div>. And there are lots of subtleties
-besides. I go with IE/Opera-style behavior, as discussed in this thread:
-
-http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2011-May/031577.html
--->
+<p>Then, of course, we have several flavors of line-breaking behavior to choose
+from. Firefox prefers <br>s, unless it's in the middle of a <p> or
+something. Opera and IE like <p>. Chrome prefers <div>. And there are
+lots of subtleties besides. I go with IE/Opera-style behavior, as discussed in
+<a href=http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2011-May/031577.html>a
+whatwg thread</a>.
+</div>
<p><span>Action</span>:
@@ -7373,10 +7396,12 @@
the same editing host</span> as <var>node</var>, set <var>container</var> to
its [[parent]].
- <li>If <var>container</var> is not <span>editable</span> or not <span>in the
+ <li>
+ <p class=comments>We add the default wrapper in this case.
+
+ <p>If <var>container</var> is not <span>editable</span> or not <span>in the
same editing host</span> as <var>node</var> or is not a <span>single-line
container</span>:
- <!-- Add the default wrapper. -->
<ol>
<li>Let <var>tag</var> be the <span>default single-line container
@@ -7394,12 +7419,14 @@
<li>If <var>node list</var> is empty:
<ol>
- <!-- Ideally, we should normalize things so that the cursor is never in a
- weird place after deletion, but let's be safe and bail out if we do hit
- this scenario. It's not clear if we need this line in the long term, but
- at the time of this writing there's at least one corner case where
- deleting can leave the cursor inside a <tr>. -->
- <li>If <var>tag</var> is not an <span>allowed child</span> of
+ <li>
+ <p class=comments>Ideally, we should normalize things so that the cursor
+ is never in a weird place after deletion, but let's be safe and bail out
+ if we do hit this scenario. It's not clear if we need this line in the
+ long term, but at the time of this writing there's at least one corner
+ case where deleting can leave the cursor inside a <tr>.
+
+ <p>If <var>tag</var> is not an <span>allowed child</span> of
<var>range</var>'s [[startnode]], abort these steps.
<li>Set <var>container</var> to the result of calling
@@ -7416,14 +7443,14 @@
<li>Abort these steps.
</ol>
- <li>While the [[nextsibling]] of the last member of <var>node list</var> is
+ <li>
+ <p class=comments>TODO: It is not at all obvious that this is the correct
+ list of nodes in all cases. It should probably work because of how the
+ block-extend algorithm works, but further thought would be good.
+
+ <p>While the [[nextsibling]] of the last member of <var>node list</var> is
not null and is an <span>allowed child</span> of "p", append it to
<var>node list</var>.
- <!--
- TODO: It is not at all obvious that this is the correct list of nodes in
- all cases. It should probably work because of how the block-extend
- algorithm works, but further thought would be good.
- -->
<li><span>Wrap</span> <var>node list</var>, with <span>sibling
criteria</span> matching nothing and <span>new parent instructions</span>
@@ -7431,28 +7458,30 @@
[[contextobject]]. Set <var>container</var> to the result.
</ol>
- <li>If <var>container</var>'s [[localname]] is "address", "listing", or
- "pre":
- <!--
- IE9 and Chrome 13 dev just break <pre> up into multiple <pre>s. Firefox
- 5.0a2 and Opera 11.10 insert a <br> instead, treating it differently from
- <p>. The latter makes more sense. What might make the most sense is to just
- insert an actual newline character, though, since this is a pre after all
- . . .
-
- IE9 and Chrome 13 dev also break <address> up into multiple <address>es.
- Firefox 5.0a2 inserts <br> instead. Opera 11.10 nests <p>s inside. I don't
- like Opera's behavior, because it means we nest formatBlock candidates inside
- one another, so I'll go with Firefox.
-
- listing and xmp work the same as pre in all browsers. For Firefox and Opera,
- this results in trying to put a br inside an xmp, so I go with IE/Chrome for
- xmp.
-
- TODO: In cases where hitting enter in a header doesn't break out of the
+ <li>
+ <div class=comments>
+ <p>IE9 and Chrome 13 dev just break <pre> up into multiple <pre>s.
+ Firefox 5.0a2 and Opera 11.10 insert a <br> instead, treating it
+ differently from <p>. The latter makes more sense. What might make the
+ most sense is to just insert an actual newline character, though, since this
+ is a pre after all . . .
+
+ <p>IE9 and Chrome 13 dev also break <address> up into multiple
+ <address>es. Firefox 5.0a2 inserts <br> instead. Opera 11.10 nests
+ <p>s inside. I don't like Opera's behavior, because it means we nest
+ formatBlock candidates inside one another, so I'll go with Firefox.
+
+ <p>listing and xmp work the same as pre in all browsers. For Firefox and
+ Opera, this results in trying to put a br inside an xmp, so I go with
+ IE/Chrome for xmp.
+
+ <p>TODO: In cases where hitting enter in a header doesn't break out of the
header, we should probably follow this code path too, instead of creating an
adjoining header. No browser does this, though, so we don't.
- -->
+ </div>
+
+ <p>If <var>container</var>'s [[localname]] is "address", "listing", or
+ "pre":
<ol>
<li>Let <var>br</var> be the result of calling [[createelement|"br"]] on
@@ -7463,22 +7492,26 @@
<li>Increment <var>range</var>'s [[rangestart]] and [[rangeend]]
[[bpoffsets]].
- <li>If <var>br</var> is the last [[descendant]] of <var>container</var>,
+ <li>
+ <p class=comments>Necessary because adding a br to the end of a block
+ element does nothing if there wasn't one there already. A single newline
+ immediately preceding a block boundary does nothing.
+
+ <p>If <var>br</var> is the last [[descendant]] of <var>container</var>,
let <var>br</var> be the result of calling [[createelement|"br"]] on the
[[contextobject]], then call [[insertnode|<var>br</var>]] on
<var>range</var>.
- <!-- Necessary because adding a br to the end of a block element does
- nothing if there wasn't one there already. A single newline immediately
- preceding a block boundary does nothing. -->
<li>Abort these steps.
</ol>
- <li>If <var>container</var>'s [[localname]] is "li", "dt", or "dd"; and
+ <li>
+ <p class=comments>Including dt/dd here follows Firefox 5.0a2, as with the
+ special dt/dd handling below.
+
+ <p>If <var>container</var>'s [[localname]] is "li", "dt", or "dd"; and
either it has no [[children]] or it has a single [[child]] and that [[child]]
is a [[br]]:
- <!-- Including dt/dd here follows Firefox 5.0a2, as with the special dt/dd
- handling below. -->
<ol>
<li><span>Split the parent</span> of the one-[[node]] list consisting of
@@ -7488,17 +7521,17 @@
[[createelement|"br"]] on the [[contextobject]] and append the result as
the last [[child]] of <var>container</var>.
- <li>If <var>container</var> is a [[dd]] or [[dt]], and it is not an
+ <li>
+ <p class=comments>Annoying hack to prevent the dl from being re-added when
+ fixing disallowed ancestors. In most cases we want a wrapper dl added, but
+ in two cases (delete and insertParagraph) we're actually trying to outdent
+ the list item. TODO: there might be a better way to do this.
+
+ <p>If <var>container</var> is a [[dd]] or [[dt]], and it is not an
<span>allowed child</span> of any of its [[ancestors]] <span>in the same
editing host</span>, <span>set the tag name</span> of <var>container</var>
to the <span>default single-line container name</span> and let
<var>container</var> be the result.
- <!--
- Annoying hack to prevent the dl from being re-added when fixing disallowed
- ancestors. In most cases we want a wrapper dl added, but in two cases
- (delete and insertParagraph) we're actually trying to outdent the list
- item. There might be a better way to do this.
- -->
<li><span>Fix disallowed ancestors</span> of <var>container</var>.
@@ -7509,11 +7542,13 @@
the same as <var>range</var>'s, and whose [[rangeend]] is
(<var>container</var>, [[nodelength]] of <var>container</var>).
- <!-- We don't want the start to be just inside a node, because if it is,
- we'll leave behind an empty element either in the new or old container.
- Clearly we don't want the start point to get any higher than the container
- itself, though. -->
- <li>While <var>new line range</var>'s [[startoffset]] is zero and its
+ <li>
+ <p class=comments>We don't want the start to be just inside a node, because
+ if it is, we'll leave behind an empty element either in the new or old
+ container. Clearly we don't want the start point to get any higher than the
+ container itself, though.
+
+ <p>While <var>new line range</var>'s [[startoffset]] is zero and its
[[startnode]] is not <var>container</var>, set its [[rangestart]] to
([[parent]] of [[startnode]], [[index]] of [[startnode]]).
@@ -7526,22 +7561,27 @@
data-anolis-spec=domrange title=contained>contains</span> either nothing or a
single [[br]], and false otherwise.
- <li>If the [[localname]] of <var>container</var> is "h1", "h2", "h3", "h4",
+ <li>
+ <p class=comments>IE9 makes a new header if there's a trailing <br>.
+ Firefox 5.0a2, Chrome 13 dev, and Opera 11.10 do not, and I follow them,
+ since it makes more sense (such a <br> is invisible).
+
+ <p>If the [[localname]] of <var>container</var> is "h1", "h2", "h3", "h4",
"h5", or "h6", and <var>end of line</var> is true, let <var>new container
name</var> be the <span>default single-line container name</span>.
- <!-- IE9 makes a new header if there's a trailing <br>. Firefox 5.0a2,
- Chrome 13 dev, and Opera 11.10 do not, and I follow them, since it makes more
- sense (such a <br> is invisible). -->
-
- <li>Otherwise, if the [[localname]] of <var>container</var> is "dt" and
+
+ <li>
+ <p class=comments>This step and the next follow Firefox 5.0a2. IE9 and
+ Chrome 13 dev act as though these two lines were not present (they clone the
+ existing element). Opera 11.10 nests a <p> inside. Firefox is the most
+ useful, assuming a definition list somehow winds up inside the content (like
+ via formatBlock).
+
+ <p>Otherwise, if the [[localname]] of <var>container</var> is "dt" and
<var>end of line</var> is true, let <var>new container name</var> be "dd".
<li>Otherwise, if the [[localname]] of <var>container</var> is "dd" and
<var>end of line</var> is true, let <var>new container name</var> be "dt".
- <!-- These two follow Firefox 5.0a2. IE9 and Chrome 13 dev act as though
- these two lines were not present (they clone the existing element). Opera
- 11.10 nests a <p> inside. Firefox is the most useful, assuming a definition
- list somehow winds up inside the content. -->
<li>Otherwise, let <var>new container name</var> be the [[localname]] of
<var>container</var>.
@@ -7559,14 +7599,15 @@
<li>Let <var>contained nodes</var> be all [[nodes]] [[contained]] in <var>new
line range</var>.
- <li>Let <var>frag</var> be the result of calling [[extractcontents]] on
+ <li>
+ <p class=comments>TODO: This blows up any ranges (other than the selection,
+ which we reset), and can alter non-editable nodes, and maybe other bad stuff.
+ May or may not be the best solution. The intermediate fragment is also
+ possibly black-box detectable by DOM mutation events, but I like to pretend
+ those don't exist.
+
+ <p>Let <var>frag</var> be the result of calling [[extractcontents]] on
<var>new line range</var>.
- <!--
- TODO: This blows up any ranges (other than the selection, which we reset),
- and can alter non-editable nodes, and maybe other bad stuff. May or may not
- be the best solution. The intermediate fragment is also probably black-box
- detectable by DOM mutation events, but I like to pretend those don't exist.
- -->
<li>Unset the [[id]] attribute (if any) of each [[element]] [[descendant]] of
<var>frag</var> that is not in <var>contained nodes</var>.
@@ -7577,13 +7618,16 @@
[[createelement|"br"]] on the [[contextobject]], and append the result as the
last [[child]] of <var>container</var>.
- <li>If <var>new container</var> has no <span>visible</span> [[children]],
+ <li>
+ <p class=comments>These two steps follow Firefox 5.0a2, Chrome 13 dev, and
+ Opera 11.10. IE9 instead inserts an &nbsp; which magically does not
+ appear in innerHTML. In all cases, the reason is that an empty block box in
+ CSS will have zero height, so the user won't be able to put the selection
+ cursor inside it.
+
+ <p>If <var>new container</var> has no <span>visible</span> [[children]],
call [[createelement|"br"]] on the [[contextobject]], and append the result
as the last [[child]] of <var>new container</var>.
- <!-- These two steps follow Firefox 5.0a2, Chrome 13 dev, and Opera 11.10.
- IE9 instead inserts an which magically does not appear in innerHTML.
- In all cases, the reason is that an empty block box in CSS will have zero
- height, so the user won't be able to put the selection cursor inside it. -->
<li>Set the [[rangestart]] of <var>range</var> to (<var>new container</var>,
0).
@@ -7592,23 +7636,24 @@
<!-- @} -->
<h3><dfn>The <code title>insertText</code> command</dfn></h3>
<!-- @{ -->
-<!--
-Supported only by WebKit. Tests in other browsers were manual. In the manual
-tests, where the value was always "a", IE9 and Firefox 5.0a2 match the spec
-exactly as far as I can tell; Chrome 14 dev and Opera 11.11 might match it in
-theory, but normalize the selection first, so they don't match it in practice.
--->
-<p><span>Action</span>:
-
-<!--
-Non-breaking space fun! The issue: if the user hits space twice, they expect
-it to create two spaces, not collapse. Also, if they're at the beginning or
-end of a line and hit space, again, they expect it not to collapse. Since we
-don't want to require that all contenteditable element contents always be used
-only with white-space: pre-wrap, we need to convert to and from non-breaking
-spaces.
-
-But there's a catch: you can't just make spaces non-breaking willy-nilly,
+<div class=comments>
+<p>Supported only by WebKit. Tests in other browsers were manual.
+
+<p>TODO: This doesn't work well if the input contains things that aren't
+supposed to appear in HTML, like carriage returns or nulls. Nor is it going to
+work well if the current cursor position is in between two halves of a non-BMP
+character. This will result in unserializability. The current spec disregards
+this, as Chrome 14 dev does. (It's not relevant to other browsers, since they
+don't support this as a command.)
+
+<p>Important issue: non-breaking space fun! The issue: if the user hits space
+twice, they expect it to create two spaces, not collapse. Also, if they're at
+the beginning or end of a line and hit space, again, they expect it not to
+collapse. Since we don't want to require that all contenteditable element
+contents always be used only with white-space: pre-wrap, we need to convert to
+and from non-breaking spaces.
+
+<p>But there's a catch: you can't just make spaces non-breaking willy-nilly,
because that doesn't just stop the space from collapsing, it also prevents
breaking. (Chrome 14 dev actually cheats here: in contenteditable, it doesn't
collapse nbsp, but breaks after it like a regular space.) The upshot of this
@@ -7618,91 +7663,92 @@
goals when there are an even number of spaces to display is left as an exercise
for the reader.
-Browsers vary greatly in how they handle all this, of course!
-
-The basic philosophy of IE9 is that if you're inserting a space, and one or
+<p>Browsers vary greatly in how they handle all this, of course!
+
+<p>The basic philosophy of IE9 is that if you're inserting a space, and one or
both of the neighboring characters is a space, change the neighboring
characters to non-breaking spaces. This breaks if one of the neighboring
characters is part of a run of collapsed whitespace: "foo []bar" becomes "foo
- []bar", which converts one visible space to three.
-
-Firefox 6.0a2 will sometimes convert the space you're inserting to an nbsp,
+&nbsp; []bar", which converts one visible space to three.
+
+<p>Firefox 6.0a2 will sometimes convert the space you're inserting to an nbsp,
sometimes convert neighboring spaces to nbsps, and sometimes convert
neighboring nbsps to spaces. I cannot discern any clear reason to when it
chooses what, except that it seems to prefer runs of nbsp's followed by a
single space (although not always). I didn't find any outright bugs, except
the inevitable ones like nbsp's sometimes being right after letters.
-Chrome 14 dev tries to normalize everything to look like " ...",
-alternating with space then nbsp. Unfortunately, it does so buggily, because
-it converts collapsed spaces to nbsp's, so inserting a space before " " makes
-it into " ", which changes one visible space to four (or
-arbitrarily many).
-
-Opera 11.11 has varying behavior, like Firefox and Chrome. Like Firefox, I
+<p>Chrome 14 dev tries to normalize everything to look like " &nbsp;
+&nbsp; ...", alternating with space then nbsp. Unfortunately, it does so
+buggily, because it converts collapsed spaces to nbsp's, so inserting a space
+before " " makes it into " &nbsp; &nbsp;", which changes one visible
+space to four (or arbitrarily many).
+
+<p>Opera 11.11 has varying behavior, like Firefox and Chrome. Like Firefox, I
didn't discern an obvious pattern.
-This was discussed: http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-June/032187.html
-
-Unfortunately, we're stuck with this nbsp stuff, because of 1) legacy reasons,
-2) mail clients might not support CSS equivalents, 3) authors might not know to
-apply any CSS to wherever the content is eventually used. The behavior I
-decided on to minimize the evil is as follows:
-
-* If the first and last spaces are in non-collapsing positions, two spaces is
- nbsp+space, three is space+nbsp+space, four or more is space+nbsp followed by
- the pattern for two less.
-* If the first space has to be an nbsp so it doesn't collapse, three is instead
- nbsp+nbsp+space, four or more is nbsp+space followed by the pattern for two
- less.
-* If the last space has to be nbsp, two is space+nbsp, three is
+<p>This was all <a href=http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-June/032187.html>discussed</a>.
+
+<p>Unfortunately, we're stuck with this nbsp stuff, because of 1) legacy
+reasons, 2) mail clients might not support CSS equivalents, 3) authors might
+not know to apply any CSS to wherever the content is eventually used. The
+behavior I decided on to minimize the evil is as follows:
+
+<ul>
+ <li>If the first and last spaces are in non-collapsing positions, two spaces
+ is nbsp+space, three is space+nbsp+space, four or more is space+nbsp followed
+ by the pattern for two less.
+
+ <li>If the first space has to be an nbsp so it doesn't collapse, three is
+ instead nbsp+nbsp+space, four or more is nbsp+space followed by the pattern
+ for two less.
+
+ <li>If the last space has to be nbsp, two is space+nbsp, three is
space+nbsp+nbsp, four or more is space+nbsp followed by the pattern for two
less.
-* If the first and last space must both be nbsp, two is nbsp+nbsp, three is
+
+ <li>If the first and last space must both be nbsp, two is nbsp+nbsp, three is
nbsp+space+nbsp, four or more nbsp+space followed by the pattern for two
less.
-
-This avoids nbsp at the end of a run except where it's needed, so words won't
-appear indented if they wrap to the next line. It avoids more than two nbsp's
-in a row, so there won't be huge chunks of space that get wrapped all at once.
-And it avoids nbsp at the beginning of a run except where it's needed or
+</ul>
+
+<p>This avoids nbsp at the end of a run except where it's needed, so words
+won't appear indented if they wrap to the next line. It avoids more than two
+nbsp's in a row, so there won't be huge chunks of space that get wrapped all at
+once. And it avoids nbsp at the beginning of a run except where it's needed or
if there are only two spaces in the run, so words won't have to wrap
unnecessarily.
-This is still a huge headache, though.
--->
-
-<!--
-TODO: This doesn't work well if the input contains things that aren't supposed
-to appear in HTML, like carriage returns or nulls. Nor is it going to work
-well if the current cursor position is in between two halves of a non-BMP
-character. This will result in unserializability. The current spec disregards
-this, as Chrome 14 dev does.
--->
+<p>This is still a huge headache, though.
+</div>
+
+<p><span>Action</span>:
<ol>
- <li><span>Delete the contents</span> of the <span>active range</span>, with
- <var>strip wrappers</var> false.
- <!--
- Chrome 14 dev does the deletion even if the value is empty. Of course, other
- browsers don't expose this as an execCommand(), so no one else has any
+ <li>
+ <div class=comments>
+ <p>Chrome 14 dev does the deletion even if the value is empty. Of course,
+ other browsers don't expose this as an execCommand(), so no one else has any
defined behavior in this case at all, so I follow Chrome.
- IE9, Firefox 7.0a2, Chrome 14 dev, and Opera 11.50 all don't strip wrappers,
- except that as usual, Gecko does if you select the whole wrapper, like
- {<b>foo</b>}. Also, Chrome 14 dev seems to strip the wrapper and try
- recreating the style in cases like <b>[foo</b>bar], where it starts in a
- wrapper but ends after it; this doesn't always work so well, so I don't do
- it. Firefox 7.0a2 also has the deletion set overrides for indeterminate
- state commands, so if you run insertText on [foo<b>bar</b>baz] it will make
- the result bold.
-
- These things don't make any sense to me, so I don't do them. I set overrides
- based on the first editable text node in the range when deleting; preserve
- any wrappers at the start of the range; and restore the overrides in case
- preserving the wrappers isn't enough (like if they weren't set by deletion at
- all). This behavior seems to closely match IE9.
- -->
+ <p>IE9, Firefox 7.0a2, Chrome 14 dev, and Opera 11.50 all don't strip
+ wrappers, except that as usual, Gecko does if you select the whole wrapper,
+ like {<b>foo</b>}. Also, Chrome 14 dev seems to strip the wrapper and
+ try recreating the style in cases like <b>[foo</b>bar], where it starts
+ in a wrapper but ends after it; this doesn't always work so well, so I don't
+ do it. Firefox 7.0a2 also has the deletion set overrides for indeterminate
+ state commands, so if you run insertText on [foo<b>bar</b>baz] it will
+ make the result bold.
+
+ <p>These things don't make any sense to me, so I don't do them. I set
+ overrides based on the first editable text node in the range when deleting;
+ preserve any wrappers at the start of the range; and restore the overrides in
+ case preserving the wrappers isn't enough (like if they weren't set by
+ deletion at all). This behavior seems to closely match IE9.
+ </div>
+
+ <p><span>Delete the contents</span> of the <span>active range</span>, with
+ <var>strip wrappers</var> false.
<li>If the <span>active range</span>'s [[startnode]] is neither
<span>editable</span> nor an <span>editing host</span>, abort these steps.
@@ -7719,25 +7765,27 @@
<li>If <var>value</var> is the empty string, abort these steps.
- <li>If <var>value</var> is a newline (U+00A0), take the <span>action</span>
+ <li>
+ <p class=comments>TODO: WebKit also does magic for tabs, wrapping them in a
+ whitespace-preserving span. Should we?
+
+ <p>If <var>value</var> is a newline (U+00A0), take the <span>action</span>
for <span>the <code title>insertParagraph</code> command</span> and abort
these steps.
- <!-- TODO: WebKit also does magic for tabs, wrapping them in a
- whitespace-preserving span. Should we? -->
<li>Let <var>node</var> and <var>offset</var> be the <span>active
range</span>'s [[startnode]] and [[bpoffset]].
- <!--
- Just to be tidy, add to an existing text node if there is one. Firefox 5.0a2
- only adds to an existing one if the range is in a text node. IE9, Chrome 14
- dev, and Opera 11.11 also add to an existing text node if the range is in an
- element adjacent to a text node. If there are two text nodes and it's in
- between, like foo{}bar, IE and Opera add to the first, Chrome adds to the
- second, although it probably doesn't matter in practice exactly which we
- choose.
- -->
- <li>If <var>node</var> has a [[child]] whose [[index]] is <var>offset</var>
+ <li>
+ <p class=comments>Just to be tidy, add to an existing text node if there is
+ one. Firefox 5.0a2 only adds to an existing one if the range is in a text
+ node. IE9, Chrome 14 dev, and Opera 11.11 also add to an existing text node
+ if the range is in an element adjacent to a text node. If there are two text
+ nodes and it's in between, like foo{}bar, IE and Opera add to the first,
+ Chrome adds to the second, although it probably doesn't matter in practice
+ exactly which we choose.
+
+ <p>If <var>node</var> has a [[child]] whose [[index]] is <var>offset</var>
− 1, and that [[child]] is a [[text]] node, set <var>node</var> to that
[[child]], then set <var>offset</var> to <var>node</var>'s [[length]].
@@ -7745,12 +7793,15 @@
and that [[child]] is a [[text]] node, set <var>node</var> to that [[child]],
then set <var>offset</var> to zero.
- <li>If <var>value</var> is a space (U+0020), and either <var>node</var> is an
+ <li>
+ <p class=comments><var>value</var> may change back to a space when we
+ canonicalize, even if this step is triggered.
+
+ <p>If <var>value</var> is a space (U+0020), and either <var>node</var> is an
[[element]] whose [[resval]] for "white-space" is neither "pre" nor
"pre-wrap" or <var>node</var> is not an [[element]] but its [[parent]] is an
[[element]] whose [[resval]] for "white-space" is neither "pre" nor
"pre-wrap", set <var>value</var> to a non-breaking space (U+00A0).
- <!-- This may change to a space when we canonicalize. -->
<li><span>Record current overrides</span>, and let <var>overrides</var> be
the result.
@@ -7771,9 +7822,11 @@
<li>Otherwise:
<ol>
- <!-- If some text is inserted into <p><br></p> or similar, we no longer need
- the <br>. -->
- <li>If <var>node</var> has only one [[child]], which is a <span>collapsed
+ <li>
+ <p class=comments>If some text is inserted into <p><br></p> or
+ similar, we no longer need the <br>.
+
+ <p>If <var>node</var> has only one [[child]], which is a <span>collapsed
line break</span>, remove its [[child]] from it.
<li>Let <var>text</var> be the result of calling <code
@@ -7804,6 +7857,9 @@
<!-- @} -->
<h3><dfn>The <code title>insertUnorderedList</code> command</dfn></h3>
<!-- @{ -->
+<p class=comments>See comments for <a
+href=#the-insertorderedlist-command>insertOrderedList</a>.
+
<p><span>Action</span>: <span>Toggle lists</span> with <var>tag name</var>
"ul".
@@ -7819,64 +7875,66 @@
<p><span>Action</span>: <span>Justify the selection</span> with
<var>alignment</var> "center".
+<div class=comments>
+<p>This roughly matches Chrome 14 dev, although not exactly. Firefox 6.0a2
+always returns false.
+
+<p>As a general rule, ignoring nodes with children saves us from treating
+<div align=left><div align=center>foo</div></div> as though it's
+indeterminate. Chrome 14 dev seems to only pay attention to text nodes,
+instead, or something like that. At any rate, it fails on images. Firefox
+6.0a2 (for state and value) gets tripped up by examples like the one given.
+
+<p>If we ever support centering of tables and similar, we'd want to pay
+attention even to some nodes that do have children.
+</div>
+
<p><span>Indeterminate</span>: <span>Block-extend</span> the <span>active
range</span>. Return true if among <span>visible</span> <span>editable</span>
[[nodes]] that are [[contained]] in the result and have no [[children]], at
least one has <span>alignment value</span> "center" and at least one does not.
Otherwise return false.
-<!--
-This roughly matches Chrome 14 dev, although not exactly. Firefox 6.0a2 always
-returns false.
-
-As a general rule, ignoring nodes with children saves us from treating <div
-align=left><div align=center>foo</div></div> as though it's indeterminate.
-Chrome 14 dev seems to only pay attention to text nodes, instead, or something
-like that. At any rate, it fails on images. Firefox 6.0a2 (for state and
-value) gets tripped up by examples like the one given.
-
-If we ever support centering of tables and similar, we'd want to pay attention
-even to some nodes that do have children.
--->
+
+<div class=comments>
+<p>IE9 throws exceptions in almost every case when querying the state of
+justify*, and Opera 11.11 returns false in every case except some seemingly
+random crazy ones.
+
+<p>Firefox 6.0a2 returns true for the state of justify* if anything in the
+range has the right alignment, not if everything does. This isn't consistent
+with how state works for the inline commands, nor with WebKit.
+
+<p>Chrome 14 dev counts text-align on inline elements, which is wrong, because
+the property has no effect. It also counts it on non-editable elements, which
+is wrong, because then the state for justify* wouldn't necessarily be true
+after executing it. (Chrome actually does align the non-editable elements, but
+that's just a bug.) Chrome further returns false for justify* if the
+justification is just the default inherited justification, e.g., left for LTR.
+This doesn't seem to make sense either.
+
+<p>State is kind of redundant here, because it's true if and only if
+indeterminate is false and the value is equal to the desired value. However,
+I'll support it anyway, since Gecko/WebKit do.
+</div>
<p><span>State</span>: <span>Block-extend</span> the <span>active range</span>.
Return true if there is at least one <span>visible</span> <span>editable</span>
[[node]] that is [[contained]] in the result and has no [[children]], and all
such [[nodes]] have <span>alignment value</span> "center". Otherwise return
false.
-<!--
-IE9 throws exceptions in almost every case when querying the state of justify*,
-and Opera 11.11 returns false in every case except some seemingly random crazy
-ones.
-
-Firefox 6.0a2 returns true for the state of justify* if anything in the range
-has the right alignment, not if everything does. This isn't consistent with
-how state works for the inline commands, nor with WebKit.
-
-Chrome 14 dev counts text-align on inline elements, which is wrong, because the
-property has no effect. It also counts it on non-editable elements, which is
-wrong, because then the state for justify* wouldn't necessarily be true after
-executing it. (Chrome actually does align the non-editable elements, but
-that's just a bug.) Chrome further returns false for justify* if the
-justification is just the default inherited justification, e.g., left for LTR.
-This doesn't seem to make sense either.
-
-State is kind of redundant here, because it's true if and only if indeterminate
-is false and the value is equal to the desired value. However, I'll support it
-anyway, since Gecko/WebKit do.
--->
+
+<p class=comments>Not bidi-safe, but it's a pretty marginal corner case where
+it fails. Firefox 6.0a2 behaves weirdly here: it keys off the start node of
+the active range, even if that's not contained. Thus {<div
+align=center>foo</div>} has value "left" and indeterminate false, which
+would suggest that the whole selection is aligned left, but that's not the
+case. Chrome 14 dev returns the state cast to a string, as usual. Opera 11.11
+always returns the empty string.
<p><span>Value</span>: <span>Block-extend</span> the <span>active range</span>,
and return the <span>alignment value</span> of the first <span>visible</span>
<span>editable</span> [[node]] that is [[contained]] in the result and has no
[[children]]. If there is no such [[node]], return "left".
-<!--
-Not bidi-safe, but it's a pretty marginal corner case. Firefox 6.0a2 behaves
-weirdly here: it keys off the start node of the active range, even if that's
-not contained. Thus {<div align=center>foo</div>} has value "left" and
-indeterminate false, which would suggest that the whole selection is aligned
-left, but that's not the case. Chrome 14 dev returns the state cast to a
-string, as usual. Opera 11.11 always returns the empty string.
--->
<!-- @} -->
<h3><dfn>The <code title>justifyFull</code> command</dfn></h3>
@@ -7957,43 +8015,47 @@
[[ancestorcontainers]] of the <span>active range</span>'s [[rangestart]]
and/or [[rangeend]] [[bpnode]].
- <li>For each <var>item</var> in <var>items</var>, <span>normalize
+ <li>
+ <p class=comments>TODO: This overnormalizes, but it seems like the simplest
+ solution for now.
+
+ <p>For each <var>item</var> in <var>items</var>, <span>normalize
sublists</span> of <var>item</var>.
- <!-- This overnormalizes, but it seems like the simplest solution for now.
- -->
<li><span>Block-extend</span> the <span>active range</span>, and let <var>new
range</var> be the result.
<li>Let <var>node list</var> be a list of [[nodes]], initially empty.
- <li>For each [[node]] <var>node</var> [[contained]] in <var>new range</var>,
+ <li>
+ <div class=comments>
+ <p>This step is kind of weird. For regular outdenting, we start at the
+ inside and outdent going out, so that we remove the innermost indentation, on
+ the theory that that will produce the cleanest markup (remove the most
+ nodes). For lists, we remove the outermost indentation, because it makes a
+ difference whether we remove inner or outer indentation, and logically we
+ want to remove outer. E.g.,
+
+ <pre><ol><li>foo</li><ul><li>bar</li></ul></ol></pre>
+
+ <p>should become
+
+ <pre>foo<ul><li>bar</li></ul></pre>
+
+ <p>not
+
+ <pre>foo<ol><li>bar</li></ol>.</pre>
+
+ <p>But this is a bit weird and I'm wondering if it's really correct. TODO:
+ Reexamine this.
+ </div>
+
+ <p>For each [[node]] <var>node</var> [[contained]] in <var>new range</var>,
append <var>node</var> to <var>node list</var> if the last member of
<var>node list</var> (if any) is not an [[ancestor]] of <var>node</var>;
<var>node</var> is <span>editable</span>; and either <var>node</var> has no
<span>editable</span> [[descendants]], or is an [[ol]] or [[ul]], or is an
[[li]] whose [[parent]] is an [[ol]] or [[ul]].
- <!--
- This step is kind of weird. For regular outdenting, we start at the inside
- and outdent going out, so that we remove the innermost indentation, on the
- theory that that will produce the cleanest markup (remove the most nodes).
- For lists, we remove the outermost indentation, because it makes a difference
- whether we remove inner or outer indentation, and logically we want to remove
- outer. E.g.,
-
- <ol><li>foo</li><ul><li>bar</li></ul></ol>
-
- should become
-
- foo<ul><li>bar</li></ul>
-
- not
-
- foo<ol><li>bar</li></ol>.
-
- But this is a bit weird and I'm wondering if it's really correct. TODO:
- Reexamine this.
- -->
<li>While <var>node list</var> is not empty:
@@ -8031,17 +8093,13 @@
<h3><dfn>The <code title>copy</code> command</dfn></h3>
<!-- @{ -->
-<!--
-IE9 supports copy/cut/paste with a security warning. Firefox reportedly only
-supports it if you set a pref. I didn't find info on other browsers, but in my
-tests it didn't do anything. I'm not going to try speccing it unless
-implementers are interested in working out the security problems and trying to
-get interop. It seems like as of June 2011, everyone just uses Flash for this:
-
-http://code.google.com/p/zeroclipboard/
-
-So it would be nice if we could work out a more secure standardized substitute.
--->
+<p class=comments>IE9 supports copy/cut/paste with a security warning. Firefox
+reportedly only supports it if you set a pref. I didn't find info on other
+browsers, but in my tests it didn't do anything. I'm not going to try speccing
+it unless implementers are interested in working out the security problems and
+trying to get interop. It seems like as of June 2011, everyone just <a
+href=http://code.google.com/p/zeroclipboard/>uses Flash for this</a>. So it
+would be nice if we could work out a more secure standardized substitute.
<p><span>Action</span>: The user agent must either copy the current selection
to the clipboard as though the user had requested it, or raise a
@@ -8054,23 +8112,22 @@
because sites could abuse it to confuse and annoy the user by overwriting the
clipboard with extremely long, obscene, or otherwise objectionable content.
+<p class=comments>The idea is sites might catch the SECURITY_ERR and treat it
+differently from NOT_SUPPORTED_ERR, like encouraging users to reconfigure their
+browser. However, browsers might not want to encourage authors to tell users
+to reconfigure their browser insecurely.
+
<p>User agents may choose not to <span title=supported>support</span> this
<span>command</span> at all. If a user agent will only honor the
<span>command</span> for some whitelisted sites depending on configuration, it
may either raise a [[SECURITY_ERR]] for non-whitelisted sites, or it may act as
though the <span>command</span> is <span title=supported>unsupported</span> on
those sites.
-<!--
-The idea is sites might catch the SECURITY_ERR and treat it differently from
-NOT_SUPPORTED_ERR, like encouraging users to reconfigure their browser.
-However, browsers might not want to encourage authors to tell users to
-reconfigure their browser insecurely.
--->
<!-- @} -->
<h3><dfn>The <code title>cut</code> command</dfn></h3>
<!-- @{ -->
-<!-- See comment for copy -->
+<p class=comments>See comment for <a href=#the-copy-command>copy</a>.
<p><span>Action</span>: The user agent must either copy the current selection
to the clipboard and then delete it, as though the user had requested it, or
@@ -8093,7 +8150,7 @@
<!-- @} -->
<h3><dfn>The <code title>paste</code> command</dfn></h3>
<!-- @{ -->
-<!-- See comment for copy -->
+<p class=comments>See comment for <a href=#the-copy-command>copy</a>.
<p><span>Action</span>: The user agent must either <span>delete the
contents</span> of the <span>active range</span> and then paste the clipboard's
@@ -8116,46 +8173,53 @@
<!-- @} -->
<h3><dfn>The <code title>selectAll</code> command</dfn></h3>
<!-- @{ -->
-<!--
-Tested using roughly this:
-
-http://software.hixie.ch/utilities/js/live-dom-viewer/saved/1018
-
-IE9: A bit confusing. The gist seems to be that it does selectAllChildren() on
-the body, except sometimes it doesn't.
-
-Firefox 5.0a2: Throws an exception if nothing in the document is editable,
-which apparently it always does for execCommand(). If there's a body, it does
-selectAllChildren() on that, and otherwise it does selectAllChildren() on the
-root element. If there's no root element, throws an exception.
-
-Chrome 13 dev: If there's no root element, removes the selection. If there's
-a root element but no body, collapses the selection at (document, 0). If
-there's a body, it selects all the contents of the body, although that doesn't
-mean the resulting anchor or focus actually are the body node (they're usually
-text nodes). But it seems to *avoid* selecting contenteditable stuff: if all
-the visible things in the body are contenteditable, it removes all ranges from
-the selection, and if some are, it freaks out and behaves oddly. But
-designMode doesn't trouble it.
-
-Opera 11.11: Was characteristically uncooperative in my tests, and I didn't try
-to investigate further.
-
-The behavior here is relatively simple and largely matches implementations.
--->
+<div class=comments>
+<p>Tested using roughly <a href=http://software.hixie.ch/utilities/js/live-dom-viewer/saved/1018>this</a>.
+
+<dl>
+ <dt>IE9
+ <dd>A bit confusing. The gist seems to be that it does selectAllChildren()
+ on the body, except sometimes it doesn't.
+
+ <dt>Firefox 5.0a2
+ <dd>Throws an exception if nothing in the document is editable, which
+ apparently it always does for execCommand(). If there's a body, it does
+ selectAllChildren() on that, and otherwise it does selectAllChildren() on the
+ root element. If there's no root element, throws an exception.
+
+ <dt>Chrome 13 dev
+ <dd>If there's no root element, removes the selection. If there's a root
+ element but no body, collapses the selection at (document, 0). If there's a
+ body, it selects all the contents of the body, although that doesn't mean the
+ resulting anchor or focus actually are the body node (they're usually text
+ nodes). But it seems to *avoid* selecting contenteditable stuff: if all the
+ visible things in the body are contenteditable, it removes all ranges from
+ the selection, and if some are, it freaks out and behaves oddly. But
+ designMode doesn't trouble it.
+
+ <dt>Opera 11.11
+ <dd>Was characteristically uncooperative in my tests, and I didn't try to
+ investigate further.
+</dl>
+
+<p>The behavior here is relatively simple and largely matches implementations.
+</div>
<p><span>Action</span>:
<ol>
- <li>Let <var>target</var> be <span data-anolis-spec=html
+ <li>
+ <p class=comments>TODO: Is this right even for framesets?
+
+ <p>Let <var>target</var> be <span data-anolis-spec=html
title=the-body-element-0>the body element</span> of the [[contextobject]].
- <!-- TODO: Is this right even for framesets? -->
-
- <li>If <var>target</var> is null, let <var>target</var> be the
+
+ <p class=comments>TODO: Is this right even for documents whose root element
+ is not an HTML element?
+
+ <p>If <var>target</var> is null, let <var>target</var> be the
[[contextobject]]'s <code data-anolis-spec=domcore
title=dom-Document-documentElement>documentElement</code>.
- <!-- TODO: Is this right even for documents whose root element is not an HTML
- element? -->
<li>If <var>target</var> is null, call [[getselection]] on the
[[contextobject]], and call [[removeallranges]] on the result.
@@ -8167,41 +8231,44 @@
<!-- @} -->
<h3><dfn>The <code title>styleWithCSS</code> command</dfn></h3>
<!-- @{ -->
-<!-- IE9 and Opera 11.00 don't support this command. By and large, they act
-the way Gecko and WebKit do when styleWithCSS is off. Gecko invented it, and
-WebKit also supports it:
-
-https://bugs.webkit.org/show_bug.cgi?id=13490
-
-The default in Firefox 4.0 is off, while all other browsers behave like the
-default is on (and IE/Opera give no way to turn it off), so I default it to on.
--->
+<div class=comments>
+<p>IE9 and Opera 11.00 don't support this command. By and large, they act the
+way Gecko and WebKit do when styleWithCSS is off. Gecko invented it, and
+WebKit also <a href=https://bugs.webkit.org/show_bug.cgi?id=13490>supports</a>
+it. The default in Firefox 4.0 is off, while all other browsers behave like
+the default is on (and IE/Opera give no way to turn it off), so I default it to
+on.
+
+<p>Handling of <var>value</var> matches Firefox 5.0a2. Chrome 13 dev treats
+the case-sensitive string "true" as true, the case-sensitive string "false" as
+false, and does nothing for any other string. I went with Gecko because this
+way there are only two possible effects, not three, which makes it easier to
+reason about and debug. Also, Gecko made up the command, so this is probably
+more web-compatible. Cursory searches of Google Code and GitHub suggest that
+authors almost always pass a boolean as the third argument when using
+styleWithCSS, in which case the two behaviors work the same.
+</div>
<p><span>Action</span>: If <var>value</var> is an <span
data-anolis-spec=domcore>ASCII case-insensitive</span> match for the string
"false", set the <span>CSS styling flag</span> to false. Otherwise, set the
<span>CSS styling flag</span> to true.
-<!-- This matches Firefox 5.0a2. Chrome 13 dev treats the case-sensitive
-string "true" as true, the case-sensitive string "false" as false, and does
-nothing for any other string. I went with Gecko because this way there are
-only two possible effects, not three, which makes it easier to reason about and
-debug. Also, Gecko made up the command and has larger market share, so this is
-probably more web-compatible. Cursory searches of Google Code and GitHub
-suggest that authors almost always pass a boolean as the third argument when
-using styleWithCSS, in which case the two behaviors work the same. -->
+
+<p class=comments>This follows Chrome 13 dev. Firefox 5.0a2 doesn't support
+queryCommandState() for styleWithCSS.
<p><span>State</span>: True if the <span>CSS styling flag</span> is true,
otherwise false.
-<!-- This follows Chrome 13 dev. Firefox 5.0a2 doesn't support
-queryCommandState() for styleWithCSS. -->
<!-- @} -->
<h3><dfn>The <code title>useCSS</code> command</dfn></h3>
<!-- @{ -->
-<!-- Supported by Firefox 4.0, but not IE9 or Opera 11.00 (which don't support
-styleWithCSS either), nor by Chrome 12 dev (which does support styleWithCSS.
-useCSS was the original feature in Mozilla 1.3, but the meaning is backward, so
-Gecko added styleWithCSS as a replacement. -->
+<p class=comments>Supported by Firefox 4.0, but not IE9 or Opera 11.00 (which
+don't support styleWithCSS either), nor by Chrome 12 dev (which does support
+styleWithCSS). useCSS was the original feature in Mozilla 1.3, but the meaning
+is backward, so Gecko added styleWithCSS as a replacement. No state is
+defined, since only Gecko supports useCss at all, and as of Firefox 6.0a2, it
+doesn't support queryCommandState() for it.
<p><span>Action</span>: If <var>value</var> is an <span
data-anolis-spec=domcore>ASCII case-insensitive</span> match for the string
@@ -8217,9 +8284,6 @@
<p class=XXX>The meaning of this command is backwards, and only Gecko supports
it. It would be great if Gecko would agree to drop support, so that we could
get rid of it.
-
-<!-- No state defined, since only Gecko supports useCss at all, and as of
-Firefox 6.0a2, it doesn't support queryCommandState() for it. -->
<!-- @} -->
<h2>Additional requirements</h2>