[html5] r7597 - [acgiow] (0) New feature: sorting tables. The actual sort algorithm isn't done y [...]

whatwg at whatwg.org whatwg at whatwg.org
Wed Dec 26 15:58:25 PST 2012


Author: ianh
Date: 2012-12-26 15:58:23 -0800 (Wed, 26 Dec 2012)
New Revision: 7597

Modified:
   complete.html
   index
   source
Log:
[acgiow] (0) New feature: sorting tables. The actual sort algorithm isn't done yet, but this should be a good start for first draft reviewers.
Affected topics: DOM APIs, HTML, Rendering

Modified: complete.html
===================================================================
--- complete.html	2012-12-19 20:11:40 UTC (rev 7596)
+++ complete.html	2012-12-26 23:58:23 UTC (rev 7597)
@@ -248,7 +248,7 @@
 
   <header class=head id=head><p><a class=logo href=http://www.whatwg.org/><img alt=WHATWG height=101 src=/images/logo width=101></a></p>
    <hgroup><h1 class=allcaps>HTML</h1>
-    <h2 class="no-num no-toc">Living Standard — Last Updated 19 December 2012</h2>
+    <h2 class="no-num no-toc">Living Standard — Last Updated 26 December 2012</h2>
    </hgroup><dl><dt><strong>Web developer edition:</strong></dt>
     <dd><strong><a href=http://developers.whatwg.org/>http://developers.whatwg.org/</a></strong></dd>
     <dt>Multiple-page version:</dt>
@@ -665,7 +665,8 @@
       <ol>
        <li><a href=#forming-a-table><span class=secno>4.9.12.1 </span>Forming a table</a></li>
        <li><a href=#header-and-data-cell-semantics><span class=secno>4.9.12.2 </span>Forming relationships between data cells and header cells</a></ol></li>
-     <li><a href=#examples-0><span class=secno>4.9.13 </span>Examples</a></ol></li>
+     <li><a href=#table-sorting-model><span class=secno>4.9.13 </span>Table sorting model</a></li>
+     <li><a href=#examples-0><span class=secno>4.9.14 </span>Examples</a></ol></li>
    <li><a href=#forms><span class=secno>4.10 </span>Forms</a>
     <ol>
      <li><a href=#introduction-1><span class=secno>4.10.1 </span>Introduction</a>
@@ -4049,7 +4050,7 @@
      <li><dfn id=dom-element-id title=dom-Element-id><code>id</code></dfn> attribute</li>
      <li><dfn id=textcontent><code>textContent</code></dfn> attribute</li>
 
-     <li>The <dfn id=concept-node-insert title=concept-node-insert>insert</dfn>, <dfn id=concept-node-append title=concept-node-append>append</dfn>, and <dfn id=concept-node-replace title=concept-node-replace>replace</dfn> algorithms for nodes</li>
+     <li>The <dfn id=concept-node-insert title=concept-node-insert>insert</dfn>, <dfn id=concept-node-append title=concept-node-append>append</dfn>, <dfn id=concept-node-remove title=concept-node-remove>remove</dfn>, and <dfn id=concept-node-replace title=concept-node-replace>replace</dfn> algorithms for nodes</li>
      <li>The <dfn id=nodes-are-inserted>nodes are inserted</dfn> and <dfn id=nodes-are-removed>nodes are removed</dfn> concepts</li>
 
      <li><dfn id=event><code>Event</code></dfn> interface</li>
@@ -6353,6 +6354,9 @@
 
   <h5 id=durations><span class=secno>2.5.5.9 </span>Durations</h5>
 
+  <!-- if you add support for year and month durations, then search for MONTHS throughout the spec
+  (not just this section) for things that have to change -->
+
   <p>A <dfn id=concept-duration title=concept-duration>duration</dfn> consists of <!--MONTHS: either a number of
   months or--> a number of seconds.</p>
 
@@ -9662,6 +9666,7 @@
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onseeking title=handler-onseeking>onseeking</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onselect title=handler-onselect>onselect</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onshow title=handler-onshow>onshow</a>;
+           attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsort title=handler-onsort>onsort</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onstalled title=handler-onstalled>onstalled</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsubmit title=handler-onsubmit>onsubmit</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsuspend title=handler-onsuspend>onsuspend</a>;
@@ -10671,6 +10676,7 @@
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onseeking title=handler-onseeking>onseeking</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onselect title=handler-onselect>onselect</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onshow title=handler-onshow>onshow</a>;
+           attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsort title=handler-onsort>onsort</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onstalled title=handler-onstalled>onstalled</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsubmit title=handler-onsubmit>onsubmit</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsuspend title=handler-onsuspend>onsuspend</a>;
@@ -10803,6 +10809,7 @@
    <li><code title=handler-onseeking><a href=#handler-onseeking>onseeking</a></code></li>
    <li><code title=handler-onselect><a href=#handler-onselect>onselect</a></code></li>
    <li><code title=handler-onshow><a href=#handler-onshow>onshow</a></code></li>
+   <li><code title=handler-onsort><a href=#handler-onsort>onsort</a></code></li>
    <li><code title=handler-onstalled><a href=#handler-onstalled>onstalled</a></code></li>
    <li><code title=handler-onsubmit><a href=#handler-onsubmit>onsubmit</a></code></li>
    <li><code title=handler-onsuspend><a href=#handler-onsuspend>onsuspend</a></code></li>
@@ -21252,12 +21259,11 @@
 
   <div class=example>
 
-   <p>Here, a short table has its numeric values encoded using
-   <code><a href=#the-data-element>data</a></code> so that a script can provide a sorting mechanism
-   on each column, despite the numbers being presented in textual
-   form in one column and in a decomposed form in another.</p>
+   <p>Here, a short table has its numeric values encoded using <code><a href=#the-data-element>data</a></code> so that the
+   <a href=#table-sorting-model>table sorting model</a> can provide a sorting mechanism on each column, despite the
+   numbers being presented in textual form in one column and in a decomposed form in another.</p>
 
-   <pre><table class="sortable"> <!-- class used by script to find tables to which to add sorting controls -->
+   <pre><table sortable>
  <thead> <tr> <th> Game <th> Corporations <th> Map Size
  <tbody>
   <tr> <td> 1830 <td> <data value="8">Eight</data> <td> <data value="93">19+74 hexes (93 total)</data>
@@ -21455,9 +21461,8 @@
 
   </dl><div class=impl>
 
-  <p>The machine-readable equivalent of the element's contents must be
-  obtained from the element's <a href=#datetime-value>datetime value</a> by using the
-  following algorithm:</p>
+  <p>The <dfn id="machine-readable-equivalent-of-the-element's-contents">machine-readable equivalent of the element's contents</dfn> must be obtained from the
+  element's <a href=#datetime-value>datetime value</a> by using the following algorithm:</p>
 
   <ol><li><p>If <a href=#parse-a-month-string title="parse a month string">parsing a month
    string</a> from the element's <a href=#datetime-value>datetime value</a>
@@ -41443,6 +41448,7 @@
    total).</dd>
    <dt><a href=#element-dfn-attributes title=element-dfn-attributes>Content attributes</a>:</dt>
    <dd><a href=#global-attributes>Global attributes</a></dd>
+   <dd><code title=attr-table-sortable><a href=#attr-table-sortable>sortable</a></code></dd>
    <dt><a href=#element-dfn-dom title=element-dfn-dom>DOM interface</a>:</dt><!--TOPIC:DOM APIs-->
    <dd>
 <pre class=idl>interface <dfn id=htmltableelement>HTMLTableElement</dfn> : <a href=#htmlelement>HTMLElement</a> {
@@ -41460,6 +41466,8 @@
   readonly attribute <a href=#htmlcollection>HTMLCollection</a> <a href=#dom-table-rows title=dom-table-rows>rows</a>;
   <a href=#htmlelement>HTMLElement</a> <a href=#dom-table-insertrow title=dom-table-insertRow>insertRow</a>(optional long index);
   void <a href=#dom-table-deleterow title=dom-table-deleteRow>deleteRow</a>(long index);
+           attribute boolean <a href=#dom-table-sortable title=dom-table-sortable>sortable</a>;
+  void <a href=#dom-table-stopsorting title=dom-table-stopSorting>stopSorting</a>();
 };</pre>
    </dd>
   </dl><!--TOPIC:HTML--><p>The <code><a href=#the-table-element>table</a></code> element <a href=#represents>represents</a> data with
@@ -41547,6 +41555,9 @@
 
   </div>
 
+  <hr><p>The <code title=attr-table-sortable><a href=#attr-table-sortable>sortable</a></code> attribute is used in the <a href=#table-sorting-model>table
+  sorting model</a>.</p>
+
   <hr><!--TOPIC:DOM APIs--><dl class=domintro><dt><var title="">table</var> . <code title=dom-table-caption><a href=#dom-table-caption>caption</a></code> [ = <var title="">value</var> ]</dt>
    <dd>
     <p>Returns the table's <code><a href=#the-caption-element>caption</a></code> element.</p>
@@ -41795,7 +41806,13 @@
 
    <li><p>Otherwise, the method must remove the <var title="">index</var>th element in the <code title=dom-table-rows><a href=#dom-table-rows>rows</a></code> collection from its parent.</p>
 
-  </ol></div>
+  </ol><p>The <code title=dom-table-stopSorting><a href=#dom-table-stopsorting>stopSorting()</a></code> method is used in the <a href=#table-sorting-model>table
+  sorting model</a>.</p>
+
+  <p>The IDL attribute <dfn id=dom-table-sortable title=dom-table-sortable><code>sortable</code></dfn> must
+  <a href=#reflect>reflect</a> the <code title=attr-table-sortable><a href=#attr-table-sortable>sortable</a></code> content attribute.</p>
+
+  </div>
 <!--TOPIC:HTML-->
 
   <div class=example>
@@ -42638,11 +42655,14 @@
    <dd><code title=attr-tdth-headers><a href=#attr-tdth-headers>headers</a></code></dd>
    <dd><code title=attr-th-scope><a href=#attr-th-scope>scope</a></code></dd>
    <dd><code title=attr-th-abbr><a href=#attr-th-abbr>abbr</a></code></dd>
+   <dd><code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code></dd>
    <dt><a href=#element-dfn-dom title=element-dfn-dom>DOM interface</a>:</dt><!--TOPIC:DOM APIs-->
    <dd>
     <pre class=idl>interface <dfn id=htmltableheadercellelement>HTMLTableHeaderCellElement</dfn> : <a href=#htmltablecellelement>HTMLTableCellElement</a> {
            attribute DOMString <a href=#dom-th-scope title=dom-th-scope>scope</a>;
            attribute DOMString <a href=#dom-th-abbr title=dom-th-abbr>abbr</a>;
+           attribute DOMString <a href=#dom-th-sorted title=dom-th-sorted>sorted</a>;
+  void <a href=#dom-th-sort title=dom-th-sort>sort</a>();
 };</pre>
    </dd>
   </dl><!--TOPIC:HTML--><p>The <code><a href=#the-th-element>th</a></code> element <a href=#represents>represents</a> a header <a href=#concept-cell title=concept-cell>cell</a> in a table.</p>
@@ -42696,17 +42716,23 @@
   to a data cell). It is typically an abbreviated form of the full header cell, but can also be an
   expansion, or merely a different phrasing.</p>
 
+  <p>The <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute is used in the <a href=#table-sorting-model>table
+  sorting model</a>.</p>
+
   <div class=impl>
 
   <p>The <code><a href=#the-th-element>th</a></code> element and its <code title=attr-tdth-colspan><a href=#attr-tdth-colspan>colspan</a></code>, <code title=attr-tdth-rowspan><a href=#attr-tdth-rowspan>rowspan</a></code>, <code title=attr-tdth-headers><a href=#attr-tdth-headers>headers</a></code>, and <code title=attr-th-scope><a href=#attr-th-scope>scope</a></code> attributes take part in the
   <a href=#table-model>table model</a>.</p>
 
+  <p>The <code title=dom-th-sort><a href=#dom-th-sort>sort()</a></code> method is used in the <a href=#table-sorting-model>table sorting
+  model</a>.</p>
+
   <p>The <dfn id=dom-th-scope title=dom-th-scope><code>scope</code></dfn> IDL
   attribute must <a href=#reflect>reflect</a> the content attribute of the
   same name, <a href=#limited-to-only-known-values>limited to only known values</a>.</p>
 
-  <p>The <dfn id=dom-th-abbr title=dom-th-abbr><code>abbr</code></dfn> IDL attribute must <a href=#reflect>reflect</a>
-  the content attribute of the same name.</p>
+  <p>The <dfn id=dom-th-abbr title=dom-th-abbr><code>abbr</code></dfn> and <dfn id=dom-th-sorted title=dom-th-sorted><code>sorted</code></dfn> IDL attributes must <a href=#reflect>reflect</a> the
+  content attributes of the same name.</p>
 
   </div>
 
@@ -42885,8 +42911,10 @@
   <p>It is possible, in certain error cases, for two cells to occupy
   the same slot.</p>
 
-  <p>A <dfn id=concept-row title=concept-row>row</dfn> is a complete set of slots
-  from <span title=""><var title="">x</var>=0</span> to <span title=""><var title="">x</var>=<var title="">x<sub title="">width</sub></var>-1</span>, for a particular value of <var title="">y</var>. Rows correspond to <code><a href=#the-tr-element>tr</a></code> elements.</p>
+  <p>A <dfn id=concept-row title=concept-row>row</dfn> is a complete set of slots from <span title=""><var title="">x</var>=0</span> to <span title=""><var title="">x</var>=<var title="">x<sub title="">width</sub></var>-1</span>, for a particular value of <var title="">y</var>. Rows usually
+  correspond to <code><a href=#the-tr-element>tr</a></code> elements, though a <a href=#concept-row-group title=concept-row-group>row group</a>
+  can have some implied <a href=#concept-row title=concept-row>rows</a> at the end in some cases involving
+  <a href=#concept-cell title=concept-cell>cells</a> spanning multiple rows.</p>
 
   <p>A <dfn id=concept-column title=concept-column>column</dfn> is a complete set of
   slots from <span title=""><var title="">y</var>=0</span> to <span title=""><var title="">y</var>=<var title="">y<sub title="">height</sub></var>-1</span>, for a particular value of <var title="">x</var>. Columns can correspond to <code><a href=#the-col-element>col</a></code>
@@ -43858,8 +43886,656 @@
   </div>
 
 
-  <h4 id=examples-0><span class=secno>4.9.13 </span>Examples</h4>
+  <h4 id=table-sorting-model><span class=secno>4.9.13 </span><dfn>Table sorting model</dfn></h4>
 
+  <p>The <dfn id=attr-table-sortable title=attr-table-sortable><code>sortable</code></dfn> attribute on
+  <code><a href=#the-table-element>table</a></code> elements is a <a href=#boolean-attribute>boolean attribute</a>. When present, it indicates that
+  the user agent is to <a href=#sortable-ui>allow the user to sort</a> the <code><a href=#the-table-element>table</a></code>.</p>
+
+  <p>To make a column sortable in a <code><a href=#the-table-element>table</a></code> with a <code><a href=#the-thead-element>thead</a></code>, the column needs
+  to have <code><a href=#the-th-element>th</a></code> element that does not <a href=#attr-tdth-colspan title=attr-tdth-colspan>span multiple
+  columns</a> in a <code><a href=#the-thead-element>thead</a></code> above any rows that it is to sort.</p>
+
+  <p>To make a column sortable in a <code><a href=#the-table-element>table</a></code> without a <code><a href=#the-thead-element>thead</a></code>, the column
+  needs to have <code><a href=#the-th-element>th</a></code> element that does not <a href=#attr-tdth-colspan title=attr-tdth-colspan>span multiple
+  columns</a> in the first <code><a href=#the-tr-element>tr</a></code> element of the <code><a href=#the-table-element>table</a></code>, where that
+  <code><a href=#the-tr-element>tr</a></code> element is not in a <code><a href=#the-tfoot-element>tfoot</a></code>.</p>
+
+  <p>When the user selects a column by which to sort, the user agent sets the <code><a href=#the-th-element>th</a></code>
+  element's <dfn id=attr-th-sorted title=attr-th-sorted><code>sorted</code></dfn> attribute. This attribute can also
+  be set manually, to indicate that the table should be automatically sorted, even when scripts
+  modify the page on when the page is loaded.</p>
+
+  <p>The <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute, if specified, must have a value that
+  is a <a href=#set-of-space-separated-tokens>set of space-separated tokens</a> consisting of optionally a token whose value is an
+  <a href=#ascii-case-insensitive>ASCII case-insensitive</a> match for the string "<dfn id=attr-th-sorted-reversed title=attr-th-sorted-reversed><code>reversed</code></dfn>", and optionally a token whose value
+  is a <a href=#valid-non-negative-integer>valid non-negative integer</a> greater than zero, in either order.</p>
+
+  <p class=note>In other words, ignoring spaces and case, the <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute's value can be empty, "<code title="">reversed</code>", "<code title="">1</code>", "<code title="">reversed 1</code>", or
+  "<code title="">1 reversed</code>", where "1" is any number equal to or greater than 1.</p>
+
+  <p>While one or more <code><a href=#the-th-element>th</a></code> elements in the table have a <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute, the user agent will keep the table's data rows
+  sorted. The value of the attribute controls how the column is used in determining the sort order.
+  The <code title=attr-th-sorted-reversed><a href=#attr-th-sorted-reversed>reversed</a></code> keyword means that the <dfn id=column-sort-direction>column sort
+  direction</dfn> is <i>reversed</i>, rather than <i>normal</i>, which is the default if the keyword
+  is omitted. The number, if present, indicates the <dfn id=column-key-ordinality>column key ordinality</dfn>; if the number
+  is omitted, the column is the primary key, as if the value 1 had been specified.</p>
+
+  <p class=note>Thus, <code title="">sorted="1"</code> indicates the table's primary key, <code title="">sorted="2"</code> its secondary key, and so forth.</p>
+
+  <hr><p>A <dfn id=sorting-capable-th-element>sorting-capable <code>th</code> element</dfn> is a <code><a href=#the-th-element>th</a></code> element that matches
+  all the following conditions simultaneously:</p>
+
+  <ul><li><p>It corresponds to a <a href=#concept-cell title=concept-cell>cell</a> whose <i>width</i> is 1.
+   (Specifically, a <i>header cell</i>, since this is a <code><a href=#the-th-element>th</a></code> element.)</li>
+
+   <li><p>There is no <a href=#concept-cell title=concept-cell>cell</a> that corresponds to another
+   <a href=#sorting-capable-th-element>sorting-capable <code>th</code> element</a> that covers slots in the same <a href=#concept-column title=concept-column>column</a> but on a higher (earlier) <a href=#concept-row title=concept-row>row</a>.</li> <!-- only matters if there's a <thead> -->
+
+   <li>
+
+    <p>If the <a href=#concept-cell title=concept-cell>cell</a>'s <a href=#concept-table title=concept-table>table</a> has
+    a <a href=#concept-row-group title=concept-row-group>row group</a> corresponding to a <code><a href=#the-thead-element>thead</a></code>
+    element, the <a href=#concept-cell title=concept-cell>cell</a> is in a <a href=#concept-row-group title=concept-row-group>row
+    group</a> that corresponds to the <em>first</em> <code><a href=#the-thead-element>thead</a></code> element of the <a href=#concept-cell title=concept-cell>cell</a>'s <a href=#concept-table title=concept-table>table</a>.</p>
+
+    <p>Otherwise: the <a href=#concept-cell title=concept-cell>cell</a> is not in a <a href=#concept-row-group title=concept-row-group>row group</a> corresponding to a <code><a href=#the-tfoot-element>tfoot</a></code> element, and
+    the <a href=#concept-cell title=concept-cell>cell</a> is in the first <a href=#concept-row title=concept-row>row</a>
+    of the <a href=#concept-table title=concept-table>table</a>.</p>
+
+   </li>
+
+  </ul><p class=note>In other words, each <a href=#concept-column title=concept-column>column</a> can have one
+  <a href=#sorting-capable-th-element>sorting-capable <code>th</code> element</a>; this will be the highest <code><a href=#the-th-element>th</a></code> in
+  a <code><a href=#the-thead-element>thead</a></code> that spans no other columns, or, if there is no <code><a href=#the-thead-element>thead</a></code>, the
+  <code><a href=#the-th-element>th</a></code> in the first row (that is not in a <code><a href=#the-tfoot-element>tfoot</a></code>), assuming it spans no
+  columns.</p>
+
+  <p>The <dfn id=sorting-capable-th-elements-of-the-table-element>sorting-capable <code>th</code> elements of the <code>table</code> element</dfn> <var title="">table</var> are the <a href=#sorting-capable-th-element title="sorting-capable th element">sorting-capable
+  <code>th</code> elements</a> whose <a href=#concept-cell title=concept-cell>cell</a>'s <a href=#concept-table title=concept-table>table</a> is <var title="">table</var>.</p>
+
+  <p>A <code><a href=#the-table-element>table</a></code> element <var title="">table</var> is a <dfn id=sorting-capable-table-element>sorting-capable
+  <code>table</code> element</dfn> if there are one or more <a href=#sorting-capable-th-elements-of-the-table-element>sorting-capable <code>th</code>
+  elements of the <code>table</code> element</a> <var title="">table</var>.</p>
+
+  <p>A <code><a href=#the-th-element>th</a></code> element is a <dfn id=sorting-enabled-th-element>sorting-enabled <code>th</code> element</dfn> if it is a
+  <a href=#sorting-capable-th-element>sorting-capable <code>th</code> element</a> and it has a <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute.</p>
+
+  <p>The <dfn id=sorting-enabled-th-elements-of-the-table-element>sorting-enabled <code>th</code> elements of the <code>table</code> element</dfn> <var title="">table</var> are the <a href=#sorting-enabled-th-element title="sorting-enabled th element">sorting-enabled
+  <code>th</code> elements</a> whose <a href=#concept-cell title=concept-cell>cell</a>'s <a href=#concept-table title=concept-table>table</a> is <var title="">table</var>.</p>
+
+  <p>A <code><a href=#the-table-element>table</a></code> element <var title="">table</var> is a <dfn id=sorting-enabled-table-element>sorting-enabled
+  <code>table</code> element</dfn> if there are one or more <a href=#sorting-capable-th-elements-of-the-table-element>sorting-capable <code>th</code>
+  elements of the <code>table</code> element</a> <var title="">table</var>, and at least one of
+  them is a <a href=#sorting-enabled-th-element>sorting-enabled <code>th</code> element</a> (i.e. at least one has a <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute).</p>
+
+  <p>A <code><a href=#the-table-element>table</a></code> element is a <dfn id=table-element-with-a-user-agent-exposed-sorting-interface><code>table</code> element with a user-agent exposed
+  sorting interface</dfn> if it is a <a href=#sorting-capable-table-element>sorting-capable <code>table</code> element</a> and has
+  a <code title=attr-table-sortable><a href=#attr-table-sortable>sortable</a></code> attribute specified.</p>
+
+  <p>Each <code><a href=#the-table-element>table</a></code> element has a <dfn id=currently-sorting-flag>currently-sorting flag</dfn>, which must initially
+  be false.</p>
+
+  <hr><p>The <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute must not be specified on
+  <code><a href=#the-th-element>th</a></code> elements that are not <a href=#sorting-capable-th-element title="sorting-capable th element">sorting-capable
+  <code>th</code> elements</a>. The <code title=attr-table-sortable><a href=#attr-table-sortable>sortable</a></code> attribute
+  must not be specified on <code><a href=#the-table-element>table</a></code> elements that are not <a href=#sorting-capable-table-element title="sorting-capable
+  table element">sorting-capable <code>table</code> elements</a>.</p>
+
+  <div class=impl>
+
+  <p>To determine a <code><a href=#the-th-element>th</a></code> element's <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute's
+  <a href=#column-sort-direction>column sort direction</a> and <a href=#column-key-ordinality>column key ordinality</a>, user agents must use
+  the following algorithm:</p>
+
+  <ol><li><p>Let <var title="">direction</var> be <i>normal</i>.</p>
+
+   <li><p>Let <var title="">have explicit direction</var> be false.</p>
+
+   <li><p>Let <var title="">ordinality</var> be 1.</p>
+
+   <li><p>Let <var title="">have explicit ordinality</var> be false.</p>
+
+   <li><p>Let <var title="">tokens</var> be the result of <a href=#split-a-string-on-spaces title="split a string on
+   spaces">splitting the attribute's value on spaces</a>.</li>
+
+   <li>
+
+    <p>For each token <var title="">token</var> in <var title="">tokens</var>, run the appropriate
+    steps from the following list:</p>
+
+    <dl class=switch><dt>If <var title="">have explicit direction</var> is false and <var title="">token</var> is an
+     <a href=#ascii-case-insensitive>ASCII case-insensitive</a> match for the string "<code title=attr-th-sorted-reversed><a href=#attr-th-sorted-reversed>reversed</a></code>"</dt>
+
+     <dd>
+
+      <p>Let <var title="">direction</var> be <i>reversed</i> and <var title="">have explicit
+      direction</var> be true.</p>
+
+     </dd>
+
+
+     <dt>If <var title="">have explicit ordinality</var> is false</dt>
+
+     <dd>
+
+      <p><a href=#rules-for-parsing-integers title="rules for parsing integers">Parse <var title="">token</var> as an
+      integer</a>. If this resulted in an error or the value zero, then ignore the token.
+      Otherwise, set <var title="">ordinality</var> to the parsed value, and set <var title="">have
+      explicit ordinality</var> to true.</p>
+
+     </dd>
+
+
+     <dt>Otherwise</dt>
+
+     <dd><p>Ignore the token.</dd>
+
+    </dl></li>
+
+   <li><p>The <a href=#column-sort-direction>column sort direction</a> is the value of <var title="">direction</var>, and
+   the <a href=#column-key-ordinality>column key ordinality</a> is the value of <var title="">ordinality</var>.</li>
+
+  </ol></div>
+
+  <p>A <code><a href=#the-table-element>table</a></code> must not have two <code><a href=#the-th-element>th</a></code> elements whose <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute have the same <a href=#column-key-ordinality>column key
+  ordinality</a>.</p>
+
+  <div class=impl>
+
+  <hr><p>The <dfn id=table-sorting-algorithm>table sorting algorithm</dfn>, which is applied to a <code><a href=#the-table-element>table</a></code>, is as
+  follows:</p>
+
+  <ol><li><p>Let <var title="">table</var> be the <code><a href=#the-table-element>table</a></code> element being sorted.</li>
+
+   <li><p>If <var title="">table</var>'s <a href=#currently-sorting-flag>currently-sorting flag</a> is true, then abort
+   these steps.</li>
+
+   <li><p>Set <var title="">table</var>'s <a href=#currently-sorting-flag>currently-sorting flag</a> to true.</li>
+
+   <li><p><a href=#fire-a-simple-event>Fire a simple event</a> named <code title=event-sort>sort</code> that is
+   cancelable at <var title="">table</var>.</li>
+
+   <li><p>If the event fired in the previous step was canceled, then jump to the step labeled
+   <i>end</i> below.</li>
+
+   <li>
+
+    <p>If <var title="">table</var> is not now a <a href=#sorting-enabled-table-element>sorting-enabled <code>table</code>
+    element</a>, then jump to the step labeled <i>end</i> below.</p>
+
+    <p class=note>Even if <var title="">table</var> was a <a href=#sorting-enabled-table-element>sorting-enabled <code>table</code>
+    element</a> when the algorithm was invoked, the DOM might have been entirely changed by the
+    event handlers for the <code title=event-sort>sort</code> event, so this has to be verified at
+    this stage, not earlier.</p>
+
+   </li>
+
+   <li><p>Let <var title="">key heading cells</var> be the <a href=#sorting-enabled-th-elements-of-the-table-element>sorting-enabled <code>th</code>
+   elements of the <code>table</code> element</a> <var title="">table</var>.</li>
+
+   <li><p>Sort <var title="">key heading cells</var> in ascending order of the <a href=#column-key-ordinality>column key
+   ordinality</a> of their <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attributes, with those
+   having the same <a href=#column-key-ordinality>column key ordinality</a> being sorted in <a href=#tree-order>tree order</a>.</p>
+
+   <li>
+
+    <p>Let <var title="">row collection cursor</var> be a pointer to an element, initially pointing
+    at the first child of <var title="">table</var> that is after <var title="">table</var>'s first
+    <code><a href=#the-thead-element>thead</a></code>, if any, and that is either a <code><a href=#the-tbody-element>tbody</a></code> or a <code><a href=#the-tr-element>tr</a></code>
+    element, assuming there is one. If there is no such child, then jump to the step labeled
+    <i>end</i> below.</p>
+
+   </li>
+
+   <li><p>If <var title="">table</var> has no <a href=#concept-row-group title=concept-row-group>row group</a>
+   corresponding to a <code><a href=#the-thead-element>thead</a></code> element, then set <var title="">ignore first group</var> to
+   true. Otherwise, set it to false.</li>
+
+   <li><p><i>Row loop</i>: Let <var title="">rows</var> be an empty list of <code><a href=#the-tr-element>tr</a></code>
+   elements.</li>
+
+   <li>
+
+    <p>Run the appropriate steps from the following list:</p>
+
+    <dl class=switch><dt>If <var title="">row collection cursor</var> points to a <code><a href=#the-tr-element>tr</a></code> element
+
+     <dd>
+
+      <ol><li><p><i>Collect</i>: Append the element pointed to by <var title="">row collection
+       cursor</var> to <var title="">rows</var>.</li>
+
+       <li><p>If there are no <code><a href=#the-tr-element>tr</a></code> or <code><a href=#the-tbody-element>tbody</a></code> children of <var title="">table</var> that are later siblings of the element pointed to by <var title="">row
+       collection cursor</var>, or if the next such child is a <code><a href=#the-tbody-element>tbody</a></code> element, then jump
+       to the step labeled <i>group</i> below.</li>
+
+       <li><p>Let <var title="">row collection cursor</var> point to the next <code><a href=#the-tr-element>tr</a></code> child
+       of <var title="">table</var> that is a later sibling of the element pointed to by <var title="">row collection cursor</var>.</li>
+
+       <li><p>Returned to the step labeled <i>collect</i> above.</li>
+
+      </ol></dd>
+
+
+     <dt>If <var title="">row collection cursor</var> points to a <code><a href=#the-tbody-element>tbody</a></code> element
+
+     <dd>
+
+      <ol><li><p>Place all the <code><a href=#the-tr-element>tr</a></code> element children of the element pointed to by <var title="">row collection cursor</var> into <var title="">rows</var>, in <a href=#tree-order>tree
+       order</a>.</li>
+
+       <li><p>If <var title="">rows</var> is empty, jump to the step labeled <i>increment loop</i>
+       below.</li>
+
+      </ol></dd>
+
+    </dl></li>
+
+   <li><p><i>Group</i>: Let <var title="">groups</var> be an empty list of groups of <code><a href=#the-tr-element>tr</a></code>
+   elements.</li>
+
+   <li><p>Let <var title="">group</var> be an empty group of <code><a href=#the-tr-element>tr</a></code> elements.</li>
+
+   <li><p>Let <var title="">group cursor</var> be a pointer to an element, initially pointing at the
+   first <code><a href=#the-tr-element>tr</a></code> element in <var title="">rows</var>.</li>
+
+   <li><p><i>Start group</i>: Let <var title="">pending rows in group</var> be 1.</li>
+
+   <li><p><i>Group loop</i>: Append the <code><a href=#the-tr-element>tr</a></code> element pointed to by <var title="">group
+   cursor</var> to <var title="">group</var>.</li>
+
+   <li><p>If there are any <a href=#concept-cell title=concept-cell>cells</a> whose highest <a href=#concept-row title=concept-row>row</a>'s element is the one pointed to by <var title="">group
+   cursor</var>, then let <var title="">tallest height</var> be the number of rows covered by the
+   tallest such <a href=#concept-cell title=concept-cell>cell</a>.</li>
+
+   <li><p>If <var title="">tallest height</var> is greater than <var title="">pending rows in
+   group</var> then set <var title="">pending rows in group</var> to <var title="">tallest
+   height</var>.</li>
+
+   <li><p>Decrement <var title="">pending rows in group</var> by one.</li>
+
+   <li><p>Let <var title="">group cursor</var> point to the next <code><a href=#the-tr-element>tr</a></code> element in <var title="">rows</var>, if any; otherwise, let it be null.</li>
+
+   <li><p>If <var title="">group cursor</var> is not null and <var title="">pending rows in
+   group</var> is not zero, return to the step labeled <i>group loop</i>.</li>
+
+   <li><p>Append a new group to <var title="">groups</var> consisting of the <code><a href=#the-tr-element>tr</a></code>
+   elements in <var title="">group</var>.</li>
+
+   <li><p>Empty <var title="">group</var>.</li>
+
+   <li><p>If <var title="">group cursor</var> is not null, then return to the step labeled <i>start
+   group</i>.</li>
+
+   <li><p>If <var title="">ignore first group</var> is true, then drop the first roup in <var title="">groups</var> and set <var title="">ignore first group</var> to false.</li>
+
+   <li><p><i>Drop leading header groups</i>: If <var title="">groups</var> is now empty, jump to the
+   step labeled <i>increment loop</i> below.</li>
+
+   <!-- if you insert steps here, update the next step -->
+
+   <li><p>If the first group of <var title="">groups</var> consists of <code><a href=#the-tr-element>tr</a></code> elements
+   whose element children are all <code><a href=#the-th-element>th</a></code> elements, then drop the first group in <var title="">groups</var> and return to the previous step (labeled <i>drop leading header
+   groups</i>).</li>
+
+   <li><p>Let <var title="">insertion point</var> be a placeholder in a DOM tree, which can be used
+   to reinsert nodes at a specific point in the DOM. Insert <var title="">insertion point</var> into
+   the parent of the first <code><a href=#the-tr-element>tr</a></code> element of the first group in <var title="">groups</var>,
+   immediately before that <code><a href=#the-tr-element>tr</a></code> element.</li>
+
+   <li>
+
+    <p>Sort the groups in <var title="">groups</var>, using the following algorithm to decide the
+    relative order of any two groups <var title="">a</var> and <var title="">b</var> (the algorithm
+    either returns that <var title="">a</var> comes before <var title="">b</var>, or that <var title="">b</var> comes before <var title="">a</var>):</p>
+
+    <ol><li><p>Let <var title="">key index</var> be an index into <var title="">key heading
+     cells</var>, initially denoting the first element in the list.</li>
+
+     <li><p>Let <var title="">direction</var> be a sort direction, initially <i>ascending</i>. Its
+     other possible value is <i>descending</i>. When <var title="">direction</var> is
+     <i>toggled</i>, that means that if its value is <i>ascending</i>, it must be changed to
+     <i>descending</i>, and when its value is <i>descending</i>, it must be changed to
+     <i>ascending</i>.</li>
+
+     <li><p><i>Column loop</i>: Let <var title="">th</var> be the <var title="">key index</var>th
+     <code><a href=#the-th-element>th</a></code> in <var title="">key heading cells</var>.</li>
+
+     <li><p>If <var title="">th</var>'s <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute's
+     <a href=#column-sort-direction>column sort direction</a> is <i>reversed</i>, then toggle <var title="">direction</var>.</li>
+
+     <li><p>Let <var title="">tentative order</var> be the result of <a href=#comparing-two-row-groups-using-the-th-element>comparing two row groups
+     using the <code>th</code> element</a> <var title="">th</var>, with <var title="">a</var> and
+     <var title="">b</var> as the rows.</li>
+
+     <li><p>If <var title="">tentative order</var> is not "equal", then jump to the step labeled
+     <i>return</i> below.</li>
+
+     <li><p>Increment <var title="">key index</var>.</li>
+
+     <li><p>If <var title="">key index</var> still denotes a <code><a href=#the-th-element>th</a></code> element in <var title="">key heading cells</var>, then jump back to the step above labeled <i>column
+     loop</i>.</li>
+
+     <li><p>If <var title="">a</var>'s <code><a href=#the-tr-element>tr</a></code> elements precede <var title="">b</var>'s in
+     <a href=#tree-order>tree order</a>, then let <var title="">tentative order</var> be "a before b".
+     Otherwise, let <var title="">tentative order</var> be "b before a".</li>
+
+     <li><p><i>Return</i>: Return the relative order given by the matching option from the following
+     list:</p>
+
+      <dl class=switch><dt>If <var title="">direction</var> is <i>ascending</i> and <var title="">tentative
+       order</var> is "a before b"</dt>
+
+       <dd>Return that <var title="">a</var> comes before <var title="">b</var>.</dd>
+
+
+       <dt>If <var title="">direction</var> is <i>ascending</i> and <var title="">tentative
+       order</var> is "b before a"</dt>
+
+       <dd>Return that <var title="">b</var> comes before <var title="">a</var>.</dd>
+
+
+       <dt>If <var title="">direction</var> is <i>descending</i> and <var title="">tentative
+       order</var> is "a before b"</dt>
+
+       <dd>Return that <var title="">b</var> comes before <var title="">a</var>.</dd>
+
+
+       <dt>If <var title="">direction</var> is <i>descending</i> and <var title="">tentative
+       order</var> is "b before a"</dt>
+
+       <dd>Return that <var title="">a</var> comes before <var title="">b</var>.</dd>
+
+      </dl></li>
+
+    </ol><p>When the user agent is required to <dfn id=comparing-two-row-groups-using-the-th-element title="comparing two row groups using the th
+    element">compare two row groups using the <code>th</code> element</dfn> <var title="">th</var>,
+    with <var title="">a</var> and <var title="">b</var> being the two row groups respectively, the
+    user agent must run the following steps:</p>
+
+    <ol><li><p>Let <var title="">x</var> be the <var title="">x</var>-coordinate of the slots that
+     <code><a href=#the-th-element>th</a></code> covers in its <a href=#concept-table title=concept-table>table</a>.</li>
+
+     <li>
+
+      <p>Let <var title="">cell<sub>a</sub></var> be the element corresponding to the <a href=#concept-cell title=concept-cell>cell</a> in the first <a href=#concept-row title=concept-row>row</a> of group
+      <var title="">a</var> that covers the slot in that <a href=#concept-row title=concept-row>row</a> whose
+      <var title="">x</var>-coordinate is <var title="">x</var>.</p>
+
+      <p>Let <var title="">cell<sub>b</sub></var> be the element corresponding to the <a href=#concept-cell title=concept-cell>cell</a> in the first <a href=#concept-row title=concept-row>row</a> of group
+      <var title="">b</var> that covers the slot in that <a href=#concept-row title=concept-row>row</a> whose
+      <var title="">x</var>-coordinate is <var title="">x</var>.</p>
+
+      <!-- there can't be two cells that cover the slot, unusually, because the only way that can
+      happen is if there's a cell that's extended into this row from above, and the groups, by
+      virtue of the way they are created above, never have cells that extend into them from above.
+      -->
+
+      <p>In either case, if there's no <a href=#concept-cell title=concept-cell>cell</a> that actually covers
+      the slot, then use the value <i>null</i> instead.</p>
+
+     </li>
+
+     <li>
+
+      <p>Let <var title="">type<sub>a</sub></var> and <var title="">value<sub>a</sub></var> be
+      the <a href=#type-and-value-of-the-cell>type and value of the cell</a> <var title="">cell<sub>a</sub></var>, as defined
+      below.</p>
+
+      <p>Let <var title="">type<sub>b</sub></var> and <var title="">value<sub>b</sub></var> be
+      the <a href=#type-and-value-of-the-cell>type and value of the cell</a> <var title="">cell<sub>b</sub></var>, as defined
+      below.</p>
+
+      <p>The <dfn id=type-and-value-of-the-cell>type and value of the cell</dfn> <var title="">cell</var> are computed as follows.</p>
+
+      <ol><li><p>If <var title="">cell</var> is <i>null</i>, then the type is "string" and the value is
+       the empty string; abort these steps.</li>
+
+       <li><p>If, ignoring <a href=#inter-element-whitespace>inter-element whitespace</a> and <a href=#comment-0>Comment</a> nodes,
+       <var title="">cell</var> has only one child and that child is a <code><a href=#the-data-element>data</a></code> element,
+       then the value is the value of that <code><a href=#the-data-element>data</a></code> element's <code title=attr-data-value><a href=#attr-data-value>value</a></code> attribute, if there is one, or the empty string
+       otherwise; the type is "string".</p>
+
+       <li>
+
+        <p>If, ignoring <a href=#inter-element-whitespace>inter-element whitespace</a> and <a href=#comment-0>Comment</a> nodes, <var title="">cell</var> has only one child and that child is a <code><a href=#the-time-element>time</a></code> element, then
+        the value is the <a href="#machine-readable-equivalent-of-the-element's-contents">machine-readable equivalent of the element's contents</a>, if any,
+        and the type is the kind of value that is thus obtained
+       (a <a href=#concept-month title=concept-month>month</a>,
+        a <a href=#concept-date title=concept-date>date</a>,
+        a <a href=#concept-yearless-date title=concept-yearless-date>yearless date</a>,
+        a <a href=#concept-time title=concept-time>time</a>,
+        a <a href=#concept-datetime-local title=concept-datetime-local>local date and time</a>,
+        a <a href=#concept-timezone title=concept-timezone>time-zone offset</a>,
+        a <a href=#concept-datetime title=concept-datetime>global date and time</a>,
+        a <a href=#concept-week title=concept-week>week</a>,
+        a year, or
+        a <a href=#concept-duration title=concept-duration>duration</a>);
+        abort these steps after completing this one.</p>
+
+        <p>If there is no machine-readable equivalent, then the type is "string" and the value is
+        the empty string.</p>
+
+        <p>If the type is
+        a <a href=#concept-month title=concept-month>month</a>,
+        a <a href=#concept-date title=concept-date>date</a>,
+        a <a href=#concept-week title=concept-week>week</a>, or
+        a year,
+        then change the value to be the instant in time (with no time zone) that describes the
+        earliest moment that the value represents, and change the type to be
+        a <a href=#concept-datetime-local title=concept-datetime-local>local date and time</a>.</p>
+
+        <p class=example>For example, if the cell was
+        <code><td><time>2011-11</time></code> then for sorting purposes the value is
+        interpreted as "2011-11-01T00:00:00.000" and the type is treated as a <a href=#concept-datetime-local title=concept-datetime-local>local date and time</a> rather than a <a href=#concept-month title=concept-month>month</a>.</p>
+
+        <p class=example>Similarly, if the cell was <code><td><time
+        datetime="2011">MMXIV</time></code> then for sorting purposes the value is interpreted as
+        "2014-01-01T00:00:00.000" and the type is treated as a <a href=#concept-datetime-local title=concept-datetime-local>local date and time</a> rather than a year.</p>
+
+       </li>
+
+       <li><p>The value is the element's <code><a href=#textcontent>textContent</a></code>. The type is "string".</li>
+
+      </ol></li>
+
+     <li>
+
+      <p>If <var title="">type<sub>a</sub></var> and <var title="">type<sub>b</sub></var> are not
+      equal, then: return "a before b" if <var title="">type<sub>a</sub></var> is earlier in the
+      following list than <var title="">type<sub>b</sub></var>, otherwise, return "b before a";
+      then, abort these steps.</p>
+
+      <ol class=brief><li><a href=#concept-time title=concept-time>time</a></li>
+       <li><a href=#concept-yearless-date title=concept-yearless-date>yearless date</a></li>
+       <li><a href=#concept-datetime-local title=concept-datetime-local>local date and time</a></li>
+       <li><a href=#concept-datetime title=concept-datetime>global date and time</a></li>
+       <li><a href=#concept-timezone title=concept-timezone>time-zone offset</a></li>
+       <li><a href=#concept-duration title=concept-duration>duration</a></li>
+       <li>"string"</li>
+      </ol></li>
+
+     <li><p>If <var title="">value<sub>a</sub></var> and <var title="">value<sub>b</sub></var> are
+     equal, then return "equal" and abort these steps.</li>
+
+     <li>
+
+      <p>If <var title="">type<sub>a</sub></var> and <var title="">type<sub>b</sub></var> are not
+      "string", then: return "a before b" if <var title="">value<sub>a</sub></var> is earlier
+      than <var title="">value<sub>b</sub></var>, and return "b before a" otherwise.</p>
+
+      <p>Values sort in their natural order, with the following additional constraints:</p>
+
+      <p>For <a href=#concept-time title=concept-time>time</a> values, 00:00:00.000 is the earliest value and
+      23:59:59.999 is the latest value.</p>
+
+      <p>For <a href=#concept-yearless-date title=concept-yearless-date>yearless date</a> values, 01-01 is the earliest
+      value and 12-31 is the latest value; 02-28 is earlier than 02-29 which is earlier than
+      03-01.</p>
+
+      <p>Values that are <a href=#concept-datetime-local title=concept-datetime-local>local date and time</a> compare as
+      if they were in the same time zone.</p>
+
+      <!-- no ambiguity for <span title="concept-datetime">global date and time</span> -->
+
+      <p>For <a href=#concept-timezone title=concept-timezone>time-zone offset</a> values, -23:59 is the earliest
+      value and +23:59 is the latest value.</p>
+
+      <!-- MONTHS: <span title="concept-duration">duration</span> is unambiguous until we add months -->
+
+     </li>
+
+     <!-- At this point we know that they are both strings and they're not equal. -->
+
+     <li>
+
+      <p class=XXX>Return "a before b" if <var title="">value<sub>a</sub></var> is earlier than
+      <var title="">value<sub>b</sub></var>, and return "b before a" otherwise; for these purposes,
+      the strings must be compared using collation order of the <a href=#language>language</a> of the
+      <code><a href=#the-table-element>table</a></code> element to which <var title="">th</var>'s <a href=#concept-table title=concept-table>table</a> corresponds.</p>
+
+     </li>
+
+    </ol></li>
+
+
+   <li><p>Let <var title="">new order</var> be a list of <code><a href=#the-tr-element>tr</a></code> elements consisting of the
+   <code><a href=#the-tr-element>tr</a></code> elements of all the groups in the newly ordered <var title="">groups</var>, with
+   the <code><a href=#the-tr-element>tr</a></code> elements being in the same order as the groups to which they belong are in
+   <var title="">groups</var>, and the <code><a href=#the-tr-element>tr</a></code> elements within each such group themselves
+   being ordered in <a href=#tree-order>tree order</a>.</li>
+
+   <li><p><a href=#concept-node-remove title=concept-node-remove>Remove</a> all the <code><a href=#the-tr-element>tr</a></code> elements in <var title="">new order</var> from their parents.</li>
+
+   <li><p><a href=#concept-node-insert title=concept-node-insert>Insert</a> all the <code><a href=#the-tr-element>tr</a></code> elements in <var title="">new order</var> into the DOM at the location of <var title="">insertion point</var>, in
+   the order these elements are found in <var title="">new order</var>.</li>
+
+   <!-- done with this set of rows -->
+
+   <li><p>Remove <var title="">insertion point</var> from the DOM.</li>
+
+   <li><p><i>Increment loop</i>: If there are no <code><a href=#the-tr-element>tr</a></code> or <code><a href=#the-tbody-element>tbody</a></code> children of
+   <var title="">table</var> that are later siblings of the element pointed to by <var title="">row
+   collection cursor</var>, then jump to the step labeled <i>end</i> below.</li>
+
+   <li><p>Let <var title="">row collection cursor</var> point to the next <code><a href=#the-tr-element>tr</a></code> or
+   <code><a href=#the-tbody-element>tbody</a></code> child of <var title="">table</var> that is a later sibling of the element
+   pointed to by <var title="">row collection cursor</var>.</li>
+
+   <li><p>Return to the step labeled <i>row loop</i> above.</li>
+
+   <li><p><i>End</i>: Set <var title="">table</var>'s <a href=#currently-sorting-flag>currently-sorting flag</a> to
+   false.</li>
+
+  </ol><p>When any of the descendants of a <a href=#sorting-enabled-table-element>sorting-enabled <code>table</code> element</a> change
+  in any way (including attributes changing), and when a <code><a href=#the-table-element>table</a></code> element becomes a
+  <a href=#sorting-enabled-table-element>sorting-enabled <code>table</code> element</a>, the <code><a href=#the-table-element>table</a></code> element is said to
+  become <dfn id=a-table-with-a-pending-sort>a table with a pending sort</dfn>.</p>
+
+  <p>When the user agent is to <dfn id=sort-the-tables-with-pending-sorts>sort the tables with pending sorts</dfn>, which happens during
+  the <a href=#perform-a-microtask-checkpoint>perform a microtask checkpoint</a> algorithm, the user agent must run the following
+  algorithm:</p>
+
+  <ol><li><p>Let <var title="">tables</var> be a list of each <code><a href=#the-table-element>table</a></code> in the <a href=#unit-of-related-similar-origin-browsing-contexts>unit of
+   related similar-origin browsing contexts</a> that is <a href=#a-table-with-a-pending-sort>a table with a pending sort</a>,
+   in the order that they became such, with those that become such at the same time being listed in
+   <a href=#tree-order>tree order</a>.</p>
+
+   <li><p>Let all the <code><a href=#the-table-element>table</a></code> elements in <var title="">tables</var> no longer be <a href=#a-table-with-a-pending-sort title="a table with a pending sort">tables with a pending sort</a>.</li>
+
+   <li><p>Apply the <a href=#table-sorting-algorithm>table sorting algorithm</a> to each <code><a href=#the-table-element>table</a></code> in <var title="">tables</var>, in order.</li>
+
+  </ol><hr><p>When the user agent is to <dfn id=set-the-sort-key>set the sort key</dfn> to a <code><a href=#the-th-element>th</a></code> element <var title="">target</var>, it must run the following algorithm:</p>
+
+  <ol><li><p>Let <var title="">table</var> be the <code><a href=#the-table-element>table</a></code> of the <a href=#concept-table title=concept-table>table</a> of which <var title="">target</var> is a header cell.</li>
+
+   <li><p>If <code><a href=#the-th-element>th</a></code> is a <a href=#sorting-enabled-th-element>sorting-enabled <code>th</code> element</a> whose
+   <a href=#column-key-ordinality>column key ordinality</a> is 1, then: if its <a href=#column-sort-direction>column sort direction</a> is
+   <i>normal</i>, set that element's <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute to the
+   string "<code title="">reversed</code>", otherwise, set it to the empty string; then, abort these
+   steps.</li>
+
+   <li><p>Let <var title="">current headers</var> be the <a href=#sorting-enabled-th-elements-of-the-table-element>sorting-enabled <code>th</code>
+   elements of the <code>table</code> element</a> <var title="">table</var>, excluding <var title="">target</var>.</li>
+
+   <li><p>Sort <var title="">current headers</var> by their <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attributes' <a href=#column-key-ordinality>column key ordinality</a>, in ascending
+   order, with elements that have the same <a href=#column-key-ordinality>column key ordinality</a> being sorted in
+   <a href=#tree-order>tree order</a>.</li>
+
+   <li><p>Let <var title="">level</var> be 2.</li>
+
+   <li>
+
+    <p>For each <code><a href=#the-th-element>th</a></code> element <var title="">th</var> in <var title="">current
+    headers</var>, in order, run the following substeps:</p>
+
+    <ol><li><p>If <var title="">th</var>'s <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute's
+     <a href=#column-sort-direction>column sort direction</a> is <i>normal</i>, then set <var title="">th</var>'s <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute to a <a href=#valid-integer>valid integer</a> whose value is
+     <var title="">level</var>. Otherwise, set it to the concatenation of the string "<code title="">reversed</code>", a U+0020 SPACE character, and a <a href=#valid-integer>valid integer</a> whose
+     value is <var title="">level</var>.</p>
+
+     <li><p>Increment <var title="">level</var> by 1.</li>
+
+    </ol></li>
+
+   <li><p>Set <var title="">target</var>'s <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute to
+   the empty string.</li>
+
+  </ol><hr><p>The <a href=#activation-behavior>activation behavior</a> of the <a href=#sorting-capable-th-elements-of-the-table-element title="sorting-capable th elements of the
+  table element">sorting-capable <code>th</code> elements of</a> all <a href=#table-element-with-a-user-agent-exposed-sorting-interface title="table element
+  with a user-agent exposed sorting interface"><code>table</code> elements with a user-agent exposed
+  sorting interface</a> is to <a href=#set-the-sort-key>set the sort key</a> to the <code><a href=#the-th-element>th</a></code> element.</p>
+
+  <p class=note>The <code><a href=#the-table-element>table</a></code> will be sorted the next time the user agent <a href=#perform-a-microtask-checkpoint title="perform a microtask checkpoint">performs a microtask checkpoint</a>.</p>
+
+  </div>
+
+  <dl class=domintro><dt><var title="">th</var> . <code title=dom-th-sort><a href=#dom-th-sort>sort</a></code>()</dt>
+
+   <dd>
+
+    <p>Act as if the user had indicated that this was to be the new primary sort column.</p>
+
+    <p>The <code><a href=#the-table-element>table</a></code> won't actually be sorted until the script terminates.</p>
+
+   </dd>
+
+
+   <dt><var title="">table</var> . <code title=dom-table-stopSorting><a href=#dom-table-stopsorting>stopSorting</a></code>()</dt>
+
+   <dd>
+
+    <p>Removes all the <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attributes that are causing the
+    table to automatically sort its contents, if any.</p>
+
+   </dd>
+
+  </dl><div class=impl>
+
+  <p>The <code><a href=#the-th-element>th</a></code> element's <dfn id=dom-th-sort title=dom-th-sort><code>sort()</code></dfn> method, when
+  invoked, must run the following steps:</p>
+
+  <ol><li><p>If the <code><a href=#the-th-element>th</a></code> element is not a <a href=#sorting-capable-th-element>sorting-capable <code>th</code>
+   element</a>, then abort these steps.</li>
+
+   <li>
+
+    <p><a href=#set-the-sort-key>Set the sort key</a> to the <code><a href=#the-th-element>th</a></code> element.</p>
+
+    <p class=note>The <code><a href=#the-table-element>table</a></code> will be sorted the next time the user agent <a href=#perform-a-microtask-checkpoint title="perform a microtask checkpoint">performs a microtask checkpoint</a>.</p>
+
+   </li>
+
+  </ol><p>The <code><a href=#the-table-element>table</a></code> element's <dfn id=dom-table-stopsorting title=dom-table-stopSorting><code>stopSorting()</code></dfn> method, when invoked, must remove
+  the <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute of all the <a href=#sorting-enabled-th-elements-of-the-table-element>sorting-enabled
+  <code>th</code> elements of the table element</a> on which the method was invoked.</p>
+
+  </div>
+
+
+  <h4 id=examples-0><span class=secno>4.9.14 </span>Examples</h4>
+
   <p><i>This section is non-normative.</i></p>
 
   <p>The following shows how might one mark up the bottom part of
@@ -66243,6 +66919,7 @@
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onseeking title=handler-onseeking>onseeking</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onselect title=handler-onselect>onselect</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onshow title=handler-onshow>onshow</a>;
+           attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsort title=handler-onsort>onsort</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onstalled title=handler-onstalled>onstalled</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-window-onstorage title=handler-window-onstorage>onstorage</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsubmit title=handler-onsubmit>onsubmit</a>;
@@ -72904,7 +73581,8 @@
   <p>An <a href=#event-loop>event loop</a> must continually run through the
   following steps for as long as it exists:</p>
 
-  <ol><li><p>Run the oldest <a href=#concept-task title=concept-task>task</a> on one of the <a href=#event-loop>event
+  <ol><!-- if you add a step here, make sure to go through the spec updating references to the "first
+   step" of the event loop --><li><p>Run the oldest <a href=#concept-task title=concept-task>task</a> on one of the <a href=#event-loop>event
    loop</a>'s <a href=#task-queue title="task queue">task queues</a>, if any, ignoring tasks whose
    associated <code><a href=#document>Document</a></code>s are not <a href=#fully-active>fully active</a>. The user agent may pick any
    <a href=#task-queue>task queue</a>.</li>
@@ -72915,7 +73593,8 @@
    <li><p>If the <a href=#storage-mutex>storage mutex</a> is now owned by the <a href=#event-loop>event loop</a>, release it
    so that it is once again free.</li>
 
-   <li><p>Remove that task from its <a href=#task-queue>task queue</a>.</li>
+   <li><p>If a task was run in the first step above, remove that task from its <a href=#task-queue>task
+   queue</a>.</li>
 
    <li><p><a href=#perform-a-microtask-checkpoint>Perform a microtask checkpoint</a>.</li>
 
@@ -72935,6 +73614,8 @@
   <ol><li><p>Let the <a href=#running-mutation-observers>running mutation observers</a> flag be
    true.</li>
 
+   <li><p><a href=#sort-the-tables-with-pending-sorts>Sort the tables with pending sorts</a>.</li>
+
    <li>
 
     <p><a href=#concept-mo-invoke title=concept-mo-invoke>Invoke
@@ -73602,6 +74283,7 @@
     <tr><td><dfn id=handler-onseeking title=handler-onseeking><code>onseeking</code></dfn> <td> <code title=event-media-seeking><a href=#event-media-seeking>seeking</a></code>
     <tr><td><dfn id=handler-onselect title=handler-onselect><code>onselect</code></dfn> <td> <code title=event-select>select</code> <!-- widely used --> <!-- [CSSOM] -->
     <tr><td><dfn id=handler-onshow title=handler-onshow><code>onshow</code></dfn> <td> <code title=event-show>show</code>
+    <tr><td><dfn id=handler-onsort title=handler-onsort><code>onsort</code></dfn> <td> <code title=event-sort>sort</code>
     <tr><td><dfn id=handler-onstalled title=handler-onstalled><code>onstalled</code></dfn> <td> <code title=event-media-stalled><a href=#event-media-stalled>stalled</a></code>
     <tr><td><dfn id=handler-onsubmit title=handler-onsubmit><code>onsubmit</code></dfn> <td> <code title=event-submit>submit</code> <!-- widely used -->
     <tr><td><dfn id=handler-onsuspend title=handler-onsuspend><code>onsuspend</code></dfn> <td> <code title=event-media-suspend><a href=#event-media-suspend>suspend</a></code>
@@ -96520,7 +97202,13 @@
   <!-- http://software.hixie.ch/utilities/js/live-dom-viewer/saved/1793 -->
   <!-- note that the "rules for parsing dimension values" can't return 0, if the value is "0" they treat it as an error -->
 
+  <hr><p id=sortable-ui>User agents are expected to render <a href=#sorting-capable-th-elements-of-the-table-element title="sorting-capable th elements of
+  the table element">sorting-capable <code>th</code> elements of</a> all <a href=#table-element-with-a-user-agent-exposed-sorting-interface title="table
+  element with a user-agent exposed sorting interface"><code>table</code> elements with a user-agent
+  exposed sorting interface</a> in such a manner as to indicate that activating the elements will
+  cause the table to be sorted.</p>
 
+
   <h4 id=form-controls><span class=secno>14.3.10 </span>Form controls</h4>
 
   <pre class=css>@namespace url(http://www.w3.org/1999/xhtml);
@@ -102952,6 +103640,11 @@
      <td> <code title=event-show>show</code> event handler
      <td> <a href=#event-handler-content-attributes title="event handler content attributes">Event handler content attribute</a>
 
+    <tr><th id=ix-handler-onsort> <code title="">onsort</code>
+     <td> <a href=#handler-onsort title=handler-onsort>HTML elements</a>
+     <td> <code title=event-sort>sort</code> event handler
+     <td> <a href=#event-handler-content-attributes title="event handler content attributes">Event handler content attribute</a>
+
     <tr><th id=ix-handler-onstalled> <code title="">onstalled</code>
      <td> <a href=#handler-onstalled title=handler-onstalled>HTML elements</a>
      <td> <code title=event-media-stalled><a href=#event-media-stalled>stalled</a></code> event handler

Modified: index
===================================================================
--- index	2012-12-19 20:11:40 UTC (rev 7596)
+++ index	2012-12-26 23:58:23 UTC (rev 7597)
@@ -248,7 +248,7 @@
 
   <header class=head id=head><p><a class=logo href=http://www.whatwg.org/><img alt=WHATWG height=101 src=/images/logo width=101></a></p>
    <hgroup><h1 class=allcaps>HTML</h1>
-    <h2 class="no-num no-toc">Living Standard — Last Updated 19 December 2012</h2>
+    <h2 class="no-num no-toc">Living Standard — Last Updated 26 December 2012</h2>
    </hgroup><dl><dt><strong>Web developer edition:</strong></dt>
     <dd><strong><a href=http://developers.whatwg.org/>http://developers.whatwg.org/</a></strong></dd>
     <dt>Multiple-page version:</dt>
@@ -665,7 +665,8 @@
       <ol>
        <li><a href=#forming-a-table><span class=secno>4.9.12.1 </span>Forming a table</a></li>
        <li><a href=#header-and-data-cell-semantics><span class=secno>4.9.12.2 </span>Forming relationships between data cells and header cells</a></ol></li>
-     <li><a href=#examples-0><span class=secno>4.9.13 </span>Examples</a></ol></li>
+     <li><a href=#table-sorting-model><span class=secno>4.9.13 </span>Table sorting model</a></li>
+     <li><a href=#examples-0><span class=secno>4.9.14 </span>Examples</a></ol></li>
    <li><a href=#forms><span class=secno>4.10 </span>Forms</a>
     <ol>
      <li><a href=#introduction-1><span class=secno>4.10.1 </span>Introduction</a>
@@ -4049,7 +4050,7 @@
      <li><dfn id=dom-element-id title=dom-Element-id><code>id</code></dfn> attribute</li>
      <li><dfn id=textcontent><code>textContent</code></dfn> attribute</li>
 
-     <li>The <dfn id=concept-node-insert title=concept-node-insert>insert</dfn>, <dfn id=concept-node-append title=concept-node-append>append</dfn>, and <dfn id=concept-node-replace title=concept-node-replace>replace</dfn> algorithms for nodes</li>
+     <li>The <dfn id=concept-node-insert title=concept-node-insert>insert</dfn>, <dfn id=concept-node-append title=concept-node-append>append</dfn>, <dfn id=concept-node-remove title=concept-node-remove>remove</dfn>, and <dfn id=concept-node-replace title=concept-node-replace>replace</dfn> algorithms for nodes</li>
      <li>The <dfn id=nodes-are-inserted>nodes are inserted</dfn> and <dfn id=nodes-are-removed>nodes are removed</dfn> concepts</li>
 
      <li><dfn id=event><code>Event</code></dfn> interface</li>
@@ -6353,6 +6354,9 @@
 
   <h5 id=durations><span class=secno>2.5.5.9 </span>Durations</h5>
 
+  <!-- if you add support for year and month durations, then search for MONTHS throughout the spec
+  (not just this section) for things that have to change -->
+
   <p>A <dfn id=concept-duration title=concept-duration>duration</dfn> consists of <!--MONTHS: either a number of
   months or--> a number of seconds.</p>
 
@@ -9662,6 +9666,7 @@
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onseeking title=handler-onseeking>onseeking</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onselect title=handler-onselect>onselect</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onshow title=handler-onshow>onshow</a>;
+           attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsort title=handler-onsort>onsort</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onstalled title=handler-onstalled>onstalled</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsubmit title=handler-onsubmit>onsubmit</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsuspend title=handler-onsuspend>onsuspend</a>;
@@ -10671,6 +10676,7 @@
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onseeking title=handler-onseeking>onseeking</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onselect title=handler-onselect>onselect</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onshow title=handler-onshow>onshow</a>;
+           attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsort title=handler-onsort>onsort</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onstalled title=handler-onstalled>onstalled</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsubmit title=handler-onsubmit>onsubmit</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsuspend title=handler-onsuspend>onsuspend</a>;
@@ -10803,6 +10809,7 @@
    <li><code title=handler-onseeking><a href=#handler-onseeking>onseeking</a></code></li>
    <li><code title=handler-onselect><a href=#handler-onselect>onselect</a></code></li>
    <li><code title=handler-onshow><a href=#handler-onshow>onshow</a></code></li>
+   <li><code title=handler-onsort><a href=#handler-onsort>onsort</a></code></li>
    <li><code title=handler-onstalled><a href=#handler-onstalled>onstalled</a></code></li>
    <li><code title=handler-onsubmit><a href=#handler-onsubmit>onsubmit</a></code></li>
    <li><code title=handler-onsuspend><a href=#handler-onsuspend>onsuspend</a></code></li>
@@ -21252,12 +21259,11 @@
 
   <div class=example>
 
-   <p>Here, a short table has its numeric values encoded using
-   <code><a href=#the-data-element>data</a></code> so that a script can provide a sorting mechanism
-   on each column, despite the numbers being presented in textual
-   form in one column and in a decomposed form in another.</p>
+   <p>Here, a short table has its numeric values encoded using <code><a href=#the-data-element>data</a></code> so that the
+   <a href=#table-sorting-model>table sorting model</a> can provide a sorting mechanism on each column, despite the
+   numbers being presented in textual form in one column and in a decomposed form in another.</p>
 
-   <pre><table class="sortable"> <!-- class used by script to find tables to which to add sorting controls -->
+   <pre><table sortable>
  <thead> <tr> <th> Game <th> Corporations <th> Map Size
  <tbody>
   <tr> <td> 1830 <td> <data value="8">Eight</data> <td> <data value="93">19+74 hexes (93 total)</data>
@@ -21455,9 +21461,8 @@
 
   </dl><div class=impl>
 
-  <p>The machine-readable equivalent of the element's contents must be
-  obtained from the element's <a href=#datetime-value>datetime value</a> by using the
-  following algorithm:</p>
+  <p>The <dfn id="machine-readable-equivalent-of-the-element's-contents">machine-readable equivalent of the element's contents</dfn> must be obtained from the
+  element's <a href=#datetime-value>datetime value</a> by using the following algorithm:</p>
 
   <ol><li><p>If <a href=#parse-a-month-string title="parse a month string">parsing a month
    string</a> from the element's <a href=#datetime-value>datetime value</a>
@@ -41443,6 +41448,7 @@
    total).</dd>
    <dt><a href=#element-dfn-attributes title=element-dfn-attributes>Content attributes</a>:</dt>
    <dd><a href=#global-attributes>Global attributes</a></dd>
+   <dd><code title=attr-table-sortable><a href=#attr-table-sortable>sortable</a></code></dd>
    <dt><a href=#element-dfn-dom title=element-dfn-dom>DOM interface</a>:</dt><!--TOPIC:DOM APIs-->
    <dd>
 <pre class=idl>interface <dfn id=htmltableelement>HTMLTableElement</dfn> : <a href=#htmlelement>HTMLElement</a> {
@@ -41460,6 +41466,8 @@
   readonly attribute <a href=#htmlcollection>HTMLCollection</a> <a href=#dom-table-rows title=dom-table-rows>rows</a>;
   <a href=#htmlelement>HTMLElement</a> <a href=#dom-table-insertrow title=dom-table-insertRow>insertRow</a>(optional long index);
   void <a href=#dom-table-deleterow title=dom-table-deleteRow>deleteRow</a>(long index);
+           attribute boolean <a href=#dom-table-sortable title=dom-table-sortable>sortable</a>;
+  void <a href=#dom-table-stopsorting title=dom-table-stopSorting>stopSorting</a>();
 };</pre>
    </dd>
   </dl><!--TOPIC:HTML--><p>The <code><a href=#the-table-element>table</a></code> element <a href=#represents>represents</a> data with
@@ -41547,6 +41555,9 @@
 
   </div>
 
+  <hr><p>The <code title=attr-table-sortable><a href=#attr-table-sortable>sortable</a></code> attribute is used in the <a href=#table-sorting-model>table
+  sorting model</a>.</p>
+
   <hr><!--TOPIC:DOM APIs--><dl class=domintro><dt><var title="">table</var> . <code title=dom-table-caption><a href=#dom-table-caption>caption</a></code> [ = <var title="">value</var> ]</dt>
    <dd>
     <p>Returns the table's <code><a href=#the-caption-element>caption</a></code> element.</p>
@@ -41795,7 +41806,13 @@
 
    <li><p>Otherwise, the method must remove the <var title="">index</var>th element in the <code title=dom-table-rows><a href=#dom-table-rows>rows</a></code> collection from its parent.</p>
 
-  </ol></div>
+  </ol><p>The <code title=dom-table-stopSorting><a href=#dom-table-stopsorting>stopSorting()</a></code> method is used in the <a href=#table-sorting-model>table
+  sorting model</a>.</p>
+
+  <p>The IDL attribute <dfn id=dom-table-sortable title=dom-table-sortable><code>sortable</code></dfn> must
+  <a href=#reflect>reflect</a> the <code title=attr-table-sortable><a href=#attr-table-sortable>sortable</a></code> content attribute.</p>
+
+  </div>
 <!--TOPIC:HTML-->
 
   <div class=example>
@@ -42638,11 +42655,14 @@
    <dd><code title=attr-tdth-headers><a href=#attr-tdth-headers>headers</a></code></dd>
    <dd><code title=attr-th-scope><a href=#attr-th-scope>scope</a></code></dd>
    <dd><code title=attr-th-abbr><a href=#attr-th-abbr>abbr</a></code></dd>
+   <dd><code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code></dd>
    <dt><a href=#element-dfn-dom title=element-dfn-dom>DOM interface</a>:</dt><!--TOPIC:DOM APIs-->
    <dd>
     <pre class=idl>interface <dfn id=htmltableheadercellelement>HTMLTableHeaderCellElement</dfn> : <a href=#htmltablecellelement>HTMLTableCellElement</a> {
            attribute DOMString <a href=#dom-th-scope title=dom-th-scope>scope</a>;
            attribute DOMString <a href=#dom-th-abbr title=dom-th-abbr>abbr</a>;
+           attribute DOMString <a href=#dom-th-sorted title=dom-th-sorted>sorted</a>;
+  void <a href=#dom-th-sort title=dom-th-sort>sort</a>();
 };</pre>
    </dd>
   </dl><!--TOPIC:HTML--><p>The <code><a href=#the-th-element>th</a></code> element <a href=#represents>represents</a> a header <a href=#concept-cell title=concept-cell>cell</a> in a table.</p>
@@ -42696,17 +42716,23 @@
   to a data cell). It is typically an abbreviated form of the full header cell, but can also be an
   expansion, or merely a different phrasing.</p>
 
+  <p>The <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute is used in the <a href=#table-sorting-model>table
+  sorting model</a>.</p>
+
   <div class=impl>
 
   <p>The <code><a href=#the-th-element>th</a></code> element and its <code title=attr-tdth-colspan><a href=#attr-tdth-colspan>colspan</a></code>, <code title=attr-tdth-rowspan><a href=#attr-tdth-rowspan>rowspan</a></code>, <code title=attr-tdth-headers><a href=#attr-tdth-headers>headers</a></code>, and <code title=attr-th-scope><a href=#attr-th-scope>scope</a></code> attributes take part in the
   <a href=#table-model>table model</a>.</p>
 
+  <p>The <code title=dom-th-sort><a href=#dom-th-sort>sort()</a></code> method is used in the <a href=#table-sorting-model>table sorting
+  model</a>.</p>
+
   <p>The <dfn id=dom-th-scope title=dom-th-scope><code>scope</code></dfn> IDL
   attribute must <a href=#reflect>reflect</a> the content attribute of the
   same name, <a href=#limited-to-only-known-values>limited to only known values</a>.</p>
 
-  <p>The <dfn id=dom-th-abbr title=dom-th-abbr><code>abbr</code></dfn> IDL attribute must <a href=#reflect>reflect</a>
-  the content attribute of the same name.</p>
+  <p>The <dfn id=dom-th-abbr title=dom-th-abbr><code>abbr</code></dfn> and <dfn id=dom-th-sorted title=dom-th-sorted><code>sorted</code></dfn> IDL attributes must <a href=#reflect>reflect</a> the
+  content attributes of the same name.</p>
 
   </div>
 
@@ -42885,8 +42911,10 @@
   <p>It is possible, in certain error cases, for two cells to occupy
   the same slot.</p>
 
-  <p>A <dfn id=concept-row title=concept-row>row</dfn> is a complete set of slots
-  from <span title=""><var title="">x</var>=0</span> to <span title=""><var title="">x</var>=<var title="">x<sub title="">width</sub></var>-1</span>, for a particular value of <var title="">y</var>. Rows correspond to <code><a href=#the-tr-element>tr</a></code> elements.</p>
+  <p>A <dfn id=concept-row title=concept-row>row</dfn> is a complete set of slots from <span title=""><var title="">x</var>=0</span> to <span title=""><var title="">x</var>=<var title="">x<sub title="">width</sub></var>-1</span>, for a particular value of <var title="">y</var>. Rows usually
+  correspond to <code><a href=#the-tr-element>tr</a></code> elements, though a <a href=#concept-row-group title=concept-row-group>row group</a>
+  can have some implied <a href=#concept-row title=concept-row>rows</a> at the end in some cases involving
+  <a href=#concept-cell title=concept-cell>cells</a> spanning multiple rows.</p>
 
   <p>A <dfn id=concept-column title=concept-column>column</dfn> is a complete set of
   slots from <span title=""><var title="">y</var>=0</span> to <span title=""><var title="">y</var>=<var title="">y<sub title="">height</sub></var>-1</span>, for a particular value of <var title="">x</var>. Columns can correspond to <code><a href=#the-col-element>col</a></code>
@@ -43858,8 +43886,656 @@
   </div>
 
 
-  <h4 id=examples-0><span class=secno>4.9.13 </span>Examples</h4>
+  <h4 id=table-sorting-model><span class=secno>4.9.13 </span><dfn>Table sorting model</dfn></h4>
 
+  <p>The <dfn id=attr-table-sortable title=attr-table-sortable><code>sortable</code></dfn> attribute on
+  <code><a href=#the-table-element>table</a></code> elements is a <a href=#boolean-attribute>boolean attribute</a>. When present, it indicates that
+  the user agent is to <a href=#sortable-ui>allow the user to sort</a> the <code><a href=#the-table-element>table</a></code>.</p>
+
+  <p>To make a column sortable in a <code><a href=#the-table-element>table</a></code> with a <code><a href=#the-thead-element>thead</a></code>, the column needs
+  to have <code><a href=#the-th-element>th</a></code> element that does not <a href=#attr-tdth-colspan title=attr-tdth-colspan>span multiple
+  columns</a> in a <code><a href=#the-thead-element>thead</a></code> above any rows that it is to sort.</p>
+
+  <p>To make a column sortable in a <code><a href=#the-table-element>table</a></code> without a <code><a href=#the-thead-element>thead</a></code>, the column
+  needs to have <code><a href=#the-th-element>th</a></code> element that does not <a href=#attr-tdth-colspan title=attr-tdth-colspan>span multiple
+  columns</a> in the first <code><a href=#the-tr-element>tr</a></code> element of the <code><a href=#the-table-element>table</a></code>, where that
+  <code><a href=#the-tr-element>tr</a></code> element is not in a <code><a href=#the-tfoot-element>tfoot</a></code>.</p>
+
+  <p>When the user selects a column by which to sort, the user agent sets the <code><a href=#the-th-element>th</a></code>
+  element's <dfn id=attr-th-sorted title=attr-th-sorted><code>sorted</code></dfn> attribute. This attribute can also
+  be set manually, to indicate that the table should be automatically sorted, even when scripts
+  modify the page on when the page is loaded.</p>
+
+  <p>The <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute, if specified, must have a value that
+  is a <a href=#set-of-space-separated-tokens>set of space-separated tokens</a> consisting of optionally a token whose value is an
+  <a href=#ascii-case-insensitive>ASCII case-insensitive</a> match for the string "<dfn id=attr-th-sorted-reversed title=attr-th-sorted-reversed><code>reversed</code></dfn>", and optionally a token whose value
+  is a <a href=#valid-non-negative-integer>valid non-negative integer</a> greater than zero, in either order.</p>
+
+  <p class=note>In other words, ignoring spaces and case, the <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute's value can be empty, "<code title="">reversed</code>", "<code title="">1</code>", "<code title="">reversed 1</code>", or
+  "<code title="">1 reversed</code>", where "1" is any number equal to or greater than 1.</p>
+
+  <p>While one or more <code><a href=#the-th-element>th</a></code> elements in the table have a <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute, the user agent will keep the table's data rows
+  sorted. The value of the attribute controls how the column is used in determining the sort order.
+  The <code title=attr-th-sorted-reversed><a href=#attr-th-sorted-reversed>reversed</a></code> keyword means that the <dfn id=column-sort-direction>column sort
+  direction</dfn> is <i>reversed</i>, rather than <i>normal</i>, which is the default if the keyword
+  is omitted. The number, if present, indicates the <dfn id=column-key-ordinality>column key ordinality</dfn>; if the number
+  is omitted, the column is the primary key, as if the value 1 had been specified.</p>
+
+  <p class=note>Thus, <code title="">sorted="1"</code> indicates the table's primary key, <code title="">sorted="2"</code> its secondary key, and so forth.</p>
+
+  <hr><p>A <dfn id=sorting-capable-th-element>sorting-capable <code>th</code> element</dfn> is a <code><a href=#the-th-element>th</a></code> element that matches
+  all the following conditions simultaneously:</p>
+
+  <ul><li><p>It corresponds to a <a href=#concept-cell title=concept-cell>cell</a> whose <i>width</i> is 1.
+   (Specifically, a <i>header cell</i>, since this is a <code><a href=#the-th-element>th</a></code> element.)</li>
+
+   <li><p>There is no <a href=#concept-cell title=concept-cell>cell</a> that corresponds to another
+   <a href=#sorting-capable-th-element>sorting-capable <code>th</code> element</a> that covers slots in the same <a href=#concept-column title=concept-column>column</a> but on a higher (earlier) <a href=#concept-row title=concept-row>row</a>.</li> <!-- only matters if there's a <thead> -->
+
+   <li>
+
+    <p>If the <a href=#concept-cell title=concept-cell>cell</a>'s <a href=#concept-table title=concept-table>table</a> has
+    a <a href=#concept-row-group title=concept-row-group>row group</a> corresponding to a <code><a href=#the-thead-element>thead</a></code>
+    element, the <a href=#concept-cell title=concept-cell>cell</a> is in a <a href=#concept-row-group title=concept-row-group>row
+    group</a> that corresponds to the <em>first</em> <code><a href=#the-thead-element>thead</a></code> element of the <a href=#concept-cell title=concept-cell>cell</a>'s <a href=#concept-table title=concept-table>table</a>.</p>
+
+    <p>Otherwise: the <a href=#concept-cell title=concept-cell>cell</a> is not in a <a href=#concept-row-group title=concept-row-group>row group</a> corresponding to a <code><a href=#the-tfoot-element>tfoot</a></code> element, and
+    the <a href=#concept-cell title=concept-cell>cell</a> is in the first <a href=#concept-row title=concept-row>row</a>
+    of the <a href=#concept-table title=concept-table>table</a>.</p>
+
+   </li>
+
+  </ul><p class=note>In other words, each <a href=#concept-column title=concept-column>column</a> can have one
+  <a href=#sorting-capable-th-element>sorting-capable <code>th</code> element</a>; this will be the highest <code><a href=#the-th-element>th</a></code> in
+  a <code><a href=#the-thead-element>thead</a></code> that spans no other columns, or, if there is no <code><a href=#the-thead-element>thead</a></code>, the
+  <code><a href=#the-th-element>th</a></code> in the first row (that is not in a <code><a href=#the-tfoot-element>tfoot</a></code>), assuming it spans no
+  columns.</p>
+
+  <p>The <dfn id=sorting-capable-th-elements-of-the-table-element>sorting-capable <code>th</code> elements of the <code>table</code> element</dfn> <var title="">table</var> are the <a href=#sorting-capable-th-element title="sorting-capable th element">sorting-capable
+  <code>th</code> elements</a> whose <a href=#concept-cell title=concept-cell>cell</a>'s <a href=#concept-table title=concept-table>table</a> is <var title="">table</var>.</p>
+
+  <p>A <code><a href=#the-table-element>table</a></code> element <var title="">table</var> is a <dfn id=sorting-capable-table-element>sorting-capable
+  <code>table</code> element</dfn> if there are one or more <a href=#sorting-capable-th-elements-of-the-table-element>sorting-capable <code>th</code>
+  elements of the <code>table</code> element</a> <var title="">table</var>.</p>
+
+  <p>A <code><a href=#the-th-element>th</a></code> element is a <dfn id=sorting-enabled-th-element>sorting-enabled <code>th</code> element</dfn> if it is a
+  <a href=#sorting-capable-th-element>sorting-capable <code>th</code> element</a> and it has a <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute.</p>
+
+  <p>The <dfn id=sorting-enabled-th-elements-of-the-table-element>sorting-enabled <code>th</code> elements of the <code>table</code> element</dfn> <var title="">table</var> are the <a href=#sorting-enabled-th-element title="sorting-enabled th element">sorting-enabled
+  <code>th</code> elements</a> whose <a href=#concept-cell title=concept-cell>cell</a>'s <a href=#concept-table title=concept-table>table</a> is <var title="">table</var>.</p>
+
+  <p>A <code><a href=#the-table-element>table</a></code> element <var title="">table</var> is a <dfn id=sorting-enabled-table-element>sorting-enabled
+  <code>table</code> element</dfn> if there are one or more <a href=#sorting-capable-th-elements-of-the-table-element>sorting-capable <code>th</code>
+  elements of the <code>table</code> element</a> <var title="">table</var>, and at least one of
+  them is a <a href=#sorting-enabled-th-element>sorting-enabled <code>th</code> element</a> (i.e. at least one has a <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute).</p>
+
+  <p>A <code><a href=#the-table-element>table</a></code> element is a <dfn id=table-element-with-a-user-agent-exposed-sorting-interface><code>table</code> element with a user-agent exposed
+  sorting interface</dfn> if it is a <a href=#sorting-capable-table-element>sorting-capable <code>table</code> element</a> and has
+  a <code title=attr-table-sortable><a href=#attr-table-sortable>sortable</a></code> attribute specified.</p>
+
+  <p>Each <code><a href=#the-table-element>table</a></code> element has a <dfn id=currently-sorting-flag>currently-sorting flag</dfn>, which must initially
+  be false.</p>
+
+  <hr><p>The <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute must not be specified on
+  <code><a href=#the-th-element>th</a></code> elements that are not <a href=#sorting-capable-th-element title="sorting-capable th element">sorting-capable
+  <code>th</code> elements</a>. The <code title=attr-table-sortable><a href=#attr-table-sortable>sortable</a></code> attribute
+  must not be specified on <code><a href=#the-table-element>table</a></code> elements that are not <a href=#sorting-capable-table-element title="sorting-capable
+  table element">sorting-capable <code>table</code> elements</a>.</p>
+
+  <div class=impl>
+
+  <p>To determine a <code><a href=#the-th-element>th</a></code> element's <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute's
+  <a href=#column-sort-direction>column sort direction</a> and <a href=#column-key-ordinality>column key ordinality</a>, user agents must use
+  the following algorithm:</p>
+
+  <ol><li><p>Let <var title="">direction</var> be <i>normal</i>.</p>
+
+   <li><p>Let <var title="">have explicit direction</var> be false.</p>
+
+   <li><p>Let <var title="">ordinality</var> be 1.</p>
+
+   <li><p>Let <var title="">have explicit ordinality</var> be false.</p>
+
+   <li><p>Let <var title="">tokens</var> be the result of <a href=#split-a-string-on-spaces title="split a string on
+   spaces">splitting the attribute's value on spaces</a>.</li>
+
+   <li>
+
+    <p>For each token <var title="">token</var> in <var title="">tokens</var>, run the appropriate
+    steps from the following list:</p>
+
+    <dl class=switch><dt>If <var title="">have explicit direction</var> is false and <var title="">token</var> is an
+     <a href=#ascii-case-insensitive>ASCII case-insensitive</a> match for the string "<code title=attr-th-sorted-reversed><a href=#attr-th-sorted-reversed>reversed</a></code>"</dt>
+
+     <dd>
+
+      <p>Let <var title="">direction</var> be <i>reversed</i> and <var title="">have explicit
+      direction</var> be true.</p>
+
+     </dd>
+
+
+     <dt>If <var title="">have explicit ordinality</var> is false</dt>
+
+     <dd>
+
+      <p><a href=#rules-for-parsing-integers title="rules for parsing integers">Parse <var title="">token</var> as an
+      integer</a>. If this resulted in an error or the value zero, then ignore the token.
+      Otherwise, set <var title="">ordinality</var> to the parsed value, and set <var title="">have
+      explicit ordinality</var> to true.</p>
+
+     </dd>
+
+
+     <dt>Otherwise</dt>
+
+     <dd><p>Ignore the token.</dd>
+
+    </dl></li>
+
+   <li><p>The <a href=#column-sort-direction>column sort direction</a> is the value of <var title="">direction</var>, and
+   the <a href=#column-key-ordinality>column key ordinality</a> is the value of <var title="">ordinality</var>.</li>
+
+  </ol></div>
+
+  <p>A <code><a href=#the-table-element>table</a></code> must not have two <code><a href=#the-th-element>th</a></code> elements whose <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute have the same <a href=#column-key-ordinality>column key
+  ordinality</a>.</p>
+
+  <div class=impl>
+
+  <hr><p>The <dfn id=table-sorting-algorithm>table sorting algorithm</dfn>, which is applied to a <code><a href=#the-table-element>table</a></code>, is as
+  follows:</p>
+
+  <ol><li><p>Let <var title="">table</var> be the <code><a href=#the-table-element>table</a></code> element being sorted.</li>
+
+   <li><p>If <var title="">table</var>'s <a href=#currently-sorting-flag>currently-sorting flag</a> is true, then abort
+   these steps.</li>
+
+   <li><p>Set <var title="">table</var>'s <a href=#currently-sorting-flag>currently-sorting flag</a> to true.</li>
+
+   <li><p><a href=#fire-a-simple-event>Fire a simple event</a> named <code title=event-sort>sort</code> that is
+   cancelable at <var title="">table</var>.</li>
+
+   <li><p>If the event fired in the previous step was canceled, then jump to the step labeled
+   <i>end</i> below.</li>
+
+   <li>
+
+    <p>If <var title="">table</var> is not now a <a href=#sorting-enabled-table-element>sorting-enabled <code>table</code>
+    element</a>, then jump to the step labeled <i>end</i> below.</p>
+
+    <p class=note>Even if <var title="">table</var> was a <a href=#sorting-enabled-table-element>sorting-enabled <code>table</code>
+    element</a> when the algorithm was invoked, the DOM might have been entirely changed by the
+    event handlers for the <code title=event-sort>sort</code> event, so this has to be verified at
+    this stage, not earlier.</p>
+
+   </li>
+
+   <li><p>Let <var title="">key heading cells</var> be the <a href=#sorting-enabled-th-elements-of-the-table-element>sorting-enabled <code>th</code>
+   elements of the <code>table</code> element</a> <var title="">table</var>.</li>
+
+   <li><p>Sort <var title="">key heading cells</var> in ascending order of the <a href=#column-key-ordinality>column key
+   ordinality</a> of their <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attributes, with those
+   having the same <a href=#column-key-ordinality>column key ordinality</a> being sorted in <a href=#tree-order>tree order</a>.</p>
+
+   <li>
+
+    <p>Let <var title="">row collection cursor</var> be a pointer to an element, initially pointing
+    at the first child of <var title="">table</var> that is after <var title="">table</var>'s first
+    <code><a href=#the-thead-element>thead</a></code>, if any, and that is either a <code><a href=#the-tbody-element>tbody</a></code> or a <code><a href=#the-tr-element>tr</a></code>
+    element, assuming there is one. If there is no such child, then jump to the step labeled
+    <i>end</i> below.</p>
+
+   </li>
+
+   <li><p>If <var title="">table</var> has no <a href=#concept-row-group title=concept-row-group>row group</a>
+   corresponding to a <code><a href=#the-thead-element>thead</a></code> element, then set <var title="">ignore first group</var> to
+   true. Otherwise, set it to false.</li>
+
+   <li><p><i>Row loop</i>: Let <var title="">rows</var> be an empty list of <code><a href=#the-tr-element>tr</a></code>
+   elements.</li>
+
+   <li>
+
+    <p>Run the appropriate steps from the following list:</p>
+
+    <dl class=switch><dt>If <var title="">row collection cursor</var> points to a <code><a href=#the-tr-element>tr</a></code> element
+
+     <dd>
+
+      <ol><li><p><i>Collect</i>: Append the element pointed to by <var title="">row collection
+       cursor</var> to <var title="">rows</var>.</li>
+
+       <li><p>If there are no <code><a href=#the-tr-element>tr</a></code> or <code><a href=#the-tbody-element>tbody</a></code> children of <var title="">table</var> that are later siblings of the element pointed to by <var title="">row
+       collection cursor</var>, or if the next such child is a <code><a href=#the-tbody-element>tbody</a></code> element, then jump
+       to the step labeled <i>group</i> below.</li>
+
+       <li><p>Let <var title="">row collection cursor</var> point to the next <code><a href=#the-tr-element>tr</a></code> child
+       of <var title="">table</var> that is a later sibling of the element pointed to by <var title="">row collection cursor</var>.</li>
+
+       <li><p>Returned to the step labeled <i>collect</i> above.</li>
+
+      </ol></dd>
+
+
+     <dt>If <var title="">row collection cursor</var> points to a <code><a href=#the-tbody-element>tbody</a></code> element
+
+     <dd>
+
+      <ol><li><p>Place all the <code><a href=#the-tr-element>tr</a></code> element children of the element pointed to by <var title="">row collection cursor</var> into <var title="">rows</var>, in <a href=#tree-order>tree
+       order</a>.</li>
+
+       <li><p>If <var title="">rows</var> is empty, jump to the step labeled <i>increment loop</i>
+       below.</li>
+
+      </ol></dd>
+
+    </dl></li>
+
+   <li><p><i>Group</i>: Let <var title="">groups</var> be an empty list of groups of <code><a href=#the-tr-element>tr</a></code>
+   elements.</li>
+
+   <li><p>Let <var title="">group</var> be an empty group of <code><a href=#the-tr-element>tr</a></code> elements.</li>
+
+   <li><p>Let <var title="">group cursor</var> be a pointer to an element, initially pointing at the
+   first <code><a href=#the-tr-element>tr</a></code> element in <var title="">rows</var>.</li>
+
+   <li><p><i>Start group</i>: Let <var title="">pending rows in group</var> be 1.</li>
+
+   <li><p><i>Group loop</i>: Append the <code><a href=#the-tr-element>tr</a></code> element pointed to by <var title="">group
+   cursor</var> to <var title="">group</var>.</li>
+
+   <li><p>If there are any <a href=#concept-cell title=concept-cell>cells</a> whose highest <a href=#concept-row title=concept-row>row</a>'s element is the one pointed to by <var title="">group
+   cursor</var>, then let <var title="">tallest height</var> be the number of rows covered by the
+   tallest such <a href=#concept-cell title=concept-cell>cell</a>.</li>
+
+   <li><p>If <var title="">tallest height</var> is greater than <var title="">pending rows in
+   group</var> then set <var title="">pending rows in group</var> to <var title="">tallest
+   height</var>.</li>
+
+   <li><p>Decrement <var title="">pending rows in group</var> by one.</li>
+
+   <li><p>Let <var title="">group cursor</var> point to the next <code><a href=#the-tr-element>tr</a></code> element in <var title="">rows</var>, if any; otherwise, let it be null.</li>
+
+   <li><p>If <var title="">group cursor</var> is not null and <var title="">pending rows in
+   group</var> is not zero, return to the step labeled <i>group loop</i>.</li>
+
+   <li><p>Append a new group to <var title="">groups</var> consisting of the <code><a href=#the-tr-element>tr</a></code>
+   elements in <var title="">group</var>.</li>
+
+   <li><p>Empty <var title="">group</var>.</li>
+
+   <li><p>If <var title="">group cursor</var> is not null, then return to the step labeled <i>start
+   group</i>.</li>
+
+   <li><p>If <var title="">ignore first group</var> is true, then drop the first roup in <var title="">groups</var> and set <var title="">ignore first group</var> to false.</li>
+
+   <li><p><i>Drop leading header groups</i>: If <var title="">groups</var> is now empty, jump to the
+   step labeled <i>increment loop</i> below.</li>
+
+   <!-- if you insert steps here, update the next step -->
+
+   <li><p>If the first group of <var title="">groups</var> consists of <code><a href=#the-tr-element>tr</a></code> elements
+   whose element children are all <code><a href=#the-th-element>th</a></code> elements, then drop the first group in <var title="">groups</var> and return to the previous step (labeled <i>drop leading header
+   groups</i>).</li>
+
+   <li><p>Let <var title="">insertion point</var> be a placeholder in a DOM tree, which can be used
+   to reinsert nodes at a specific point in the DOM. Insert <var title="">insertion point</var> into
+   the parent of the first <code><a href=#the-tr-element>tr</a></code> element of the first group in <var title="">groups</var>,
+   immediately before that <code><a href=#the-tr-element>tr</a></code> element.</li>
+
+   <li>
+
+    <p>Sort the groups in <var title="">groups</var>, using the following algorithm to decide the
+    relative order of any two groups <var title="">a</var> and <var title="">b</var> (the algorithm
+    either returns that <var title="">a</var> comes before <var title="">b</var>, or that <var title="">b</var> comes before <var title="">a</var>):</p>
+
+    <ol><li><p>Let <var title="">key index</var> be an index into <var title="">key heading
+     cells</var>, initially denoting the first element in the list.</li>
+
+     <li><p>Let <var title="">direction</var> be a sort direction, initially <i>ascending</i>. Its
+     other possible value is <i>descending</i>. When <var title="">direction</var> is
+     <i>toggled</i>, that means that if its value is <i>ascending</i>, it must be changed to
+     <i>descending</i>, and when its value is <i>descending</i>, it must be changed to
+     <i>ascending</i>.</li>
+
+     <li><p><i>Column loop</i>: Let <var title="">th</var> be the <var title="">key index</var>th
+     <code><a href=#the-th-element>th</a></code> in <var title="">key heading cells</var>.</li>
+
+     <li><p>If <var title="">th</var>'s <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute's
+     <a href=#column-sort-direction>column sort direction</a> is <i>reversed</i>, then toggle <var title="">direction</var>.</li>
+
+     <li><p>Let <var title="">tentative order</var> be the result of <a href=#comparing-two-row-groups-using-the-th-element>comparing two row groups
+     using the <code>th</code> element</a> <var title="">th</var>, with <var title="">a</var> and
+     <var title="">b</var> as the rows.</li>
+
+     <li><p>If <var title="">tentative order</var> is not "equal", then jump to the step labeled
+     <i>return</i> below.</li>
+
+     <li><p>Increment <var title="">key index</var>.</li>
+
+     <li><p>If <var title="">key index</var> still denotes a <code><a href=#the-th-element>th</a></code> element in <var title="">key heading cells</var>, then jump back to the step above labeled <i>column
+     loop</i>.</li>
+
+     <li><p>If <var title="">a</var>'s <code><a href=#the-tr-element>tr</a></code> elements precede <var title="">b</var>'s in
+     <a href=#tree-order>tree order</a>, then let <var title="">tentative order</var> be "a before b".
+     Otherwise, let <var title="">tentative order</var> be "b before a".</li>
+
+     <li><p><i>Return</i>: Return the relative order given by the matching option from the following
+     list:</p>
+
+      <dl class=switch><dt>If <var title="">direction</var> is <i>ascending</i> and <var title="">tentative
+       order</var> is "a before b"</dt>
+
+       <dd>Return that <var title="">a</var> comes before <var title="">b</var>.</dd>
+
+
+       <dt>If <var title="">direction</var> is <i>ascending</i> and <var title="">tentative
+       order</var> is "b before a"</dt>
+
+       <dd>Return that <var title="">b</var> comes before <var title="">a</var>.</dd>
+
+
+       <dt>If <var title="">direction</var> is <i>descending</i> and <var title="">tentative
+       order</var> is "a before b"</dt>
+
+       <dd>Return that <var title="">b</var> comes before <var title="">a</var>.</dd>
+
+
+       <dt>If <var title="">direction</var> is <i>descending</i> and <var title="">tentative
+       order</var> is "b before a"</dt>
+
+       <dd>Return that <var title="">a</var> comes before <var title="">b</var>.</dd>
+
+      </dl></li>
+
+    </ol><p>When the user agent is required to <dfn id=comparing-two-row-groups-using-the-th-element title="comparing two row groups using the th
+    element">compare two row groups using the <code>th</code> element</dfn> <var title="">th</var>,
+    with <var title="">a</var> and <var title="">b</var> being the two row groups respectively, the
+    user agent must run the following steps:</p>
+
+    <ol><li><p>Let <var title="">x</var> be the <var title="">x</var>-coordinate of the slots that
+     <code><a href=#the-th-element>th</a></code> covers in its <a href=#concept-table title=concept-table>table</a>.</li>
+
+     <li>
+
+      <p>Let <var title="">cell<sub>a</sub></var> be the element corresponding to the <a href=#concept-cell title=concept-cell>cell</a> in the first <a href=#concept-row title=concept-row>row</a> of group
+      <var title="">a</var> that covers the slot in that <a href=#concept-row title=concept-row>row</a> whose
+      <var title="">x</var>-coordinate is <var title="">x</var>.</p>
+
+      <p>Let <var title="">cell<sub>b</sub></var> be the element corresponding to the <a href=#concept-cell title=concept-cell>cell</a> in the first <a href=#concept-row title=concept-row>row</a> of group
+      <var title="">b</var> that covers the slot in that <a href=#concept-row title=concept-row>row</a> whose
+      <var title="">x</var>-coordinate is <var title="">x</var>.</p>
+
+      <!-- there can't be two cells that cover the slot, unusually, because the only way that can
+      happen is if there's a cell that's extended into this row from above, and the groups, by
+      virtue of the way they are created above, never have cells that extend into them from above.
+      -->
+
+      <p>In either case, if there's no <a href=#concept-cell title=concept-cell>cell</a> that actually covers
+      the slot, then use the value <i>null</i> instead.</p>
+
+     </li>
+
+     <li>
+
+      <p>Let <var title="">type<sub>a</sub></var> and <var title="">value<sub>a</sub></var> be
+      the <a href=#type-and-value-of-the-cell>type and value of the cell</a> <var title="">cell<sub>a</sub></var>, as defined
+      below.</p>
+
+      <p>Let <var title="">type<sub>b</sub></var> and <var title="">value<sub>b</sub></var> be
+      the <a href=#type-and-value-of-the-cell>type and value of the cell</a> <var title="">cell<sub>b</sub></var>, as defined
+      below.</p>
+
+      <p>The <dfn id=type-and-value-of-the-cell>type and value of the cell</dfn> <var title="">cell</var> are computed as follows.</p>
+
+      <ol><li><p>If <var title="">cell</var> is <i>null</i>, then the type is "string" and the value is
+       the empty string; abort these steps.</li>
+
+       <li><p>If, ignoring <a href=#inter-element-whitespace>inter-element whitespace</a> and <a href=#comment-0>Comment</a> nodes,
+       <var title="">cell</var> has only one child and that child is a <code><a href=#the-data-element>data</a></code> element,
+       then the value is the value of that <code><a href=#the-data-element>data</a></code> element's <code title=attr-data-value><a href=#attr-data-value>value</a></code> attribute, if there is one, or the empty string
+       otherwise; the type is "string".</p>
+
+       <li>
+
+        <p>If, ignoring <a href=#inter-element-whitespace>inter-element whitespace</a> and <a href=#comment-0>Comment</a> nodes, <var title="">cell</var> has only one child and that child is a <code><a href=#the-time-element>time</a></code> element, then
+        the value is the <a href="#machine-readable-equivalent-of-the-element's-contents">machine-readable equivalent of the element's contents</a>, if any,
+        and the type is the kind of value that is thus obtained
+       (a <a href=#concept-month title=concept-month>month</a>,
+        a <a href=#concept-date title=concept-date>date</a>,
+        a <a href=#concept-yearless-date title=concept-yearless-date>yearless date</a>,
+        a <a href=#concept-time title=concept-time>time</a>,
+        a <a href=#concept-datetime-local title=concept-datetime-local>local date and time</a>,
+        a <a href=#concept-timezone title=concept-timezone>time-zone offset</a>,
+        a <a href=#concept-datetime title=concept-datetime>global date and time</a>,
+        a <a href=#concept-week title=concept-week>week</a>,
+        a year, or
+        a <a href=#concept-duration title=concept-duration>duration</a>);
+        abort these steps after completing this one.</p>
+
+        <p>If there is no machine-readable equivalent, then the type is "string" and the value is
+        the empty string.</p>
+
+        <p>If the type is
+        a <a href=#concept-month title=concept-month>month</a>,
+        a <a href=#concept-date title=concept-date>date</a>,
+        a <a href=#concept-week title=concept-week>week</a>, or
+        a year,
+        then change the value to be the instant in time (with no time zone) that describes the
+        earliest moment that the value represents, and change the type to be
+        a <a href=#concept-datetime-local title=concept-datetime-local>local date and time</a>.</p>
+
+        <p class=example>For example, if the cell was
+        <code><td><time>2011-11</time></code> then for sorting purposes the value is
+        interpreted as "2011-11-01T00:00:00.000" and the type is treated as a <a href=#concept-datetime-local title=concept-datetime-local>local date and time</a> rather than a <a href=#concept-month title=concept-month>month</a>.</p>
+
+        <p class=example>Similarly, if the cell was <code><td><time
+        datetime="2011">MMXIV</time></code> then for sorting purposes the value is interpreted as
+        "2014-01-01T00:00:00.000" and the type is treated as a <a href=#concept-datetime-local title=concept-datetime-local>local date and time</a> rather than a year.</p>
+
+       </li>
+
+       <li><p>The value is the element's <code><a href=#textcontent>textContent</a></code>. The type is "string".</li>
+
+      </ol></li>
+
+     <li>
+
+      <p>If <var title="">type<sub>a</sub></var> and <var title="">type<sub>b</sub></var> are not
+      equal, then: return "a before b" if <var title="">type<sub>a</sub></var> is earlier in the
+      following list than <var title="">type<sub>b</sub></var>, otherwise, return "b before a";
+      then, abort these steps.</p>
+
+      <ol class=brief><li><a href=#concept-time title=concept-time>time</a></li>
+       <li><a href=#concept-yearless-date title=concept-yearless-date>yearless date</a></li>
+       <li><a href=#concept-datetime-local title=concept-datetime-local>local date and time</a></li>
+       <li><a href=#concept-datetime title=concept-datetime>global date and time</a></li>
+       <li><a href=#concept-timezone title=concept-timezone>time-zone offset</a></li>
+       <li><a href=#concept-duration title=concept-duration>duration</a></li>
+       <li>"string"</li>
+      </ol></li>
+
+     <li><p>If <var title="">value<sub>a</sub></var> and <var title="">value<sub>b</sub></var> are
+     equal, then return "equal" and abort these steps.</li>
+
+     <li>
+
+      <p>If <var title="">type<sub>a</sub></var> and <var title="">type<sub>b</sub></var> are not
+      "string", then: return "a before b" if <var title="">value<sub>a</sub></var> is earlier
+      than <var title="">value<sub>b</sub></var>, and return "b before a" otherwise.</p>
+
+      <p>Values sort in their natural order, with the following additional constraints:</p>
+
+      <p>For <a href=#concept-time title=concept-time>time</a> values, 00:00:00.000 is the earliest value and
+      23:59:59.999 is the latest value.</p>
+
+      <p>For <a href=#concept-yearless-date title=concept-yearless-date>yearless date</a> values, 01-01 is the earliest
+      value and 12-31 is the latest value; 02-28 is earlier than 02-29 which is earlier than
+      03-01.</p>
+
+      <p>Values that are <a href=#concept-datetime-local title=concept-datetime-local>local date and time</a> compare as
+      if they were in the same time zone.</p>
+
+      <!-- no ambiguity for <span title="concept-datetime">global date and time</span> -->
+
+      <p>For <a href=#concept-timezone title=concept-timezone>time-zone offset</a> values, -23:59 is the earliest
+      value and +23:59 is the latest value.</p>
+
+      <!-- MONTHS: <span title="concept-duration">duration</span> is unambiguous until we add months -->
+
+     </li>
+
+     <!-- At this point we know that they are both strings and they're not equal. -->
+
+     <li>
+
+      <p class=XXX>Return "a before b" if <var title="">value<sub>a</sub></var> is earlier than
+      <var title="">value<sub>b</sub></var>, and return "b before a" otherwise; for these purposes,
+      the strings must be compared using collation order of the <a href=#language>language</a> of the
+      <code><a href=#the-table-element>table</a></code> element to which <var title="">th</var>'s <a href=#concept-table title=concept-table>table</a> corresponds.</p>
+
+     </li>
+
+    </ol></li>
+
+
+   <li><p>Let <var title="">new order</var> be a list of <code><a href=#the-tr-element>tr</a></code> elements consisting of the
+   <code><a href=#the-tr-element>tr</a></code> elements of all the groups in the newly ordered <var title="">groups</var>, with
+   the <code><a href=#the-tr-element>tr</a></code> elements being in the same order as the groups to which they belong are in
+   <var title="">groups</var>, and the <code><a href=#the-tr-element>tr</a></code> elements within each such group themselves
+   being ordered in <a href=#tree-order>tree order</a>.</li>
+
+   <li><p><a href=#concept-node-remove title=concept-node-remove>Remove</a> all the <code><a href=#the-tr-element>tr</a></code> elements in <var title="">new order</var> from their parents.</li>
+
+   <li><p><a href=#concept-node-insert title=concept-node-insert>Insert</a> all the <code><a href=#the-tr-element>tr</a></code> elements in <var title="">new order</var> into the DOM at the location of <var title="">insertion point</var>, in
+   the order these elements are found in <var title="">new order</var>.</li>
+
+   <!-- done with this set of rows -->
+
+   <li><p>Remove <var title="">insertion point</var> from the DOM.</li>
+
+   <li><p><i>Increment loop</i>: If there are no <code><a href=#the-tr-element>tr</a></code> or <code><a href=#the-tbody-element>tbody</a></code> children of
+   <var title="">table</var> that are later siblings of the element pointed to by <var title="">row
+   collection cursor</var>, then jump to the step labeled <i>end</i> below.</li>
+
+   <li><p>Let <var title="">row collection cursor</var> point to the next <code><a href=#the-tr-element>tr</a></code> or
+   <code><a href=#the-tbody-element>tbody</a></code> child of <var title="">table</var> that is a later sibling of the element
+   pointed to by <var title="">row collection cursor</var>.</li>
+
+   <li><p>Return to the step labeled <i>row loop</i> above.</li>
+
+   <li><p><i>End</i>: Set <var title="">table</var>'s <a href=#currently-sorting-flag>currently-sorting flag</a> to
+   false.</li>
+
+  </ol><p>When any of the descendants of a <a href=#sorting-enabled-table-element>sorting-enabled <code>table</code> element</a> change
+  in any way (including attributes changing), and when a <code><a href=#the-table-element>table</a></code> element becomes a
+  <a href=#sorting-enabled-table-element>sorting-enabled <code>table</code> element</a>, the <code><a href=#the-table-element>table</a></code> element is said to
+  become <dfn id=a-table-with-a-pending-sort>a table with a pending sort</dfn>.</p>
+
+  <p>When the user agent is to <dfn id=sort-the-tables-with-pending-sorts>sort the tables with pending sorts</dfn>, which happens during
+  the <a href=#perform-a-microtask-checkpoint>perform a microtask checkpoint</a> algorithm, the user agent must run the following
+  algorithm:</p>
+
+  <ol><li><p>Let <var title="">tables</var> be a list of each <code><a href=#the-table-element>table</a></code> in the <a href=#unit-of-related-similar-origin-browsing-contexts>unit of
+   related similar-origin browsing contexts</a> that is <a href=#a-table-with-a-pending-sort>a table with a pending sort</a>,
+   in the order that they became such, with those that become such at the same time being listed in
+   <a href=#tree-order>tree order</a>.</p>
+
+   <li><p>Let all the <code><a href=#the-table-element>table</a></code> elements in <var title="">tables</var> no longer be <a href=#a-table-with-a-pending-sort title="a table with a pending sort">tables with a pending sort</a>.</li>
+
+   <li><p>Apply the <a href=#table-sorting-algorithm>table sorting algorithm</a> to each <code><a href=#the-table-element>table</a></code> in <var title="">tables</var>, in order.</li>
+
+  </ol><hr><p>When the user agent is to <dfn id=set-the-sort-key>set the sort key</dfn> to a <code><a href=#the-th-element>th</a></code> element <var title="">target</var>, it must run the following algorithm:</p>
+
+  <ol><li><p>Let <var title="">table</var> be the <code><a href=#the-table-element>table</a></code> of the <a href=#concept-table title=concept-table>table</a> of which <var title="">target</var> is a header cell.</li>
+
+   <li><p>If <code><a href=#the-th-element>th</a></code> is a <a href=#sorting-enabled-th-element>sorting-enabled <code>th</code> element</a> whose
+   <a href=#column-key-ordinality>column key ordinality</a> is 1, then: if its <a href=#column-sort-direction>column sort direction</a> is
+   <i>normal</i>, set that element's <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute to the
+   string "<code title="">reversed</code>", otherwise, set it to the empty string; then, abort these
+   steps.</li>
+
+   <li><p>Let <var title="">current headers</var> be the <a href=#sorting-enabled-th-elements-of-the-table-element>sorting-enabled <code>th</code>
+   elements of the <code>table</code> element</a> <var title="">table</var>, excluding <var title="">target</var>.</li>
+
+   <li><p>Sort <var title="">current headers</var> by their <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attributes' <a href=#column-key-ordinality>column key ordinality</a>, in ascending
+   order, with elements that have the same <a href=#column-key-ordinality>column key ordinality</a> being sorted in
+   <a href=#tree-order>tree order</a>.</li>
+
+   <li><p>Let <var title="">level</var> be 2.</li>
+
+   <li>
+
+    <p>For each <code><a href=#the-th-element>th</a></code> element <var title="">th</var> in <var title="">current
+    headers</var>, in order, run the following substeps:</p>
+
+    <ol><li><p>If <var title="">th</var>'s <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute's
+     <a href=#column-sort-direction>column sort direction</a> is <i>normal</i>, then set <var title="">th</var>'s <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute to a <a href=#valid-integer>valid integer</a> whose value is
+     <var title="">level</var>. Otherwise, set it to the concatenation of the string "<code title="">reversed</code>", a U+0020 SPACE character, and a <a href=#valid-integer>valid integer</a> whose
+     value is <var title="">level</var>.</p>
+
+     <li><p>Increment <var title="">level</var> by 1.</li>
+
+    </ol></li>
+
+   <li><p>Set <var title="">target</var>'s <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute to
+   the empty string.</li>
+
+  </ol><hr><p>The <a href=#activation-behavior>activation behavior</a> of the <a href=#sorting-capable-th-elements-of-the-table-element title="sorting-capable th elements of the
+  table element">sorting-capable <code>th</code> elements of</a> all <a href=#table-element-with-a-user-agent-exposed-sorting-interface title="table element
+  with a user-agent exposed sorting interface"><code>table</code> elements with a user-agent exposed
+  sorting interface</a> is to <a href=#set-the-sort-key>set the sort key</a> to the <code><a href=#the-th-element>th</a></code> element.</p>
+
+  <p class=note>The <code><a href=#the-table-element>table</a></code> will be sorted the next time the user agent <a href=#perform-a-microtask-checkpoint title="perform a microtask checkpoint">performs a microtask checkpoint</a>.</p>
+
+  </div>
+
+  <dl class=domintro><dt><var title="">th</var> . <code title=dom-th-sort><a href=#dom-th-sort>sort</a></code>()</dt>
+
+   <dd>
+
+    <p>Act as if the user had indicated that this was to be the new primary sort column.</p>
+
+    <p>The <code><a href=#the-table-element>table</a></code> won't actually be sorted until the script terminates.</p>
+
+   </dd>
+
+
+   <dt><var title="">table</var> . <code title=dom-table-stopSorting><a href=#dom-table-stopsorting>stopSorting</a></code>()</dt>
+
+   <dd>
+
+    <p>Removes all the <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attributes that are causing the
+    table to automatically sort its contents, if any.</p>
+
+   </dd>
+
+  </dl><div class=impl>
+
+  <p>The <code><a href=#the-th-element>th</a></code> element's <dfn id=dom-th-sort title=dom-th-sort><code>sort()</code></dfn> method, when
+  invoked, must run the following steps:</p>
+
+  <ol><li><p>If the <code><a href=#the-th-element>th</a></code> element is not a <a href=#sorting-capable-th-element>sorting-capable <code>th</code>
+   element</a>, then abort these steps.</li>
+
+   <li>
+
+    <p><a href=#set-the-sort-key>Set the sort key</a> to the <code><a href=#the-th-element>th</a></code> element.</p>
+
+    <p class=note>The <code><a href=#the-table-element>table</a></code> will be sorted the next time the user agent <a href=#perform-a-microtask-checkpoint title="perform a microtask checkpoint">performs a microtask checkpoint</a>.</p>
+
+   </li>
+
+  </ol><p>The <code><a href=#the-table-element>table</a></code> element's <dfn id=dom-table-stopsorting title=dom-table-stopSorting><code>stopSorting()</code></dfn> method, when invoked, must remove
+  the <code title=attr-th-sorted><a href=#attr-th-sorted>sorted</a></code> attribute of all the <a href=#sorting-enabled-th-elements-of-the-table-element>sorting-enabled
+  <code>th</code> elements of the table element</a> on which the method was invoked.</p>
+
+  </div>
+
+
+  <h4 id=examples-0><span class=secno>4.9.14 </span>Examples</h4>
+
   <p><i>This section is non-normative.</i></p>
 
   <p>The following shows how might one mark up the bottom part of
@@ -66243,6 +66919,7 @@
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onseeking title=handler-onseeking>onseeking</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onselect title=handler-onselect>onselect</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onshow title=handler-onshow>onshow</a>;
+           attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsort title=handler-onsort>onsort</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onstalled title=handler-onstalled>onstalled</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-window-onstorage title=handler-window-onstorage>onstorage</a>;
            attribute <a href=#eventhandler>EventHandler</a> <a href=#handler-onsubmit title=handler-onsubmit>onsubmit</a>;
@@ -72904,7 +73581,8 @@
   <p>An <a href=#event-loop>event loop</a> must continually run through the
   following steps for as long as it exists:</p>
 
-  <ol><li><p>Run the oldest <a href=#concept-task title=concept-task>task</a> on one of the <a href=#event-loop>event
+  <ol><!-- if you add a step here, make sure to go through the spec updating references to the "first
+   step" of the event loop --><li><p>Run the oldest <a href=#concept-task title=concept-task>task</a> on one of the <a href=#event-loop>event
    loop</a>'s <a href=#task-queue title="task queue">task queues</a>, if any, ignoring tasks whose
    associated <code><a href=#document>Document</a></code>s are not <a href=#fully-active>fully active</a>. The user agent may pick any
    <a href=#task-queue>task queue</a>.</li>
@@ -72915,7 +73593,8 @@
    <li><p>If the <a href=#storage-mutex>storage mutex</a> is now owned by the <a href=#event-loop>event loop</a>, release it
    so that it is once again free.</li>
 
-   <li><p>Remove that task from its <a href=#task-queue>task queue</a>.</li>
+   <li><p>If a task was run in the first step above, remove that task from its <a href=#task-queue>task
+   queue</a>.</li>
 
    <li><p><a href=#perform-a-microtask-checkpoint>Perform a microtask checkpoint</a>.</li>
 
@@ -72935,6 +73614,8 @@
   <ol><li><p>Let the <a href=#running-mutation-observers>running mutation observers</a> flag be
    true.</li>
 
+   <li><p><a href=#sort-the-tables-with-pending-sorts>Sort the tables with pending sorts</a>.</li>
+
    <li>
 
     <p><a href=#concept-mo-invoke title=concept-mo-invoke>Invoke
@@ -73602,6 +74283,7 @@
     <tr><td><dfn id=handler-onseeking title=handler-onseeking><code>onseeking</code></dfn> <td> <code title=event-media-seeking><a href=#event-media-seeking>seeking</a></code>
     <tr><td><dfn id=handler-onselect title=handler-onselect><code>onselect</code></dfn> <td> <code title=event-select>select</code> <!-- widely used --> <!-- [CSSOM] -->
     <tr><td><dfn id=handler-onshow title=handler-onshow><code>onshow</code></dfn> <td> <code title=event-show>show</code>
+    <tr><td><dfn id=handler-onsort title=handler-onsort><code>onsort</code></dfn> <td> <code title=event-sort>sort</code>
     <tr><td><dfn id=handler-onstalled title=handler-onstalled><code>onstalled</code></dfn> <td> <code title=event-media-stalled><a href=#event-media-stalled>stalled</a></code>
     <tr><td><dfn id=handler-onsubmit title=handler-onsubmit><code>onsubmit</code></dfn> <td> <code title=event-submit>submit</code> <!-- widely used -->
     <tr><td><dfn id=handler-onsuspend title=handler-onsuspend><code>onsuspend</code></dfn> <td> <code title=event-media-suspend><a href=#event-media-suspend>suspend</a></code>
@@ -96520,7 +97202,13 @@
   <!-- http://software.hixie.ch/utilities/js/live-dom-viewer/saved/1793 -->
   <!-- note that the "rules for parsing dimension values" can't return 0, if the value is "0" they treat it as an error -->
 
+  <hr><p id=sortable-ui>User agents are expected to render <a href=#sorting-capable-th-elements-of-the-table-element title="sorting-capable th elements of
+  the table element">sorting-capable <code>th</code> elements of</a> all <a href=#table-element-with-a-user-agent-exposed-sorting-interface title="table
+  element with a user-agent exposed sorting interface"><code>table</code> elements with a user-agent
+  exposed sorting interface</a> in such a manner as to indicate that activating the elements will
+  cause the table to be sorted.</p>
 
+
   <h4 id=form-controls><span class=secno>14.3.10 </span>Form controls</h4>
 
   <pre class=css>@namespace url(http://www.w3.org/1999/xhtml);
@@ -102952,6 +103640,11 @@
      <td> <code title=event-show>show</code> event handler
      <td> <a href=#event-handler-content-attributes title="event handler content attributes">Event handler content attribute</a>
 
+    <tr><th id=ix-handler-onsort> <code title="">onsort</code>
+     <td> <a href=#handler-onsort title=handler-onsort>HTML elements</a>
+     <td> <code title=event-sort>sort</code> event handler
+     <td> <a href=#event-handler-content-attributes title="event handler content attributes">Event handler content attribute</a>
+
     <tr><th id=ix-handler-onstalled> <code title="">onstalled</code>
      <td> <a href=#handler-onstalled title=handler-onstalled>HTML elements</a>
      <td> <code title=event-media-stalled><a href=#event-media-stalled>stalled</a></code> event handler

Modified: source
===================================================================
--- source	2012-12-19 20:11:40 UTC (rev 7596)
+++ source	2012-12-26 23:58:23 UTC (rev 7597)
@@ -2936,7 +2936,7 @@
      <li><dfn title="dom-Element-id"><code>id</code></dfn> attribute</li>
      <li><dfn><code>textContent</code></dfn> attribute</li>
 
-     <li>The <dfn title="concept-node-insert">insert</dfn>, <dfn title="concept-node-append">append</dfn>, and <dfn title="concept-node-replace">replace</dfn> algorithms for nodes</li>
+     <li>The <dfn title="concept-node-insert">insert</dfn>, <dfn title="concept-node-append">append</dfn>, <dfn title="concept-node-remove">remove</dfn>, and <dfn title="concept-node-replace">replace</dfn> algorithms for nodes</li>
      <li>The <dfn>nodes are inserted</dfn> and <dfn>nodes are removed</dfn> concepts</li>
 
      <li><dfn><code>Event</code></dfn> interface</li>
@@ -5740,6 +5740,9 @@
 
   <h5>Durations</h5>
 
+  <!-- if you add support for year and month durations, then search for MONTHS throughout the spec
+  (not just this section) for things that have to change -->
+
   <p>A <dfn title="concept-duration">duration</dfn> consists of <!--MONTHS: either a number of
   months or--> a number of seconds.</p>
 
@@ -9593,6 +9596,7 @@
            attribute <span>EventHandler</span> <span title="handler-onseeking">onseeking</span>;
            attribute <span>EventHandler</span> <span title="handler-onselect">onselect</span>;
            attribute <span>EventHandler</span> <span title="handler-onshow">onshow</span>;
+           attribute <span>EventHandler</span> <span title="handler-onsort">onsort</span>;
            attribute <span>EventHandler</span> <span title="handler-onstalled">onstalled</span>;
            attribute <span>EventHandler</span> <span title="handler-onsubmit">onsubmit</span>;
            attribute <span>EventHandler</span> <span title="handler-onsuspend">onsuspend</span>;
@@ -10773,6 +10777,7 @@
            attribute <span>EventHandler</span> <span title="handler-onseeking">onseeking</span>;
            attribute <span>EventHandler</span> <span title="handler-onselect">onselect</span>;
            attribute <span>EventHandler</span> <span title="handler-onshow">onshow</span>;
+           attribute <span>EventHandler</span> <span title="handler-onsort">onsort</span>;
            attribute <span>EventHandler</span> <span title="handler-onstalled">onstalled</span>;
            attribute <span>EventHandler</span> <span title="handler-onsubmit">onsubmit</span>;
            attribute <span>EventHandler</span> <span title="handler-onsuspend">onsuspend</span>;
@@ -10915,6 +10920,7 @@
    <li><code title="handler-onseeking">onseeking</code></li>
    <li><code title="handler-onselect">onselect</code></li>
    <li><code title="handler-onshow">onshow</code></li>
+   <li><code title="handler-onsort">onsort</code></li>
    <li><code title="handler-onstalled">onstalled</code></li>
    <li><code title="handler-onsubmit">onsubmit</code></li>
    <li><code title="handler-onsuspend">onsuspend</code></li>
@@ -22517,12 +22523,11 @@
 
   <div class="example">
 
-   <p>Here, a short table has its numeric values encoded using
-   <code>data</code> so that a script can provide a sorting mechanism
-   on each column, despite the numbers being presented in textual
-   form in one column and in a decomposed form in another.</p>
+   <p>Here, a short table has its numeric values encoded using <code>data</code> so that the
+   <span>table sorting model</span> can provide a sorting mechanism on each column, despite the
+   numbers being presented in textual form in one column and in a decomposed form in another.</p>
 
-   <pre><table class="sortable"> <!-- class used by script to find tables to which to add sorting controls -->
+   <pre><table sortable>
  <thead> <tr> <th> Game <th> Corporations <th> Map Size
  <tbody>
   <tr> <td> 1830 <td> <data value="8">Eight</data> <td> <data value="93">19+74 hexes (93 total)</data>
@@ -22729,9 +22734,8 @@
 
   <div class="impl">
 
-  <p>The machine-readable equivalent of the element's contents must be
-  obtained from the element's <span>datetime value</span> by using the
-  following algorithm:</p>
+  <p>The <dfn>machine-readable equivalent of the element's contents</dfn> must be obtained from the
+  element's <span>datetime value</span> by using the following algorithm:</p>
 
   <ol>
 
@@ -48469,6 +48473,7 @@
    total).</dd>
    <dt><span title="element-dfn-attributes">Content attributes</span>:</dt>
    <dd><span>Global attributes</span></dd>
+   <dd><code title="attr-table-sortable">sortable</code></dd>
    <dt><span title="element-dfn-dom">DOM interface</span>:</dt><!--TOPIC:DOM APIs-->
    <dd>
 <pre class="idl">interface <dfn>HTMLTableElement</dfn> : <span>HTMLElement</span> {
@@ -48486,6 +48491,8 @@
   readonly attribute <span>HTMLCollection</span> <span title="dom-table-rows">rows</span>;
   <span>HTMLElement</span> <span title="dom-table-insertRow">insertRow</span>(optional long index);
   void <span title="dom-table-deleteRow">deleteRow</span>(long index);
+           attribute boolean <span title="dom-table-sortable">sortable</span>;
+  void <span title="dom-table-stopSorting">stopSorting</span>();
 };</pre>
    </dd>
   </dl><!--TOPIC:HTML-->
@@ -48599,6 +48606,11 @@
 
   <hr>
 
+  <p>The <code title="attr-table-sortable">sortable</code> attribute is used in the <span>table
+  sorting model</span>.</p>
+
+  <hr>
+
 <!--TOPIC:DOM APIs-->
   <dl class="domintro">
 
@@ -48875,6 +48887,12 @@
 
   </ol>
 
+  <p>The <code title="dom-table-stopSorting">stopSorting()</code> method is used in the <span>table
+  sorting model</span>.</p>
+
+  <p>The IDL attribute <dfn title="dom-table-sortable"><code>sortable</code></dfn> must
+  <span>reflect</span> the <code title="attr-table-sortable">sortable</code> content attribute.</p>
+
   </div>
 <!--TOPIC:HTML-->
 
@@ -49811,11 +49829,14 @@
    <dd><code title="attr-tdth-headers">headers</code></dd>
    <dd><code title="attr-th-scope">scope</code></dd>
    <dd><code title="attr-th-abbr">abbr</code></dd>
+   <dd><code title="attr-th-sorted">sorted</code></dd>
    <dt><span title="element-dfn-dom">DOM interface</span>:</dt><!--TOPIC:DOM APIs-->
    <dd>
     <pre class="idl">interface <dfn>HTMLTableHeaderCellElement</dfn> : <span>HTMLTableCellElement</span> {
            attribute DOMString <span title="dom-th-scope">scope</span>;
            attribute DOMString <span title="dom-th-abbr">abbr</span>;
+           attribute DOMString <span title="dom-th-sorted">sorted</span>;
+  void <span title="dom-th-sort">sort</span>();
 };</pre>
    </dd>
   </dl><!--TOPIC:HTML-->
@@ -49881,6 +49902,9 @@
   to a data cell). It is typically an abbreviated form of the full header cell, but can also be an
   expansion, or merely a different phrasing.</p>
 
+  <p>The <code title="attr-th-sorted">sorted</code> attribute is used in the <span>table
+  sorting model</span>.</p>
+
   <div class="impl">
 
   <p>The <code>th</code> element and its <code
@@ -49890,12 +49914,16 @@
   title="attr-th-scope">scope</code> attributes take part in the
   <span>table model</span>.</p>
 
+  <p>The <code title="dom-th-sort">sort()</code> method is used in the <span>table sorting
+  model</span>.</p>
+
   <p>The <dfn title="dom-th-scope"><code>scope</code></dfn> IDL
   attribute must <span>reflect</span> the content attribute of the
   same name, <span>limited to only known values</span>.</p>
 
-  <p>The <dfn title="dom-th-abbr"><code>abbr</code></dfn> IDL attribute must <span>reflect</span>
-  the content attribute of the same name.</p>
+  <p>The <dfn title="dom-th-abbr"><code>abbr</code></dfn> and <dfn
+  title="dom-th-sorted"><code>sorted</code></dfn> IDL attributes must <span>reflect</span> the
+  content attributes of the same name.</p>
 
   </div>
 
@@ -50119,11 +50147,12 @@
   <p>It is possible, in certain error cases, for two cells to occupy
   the same slot.</p>
 
-  <p>A <dfn title="concept-row">row</dfn> is a complete set of slots
-  from <span title=""><var title="">x</var>=0</span> to <span title=""><var
-  title="">x</var>=<var title="">x<sub
-  title="">width</sub></var>-1</span>, for a particular value of <var
-  title="">y</var>. Rows correspond to <code>tr</code> elements.</p>
+  <p>A <dfn title="concept-row">row</dfn> is a complete set of slots from <span title=""><var
+  title="">x</var>=0</span> to <span title=""><var title="">x</var>=<var title="">x<sub
+  title="">width</sub></var>-1</span>, for a particular value of <var title="">y</var>. Rows usually
+  correspond to <code>tr</code> elements, though a <span title="concept-row-group">row group</span>
+  can have some implied <span title="concept-row">rows</span> at the end in some cases involving
+  <span title="concept-cell">cells</span> spanning multiple rows.</p>
 
   <p>A <dfn title="concept-column">column</dfn> is a complete set of
   slots from <span title=""><var title="">y</var>=0</span> to <span
@@ -51337,6 +51366,780 @@
   </div>
 
 
+  <h4><dfn>Table sorting model</dfn></h4>
+
+  <p>The <dfn title="attr-table-sortable"><code>sortable</code></dfn> attribute on
+  <code>table</code> elements is a <span>boolean attribute</span>. When present, it indicates that
+  the user agent is to <a href="#sortable-ui">allow the user to sort</a> the <code>table</code>.</p>
+
+  <p>To make a column sortable in a <code>table</code> with a <code>thead</code>, the column needs
+  to have <code>th</code> element that does not <span title="attr-tdth-colspan">span multiple
+  columns</span> in a <code>thead</code> above any rows that it is to sort.</p>
+
+  <p>To make a column sortable in a <code>table</code> without a <code>thead</code>, the column
+  needs to have <code>th</code> element that does not <span title="attr-tdth-colspan">span multiple
+  columns</span> in the first <code>tr</code> element of the <code>table</code>, where that
+  <code>tr</code> element is not in a <code>tfoot</code>.</p>
+
+  <p>When the user selects a column by which to sort, the user agent sets the <code>th</code>
+  element's <dfn title="attr-th-sorted"><code>sorted</code></dfn> attribute. This attribute can also
+  be set manually, to indicate that the table should be automatically sorted, even when scripts
+  modify the page on when the page is loaded.</p>
+
+  <p>The <code title="attr-th-sorted">sorted</code> attribute, if specified, must have a value that
+  is a <span>set of space-separated tokens</span> consisting of optionally a token whose value is an
+  <span>ASCII case-insensitive</span> match for the string "<dfn
+  title="attr-th-sorted-reversed"><code>reversed</code></dfn>", and optionally a token whose value
+  is a <span>valid non-negative integer</span> greater than zero, in either order.</p>
+
+  <p class="note">In other words, ignoring spaces and case, the <code
+  title="attr-th-sorted">sorted</code> attribute's value can be empty, "<code
+  title="">reversed</code>", "<code title="">1</code>", "<code title="">reversed 1</code>", or
+  "<code title="">1 reversed</code>", where "1" is any number equal to or greater than 1.</p>
+
+  <p>While one or more <code>th</code> elements in the table have a <code
+  title="attr-th-sorted">sorted</code> attribute, the user agent will keep the table's data rows
+  sorted. The value of the attribute controls how the column is used in determining the sort order.
+  The <code title="attr-th-sorted-reversed">reversed</code> keyword means that the <dfn>column sort
+  direction</dfn> is <i>reversed</i>, rather than <i>normal</i>, which is the default if the keyword
+  is omitted. The number, if present, indicates the <dfn>column key ordinality</dfn>; if the number
+  is omitted, the column is the primary key, as if the value 1 had been specified.</p>
+
+  <p class="note">Thus, <code title="">sorted="1"</code> indicates the table's primary key, <code
+  title="">sorted="2"</code> its secondary key, and so forth.</p>
+
+  <hr>
+
+  <p>A <dfn>sorting-capable <code>th</code> element</dfn> is a <code>th</code> element that matches
+  all the following conditions simultaneously:</p>
+
+  <ul>
+
+   <li><p>It corresponds to a <span title="concept-cell">cell</span> whose <i>width</i> is 1.
+   (Specifically, a <i>header cell</i>, since this is a <code>th</code> element.)</p></li>
+
+   <li><p>There is no <span title="concept-cell">cell</span> that corresponds to another
+   <span>sorting-capable <code>th</code> element</span> that covers slots in the same <span
+   title="concept-column">column</span> but on a higher (earlier) <span
+   title="concept-row">row</span>.</p></li> <!-- only matters if there's a <thead> -->
+
+   <li>
+
+    <p>If the <span title="concept-cell">cell</span>'s <span title="concept-table">table</span> has
+    a <span title="concept-row-group">row group</span> corresponding to a <code>thead</code>
+    element, the <span title="concept-cell">cell</span> is in a <span title="concept-row-group">row
+    group</span> that corresponds to the <em>first</em> <code>thead</code> element of the <span
+    title="concept-cell">cell</span>'s <span title="concept-table">table</span>.</p>
+
+    <p>Otherwise: the <span title="concept-cell">cell</span> is not in a <span
+    title="concept-row-group">row group</span> corresponding to a <code>tfoot</code> element, and
+    the <span title="concept-cell">cell</span> is in the first <span title="concept-row">row</span>
+    of the <span title="concept-table">table</span>.</p>
+
+   </li>
+
+  </ul>
+
+  <p class="note">In other words, each <span title="concept-column">column</span> can have one
+  <span>sorting-capable <code>th</code> element</span>; this will be the highest <code>th</code> in
+  a <code>thead</code> that spans no other columns, or, if there is no <code>thead</code>, the
+  <code>th</code> in the first row (that is not in a <code>tfoot</code>), assuming it spans no
+  columns.</p>
+
+  <p>The <dfn>sorting-capable <code>th</code> elements of the <code>table</code> element</dfn> <var
+  title="">table</var> are the <span title="sorting-capable th element">sorting-capable
+  <code>th</code> elements</span> whose <span title="concept-cell">cell</span>'s <span
+  title="concept-table">table</span> is <var title="">table</var>.</p>
+
+  <p>A <code>table</code> element <var title="">table</var> is a <dfn>sorting-capable
+  <code>table</code> element</dfn> if there are one or more <span>sorting-capable <code>th</code>
+  elements of the <code>table</code> element</span> <var title="">table</var>.</p>
+
+  <p>A <code>th</code> element is a <dfn>sorting-enabled <code>th</code> element</dfn> if it is a
+  <span>sorting-capable <code>th</code> element</span> and it has a <code
+  title="attr-th-sorted">sorted</code> attribute.</p>
+
+  <p>The <dfn>sorting-enabled <code>th</code> elements of the <code>table</code> element</dfn> <var
+  title="">table</var> are the <span title="sorting-enabled th element">sorting-enabled
+  <code>th</code> elements</span> whose <span title="concept-cell">cell</span>'s <span
+  title="concept-table">table</span> is <var title="">table</var>.</p>
+
+  <p>A <code>table</code> element <var title="">table</var> is a <dfn>sorting-enabled
+  <code>table</code> element</dfn> if there are one or more <span>sorting-capable <code>th</code>
+  elements of the <code>table</code> element</span> <var title="">table</var>, and at least one of
+  them is a <span>sorting-enabled <code>th</code> element</span> (i.e. at least one has a <code
+  title="attr-th-sorted">sorted</code> attribute).</p>
+
+  <p>A <code>table</code> element is a <dfn><code>table</code> element with a user-agent exposed
+  sorting interface</dfn> if it is a <span>sorting-capable <code>table</code> element</span> and has
+  a <code title="attr-table-sortable">sortable</code> attribute specified.</p>
+
+  <p>Each <code>table</code> element has a <dfn>currently-sorting flag</dfn>, which must initially
+  be false.</p>
+
+  <hr>
+
+  <p>The <code title="attr-th-sorted">sorted</code> attribute must not be specified on
+  <code>th</code> elements that are not <span title="sorting-capable th element">sorting-capable
+  <code>th</code> elements</span>. The <code title="attr-table-sortable">sortable</code> attribute
+  must not be specified on <code>table</code> elements that are not <span title="sorting-capable
+  table element">sorting-capable <code>table</code> elements</span>.</p>
+
+  <div class="impl">
+
+  <p>To determine a <code>th</code> element's <code title="attr-th-sorted">sorted</code> attribute's
+  <span>column sort direction</span> and <span>column key ordinality</span>, user agents must use
+  the following algorithm:</p>
+
+  <ol>
+
+   <li><p>Let <var title="">direction</var> be <i>normal</i>.</p>
+
+   <li><p>Let <var title="">have explicit direction</var> be false.</p>
+
+   <li><p>Let <var title="">ordinality</var> be 1.</p>
+
+   <li><p>Let <var title="">have explicit ordinality</var> be false.</p>
+
+   <li><p>Let <var title="">tokens</var> be the result of <span title="split a string on
+   spaces">splitting the attribute's value on spaces</span>.</p></li>
+
+   <li>
+
+    <p>For each token <var title="">token</var> in <var title="">tokens</var>, run the appropriate
+    steps from the following list:</p>
+
+    <dl class="switch">
+
+     <dt>If <var title="">have explicit direction</var> is false and <var title="">token</var> is an
+     <span>ASCII case-insensitive</span> match for the string "<code
+     title="attr-th-sorted-reversed">reversed</code>"</dt>
+
+     <dd>
+
+      <p>Let <var title="">direction</var> be <i>reversed</i> and <var title="">have explicit
+      direction</var> be true.</p>
+
+     </dd>
+
+
+     <dt>If <var title="">have explicit ordinality</var> is false</dt>
+
+     <dd>
+
+      <p><span title="rules for parsing integers">Parse <var title="">token</var> as an
+      integer</span>. If this resulted in an error or the value zero, then ignore the token.
+      Otherwise, set <var title="">ordinality</var> to the parsed value, and set <var title="">have
+      explicit ordinality</var> to true.</p>
+
+     </dd>
+
+
+     <dt>Otherwise</dt>
+
+     <dd><p>Ignore the token.</p></dd>
+
+    </dl>
+
+   </li>
+
+   <li><p>The <span>column sort direction</span> is the value of <var title="">direction</var>, and
+   the <span>column key ordinality</span> is the value of <var title="">ordinality</var>.</p></li>
+
+  </ol>
+
+  </div>
+
+  <p>A <code>table</code> must not have two <code>th</code> elements whose <code
+  title="attr-th-sorted">sorted</code> attribute have the same <span>column key
+  ordinality</span>.</p>
+
+  <div class="impl">
+
+  <hr>
+
+  <p>The <dfn>table sorting algorithm</dfn>, which is applied to a <code>table</code>, is as
+  follows:</p>
+
+  <ol>
+
+   <li><p>Let <var title="">table</var> be the <code>table</code> element being sorted.</p></li>
+
+   <li><p>If <var title="">table</var>'s <span>currently-sorting flag</span> is true, then abort
+   these steps.</p></li>
+
+   <li><p>Set <var title="">table</var>'s <span>currently-sorting flag</span> to true.</p></li>
+
+   <li><p><span>Fire a simple event</span> named <code title="event-sort">sort</code> that is
+   cancelable at <var title="">table</var>.</p></li>
+
+   <li><p>If the event fired in the previous step was canceled, then jump to the step labeled
+   <i>end</i> below.</p></li>
+
+   <li>
+
+    <p>If <var title="">table</var> is not now a <span>sorting-enabled <code>table</code>
+    element</span>, then jump to the step labeled <i>end</i> below.</p>
+
+    <p class="note">Even if <var title="">table</var> was a <span>sorting-enabled <code>table</code>
+    element</span> when the algorithm was invoked, the DOM might have been entirely changed by the
+    event handlers for the <code title="event-sort">sort</code> event, so this has to be verified at
+    this stage, not earlier.</p>
+
+   </li>
+
+   <li><p>Let <var title="">key heading cells</var> be the <span>sorting-enabled <code>th</code>
+   elements of the <code>table</code> element</span> <var title="">table</var>.</p></li>
+
+   <li><p>Sort <var title="">key heading cells</var> in ascending order of the <span>column key
+   ordinality</span> of their <code title="attr-th-sorted">sorted</code> attributes, with those
+   having the same <span>column key ordinality</span> being sorted in <span>tree order</span>.</p>
+
+   <li>
+
+    <p>Let <var title="">row collection cursor</var> be a pointer to an element, initially pointing
+    at the first child of <var title="">table</var> that is after <var title="">table</var>'s first
+    <code>thead</code>, if any, and that is either a <code>tbody</code> or a <code>tr</code>
+    element, assuming there is one. If there is no such child, then jump to the step labeled
+    <i>end</i> below.</p>
+
+   </li>
+
+   <li><p>If <var title="">table</var> has no <span title="concept-row-group">row group</span>
+   corresponding to a <code>thead</code> element, then set <var title="">ignore first group</var> to
+   true. Otherwise, set it to false.</p></li>
+
+   <li><p><i>Row loop</i>: Let <var title="">rows</var> be an empty list of <code>tr</code>
+   elements.</p></li>
+
+   <li>
+
+    <p>Run the appropriate steps from the following list:</p>
+
+    <dl class="switch">
+
+     <dt>If <var title="">row collection cursor</var> points to a <code>tr</code> element
+
+     <dd>
+
+      <ol>
+
+       <li><p><i>Collect</i>: Append the element pointed to by <var title="">row collection
+       cursor</var> to <var title="">rows</var>.</p></li>
+
+       <li><p>If there are no <code>tr</code> or <code>tbody</code> children of <var
+       title="">table</var> that are later siblings of the element pointed to by <var title="">row
+       collection cursor</var>, or if the next such child is a <code>tbody</code> element, then jump
+       to the step labeled <i>group</i> below.</p></li>
+
+       <li><p>Let <var title="">row collection cursor</var> point to the next <code>tr</code> child
+       of <var title="">table</var> that is a later sibling of the element pointed to by <var
+       title="">row collection cursor</var>.</p></li>
+
+       <li><p>Returned to the step labeled <i>collect</i> above.</p></li>
+
+      </ol>
+
+     </dd>
+
+
+     <dt>If <var title="">row collection cursor</var> points to a <code>tbody</code> element
+
+     <dd>
+
+      <ol>
+
+       <li><p>Place all the <code>tr</code> element children of the element pointed to by <var
+       title="">row collection cursor</var> into <var title="">rows</var>, in <span>tree
+       order</span>.</p></li>
+
+       <li><p>If <var title="">rows</var> is empty, jump to the step labeled <i>increment loop</i>
+       below.</p></li>
+
+      </ol>
+
+     </dd>
+
+    </dl>
+
+   </li>
+
+   <li><p><i>Group</i>: Let <var title="">groups</var> be an empty list of groups of <code>tr</code>
+   elements.</p></li>
+
+   <li><p>Let <var title="">group</var> be an empty group of <code>tr</code> elements.</p></li>
+
+   <li><p>Let <var title="">group cursor</var> be a pointer to an element, initially pointing at the
+   first <code>tr</code> element in <var title="">rows</var>.</p></li>
+
+   <li><p><i>Start group</i>: Let <var title="">pending rows in group</var> be 1.</p></li>
+
+   <li><p><i>Group loop</i>: Append the <code>tr</code> element pointed to by <var title="">group
+   cursor</var> to <var title="">group</var>.</p></li>
+
+   <li><p>If there are any <span title="concept-cell">cells</span> whose highest <span
+   title="concept-row">row</span>'s element is the one pointed to by <var title="">group
+   cursor</var>, then let <var title="">tallest height</var> be the number of rows covered by the
+   tallest such <span title="concept-cell">cell</span>.</p></li>
+
+   <li><p>If <var title="">tallest height</var> is greater than <var title="">pending rows in
+   group</var> then set <var title="">pending rows in group</var> to <var title="">tallest
+   height</var>.</p></li>
+
+   <li><p>Decrement <var title="">pending rows in group</var> by one.</p></li>
+
+   <li><p>Let <var title="">group cursor</var> point to the next <code>tr</code> element in <var
+   title="">rows</var>, if any; otherwise, let it be null.</p></li>
+
+   <li><p>If <var title="">group cursor</var> is not null and <var title="">pending rows in
+   group</var> is not zero, return to the step labeled <i>group loop</i>.</p></li>
+
+   <li><p>Append a new group to <var title="">groups</var> consisting of the <code>tr</code>
+   elements in <var title="">group</var>.</p></li>
+
+   <li><p>Empty <var title="">group</var>.</p></li>
+
+   <li><p>If <var title="">group cursor</var> is not null, then return to the step labeled <i>start
+   group</i>.</p></li>
+
+   <li><p>If <var title="">ignore first group</var> is true, then drop the first roup in <var
+   title="">groups</var> and set <var title="">ignore first group</var> to false.</p></li>
+
+   <li><p><i>Drop leading header groups</i>: If <var title="">groups</var> is now empty, jump to the
+   step labeled <i>increment loop</i> below.</p></li>
+
+   <!-- if you insert steps here, update the next step -->
+
+   <li><p>If the first group of <var title="">groups</var> consists of <code>tr</code> elements
+   whose element children are all <code>th</code> elements, then drop the first group in <var
+   title="">groups</var> and return to the previous step (labeled <i>drop leading header
+   groups</i>).</p></li>
+
+   <li><p>Let <var title="">insertion point</var> be a placeholder in a DOM tree, which can be used
+   to reinsert nodes at a specific point in the DOM. Insert <var title="">insertion point</var> into
+   the parent of the first <code>tr</code> element of the first group in <var title="">groups</var>,
+   immediately before that <code>tr</code> element.</p></li>
+
+   <li>
+
+    <p>Sort the groups in <var title="">groups</var>, using the following algorithm to decide the
+    relative order of any two groups <var title="">a</var> and <var title="">b</var> (the algorithm
+    either returns that <var title="">a</var> comes before <var title="">b</var>, or that <var
+    title="">b</var> comes before <var title="">a</var>):</p>
+
+    <ol>
+
+     <li><p>Let <var title="">key index</var> be an index into <var title="">key heading
+     cells</var>, initially denoting the first element in the list.</p></li>
+
+     <li><p>Let <var title="">direction</var> be a sort direction, initially <i>ascending</i>. Its
+     other possible value is <i>descending</i>. When <var title="">direction</var> is
+     <i>toggled</i>, that means that if its value is <i>ascending</i>, it must be changed to
+     <i>descending</i>, and when its value is <i>descending</i>, it must be changed to
+     <i>ascending</i>.</p></li>
+
+     <li><p><i>Column loop</i>: Let <var title="">th</var> be the <var title="">key index</var>th
+     <code>th</code> in <var title="">key heading cells</var>.</p></li>
+
+     <li><p>If <var title="">th</var>'s <code title="attr-th-sorted">sorted</code> attribute's
+     <span>column sort direction</span> is <i>reversed</i>, then toggle <var
+     title="">direction</var>.</p></li>
+
+     <li><p>Let <var title="">tentative order</var> be the result of <span>comparing two row groups
+     using the <code>th</code> element</span> <var title="">th</var>, with <var title="">a</var> and
+     <var title="">b</var> as the rows.</p></li>
+
+     <li><p>If <var title="">tentative order</var> is not "equal", then jump to the step labeled
+     <i>return</i> below.</p></li>
+
+     <li><p>Increment <var title="">key index</var>.</p></li>
+
+     <li><p>If <var title="">key index</var> still denotes a <code>th</code> element in <var
+     title="">key heading cells</var>, then jump back to the step above labeled <i>column
+     loop</i>.</p></li>
+
+     <li><p>If <var title="">a</var>'s <code>tr</code> elements precede <var title="">b</var>'s in
+     <span>tree order</span>, then let <var title="">tentative order</var> be "a before b".
+     Otherwise, let <var title="">tentative order</var> be "b before a".</p></li>
+
+     <li><p><i>Return</i>: Return the relative order given by the matching option from the following
+     list:</p>
+
+      <dl class="switch">
+
+       <dt>If <var title="">direction</var> is <i>ascending</i> and <var title="">tentative
+       order</var> is "a before b"</dt>
+
+       <dd>Return that <var title="">a</var> comes before <var title="">b</var>.</dd>
+
+
+       <dt>If <var title="">direction</var> is <i>ascending</i> and <var title="">tentative
+       order</var> is "b before a"</dt>
+
+       <dd>Return that <var title="">b</var> comes before <var title="">a</var>.</dd>
+
+
+       <dt>If <var title="">direction</var> is <i>descending</i> and <var title="">tentative
+       order</var> is "a before b"</dt>
+
+       <dd>Return that <var title="">b</var> comes before <var title="">a</var>.</dd>
+
+
+       <dt>If <var title="">direction</var> is <i>descending</i> and <var title="">tentative
+       order</var> is "b before a"</dt>
+
+       <dd>Return that <var title="">a</var> comes before <var title="">b</var>.</dd>
+
+      </dl>
+
+     </li>
+
+    </ol>
+
+    <p>When the user agent is required to <dfn title="comparing two row groups using the th
+    element">compare two row groups using the <code>th</code> element</dfn> <var title="">th</var>,
+    with <var title="">a</var> and <var title="">b</var> being the two row groups respectively, the
+    user agent must run the following steps:</p>
+
+    <ol>
+
+     <li><p>Let <var title="">x</var> be the <var title="">x</var>-coordinate of the slots that
+     <code>th</code> covers in its <span title="concept-table">table</span>.</p></li>
+
+     <li>
+
+      <p>Let <var title="">cell<sub>a</sub></var> be the element corresponding to the <span
+      title="concept-cell">cell</span> in the first <span title="concept-row">row</span> of group
+      <var title="">a</var> that covers the slot in that <span title="concept-row">row</span> whose
+      <var title="">x</var>-coordinate is <var title="">x</var>.</p>
+
+      <p>Let <var title="">cell<sub>b</sub></var> be the element corresponding to the <span
+      title="concept-cell">cell</span> in the first <span title="concept-row">row</span> of group
+      <var title="">b</var> that covers the slot in that <span title="concept-row">row</span> whose
+      <var title="">x</var>-coordinate is <var title="">x</var>.</p>
+
+      <!-- there can't be two cells that cover the slot, unusually, because the only way that can
+      happen is if there's a cell that's extended into this row from above, and the groups, by
+      virtue of the way they are created above, never have cells that extend into them from above.
+      -->
+
+      <p>In either case, if there's no <span title="concept-cell">cell</span> that actually covers
+      the slot, then use the value <i>null</i> instead.</p>
+
+     </li>
+
+     <li>
+
+      <p>Let <var title="">type<sub>a</sub></var> and <var title="">value<sub>a</sub></var> be
+      the <span>type and value of the cell</span> <var title="">cell<sub>a</sub></var>, as defined
+      below.</p>
+
+      <p>Let <var title="">type<sub>b</sub></var> and <var title="">value<sub>b</sub></var> be
+      the <span>type and value of the cell</span> <var title="">cell<sub>b</sub></var>, as defined
+      below.</p>
+
+      <p>The <dfn>type and value of the cell</dfn> <var title="">cell</var> are computed as follows.</p>
+
+      <ol>
+
+       <li><p>If <var title="">cell</var> is <i>null</i>, then the type is "string" and the value is
+       the empty string; abort these steps.</p></li>
+
+       <li><p>If, ignoring <span>inter-element whitespace</span> and <span>Comment</span> nodes,
+       <var title="">cell</var> has only one child and that child is a <code>data</code> element,
+       then the value is the value of that <code>data</code> element's <code
+       title="attr-data-value">value</code> attribute, if there is one, or the empty string
+       otherwise; the type is "string".</p>
+
+       <li>
+
+        <p>If, ignoring <span>inter-element whitespace</span> and <span>Comment</span> nodes, <var
+        title="">cell</var> has only one child and that child is a <code>time</code> element, then
+        the value is the <span>machine-readable equivalent of the element's contents</span>, if any,
+        and the type is the kind of value that is thus obtained
+       (a <span title="concept-month">month</span>,
+        a <span title="concept-date">date</span>,
+        a <span title="concept-yearless-date">yearless date</span>,
+        a <span title="concept-time">time</span>,
+        a <span title="concept-datetime-local">local date and time</span>,
+        a <span title="concept-timezone">time-zone offset</span>,
+        a <span title="concept-datetime">global date and time</span>,
+        a <span title="concept-week">week</span>,
+        a year, or
+        a <span title="concept-duration">duration</span>);
+        abort these steps after completing this one.</p>
+
+        <p>If there is no machine-readable equivalent, then the type is "string" and the value is
+        the empty string.</p>
+
+        <p>If the type is
+        a <span title="concept-month">month</span>,
+        a <span title="concept-date">date</span>,
+        a <span title="concept-week">week</span>, or
+        a year,
+        then change the value to be the instant in time (with no time zone) that describes the
+        earliest moment that the value represents, and change the type to be
+        a <span title="concept-datetime-local">local date and time</span>.</p>
+
+        <p class="example">For example, if the cell was
+        <code><td><time>2011-11</time></code> then for sorting purposes the value is
+        interpreted as "2011-11-01T00:00:00.000" and the type is treated as a <span
+        title="concept-datetime-local">local date and time</span> rather than a <span
+        title="concept-month">month</span>.</p>
+
+        <p class="example">Similarly, if the cell was <code><td><time
+        datetime="2011">MMXIV</time></code> then for sorting purposes the value is interpreted as
+        "2014-01-01T00:00:00.000" and the type is treated as a <span
+        title="concept-datetime-local">local date and time</span> rather than a year.</p>
+
+       </li>
+
+       <li><p>The value is the element's <code>textContent</code>. The type is "string".</p></li>
+
+      </ol>
+
+     </li>
+
+     <li>
+
+      <p>If <var title="">type<sub>a</sub></var> and <var title="">type<sub>b</sub></var> are not
+      equal, then: return "a before b" if <var title="">type<sub>a</sub></var> is earlier in the
+      following list than <var title="">type<sub>b</sub></var>, otherwise, return "b before a";
+      then, abort these steps.</p>
+
+      <ol class="brief">
+       <li><span title="concept-time">time</span></li>
+       <li><span title="concept-yearless-date">yearless date</span></li>
+       <li><span title="concept-datetime-local">local date and time</span></li>
+       <li><span title="concept-datetime">global date and time</span></li>
+       <li><span title="concept-timezone">time-zone offset</span></li>
+       <li><span title="concept-duration">duration</span></li>
+       <li>"string"</li>
+      </ol>
+
+     </li>
+
+     <li><p>If <var title="">value<sub>a</sub></var> and <var title="">value<sub>b</sub></var> are
+     equal, then return "equal" and abort these steps.</p></li>
+
+     <li>
+
+      <p>If <var title="">type<sub>a</sub></var> and <var title="">type<sub>b</sub></var> are not
+      "string", then: return "a before b" if <var title="">value<sub>a</sub></var> is earlier
+      than <var title="">value<sub>b</sub></var>, and return "b before a" otherwise.</p>
+
+      <p>Values sort in their natural order, with the following additional constraints:</p>
+
+      <p>For <span title="concept-time">time</span> values, 00:00:00.000 is the earliest value and
+      23:59:59.999 is the latest value.</p>
+
+      <p>For <span title="concept-yearless-date">yearless date</span> values, 01-01 is the earliest
+      value and 12-31 is the latest value; 02-28 is earlier than 02-29 which is earlier than
+      03-01.</p>
+
+      <p>Values that are <span title="concept-datetime-local">local date and time</span> compare as
+      if they were in the same time zone.</p>
+
+      <!-- no ambiguity for <span title="concept-datetime">global date and time</span> -->
+
+      <p>For <span title="concept-timezone">time-zone offset</span> values, -23:59 is the earliest
+      value and +23:59 is the latest value.</p>
+
+      <!-- MONTHS: <span title="concept-duration">duration</span> is unambiguous until we add months -->
+
+     </li>
+
+     <!-- At this point we know that they are both strings and they're not equal. -->
+
+     <li>
+
+      <p class="XXX">Return "a before b" if <var title="">value<sub>a</sub></var> is earlier than
+      <var title="">value<sub>b</sub></var>, and return "b before a" otherwise; for these purposes,
+      the strings must be compared using collation order of the <span>language</span> of the
+      <code>table</code> element to which <var title="">th</var>'s <span
+      title="concept-table">table</span> corresponds.</p>
+
+     </li>
+
+    </ol>
+
+   </li>
+
+
+   <li><p>Let <var title="">new order</var> be a list of <code>tr</code> elements consisting of the
+   <code>tr</code> elements of all the groups in the newly ordered <var title="">groups</var>, with
+   the <code>tr</code> elements being in the same order as the groups to which they belong are in
+   <var title="">groups</var>, and the <code>tr</code> elements within each such group themselves
+   being ordered in <span>tree order</span>.</p></li>
+
+   <li><p><span title="concept-node-remove">Remove</span> all the <code>tr</code> elements in <var
+   title="">new order</var> from their parents.</p></li>
+
+   <li><p><span title="concept-node-insert">Insert</span> all the <code>tr</code> elements in <var
+   title="">new order</var> into the DOM at the location of <var title="">insertion point</var>, in
+   the order these elements are found in <var title="">new order</var>.</p></li>
+
+   <!-- done with this set of rows -->
+
+   <li><p>Remove <var title="">insertion point</var> from the DOM.</p></li>
+
+   <li><p><i>Increment loop</i>: If there are no <code>tr</code> or <code>tbody</code> children of
+   <var title="">table</var> that are later siblings of the element pointed to by <var title="">row
+   collection cursor</var>, then jump to the step labeled <i>end</i> below.</p></li>
+
+   <li><p>Let <var title="">row collection cursor</var> point to the next <code>tr</code> or
+   <code>tbody</code> child of <var title="">table</var> that is a later sibling of the element
+   pointed to by <var title="">row collection cursor</var>.</p></li>
+
+   <li><p>Return to the step labeled <i>row loop</i> above.</p></li>
+
+   <li><p><i>End</i>: Set <var title="">table</var>'s <span>currently-sorting flag</span> to
+   false.</p></li>
+
+  </ol>
+
+  <p>When any of the descendants of a <span>sorting-enabled <code>table</code> element</span> change
+  in any way (including attributes changing), and when a <code>table</code> element becomes a
+  <span>sorting-enabled <code>table</code> element</span>, the <code>table</code> element is said to
+  become <dfn>a table with a pending sort</dfn>.</p>
+
+  <p>When the user agent is to <dfn>sort the tables with pending sorts</dfn>, which happens during
+  the <span>perform a microtask checkpoint</span> algorithm, the user agent must run the following
+  algorithm:</p>
+
+  <ol>
+
+   <li><p>Let <var title="">tables</var> be a list of each <code>table</code> in the <span>unit of
+   related similar-origin browsing contexts</span> that is <span>a table with a pending sort</span>,
+   in the order that they became such, with those that become such at the same time being listed in
+   <span>tree order</span>.</p>
+
+   <li><p>Let all the <code>table</code> elements in <var title="">tables</var> no longer be <span
+   title="a table with a pending sort">tables with a pending sort</span>.</p></li>
+
+   <li><p>Apply the <span>table sorting algorithm</span> to each <code>table</code> in <var
+   title="">tables</var>, in order.</p></li>
+
+  </ol>
+
+  <hr>
+
+  <p>When the user agent is to <dfn>set the sort key</dfn> to a <code>th</code> element <var
+  title="">target</var>, it must run the following algorithm:</p>
+
+  <ol>
+
+   <li><p>Let <var title="">table</var> be the <code>table</code> of the <span
+   title="concept-table">table</span> of which <var title="">target</var> is a header cell.</p></li>
+
+   <li><p>If <code>th</code> is a <span>sorting-enabled <code>th</code> element</span> whose
+   <span>column key ordinality</span> is 1, then: if its <span>column sort direction</span> is
+   <i>normal</i>, set that element's <code title="attr-th-sorted">sorted</code> attribute to the
+   string "<code title="">reversed</code>", otherwise, set it to the empty string; then, abort these
+   steps.</p></li>
+
+   <li><p>Let <var title="">current headers</var> be the <span>sorting-enabled <code>th</code>
+   elements of the <code>table</code> element</span> <var title="">table</var>, excluding <var
+   title="">target</var>.</p></li>
+
+   <li><p>Sort <var title="">current headers</var> by their <code
+   title="attr-th-sorted">sorted</code> attributes' <span>column key ordinality</span>, in ascending
+   order, with elements that have the same <span>column key ordinality</span> being sorted in
+   <span>tree order</span>.</p></li>
+
+   <li><p>Let <var title="">level</var> be 2.</p></li>
+
+   <li>
+
+    <p>For each <code>th</code> element <var title="">th</var> in <var title="">current
+    headers</var>, in order, run the following substeps:</p>
+
+    <ol>
+
+     <li><p>If <var title="">th</var>'s <code title="attr-th-sorted">sorted</code> attribute's
+     <span>column sort direction</span> is <i>normal</i>, then set <var title="">th</var>'s <code
+     title="attr-th-sorted">sorted</code> attribute to a <span>valid integer</span> whose value is
+     <var title="">level</var>. Otherwise, set it to the concatenation of the string "<code
+     title="">reversed</code>", a U+0020 SPACE character, and a <span>valid integer</span> whose
+     value is <var title="">level</var>.</p>
+
+     <li><p>Increment <var title="">level</var> by 1.</p></li>
+
+    </ol>
+
+   </li>
+
+   <li><p>Set <var title="">target</var>'s <code title="attr-th-sorted">sorted</code> attribute to
+   the empty string.</p></li>
+
+  </ol>
+
+  <hr>
+
+  <p>The <span>activation behavior</span> of the <span title="sorting-capable th elements of the
+  table element">sorting-capable <code>th</code> elements of</span> all <span title="table element
+  with a user-agent exposed sorting interface"><code>table</code> elements with a user-agent exposed
+  sorting interface</span> is to <span>set the sort key</span> to the <code>th</code> element.</p>
+
+  <p class="note">The <code>table</code> will be sorted the next time the user agent <span
+  title="perform a microtask checkpoint">performs a microtask checkpoint</span>.</p>
+
+  </div>
+
+  <dl class="domintro">
+
+   <dt><var title="">th</var> . <code title="dom-th-sort">sort</code>()</dt>
+
+   <dd>
+
+    <p>Act as if the user had indicated that this was to be the new primary sort column.</p>
+
+    <p>The <code>table</code> won't actually be sorted until the script terminates.</p>
+
+   </dd>
+
+
+   <dt><var title="">table</var> . <code title="dom-table-stopSorting">stopSorting</code>()</dt>
+
+   <dd>
+
+    <p>Removes all the <code title="attr-th-sorted">sorted</code> attributes that are causing the
+    table to automatically sort its contents, if any.</p>
+
+   </dd>
+
+  </dl>
+
+  <div class="impl">
+
+  <p>The <code>th</code> element's <dfn title="dom-th-sort"><code>sort()</code></dfn> method, when
+  invoked, must run the following steps:</p>
+
+  <ol>
+
+   <li><p>If the <code>th</code> element is not a <span>sorting-capable <code>th</code>
+   element</span>, then abort these steps.</p></li>
+
+   <li>
+
+    <p><span>Set the sort key</span> to the <code>th</code> element.</p>
+
+    <p class="note">The <code>table</code> will be sorted the next time the user agent <span
+    title="perform a microtask checkpoint">performs a microtask checkpoint</span>.</p>
+
+   </li>
+
+  </ol>
+
+
+  <p>The <code>table</code> element's <dfn
+  title="dom-table-stopSorting"><code>stopSorting()</code></dfn> method, when invoked, must remove
+  the <code title="attr-th-sorted">sorted</code> attribute of all the <span>sorting-enabled
+  <code>th</code> elements of the table element</span> on which the method was invoked.</p>
+
+  </div>
+
+
   <h4>Examples</h4>
 
   <!--END dev-html--><p><i>This section is non-normative.</i></p><!--START dev-html-->
@@ -77516,6 +78319,7 @@
            attribute <span>EventHandler</span> <span title="handler-onseeking">onseeking</span>;
            attribute <span>EventHandler</span> <span title="handler-onselect">onselect</span>;
            attribute <span>EventHandler</span> <span title="handler-onshow">onshow</span>;
+           attribute <span>EventHandler</span> <span title="handler-onsort">onsort</span>;
            attribute <span>EventHandler</span> <span title="handler-onstalled">onstalled</span>;
            attribute <span>EventHandler</span> <span title="handler-window-onstorage">onstorage</span>;
            attribute <span>EventHandler</span> <span title="handler-onsubmit">onsubmit</span>;
@@ -85224,6 +86028,9 @@
 
   <ol>
 
+   <!-- if you add a step here, make sure to go through the spec updating references to the "first
+   step" of the event loop -->
+
    <li><p>Run the oldest <span title="concept-task">task</span> on one of the <span>event
    loop</span>'s <span title="task queue">task queues</span>, if any, ignoring tasks whose
    associated <code>Document</code>s are not <span>fully active</span>. The user agent may pick any
@@ -85235,7 +86042,8 @@
    <li><p>If the <span>storage mutex</span> is now owned by the <span>event loop</span>, release it
    so that it is once again free.</p></li>
 
-   <li><p>Remove that task from its <span>task queue</span>.</p></li>
+   <li><p>If a task was run in the first step above, remove that task from its <span>task
+   queue</span>.</p></li>
 
    <li><p><span>Perform a microtask checkpoint</span>.</p></li>
 
@@ -85261,6 +86069,8 @@
    <li><p>Let the <span>running mutation observers</span> flag be
    true.</p></li>
 
+   <li><p><span>Sort the tables with pending sorts</span>.</p></li>
+
    <li>
 
     <p><span title="concept-mo-invoke">Invoke
@@ -86033,6 +86843,7 @@
     <tr><td><dfn title="handler-onseeking"><code>onseeking</code></dfn> <td> <code title="event-media-seeking">seeking</code>
     <tr><td><dfn title="handler-onselect"><code>onselect</code></dfn> <td> <code title="event-select">select</code> <!-- widely used --> <!-- [CSSOM] -->
     <tr><td><dfn title="handler-onshow"><code>onshow</code></dfn> <td> <code title="event-show">show</code>
+    <tr><td><dfn title="handler-onsort"><code>onsort</code></dfn> <td> <code title="event-sort">sort</code>
     <tr><td><dfn title="handler-onstalled"><code>onstalled</code></dfn> <td> <code title="event-media-stalled">stalled</code>
     <tr><td><dfn title="handler-onsubmit"><code>onsubmit</code></dfn> <td> <code title="event-submit">submit</code> <!-- widely used -->
     <tr><td><dfn title="handler-onsuspend"><code>onsuspend</code></dfn> <td> <code title="event-media-suspend">suspend</code>
@@ -111578,7 +112389,15 @@
   <!-- http://software.hixie.ch/utilities/js/live-dom-viewer/saved/1793 -->
   <!-- note that the "rules for parsing dimension values" can't return 0, if the value is "0" they treat it as an error -->
 
+  <hr>
 
+  <p id="sortable-ui">User agents are expected to render <span title="sorting-capable th elements of
+  the table element">sorting-capable <code>th</code> elements of</span> all <span title="table
+  element with a user-agent exposed sorting interface"><code>table</code> elements with a user-agent
+  exposed sorting interface</span> in such a manner as to indicate that activating the elements will
+  cause the table to be sorted.</p>
+
+
   <h4>Form controls</h4>
 
   <pre class="css">@namespace url(http://www.w3.org/1999/xhtml);
@@ -120453,6 +121272,12 @@
      <td> <span title="event handler content attributes">Event handler content attribute</span>
 
     <tr>
+     <th id="ix-handler-onsort"> <code title="">onsort</code>
+     <td> <span title="handler-onsort">HTML elements</span>
+     <td> <code title="event-sort">sort</code> event handler
+     <td> <span title="event handler content attributes">Event handler content attribute</span>
+
+    <tr>
      <th id="ix-handler-onstalled"> <code title="">onstalled</code>
      <td> <span title="handler-onstalled">HTML elements</span>
      <td> <code title="event-media-stalled">stalled</code> event handler




More information about the Commit-Watchers mailing list