HTML Standard Tracker

Diff (omit for latest revision)
Filter

Short URL: http://html5.org/r/2962

File a bug

SVNBugCommentTime (UTC)
2962<datagrid> mark II, first draft2009-04-18 01:16
Index: source
===================================================================
--- source	(revision 2961)
+++ source	(revision 2962)
@@ -6256,15 +6256,6 @@
   to an underlying string that consists of an <span>unordered set of
   unique space-separated tokens</span>.</p>
 
-  <p>Which string underlies a particular <code>DOMTokenList</code>
-  object is defined when the object is created. It might be a content
-  attribute (e.g. the string that underlies the <code
-  title="dom-classList">classList</code> object is the <code
-  title="attr-class">class</code> attribute), or it might be an
-  anonymous string (e.g. when a <code>DOMTokenList</code> object is
-  passed to an author-implemented callback in the
-  <code>datagrid</code> APIs).</p>
-
   <pre class="idl">[<span title="dom-tokenlist-toString">Stringifies</span>] interface <dfn>DOMTokenList</dfn> {
   readonly attribute unsigned long <span title="dom-tokenlist-length">length</span>;
   [IndexGetter] DOMString <span title="dom-tokenlist-item">item</span>(in unsigned long index);
@@ -6737,7 +6728,7 @@
    <li value="20"><dfn><code>ABORT_ERR</code></dfn></li> <!-- actually in XHR for now -->
    <li value="21"><dfn><code>URL_MISMATCH_ERR</code></dfn></li> <!-- actually in workers for now -->
    <li value="22"><dfn><code>QUOTA_EXCEEDED_ERR</code></dfn></li> <!-- actually defined right here for now -->
-   <li value="23"><dfn><code>UNAVAILABLE_SCRIPT_ERR</code></dfn></li> <!-- actually defined right here for now -->
+   <li value="23"><dfn><code>DATAGRID_MODEL_ERR</code></dfn></li> <!-- actually defined right here for now -->
    <li value="81"><dfn><code>PARSE_ERR</code></dfn></li> <!-- actually defined in dom3ls -->
    <li value="82"><dfn><code>SERIALISE_ERR</code></dfn></li> <!-- actually defined in dom3ls -->
   </ol>
@@ -16471,6 +16462,8 @@
    <li>minimum value &le; optimum point &le; maximum value</li>
   </ul>
 
+  <!-- next two paragraphs are duplicated in the <datagrid> section -->
+
   <p><strong>UA requirements for regions of the gauge</strong>: If the
   optimum point is equal to the low boundary or the high boundary, or
   anywhere in between them, then the region between the low and high
@@ -17834,7 +17827,7 @@
 
   <p>The <code>img</code> must not be used as a layout tool. In
   particular, <code>img</code> elements should not be used to display
-  fully transparent images, as they rarely convey meaning and rarely
+   transparent images, as they rarely convey meaning and rarely
   add anything useful to the document.</p>
 
   <div class="impl">
@@ -35508,22 +35501,13 @@
   title="concept-input-list">suggestions source element</span>.</p>
 
   <p>If there is a <span title="concept-input-list">suggestions source
-  element</span>, then each <code>option</code> element that is a
-  descendant of the <span title="concept-input-list">suggestions
-  source element</span>, that is not <span
-  title="concept-option-disabled">disabled</span>, and whose <span
-  title="concept-option-value">value</span> is a string that isn't the
-  empty string and that the user would be allowed to enter as the
-  <code>input</code> element's <span
-  title="concept-fe-value">value</span>, represents a suggestion. Each
-  suggestion has a <span title="concept-option-value">value</span> and
-  a <span title="concept-option-label">label</span>.</p>
-
-  <p>When the user agent is allowing the user to edit the
-  <code>input</code> element's <span
+  element</span>, then, when the user agent is allowing the user to
+  edit the <code>input</code> element's <span
   title="concept-fe-value">value</span>, the user agent should offer
-  the suggestions to the user in a manner suitable for the type of
-  control used. The user agent may use the suggestion's <span
+  the suggestions represented by the <span
+  title="concept-input-list">suggestions source element</span> to the
+  user in a manner suitable for the type of control used. The user
+  agent may use the suggestion's <span
   title="concept-option-label">label</span> to identify the suggestion
   if appropriate. If the user selects a suggestion, then the
   <code>input</code> element's <span
@@ -35531,9 +35515,12 @@
   suggestion's <span title="concept-option-value">value</span>, as if
   the user had written that value himself.</p>
 
-  <p>User agents should filter the suggestions to hide suggestions
-  that would cause the element to not <span
-  title="concept-fv-valid">satisfy its constraints</span>.</p>
+  <p>User agents must filter the suggestions to hide suggestiosn that
+  the user would not be allowed to enter as the <code>input</code>
+  element's <span title="concept-fe-value">value</span>, and should
+  filter the suggestions to hide suggestions that would cause the
+  element to not <span title="concept-fv-valid">satisfy its
+  constraints</span>.</p>
 
   <hr>
 
@@ -36974,8 +36961,19 @@
   <p>The <code>datalist</code> element is hooked up to an
   <code>input</code> element using the <code
   title="attr-input-list">list</code> attribute on the
-  <code>input</code> element.</p>
+  <code>input</code> element. The <code>datalist</code> element can
+  also be used with a <code>datagrid</code> element, as the source of
+  autocompletion hints for <code
+  title="datagrid-type-editable">editable</code> cells.</p>
 
+  <p>Each <code>option</code> element that is a descendant of the
+  <code>datalist</code> element, that is not <span
+  title="concept-option-disabled">disabled</span>, and whose <span
+  title="concept-option-value">value</span> is a string that isn't the
+  empty string, represents a suggestion. Each suggestion has a <span
+  title="concept-option-value">value</span> and a <span
+  title="concept-option-label">label</span>.
+
   <dl class="domintro">
 
    <dt><var title="">datalist</var> . <code title="dom-datalist-options">options</code></dt>
@@ -40147,11 +40145,8 @@
 
 
 
-<div class="bad">
   <h4 id="datagrid">The <dfn><code>datagrid</code></dfn> element</h4>
 
-<p class="XXX">The API here needs rewriting. Don't implement this right now.</p>
-
   <dl class="element">
    <dt>Categories</dt>
    <dd><span>Flow content</span>.</dd>
@@ -40167,43 +40162,84 @@
    <dd>Or: A single <code>datalist</code> element.</dd>
    <dt>Content attributes:</dt>
    <dd><span>Global attributes</span></dd>
+<!--v2DGS:
    <dd><code title="attr-datagrid-multiple">multiple</code></dd>
+-->
    <dd><code title="attr-datagrid-disabled">disabled</code></dd>
    <dt>DOM interface:</dt>
    <dd>
 <pre class="idl">interface <dfn>HTMLDataGridElement</dfn> : <span>HTMLElement</span> {
-           attribute <span>DataGridDataProvider</span> <span title="dom-datagrid-data">data</span>;
-  readonly attribute <span>DataGridSelection</span> <span title="dom-datagrid-selection">selection</span>;
            attribute boolean <span title="dom-datagrid-multiple">multiple</span>;
            attribute boolean <span title="dom-datagrid-disabled">disabled</span>;
-  void <span title="dom-datagrid-updateEverything">updateEverything</span>();
-  void <span title="dom-datagrid-updateRowsChanged">updateRowsChanged</span>(in <span>RowSpecification</span> row, in unsigned long count);
-  void <span title="dom-datagrid-updateRowsInserted">updateRowsInserted</span>(in <span>RowSpecification</span> row, in unsigned long count);
-  void <span title="dom-datagrid-updateRowsRemoved">updateRowsRemoved</span>(in <span>RowSpecification</span> row, in unsigned long count);
-  void <span title="dom-datagrid-updateRowChanged">updateRowChanged</span>(in <span>RowSpecification</span> row);
-  void <span title="dom-datagrid-updateColumnChanged">updateColumnChanged</span>(in unsigned long column);
-  void <span title="dom-datagrid-updateCellChanged">updateCellChanged</span>(in <span>RowSpecification</span> row, in unsigned long column);
+           attribute <span>DataGridListener</span> <span title="dom-datagrid-listener">listener</span>;
+<!-- v2DGS:
+  readonly attribute <span>DataGridSelection</span> <span title="dom-datagrid-selection">selection</span>;
+-->
+  // columns
+  void <span title="dom-datagrid-addColumn">addColumn</span>(in <span>Column</span> id, in DOMString label, in DOMString type, [Optional] in HTMLImageElement icon, [Optional] in boolean sortable, [Optional] in boolean visible);
+           attribute DOMString <span title="dom-datagrid-sortColumn">sortColumn</span>;
+           attribute boolean <span title="dom-datagrid-sortAscending">sortAscending</span>;
+  void <span title="dom-datagrid-clearColumns">clearColumns</span>();
+
+  // rows
+  void <span title="dom-datagrid-renotify">renotify</span>();
+  void <span title="dom-datagrid-setRowCount">setRowCount</span>(in long childCount, in long rowCount);
+  void <span title="dom-datagrid-setRows">setRows</span>(in <span>RowList</span> rows);
+  void <span title="dom-datagrid-insertRows">insertRows</span>(in <span>RowList</span> rows);
+  void <span title="dom-datagrid-deleteRows">deleteRows</span>(in <span>RowIDList</span> rows);
+  void <span title="dom-datagrid-repaint">repaint</span>(in <span>RowID</span> row, in DOMString column);
+  void <span title="dom-datagrid-clearRows">clearRows</span>();
+<!--
+ v2: opening and closing a row
+     moving a row's actual ID
+      - imagine new mail moving a thread up; you just want to add the new mail to the thread and move the thread's first mail to the top
+      - though actually that should probably just be done using display sorting
+-->
+};
+
+typedef DOMString <dfn>Column</dfn>;
+typedef sequence&lt;<span>Column</span>> <dfn>ColumnList</dfn>;
+typedef sequence&lt;any> <dfn>Cell</dfn>; // <span>Column</span>, [Variadic] any (exact types expected depend on the column type)
+typedef sequence&lt;<span>Cell</span>> <dfn>CellList</dfn>;
+typedef sequence&lt;any> <dfn>Row</dfn>; // <span>RowID</span>, long, long, <span>CellList</span>, [Optional] boolean, [Optional] long
+typedef sequence&lt;<span>Row</span>> <dfn>RowList</dfn>;
+typedef sequence&lt;unsigned long> <dfn>RowID</dfn>;
+typedef sequence&lt;<span>RowID</span>> <dfn>RowIDList</dfn>;
+
+[Callback=FunctionOnly, NoInterfaceObject]
+interface <dfn>RenderingContext2DCallback</dfn> {
+  DOMString <span title="dom-Rendering2DContextCallback-handleEvent">handleEvent</span>(in <span>CanvasRenderingContext2D</span> context, in unsigned long width, in unsigned long height);
 };</pre>
    </dd>
   </dl>
 
-  <p class="XXX">One possible thing to be added is a way to
-  detect when a row/selection has been deleted, activated, etc, by the
-  user (delete key, enter key, etc).</p> <!-- XXXPA -->
+  <p>The <code>datagrid</code> element <span>represents</span> an
+  interactive representation of tree, list, or tabular data.</p>
 
-  <p>The <code>datagrid</code> element <span>represents</span> an interactive
-  representation of tree, list, or tabular data.</p>
+  <p>The data being presented is provided by script using the methods
+  described in the following sections.</p>
 
-  <p>The data being presented can come either from the content, as
-  elements given as children of the <code>datagrid</code> element, or
-  from a scripted data provider given by the <code
-  title="dom-datagrid-data">data</code> DOM attribute.</p>
+<!--v2DGS:
+  <p>The <dfn
+  title="attr-datagrid-multiple"><code>multiple</code></dfn> attribute
+  is a <span>boolean attribute</span>. When set, it indicates that the
+  user can select more than one row at a time.</p>
+-->
 
-  <p>The <code title="attr-datagrid-multiple">multiple</code> and
-  <code title="attr-datagrid-disabled">disabled</code> attributes are
-  <span title="boolean attribute">boolean attributes</span>. Their
-  effects are described in the processing model sections below.</p>
+  <p>The <dfn
+  title="attr-datagrid-disabled"><code>disabled</code></dfn> attribute
+  is a <span>boolean attribute</span> used to disable the
+  control. <span class="impl">When the attribute is set, the user
+  agent must disable the <code>datagrid</code>, preventing the user
+  from interacting with it. The <code>datagrid</code> element should
+  still continue to update itself when the underlying data changes,
+  though, as described in the next few sections. However, conformance
+  requirements stating that <code>datagrid</code> elements must react
+  to users in particular ways do not apply when one is
+  disabled.</span></p>
 
+  <div class="impl">
+
   <p>The <dfn
   title="dom-datagrid-multiple"><code>multiple</code></dfn> and <dfn
   title="dom-datagrid-disabled"><code>disabled</code></dfn> DOM
@@ -40212,16 +40248,24 @@
   title="attr-datagrid-disabled">disabled</code> content attributes
   respectively.</p>
 
+  </div>
 
-  <h5>The <code>datagrid</code> data model</h5>
+  <!-- v2DGPA: One possible thing to be added is a way to detect when a
+  row/selection has been deleted, activated, etc, by the user (delete
+  key, enter key, etc). (v2DGPA = <datagrid> Perform Action) -->
 
+
+  <h5>Introduction</h5>
+
   <p><em>This section is non-normative.</em></p>
 
   <p>In the <code>datagrid</code> data model, data is structured as a
   set of rows representing a tree, each row being split into a number
   of columns. The columns are always present in the data model,
-  although individual columns may be hidden in the presentation.</p>
+  although individual columns might be hidden in the presentation.</p>
 
+  <hr>
+
   <p>Each row can have child rows. Child rows may be hidden or
   shown, by closing or opening (respectively) the parent row.</p>
 
@@ -40232,1757 +40276,2384 @@
   is row "0,1"; the fourth child of the seventh child of the third
   child of the tenth row is "9,2,6,3", etc.</p>
 
-  <p>The columns can have captions. Those captions are not considered
-  a row in their own right, they are obtained separately.</p>
+  <p>The chains of numbers that give a row's path, or identifier, are
+  represented by arrays of positions, represented in IDL by the
+  <span>RowID</span> interface.</p>
 
+  <p>The root of the tree is represented by an empty array.</p>
+
+  <hr>
+
+  <p>Each column has a string that is used to identify it in the API,
+  a label that is shown to users interacting with the column, a type,
+  and optionally an icon.</p>
+
+  <p>The possible types are as follows:</p>
+
+  <table>
+   <thead>
+    <tr>
+     <td>Keyword
+     <td>Description
+   <tbody>
+    <tr>
+     <td><code title="datagrid-type-text">text</code>
+     <td>Simple text.
+    <tr>
+     <td><code title="datagrid-type-editable">editable</code>
+     <td>Editable text.
+    <tr>
+     <td><code title="datagrid-type-checkable">checkable</code>
+     <td>Text with a check box.
+    <tr>
+     <td><code title="datagrid-type-list">list</code>
+     <td>A list of values that the user can switch between.
+    <tr>
+     <td><code title="datagrid-type-progress">progress</code>
+     <td>A progress bar.
+    <tr>
+     <td><code title="datagrid-type-meter">meter</code>
+     <td>A gauge.
+    <tr>
+     <td><code title="datagrid-type-custom">custom</code>
+     <td>A canvas onto which arbitrary content can be drawn.
+  </table>
+
+  <p>Each column can be flagged as sortable, in which case the user
+  will be able to sort the view using that column.</p>
+
+  <p>Columns are not necessarily visible. A column can be created
+  invisible by default. The user can select which columns are to be
+  shown.</p>
+
+  <p>When no columns have been added to the <code>datagrid</code>, a
+  column with no name, whose identifier is the empty string, whose
+  type is <code title="datagrid-type-text">text</code>, and which is
+  not sortable, is implied. This column is removed if any explicit
+  columns are declared.</p>
+
+  <p>Each cell uses the type given for its column, so all cells in a
+  column present the same type of information.</p>
+
+<!--v2DGS:
   <p>Selection of data in a <code>datagrid</code> operates at the row
   level. If the <code title="attr-datagrid-multiple">multiple</code>
   attribute is present, multiple rows can be selected at once,
   otherwise the user can only select one row at a time.</p>
-
-  <p>The <code>datagrid</code> element can be disabled entirely by
-  setting the <code title="attr-datagrid-disabled">disabled</code>
-  attribute.</p>
-<!--XXXDND
-  <p class="XXX">selection draggable [normative definitions are
-  in the interactive part below]</p>
 -->
 
-  <p>Columns, rows, and cells can each have specific flags, known as
-  classes, applied to them by the data provider. These classes <a
-  href="#datagridClassSummary">affect the functionality</a> of the
-  <code>datagrid</code> element, and are also <a
-  href="#datagridPseudos">passed to the style system</a>. They are
-  similar in concept to the <code title="attr-class">class</code>
-  attribute, except that they are not specified on elements but are
-  given by scripted data providers.</p> <!-- XXX check xrefs -->
+  <!-- v2DGDND: selection should draggable to and from datagrids -->
 
 
-  <h5>How rows are identified</h5>
+  <h6>Example: a <code>datagrid</code> backed by a static <code>table</code> element</h6>
 
-  <p>The chains of numbers that give a row's path, or identifier, are
-  represented by objects that implement the
-  <span>RowSpecification</span> interface.</p>
+  <p class="XXX">...</p>
 
-  <pre class="idl">[NoInterfaceObject] interface <dfn>RowSpecification</dfn> {
-  // binding-specific interface
-};</pre>
 
-  <p>In JavaScript, two classes of objects are said to implement this
-  interface: Numbers representing non-negative integers, and
-  homogeneous arrays of Numbers representing non-negative
-  integers. Thus, <code>[1,0,9]</code> is a
-  <span>RowSpecification</span>, as is <code>1</code> on its
-  own. However, <code>[1,0.2,9]</code> is not a
-  <span>RowSpecification</span> object, since its second value is not
-  an integer.</p>
+  <h6>Example: a <code>datagrid</code> backed by nested <code>ol</code> elements</h6>
 
-  <p>User agents must always represent <code>RowSpecification</code>s
-  in JavaScript by using arrays, even if the path only has one
-  number.</p>
+  <p class="XXX">...</p>
 
-  <p>The root of the tree is represented by the empty path; in
-  JavaScript, this is the empty array (<code>[]</code>). Only the
-  <code title="dom-provider-getRowCount">getRowCount()</code> and
-  <code
-  title="dom-provider-getChildAtPosition">GetChildAtPosition()</code>
-  methods ever get called with the empty path.</p>
 
+  <h6>Example: a <code>datagrid</code> backed by a server</h6>
 
-  <h5>The data provider interface</h5>
+  <p class="XXX">...</p>
 
-  <p><em>The conformance criteria in this section apply to any
-  implementation of the <code>DataGridDataProvider</code>, including
-  (and most commonly) the content author's implementation(s).</em></p>
 
-<p class="XXX">The API here needs rewriting. Don't implement this right now.</p>
+  <h5>Populating the <code>datagrid</code></h5>
 
-  <pre class="idl">// To be implemented by Web authors as a JS object
-[NoInterfaceObject] interface <dfn>DataGridDataProvider</dfn> {
-  void <span title="dom-provider-initialize">initialize</span>(in <span>HTMLDataGridElement</span> datagrid);
-  unsigned long <span title="dom-provider-getRowCount">getRowCount</span>(in <span>RowSpecification</span> row);
-  unsigned long <span title="dom-provider-getChildAtPosition">getChildAtPosition</span>(in <span>RowSpecification</span> parentRow, in unsigned long position);
-  unsigned long <span title="dom-provider-getColumnCount">getColumnCount</span>();
-  DOMString <span title="dom-provider-getCaptionText">getCaptionText</span>(in unsigned long column);
-  void <span title="dom-provider-getCaptionClasses">getCaptionClasses</span>(in unsigned long column, in DOMTokenList classes);
-  DOMString <span title="dom-provider-getRowImage">getRowImage</span>(in <span>RowSpecification</span> row);
-  <span>HTMLMenuElement</span> <span title="dom-provider-getRowMenu">getRowMenu</span>(in <span>RowSpecification</span> row);
-  void <span title="dom-provider-getRowClasses">getRowClasses</span>(in <span>RowSpecification</span> row, in DOMTokenList classes);
-  DOMString <span title="dom-provider-getCellData">getCellData</span>(in <span>RowSpecification</span> row, in unsigned long column);
-  void <span title="dom-provider-getCellClasses">getCellClasses</span>(in <span>RowSpecification</span> row, in unsigned long column, in DOMTokenList classes);
-<!--XXXDND
-  boolean <span title="dom-provider-canDrop">canDrop</span>(in <span>RowSpecification</span> row, in <span>RowSpecification</span> position, data);
-  boolean <span title="dom-provider-dropped">dropped</span>(in <span>RowSpecification</span> row, in <span>RowSpecification</span> position, data);
--->  void <span title="dom-provider-toggleColumnSortState">toggleColumnSortState</span>(in unsigned long column);
-  void <span title="dom-provider-setCellCheckedState">setCellCheckedState</span>(in <span>RowSpecification</span> row, in unsigned long column, in long state);
-  void <span title="dom-provider-cycleCell">cycleCell</span>(in <span>RowSpecification</span> row, in unsigned long column);
-  void <span title="dom-provider-editCell">editCell</span>(in <span>RowSpecification</span> row, in unsigned long column, in DOMString data);
-<!--XXXPA
-  void <span title="dom-provider-performAction">performAction</span>(in DOMString action); // required if .performAction() is ever invoked on the datagrid
-  void <span title="dom-provider-performActionOnRow">performActionOnRow</span>(in <span>RowSpecification</span> row, in DOMString action); // required if getRowClasses ever includes 'deletable' or if <span title="dom-provider-.performActionOnRow">.performActionOnRow</span>() is ever invoked on the datagrid
-  void <span title="dom-provider-performActionOnCell">performActionOnCell</span>(in <span>RowSpecification</span> row, in unsigned long column, in DOMString action); // required if .performActionOnCell() is ever invoked on the datagrid
--->};</pre>
-<!-- based on http://lxr.mozilla.org/seamonkey/source/layout/xul/base/src/tree/public/nsITreeView.idl -->
+  <dl class="domintro">
 
-  <p>The <code>DataGridDataProvider</code> interface represents the
-  interface that objects must implement to be used as custom data
-  views for <code>datagrid</code> elements.</p>
+   <dt><var title="">datagrid</var> . <code title="dom-datagrid-listener">listener</code> [ = <var title="">value</var> ]</dt>
+   <dd>
 
-  <p>Not all the methods are required. The minimum number of methods
-  that must be implemented in a useful view is two: the <code
-  title="dom-provider-getRowCount">getRowCount()</code> and <code
-  title="dom-provider-getCellData">getCellData()</code> methods.</p>
+    <p>Return the current object that is configured as the
+    <code>datagrid</code> listener, if any. Returns null if there is
+    none.</p>
 
-  <p>Once the object is written, it must be hooked up to the
-  <code>datagrid</code> using the <dfn
-  title="dom-datagrid-data"><code>data</code></dfn> DOM attribute.</p>
+    <p>The listener is an object provided by the script author that
+    receives notifications when the <code>datagrid</code> needs row
+    data to render itself, when the user opens and closes rows with
+    children, when the user edits a cell, and when the user invokes a
+    row's context menu. (The <code>DataGridListener</code> interface
+    used for this purpose is described in the next section.)</p>
 
-  <p>The following methods may be usefully implemented:</p>
+    <p>Can be set, to change the current listener.</p>
 
-  <dl>
+   </dd>
 
-   <dt><dfn title="dom-provider-initialize"><code>initialize(<var title="">datagrid</var>)</code></dfn></dt>
 
-   <dd>Called by the <code>datagrid</code> element (the one given by
-   the <var title="">datagrid</var> argument) after it has first
-   populated itself. This would typically be used to set the initial
-   selection of the <code>datagrid</code> element when it is first
-   loaded. The data provider could also use this method call to
-   register a <code title="event-select">select</code> event handler
-   on the <code>datagrid</code> in order to monitor selection
-   changes.</dd>
+   <dt><var title="">datagrid</var> . <code title="dom-datagrid-renotify">renotify</code>()</dt>
+   <dd>
 
-   <dt><dfn title="dom-provider-getRowCount"><code>getRowCount(<var title="">row</var>)</code></dfn></dt>
+    <p>Causes the <code>datagrid</code> to resend notifications to the
+    listener (if any) for any rows or cells that the
+    <code>datagrid</code> does not yet have information for.</p>
 
-   <dd>Must return the number of rows that are children of the
-   specified <var title="">row</var>, including rows that are
-   off-screen. If <var title="">row</var> is empty, then the number of
-   rows at the top level must be returned. If the value that this
-   method would return for a given <var title="">row</var> changes,
-   the relevant update methods on the <code>datagrid</code> must be
-   called first. Otherwise, this method must always return the same
-   number. For a list (as opposed to a tree), this method must return
-   0 whenever it is called with a <var title="">row</var> identifier
-   that is not empty.</dd>
+    <!-- useful, e.g., if there is a server error and the script loses
+    track of what rows it's supposed to be reporting. -->
 
-   <dt><dfn title="dom-provider-getChildAtPosition"><code>getChildAtPosition(<var title="">parentRow</var>, <var title="">position</var>)</code></dfn></dt>
+   </dd>
 
-   <dd>Must return the index of the row that is a child of <var
-   title="">parentRow</var> and that is to be positioned as the <var
-   title="">position</var>th row under <var title="">parentRow</var>
-   when rendering the children of <var title="">parentRow</var>. If
-   <var title="">parentRow</var> is empty, then <var
-   title="">position</var> refers to the <var
-   title="">position</var>th row at the top level of the data
-   grid. May be omitted if the rows are always to be sorted in the
-   natural order. (The natural order is the one where the method
-   always returns <var title="">position</var>.) For a given <var
-   title="">parentRow</var>, this method must never return the same
-   value for different values of <var title="">position</var>. The
-   returned value <var title="">x</var> must be in the range
-   0&nbsp;&le;&nbsp;<var title="">x</var>&nbsp;&lt;&nbsp;<var
-   title="">n</var>, where <var title="">n</var> is the value returned
-   by <code title="dom-provider-getRowCount">getRowCount(<var
-   title="">parentRow</var>)</code>.</dd>
 
-   <dt><dfn title="dom-provider-getColumnCount"><code>getColumnCount()</code></dfn></dt>
+   <dt><var title="">datagrid</var> . <code title="dom-datagrid-addColumn">addColumn</code>(<var title="">id</var>, <var title="">label</var>, <var title="">type</var> [, <var title="">icon</var> [, <var title="">sortable</var> [, <var title="">visible</var> ] ] ] )</dt>
+   <dd>
 
-   <dd>Must return the number of columns currently in the data model
-   (including columns that might be hidden). May be omitted if there
-   is only one column. If the value that this method would return
-   changes, the <code>datagrid</code>'s <code
-   title="dom-datagrid-updateEverything">updateEverything()</code>
-   method must be called.</dd>
+    <p>Adds a column to the <code>datagrid</code>.</p>
 
-   <dt><dfn title="dom-provider-getCaptionText"><code>getCaptionText(<var title="">column</var>)</code></dfn></dt>
+    <p>If a column with the given identifier has already been added,
+    it just replaces the information for that column.</p>
 
-   <dd>Must return the caption, or label, for column <var
-   title="">column</var>. May be omitted if the columns have no
-   captions. If the value that this method would return changes, the
-   <code>datagrid</code>'s <code
-   title="dom-datagrid-updateColumnChanged">updateColumnChanged()</code>
-   method must be called with the appropriate column index.</dd>
+    <p>The possible types are enumerated in the previous section.</p>
 
-   <dt><dfn title="dom-provider-getCaptionClasses"><code>getCaptionClasses(<var title="">column</var>, <var title="">classes</var>)</code></dfn></dt>
+   </dd>
 
-   <dd>Must add the classes that apply to column <var
-   title="">column</var> to the <var title="">classes</var> object.
-   May be omitted if the columns have no special classes. If the
-   classes that this method would add changes, the
-   <code>datagrid</code>'s <code
-   title="dom-datagrid-updateColumnChanged">updateColumnChanged()</code>
-   method must be called with the appropriate column index. Some
-   classes have <a href="#datagridClassSummary">predefined
-   meanings</a>.</dd>
 
-   <dt><dfn title="dom-provider-getRowImage"><code>getRowImage(<var title="">row</var>)</code></dfn></dt>
+   <dt><var title="">datagrid</var> . <code title="dom-datagrid-sortColumn">sortColumn</code> [ = <var title="">value</var> ]</dt>
+   <dd>
 
-   <dd>Must return a <span>URL</span> giving the address of an image
-   that represents row <var title="">row</var>, or the empty string if
-   there is no applicable image. May be omitted if no rows have
-   associated images. If the value that this method would return
-   changes, the <code>datagrid</code>'s update methods must be called
-   to update the row in question.</dd>
+    <p>Returns the identifier of the column by which the data is to be
+    sorted.</p>
 
-   <dt><dfn title="dom-provider-getRowMenu"><code>getRowMenu(<var title="">row</var>)</code></dfn></dt>
+    <p>Can be set, to indicate that the sort order has changed. This
+    will cause the <code>datagrid</code> to clear its position
+    information for rows, so <code
+    title="dom-datagrid-setRows">setRows()</code> will have to be
+    called again with the new sort order.</p>
 
-   <dd>Must return an <code>HTMLMenuElement</code> object that is to
-   be used as a context menu for row <var title="">row</var>, or null
-   if there is no particular context menu. May be omitted if none of
-   the rows have a special context menu. As this method is called
-   immediately before showing the menu in question, no precautions
-   need to be taken if the return value of this method changes.</dd>
+    <p>The columns are not actually sorted by the
+    <code>datagrid</code>; the data has to be sorted by the script
+    that adds the rows to the <code>datagrid</code>.</p>
 
-   <dt><dfn title="dom-provider-getRowClasses"><code>getRowClasses(<var title="">row</var>, <var title="">classes</var>)</code></dfn></dt>
+   </dd>
 
-   <dd>Must add the classes that apply to row <var title="">row</var>
-   to the <var title="">classes</var> object. May be omitted if the
-   rows have no special classes. If the classes that this method would
-   add changes, the <code>datagrid</code>'s update methods must be
-   called to update the row in question. Some classes have <a
-   href="#datagridClassSummary">predefined meanings</a>.</dd>
 
-   <dt><dfn title="dom-provider-getCellData"><code>getCellData(<var title="">row</var>, <var title="">column</var>)</code></dfn></dt>
+   <dt><var title="">datagrid</var> . <code title="dom-datagrid-sortAscending">sortAscending</code> [ = <var title="">value</var> ]</dt>
+   <dd>
 
-   <dd>Must return the value of the cell on row <var
-   title="">row</var> in column <var title="">column</var>. For text
-   cells, this must be the text to show for that cell. For <span
-   title="datagrid-cell-class-progress">progress bar cells</span>,
-   this must be either a floating point number in the range 0.0 to 1.0
-   (converted to a string representation<!-- XXX this isn't
-   technically enough to define what the author must be doing here,
-   but let's let that slide until someone notices -->), indicating the
-   fraction of the progress bar to show as full (1.0 meaning
-   complete), or the empty string, indicating an indeterminate
-   progress bar. If the value that this method would return changes,
-   the <code>datagrid</code>'s update methods must be called to update
-   the rows that changed. If only one cell changed, the <code
-   title="dom-datagrid-updateCellChanged">updateCellChanged()</code>
-   method may be used.</dd>
+    <p>Returns true if the data is to be sorted with small values
+    first; otherwise, returns false, indicating that bigger values are
+    to be put first.</p>
 
-   <dt><dfn title="dom-provider-getCellClasses"><code>getCellClasses(<var title="">row</var>, <var title="">column</var>, <var title="">classes</var>)</code></dfn></dt>
+    <p>Can be set, to indicate that the order is about to change.</p>
 
-   <dd>Must add the classes that apply to the cell on row <var
-   title="">row</var> in column <var title="">column</var> to the <var
-   title="">classes</var> object. May be omitted if the cells have no
-   special classes. If the classes that this method would add changes,
-   the <code>datagrid</code>'s update methods must be called to update
-   the rows or cells in question. Some classes have <a
-   href="#datagridClassSummary">predefined meanings</a>.</dd>
+   </dd>
 
-   <dt><dfn title="dom-provider-toggleColumnSortState"><code>toggleColumnSortState(<var title="">column</var>)</code></dfn></dt>
 
-   <dd>Called by the <code>datagrid</code> when the user tries to sort
-   the data using a particular column <var title="">column</var>. The
-   data provider must update its state so that the <code
-   title="dom-provider-getChildAtPosition">GetChildAtPosition()</code>
-   method returns the new order, and the classes of the columns
-   returned by <code
-   title="dom-provider-getCaptionClasses">getCaptionClasses()</code>
-   represent the new sort status. There is no need to tell the
-   <code>datagrid</code> that it the data has changed, as the
-   <code>datagrid</code> automatically assumes that the entire data
-   model will need updating.</dd>
+   <dt><var title="">datagrid</var> . <code title="dom-datagrid-clearColumns">clearColumns</code>()</dt>
+   <dd>
 
-   <dt><dfn title="dom-provider-setCellCheckedState"><code>setCellCheckedState(<var title="">row</var>, <var title="">column</var>, <var title="">state</var>)</code></dfn></dt>
+    <p>Removes all the columns in the <code>datagrid</code>,
+    reinstating the implied column.</p>
 
-   <dd>Called by the <code>datagrid</code> when the user changes the
-   state of a checkbox cell on row <var title="">row</var>, column
-   <var title="">column</var>. The checkbox should be toggled to the
-   state given by <var title="">state</var>, which is a positive
-   integer (1) if the checkbox is to be checked, zero (0) if it is to
-   be unchecked, and a negative number (&#x2212;1) if it is to be set to the
-   indeterminate state. There is no need to tell the
-   <code>datagrid</code> that the cell has changed, as the
-   <code>datagrid</code> automatically assumes that the given cell
-   will need updating.</dd>
+   </dd>
 
-   <dt><dfn title="dom-provider-cycleCell"><code>cycleCell(<var title="">row</var>, <var title="">column</var>)</code></dfn></dt>
 
-   <dd>Called by the <code>datagrid</code> when the user changes the
-   state of a cyclable cell on row <var title="">row</var>, column
-   <var title="">column</var>. The data provider should change the
-   state of the cell to the new state, as appropriate. There is no
-   need to tell the <code>datagrid</code> that the cell has
-   changed, as the <code>datagrid</code> automatically assumes that
-   the given cell will need updating.</dd>
+   <dt><var title="">datagrid</var> . <code title="dom-datagrid-setRowCount">setRowCount</code>(<var title="">childCount</var>, <var title="">rowCount</var>)</dt>
+   <dd>
 
-   <dt><dfn title="dom-provider-editCell"><code>editCell(<var title="">row</var>, <var title="">column</var>, <var title="">data</var>)</code></dfn></dt>
+    <p>Sets the numbers of rows in the <code>datagrid</code>,
+    excluding rows that are descendants of rows that are closed.</p>
 
-   <dd>Called by the <code>datagrid</code> when the user edits the
-   cell on row <var title="">row</var>, column <var
-   title="">column</var>. The new value of the cell is given by <var
-   title="">data</var>. The data provider should update the cell
-   accordingly. There is no need to tell the <code>datagrid</code>
-   that the cell has changed, as the <code>datagrid</code>
-   automatically assumes that the given cell will need updating.</dd>
+    <p>Throws a <code>DATAGRID_MODEL_ERR</code> exception if the
+    arguments contradict each other or previously declared information
+    (e.g. declaring that the <code>datagrid</code> has three rows when
+    the 12th row has been declared).</p>
 
-<!--XXXPA
-  void performAction(in DOMString action); // required if .performAction() is ever invoked on the datagrid
-  void performActionOnRow(in <span>RowSpecification</span> row, in DOMString action); // required if getRowClasses ever includes 'deletable' or if .performActionOnRow() is ever invoked on the datagrid
-  void performActionOnCell(in <span>RowSpecification</span> row, in unsigned long column, in DOMString action); // required if .performActionOnCell() is ever invoked on the datagrid
--->
+   </dd>
 
+
+   <dt><var title="">datagrid</var> . <code title="dom-datagrid-setRows">setRows</code>(<var title="">rows</var>)</dt>
+   <dd>
+
+    <p>Updates data for rows in the <code>datagrid</code>, or fills in
+    data for rows previously implied by a call to <code
+    title="dom-datagrid-setRowCount">setRowCount()</code> but not
+    previously declared.</p>
+
+    <p>The <var title="">rows</var> argument is an array of rows, each
+    represented by a further array consisting of:</p>
+
+    <ol class="brief">
+
+     <li>A <code>RowID</code> object identifying the row.</li>
+
+     <li>An integer giving the position of the row in its parent,
+     given the current sort order, or &#x2212;1 to set other row data
+     without setting a position or changing a previously declared
+     position.</li>
+
+     <li>An integer giving the number of children of the row, or 0 if
+     the row has no children, or &#x2212;1 if the row has children but
+     the count is currently unknown. If the number of children has
+     already been set to 0 or a positive integer, then passing
+     &#x2212;1 leaves the previous count unchanged.</li>
+
+     <li>An array giving the data for zero or more cells in the row,
+     as described below.</li>
+
+     <li>A boolean declaring whether the row is open or not. This
+     entry, if omitted, is assumed to be false (closed), unless the
+     row has already been declared as open.</li>
+
+     <li>An integer giving the number of rows that are descendants of
+     this row, excluding those that are descendants of descendants of
+     this row that are closed. This entry can be omitted if the row is
+     closed or if it has already been declared.</li>
+
+    </ol>
+
+    <p>The array giving the data for the cells in the row consists of
+    a further set of arrays, one per cell. The first item of each of
+    these arrays is the column's identifier; the subsequent values
+    vary based on the type of the column, as follows:</p>
+
+    <dl>
+
+     <dt><code title="datagrid-type-text">text</code></dt>
+     <dd>
+      <ol class="brief">
+       <li>A string giving the cell's value.
+       <li>Optionally, an <code>img</code> element giving an icon for the cell.
+      </ol>
+     </dd>
+
+     <dt><code title="datagrid-type-editable">editable</code></dt>
+     <dd>
+      <ol class="brief">
+       <li>A string giving the cell's value.
+       <li>Optionally, a <code>datalist</code> element giving a set of predefined options.
+       <li>Optionally, an <code>img</code> element giving an icon for the cell.
+      </ol>
+     </dd>
+
+     <dt><code title="datagrid-type-checkable">checkable</code></dt>
+     <dd>
+      <ol class="brief">
+       <li>A string giving the cell's value.
+       <li>A boolean, indicating whether the cell is checked (true) or not (false).
+       <li>Optionally, a boolean indicating whether the value of the cell is obscured as indeterminate (true), or not (false).
+       <li>Optionally, an <code>img</code> element giving an icon for the cell.
+      </ol>
+     </dd>
+
+     <dt><code title="datagrid-type-list">list</code></dt>
+     <dd>
+      <ol class="brief">
+       <li>A string giving the cell's current value.
+       <li>A <code>select</code> element giving the <span title="concept-select-option-list">list of options</span>.
+       <li>Optionally, an <code>img</code> element giving an icon for the cell.
+      </ol>
+     </dd>
+
+     <dt><code title="datagrid-type-progress">progress</code></dt>
+     <dd>
+      <ol class="brief">
+       <li>A value in the range 0.0 (no progress) to 1.0 (task complete).
+      </ol>
+     </dd>
+
+     <dt><code title="datagrid-type-meter">meter</code></dt>
+     <dd>
+      <ol class="brief">
+       <li>A number giving the cell's value.
+       <li>Optionally, a number giving the maximum value, if it's not 1.
+       <li>Optionally, a number giving the minimum value, if it's not 0.
+       <li>Optionally, a number giving the highest value that is considered "low".
+       <li>Optionally, a number giving the lowest value that is considered "high".
+       <li>Optionally, a number giving the value that is considered optimal.
+      </ol>
+     </dd>
+
+     <dt><code title="datagrid-type-custom">custom</code></dt>
+     <dd>
+      <ol class="brief">
+       <li>A number giving the minimum width of the cell, in CSS pixels, that is desired.
+       <li>A number giving the minimum height of the cell, in CSS pixels, that is desired.
+       <li>A function that is passed a <code>CanvasRenderingContext2D</code> object, along with the width and height (in CSS pixels) of the cell that the context will draw on.
+      </ol>
+     </dd>
+
+    </dl>
+
+    <p>While the rows in a single call to the <code
+    title="dom-datagrid-setRows">setRows()</code> method can be in any
+    order, for each row, it is important that all its ancestor rows
+    and all its open previous siblings are also declared, either in
+    the same call or in an earlier one.</p>
+
+    <p>Throws a <code>DATAGRID_MODEL_ERR</code> exception if the
+    arguments contradict each other or previously declared information
+    (e.g. saying that a row's position is 5 when the parent row only
+    has 3 children, or naming a column that doesn't exist, or
+    declaring a row without declaring its parent, or changing the
+    number of children that a row has while that row and its ancestors
+    are all open).</p>
+
+   </dd>
+
+
+   <dt><var title="">datagrid</var> . <code title="dom-datagrid-insertRows">insertRows</code>(<var title="">rows</var>)</dt>
+   <dd>
+
+    <p>Inserts the given rows into the <code>datagrid</code>,
+    increasing the numbers of rows that the <code>datagrid</code>
+    assumes are present.</p>
+
+    <p>The <var title="">rows</var> argument is an array of rows in
+    the same structure as the argument to the <code
+    title="dom-datagrid-setRows">setRows()</code> method described
+    above, with the same expectations of consistency (a given row's
+    ancestors and earlier open siblings being listed either earlier or
+    in the same call as a given row). However, unlike with the <code
+    title="dom-datagrid-setRows">setRows()</code> method, if a row is
+    inserted along with its child, the child is not included in the
+    child and row counts of the parent row; every row in the <var
+    title="">rows</var> argument will increase its parent's counts
+    automatically.</p>
+
+    <p>Throws a <code>DATAGRID_MODEL_ERR</code> exception if the
+    arguments contradict each other or previously declared
+    information.</p>
+
+   </dd>
+
+
+   <dt><var title="">datagrid</var> . <code title="dom-datagrid-deleteRows">deleteRows</code>(<var title="">rows</var>)</dt>
+   <dd>
+
+    <p>Removes the given rows from the <code>datagrid</code>, and
+    updates the number of rows known to be in the
+    <code>datagrid</code> accordingly. The argument is an array of
+    <code>RowID</code> objects identifying the rows to remove.</p>
+
+    <p>Throws a <code>DATAGRID_MODEL_ERR</code> exception if the argument
+    includes a row the <code>datagrid</code> doesn't know about.</p>
+    <!-- since otherwise behaviour might depend on where the user
+    scrolled! -->
+
+   </dd>
+
+
+   <dt><var title="">datagrid</var> . <code title="dom-datagrid-repaint">repaint</code>(<var title="">row</var>, <var title="">column</var>)</dt>
+   <dd>
+
+    <p>If the given column's type is <code
+    title="datagrid-type-custom">custom</code>, then causes the
+    <code>datagrid</code> to reinvoke the function that obtains the
+    desired rendering.</p>
+
+   </dd>
+
+
+   <dt><var title="">datagrid</var> . <code title="dom-datagrid-clearRows">clearRows</code>()</dt>
+   <dd>
+
+    <p>Clears the <code>datagrid</code> of all row data, resetting it
+    to empty<!-- v2DGS:, and clears the selection-->.</p>
+
+   </dd>
+
   </dl>
 
-  <p>The following classes (for rows, columns, and cells) may be
-  usefully used in conjunction with this interface:</p>
 
-  <table id="datagridClassSummary">
-   <tr>
-    <th>Class name</th>
-    <th>Applies to</th>
-    <th>Description</th>
-   </tr>
+  <div class="impl">
 
-   <tr>
-    <td><!--checked--><dfn title="datagrid-cell-class-checked"><code>checked</code></dfn></td>
-    <td>Cells</td>
-    <td>The cell has a checkbox and it is checked. (The <code
-    title="datagrid-cell-class-cyclable">cyclable</code> and <code
-    title="datagrid-cell-class-progress">progress</code> classes
-    override this, though.)</td>
-   </tr>
+  <h6>The listener</h6>
 
-   <tr>
-    <td><!--cyclable--><dfn title="datagrid-cell-class-cyclable"><code>cyclable</code></dfn></td>
-    <td>Cells</td>
-    <td>The cell can be cycled through multiple values. (The <code
-    title="datagrid-cell-class-progress">progress</code> class
-    overrides this, though.)</td>
-   </tr>
+  <p>The <dfn
+  title="dom-datagrid-listener"><code>listener</code></dfn> DOM
+  attribute allows authors to specify an object that will receive all
+  the notifications from the <code>datagrid</code>. Initially, its
+  value must be null. On getting, it must return its value. On
+  setting, its value must be set to the new value, and then the user
+  agent must <span>queue a task</span> to call the <code
+  title="dom-listener-initialize">initalize()</code> method with the
+  <code>datagrid</code> element as its only argument.</p>
 
-   <tr>
-    <td><!--editable--><dfn title="datagrid-cell-class-editable"><code>editable</code></dfn></td>
-    <td>Cells</td>
-    <td>The cell can be edited. (The <code
-    title="datagrid-cell-class-cyclable">cyclable</code>, <code
-    title="datagrid-cell-class-progress">progress</code>, <code
-    title="datagrid-cell-class-checked">checked</code>, <code
-    title="datagrid-cell-class-checked">unchecked</code> and <code
-    title="datagrid-cell-class-checked">indeterminate</code> classes
-    override this, though.)</td>
-   </tr>
 
-   <tr>
-    <td><!--header--><dfn title="datagrid-row-class-header"><code>header</code></dfn></td>
-    <td>Rows</td>
-    <td>The row is a heading, not a data row.</td>
-   </tr>
+  <h6>The columns</h6>
 
-   <tr>
-    <td><!--indeterminate--><dfn title="datagrid-cell-class-indeterminate"><code>indeterminate</code></dfn></td>
-    <td>Cells</td>
-    <td>The cell has a checkbox, and it can be set to an indeterminate
-    state. If neither the <code
-    title="datagrid-cell-class-checked">checked</code> nor <code
-    title="datagrid-cell-class-checked">unchecked</code> classes are
-    present, then the checkbox is in that state, too. (The <code
-    title="datagrid-cell-class-cyclable">cyclable</code> and <code
-    title="datagrid-cell-class-progress">progress</code> classes
-    override this, though.)</td>
-   </tr>
+  <p>The columns are represented by the <dfn>column list</dfn>, an
+  ordered list of entries for columns, each of which consists of:</p>
 
-   <tr>
-    <td><!--initially-hidden--><dfn title="datagrid-column-class-initially-hidden"><code>initially-hidden</code></dfn></td>
-    <td>Columns</td>
-    <td>The column will not be shown when the <code>datagrid</code> is
-    initially rendered. If this class is not present on the column
-    when the <code>datagrid</code> is initially rendered, the column
-    will be visible if space allows.</td>
-   </tr>
+  <dl>
 
-   <tr>
-    <td><!--initially-closed--><dfn title="datagrid-row-class-initially-closed"><code>initially-closed</code></dfn></td>
-    <td>Rows</td>
-    <td>The row will be closed when the <code>datagrid</code> is
-    initially rendered. If neither this class nor the <code
-    title="datagrid-row-class-initially-open">initially-open</code>
-    class is present on the row when the <code>datagrid</code> is
-    initially rendered, the initial state will depend on platform
-    conventions.</td>
-   </tr>
+   <dt>An identifier</dt>
 
-   <tr>
-    <td><!--initially-open--><dfn title="datagrid-row-class-initially-open"><code>initially-open</code></dfn></td>
-    <td>Rows</td>
-    <td>The row will be opened when the <code>datagrid</code> is
-    initially rendered. If neither this class nor the <code
-    title="datagrid-row-class-initially-closed">initially-closed</code>
-    class is present on the row when the <code>datagrid</code> is
-    initially rendered, the initial state will depend on platform
-    conventions.</td>
-   </tr>
+   <dd>A string used to identify the column in the API.</dd>
 
-   <tr>
-    <td><!--progress--><dfn title="datagrid-cell-class-progress"><code>progress</code></dfn></td>
-    <td>Cells</td>
-    <td>The cell is a progress bar.</td>
-   </tr>
+   <dt>A label</dt>
 
-   <tr>
-    <td><!--reversed--><dfn title="datagrid-column-class-reversed"><code>reversed</code></dfn></td>
-    <td>Columns</td>
-    <td>If the cell is sorted, the sort direction is descending,
-    instead of ascending.</td>
-   </tr>
+   <dd>A string used in the user interface.</dd>
 
-   <tr>
-    <td><!--selectable-separator--><dfn title="datagrid-row-class-selectable-separator"><code>selectable-separator</code></dfn></td>
-    <td>Rows</td>
-    <td>The row is a normal, selectable, data row, except that instead
-    of having data, it only has a separator. (The <code
-    title="datagrid-row-class-header">header</code> and <code
-    title="datagrid-row-class-separator">separator</code> classes
-    override this, though.)</td>
-   </tr>
+   <dt>A type</dt>
 
-   <tr>
-    <td><!--separator--><dfn title="datagrid-row-class-separator"><code>separator</code></dfn></td>
-    <td>Rows</td>
-    <td>The row is a separator row, not a data row. (The <code
-    title="datagrid-row-class-header">header</code> class
-    overrides this, though.)</td>
-   </tr>
+   <dd>One of the types described below.</dd>
 
-   <tr>
-    <td><!--sortable--><dfn title="datagrid-column-class-sortable"><code>sortable</code></dfn></td>
-    <td>Columns</td>
-    <td>The data can be sorted by this column.</td>
-   </tr>
+   <dt>An icon</dt>
 
-   <tr>
-    <td><!--sorted--><dfn title="datagrid-column-class-sorted"><code>sorted</code></dfn></td>
-    <td>Columns</td>
-    <td>The data is sorted by this column. Unless the <code
-    title="datagrid-column-class-reversed">reversed</code> class is
-    also present, the sort direction is ascending.</td>
-   </tr>
+   <dd>An image, copied from an <code>img</code> element when the
+   column was declared.</dd>
 
-   <tr>
-    <td><!--unchecked--><dfn title="datagrid-cell-class-unchecked"><code>unchecked</code></dfn></td>
-    <td>Cells</td>
-    <td>The cell has a checkbox and, unless the <code
-    title="datagrid-cell-class-checked">checked</code> class is
-    present as well, it is unchecked. (The <code
-    title="datagrid-cell-class-cyclable">cyclable</code> and <code
-    title="datagrid-cell-class-progress">progress</code> classes
-    override this, though.)</td>
-   </tr>
+   <dt>Whether the column is sortable</dt>
 
-<!--XXXPA
-   <tr>
-    <td><!- -deletable- -><dfn title="datagrid-row-class-deletable"><code>deletable</code></dfn></td>
-    <td>Rows</td>
-    <td></td>
-   </tr>
--->
+   <dd>A boolean indicating whether the user can request that the data
+   be sorted by this column (true), or not (false).</dd>
 
-  </table>
+   <dt>Whether the column is visible</dt>
 
+   <dd>A boolean indicating whether the column is part of the
+   <code>datagrid</code>'s rendering.</dd>
 
-  <h5>The default data provider</h5>
+  </dl>
 
-  <p>The user agent must supply a default data provider for the case
-  where the <code>datagrid</code>'s <code
-  title="dom-datagrid-data">data</code> attribute is null. It must act
-  as described in this section.</p>
+  <p>Initially, the <span>column list</span> must have a single
+  column, the <dfn>default column</dfn>, whose identifier is the empty
+  string, whose label is the empty string, whose type is <code
+  title="datagrid-type-text">text</code>, with no icon, which is not
+  sortable, and which <em>is</em> visible.</p>
 
-  <p>The behavior of the default data provider depends on the nature
-  of the first element child of the <code>datagrid</code>.</p>
+  <hr>
 
-  <dl class="switch">
+  <p>The <dfn title="dom-datagrid-addColumn"><code>addColumn(<var
+  title="">id</var>, <var title="">label</var>, <var
+  title="">type</var>, <var title="">icon</var>, <var
+  title="">sortable</var>, <var title="">visible</var>)</code></dfn>
+  method must run the following steps:</p>
 
-   <!-- XXX some of these entries say "the method must return" and
-   other say "the characteristic must be"; this should be rationalized
-   -->
+  <ol>
 
-   <dt>While the first element child is a <code>table</code> element</dt>
+   <li><p>If there is already an entry in <span>column list</span>,
+   other than the <span>default column</span>, whose identifier is
+   <var title="">id</var>, throw a <code>DATAGRID_MODEL_ERR</code>
+   exception and abort these steps.</p></li>
 
+   <li>
+
+    <p>If <var title="">type</var> is not a string equal to one of the
+    <span>allowed <code>datagrid</code> column types</span>, then
+    throw a <code>DATAGRID_MODEL_ERR</code> exception and abort these
+    steps.</p>
+
+   </li>
+
+   <li><p>If the <var title="">icon</var> argument is present and not
+   null, and the given <code>img</code> element's <code
+   title="dom-img-complete">complete</code> attribute is false, then
+   throw an <code>INVALID_STATE_ERR</code> exception and abort these
+   steps.</p></li>
+
+   <li><p>If the <var title="">icon</var> argument is present and not
+   null, then copy the image data from that <code>img</code> element,
+   and let <var title="">image</var> be the copy of that image
+   data. Otherwise, let <var title="">image</var> be nothing.</p></li>
+
+   <li><p>Append a new entry to the <span>column list</span>, with
+   <var title="">id</var> as its identifier, <var title="">label</var>
+   as its label, <var title="">type</var> as its type, and <var
+   title="">image</var> as its icon. Let the column be sortable if the
+   <var title="">sortable</var> argument is present and true, and make
+   it visible if the <var title="">visible</var> argument is absent or
+   true.</p></li>
+
+   <li><p>If the <span>column list</span> contains the <span>default
+   column</span>, then remove the <span>default column</span> from the
+   <span>column list</span>, discard any data for cells in that column
+   in any rows in the <code>datagrid</code>, set <code
+   title="dom-datagrid-sortColumn">sortColumn</code> to <var
+   title="">id</var>, set <code
+   title="dom-datagrid-sortAscending">sortAscending</code> to true,
+   and run the <span><code>datagrid</code> resort
+   steps</span>.</p></li>
+
+  </ol>
+
+  <hr>
+
+  <p>The <dfn
+  title="dom-datagrid-sortColumn"><code>sortColumn</code></dfn> DOM
+  attribute gives the current column used for sorting.  Initially, its
+  value must be the empty string. On getting, it must return its
+  current value. On setting, if the new value doesn't match the
+  identifier of one of the columns in the <span>column list</span>,
+  then the user agent must throw a <code>DATAGRID_MODEL_ERR</code>
+  exception. Otherwise, if the new value is not the same as its
+  current value, then the user agent must set the attribute to the new
+  value, and then run the <span><code>datagrid</code> resort
+  steps</span>.</p>
+
+  <p>The <dfn
+  title="dom-datagrid-sortAscending"><code>sortAscending</code></dfn>
+  DOM attribute specifies the direction that the tree is sorted in,
+  ascending (true) or descending (false). Initially, its value must be
+  true (ascending). On getting, it must return its current value. On
+  setting, if the new value is not the same as its current value, then
+  the user agent must set the attribute to the new value, and then run
+  the <span><code>datagrid</code> resort steps</span>.</p>
+
+  <p>When a column is marked as being sortable, the user agent should
+  allow the user to select that column to be the column used for
+  sorting, and should allow the user to chose whether the sort order
+  is ascending or descending.</p>
+
+  <p>When the user changes the sort order in this manner, the user
+  agent must update the <code
+  title="dom-datagrid-sortColumn">sortColumn</code> and <code
+  title="dom-datagrid-sortAscending">sortAscending</code> attributes
+  appropriately, and then run the <span><code>datagrid</code> resort
+  steps</span>.</p>
+
+  <p class="note">The <span><code>datagrid</code> resort steps</span>
+  are described in the next section.</p>
+
+  <hr>
+  
+  <p>The <dfn
+  title="dom-datagrid-clearColumns"><code>clearColumns()</code></dfn>
+  method, if the <span>column list</span> doesn't contain the
+  <span>default column</span>, must empty the <span>column
+  list</span>, append the <span>default column</span> to the now empty
+  <span>column list</span>, discard any data for cells in all rows in
+  the <code>datagrid</code>, set <code
+  title="dom-datagrid-sortColumn">sortColumn</code> to the empty
+  string, set <code
+  title="dom-datagrid-sortAscending">sortAscending</code> to true, and
+  run the <span><code>datagrid</code> resort steps</span>. (If the
+  <span>column list</span> is already just the <span>default
+  column</span>, then the method does nothing.)</p>
+
+
+  <h6>The rows</h6>
+
+  <p>A <code>datagrid</code> element is intended to show a
+  representation of a tree, where typically the user only sees a
+  small part of the tree at a time.</p>
+
+  <p>To make this efficent, the <code>datagrid</code> element
+  <em>actually</em> shows a small part of a <em>sparse</em> tree, so
+  that only relevant parts of the data structure need be loaded at any
+  time. Specifically, the model requires only that all the ancestor
+  rows of the displayed rows be loaded, as well as any open earlier
+  siblings (in the displayed sort order) of the displayed rows.</p>
+
+  <p>Conceptually, therefore, a <code>datagrid</code> has a number of
+  related sparse data structures backing it.</p>
+
+  <p>The first is the <dfn>natural order sparse data tree</dfn>. This
+  is the structure in which rows are entered as they are declared, in
+  their natural order. This can differ from the order actually
+  displayed to the user. It consists of nested sparse lists of
+  rows. In the <span>natural order sparse data tree</span>, a row will
+  always have all its parents already declared. Once a row is added to
+  this structure, it can only be removed by the <code
+  title="dom-datagrid-deleteRows">deleteRows()</code> and <code
+  title="dom-datagrid-clearRows">clearRows()</code> methods. The order of
+  nodes in this tree never changes; to move a node in this tree, it
+  has to be removed and then another row (with the same data)
+  reinserted elsewhere.</p>
+
+  <p>The second structure is the <dfn>display order sparse data
+  tree</dfn>. This is a similar structure that contains a subset of
+  the rows in the <span>natural order sparse data tree</span>, ordered
+  in the order given by the <code
+  title="dom-datagrid-sortAscending">sortAscending</code> and <code
+  title="dom-datagrid-sortColumn">sortColumn</code> attributes, and
+  excluding rows with one or more ancestors that are closed. This tree
+  is cleared whenever the <code
+  title="dom-datagrid-sortAscending">sortAscending</code> and <code
+  title="dom-datagrid-sortColumn">sortColumn</code> attributes
+  change.</p>
+
+  <p>The third structure is the <dfn>display order sparse data
+  list</dfn>. This structure is a flattened representation of the
+  <span>display order sparse data tree</span>.</p>
+
+  <p>At any time, a number of consecutive rows in the <span>display
+  order sparse data list</span> are physically visible to the
+  user. The <code>datagrid</code> fires notifications to a <span
+  title="dom-datagrid-listener">listener</span> (provided by script),
+  and the listener, or other some script, is expected to feed the
+  <code>datagrid</code> with the information needed to render the
+  control.</p>
+
+  <p>A <code>datagrid</code> has a <dfn>pending <code>datagrid</code>
+  rows list</dfn>, which is a list of rows in the <span>display order
+  sparse data list</span> for which the <code>datagrid</code> has sent
+  notifications requesting information but not yet received
+  information about.</p>
+
+  <p>A <code>datagrid</code> also has a <dfn>pending
+  <code>datagrid</code> <em>cells</em> list</dfn>, which is a list of
+  row/column pairs (cells) for which the <code>datagrid</code> has
+  sent notifications requesting information but not yet received
+  information about.</p>
+
+  <p>User agents may discard information about rows that are not
+  displayed and that are not ancestors or open earlier siblings of
+  rows or ancestors of rows that are displayed.</p>
+
+  <hr>
+
+  <p>These structures are different views of the collection of rows
+  that form the <code>datagrid</code>. Each row has the following
+  information associated with it:</p>
+
+  <dl>
+
+   <dt>A parent</dt>
+
+   <dd><p>Either another row, or the <code>datagrid</code> itself. This
+   is the parent of the row in the <span>natural order sparse data
+   tree</span> and the <span>display order sparse data tree</span>
+   for the <code>datagrid</code>.</p></dd>
+
+   <dt>A natural order position relative to the other rows with the
+   same parent</dt>
+
    <dd>
 
-    <p><strong><code
-    title="dom-provider-getRowCount">getRowCount(<var title="">row</var>)</code></strong>:
-    The number of rows returned by the default data provider for the
-    root of the tree (when <var title="">row</var> is empty) must be the total number of <code>tr</code> elements
-    that are children of <code>tbody</code> elements that are children
-    of the <code>table</code>, if there are any such child
-    <code>tbody</code> elements. If there are no such
-    <code>tbody</code> elements then the number of rows returned for
-    the root must be the number of <code>tr</code> elements that are
-    children of the <code>table</code>.</p>
+    <p>This is the number of rows that precede this row under the same
+    parent in the <span>natural order sparse data tree</span>. This
+    number can't be changed relative to other rows in the same parent;
+    to change the relative natural order of data in the
+    <code>datagrid</code>, the original rows have to be removed and
+    new rows (with the same data but different natural positions)
+    inserted in their place. (The exact number of a row can change, as
+    new rows can be inserted above it.)</p>
 
-    <p>When <var title="">row</var> is not empty, the number of rows
-    returned must be zero.</p>
+    <p>A row can be identified by a <code>RowID</code> object. This is
+    an array of numbers, consisting of the natural order positions of
+    each ancestor row and the row itself, starting from the furthest
+    ancestor. Thus, for instance, the fourth child row of the first
+    child row of the second row in a <code>datagrid</code> would be
+    identified by a <code>RowID</code> object whose value is <code
+    title="">[1, 0, 3]</code>. A row's identifier changes if rows are
+    <span title="dom-datagrid-insertRows">inserted before it</span> in
+    the <code>datagrid</code>.</p>
 
-    <p class="note">The <code>table</code>-based default data provider
-    cannot represent a tree.</p>
+   </dd>
 
-    <p class="note">Rows in <code>thead</code> elements do not
-    contribute to the number of rows returned, although they do affect
-    the columns and column captions. Rows in <code>tfoot</code>
-    elements are <span title="ignore">ignored</span> completely by
-    this algorithm.</p>
+   <dt>A display order position relative to the other rows with
+   the same parent</dt>
 
-    <p id="defaultDataProviderTableMapper"><strong><code
-    title="dom-provider-getChildAtPosition">getChildAtPosition(<var
-    title="">row</var>, <var title="">i</var>)</code></strong>: The
-    default data provider must return the mapping appropriate to the
-    <a href="#defaultDataProviderTableSort">current sort
-    order</a>.</p>
+   <dd><p>This is the number of rows that precede this row under the
+   same parent in the <span>display order sparse data
+   tree</span>. This number can be unknown. If the sort order
+   changes, then this information is lost (as the <span>display order
+   sparse data tree</span> is cleared).</p></dd>
 
-    <p><strong><code
-    title="dom-provider-getColumnCount">getColumnCount()</code></strong>:
-    The number of columns returned must be the number of
-    <code>td</code> element children in the first <code>tr</code>
-    element child of the first <code>tbody</code> element child of the
-    <code>table</code>, if there are any such <code>tbody</code>
-    elements. If there are no such <code>tbody</code> elements, then
-    it must be the number of <code>td</code> element children in the
-    first <code>tr</code> element child of the <code>table</code>, if
-    any, or otherwise 1. If the number that would be returned by these
-    rules is 0, then 1 must be returned instead.</p>
+   <dt>A child count</dt>
 
-    <p><strong><code
-    title="dom-provider-getCaptionText">getCaptionText(<var
-    title="">i</var>)</code></strong>: If the <code>table</code> has
-    no <code>thead</code> element child, or if its first
-    <code>thead</code> element child has no <code>tr</code> element
-    child, the default data provider must return the empty string for
-    all captions. Otherwise, the value of the <code>textContent</code>
-    attribute of the <var title="">i</var>th <code>th</code> element
-    child of the first <code>tr</code> element child of the first
-    <code>thead</code> element child of the <code>table</code> element
-    must be returned. If there is no such <code>th</code> element, the
-    empty string must be returned.</p>
+   <dd><p>The number of rows that have this row as a parent. If this is
+   zero, the row cannot be opened. If this is &#x2212;1, then the
+   child count is unknown but the row can be opened. This value can be
+   changed by the <code title="dom-datagrid-setRows">setRows()</code>
+   method only if the current value is &#x2212;1 or if the row or one
+   of its ancestors is closed. Otherwise, it can only be changed
+   indirectly using the <code
+   title="dom-datagrid-insertRows">insertRows()</code> and <code
+   title="dom-datagrid-deleteRows">deleteRows()</code> methods.</p></dd>
 
-    <p><strong><code
-    title="dom-provider-getCaptionClasses">getCaptionClasses(<var
-    title="">i</var>, <var title="">classes</var>)</code></strong>: If
-    the <code>table</code> has no <code>thead</code> element child, or
-    if its first <code>thead</code> element child has no
-    <code>tr</code> element child, the default data provider must not
-    add any classes for any of the captions. Otherwise, each class
-    in the <code title="attr-class">class</code> attribute of the <var
-    title="">i</var>th <code>th</code> element child of the first
-    <code>tr</code> element child of the first <code>thead</code>
-    element child of the <code>table</code> element must be added to
-    the <var title="">classes</var>. If there is no such
-    <code>th</code> element, no classes must be added. The user agent
-    must then:</p>
+   <dt>An open flag</dt>
 
+   <dd><p>A boolean indicating whether the row is open (true) or
+   closed (false). Once set, can only be changed by the user or if one
+   of the row's ancestors is itself closed. A row can also be in a
+   third state, "opening", which is treated as closed for all purposes
+   except that the user agent may indicate that the row is in this
+   special state, and except that when the row is updated to have a
+   row count, the row will switch to being open.</p></dd>
+
+   <dt>A row count</dt>
+
+   <dd><p>The number of rows that have this row as a parent or
+   ancestor, and that do not have an ancestor that is a descendant of
+   this row that is itself closed. If this is &#x2212;1, then the row
+   count is unknown. This value can be changed by the <code
+   title="dom-datagrid-setRows">setRows()</code> method only if the
+   row or one of its ancestors is closed (or opening, but not
+   open). Otherwise, it can only be changed indirectly using the <code
+   title="dom-datagrid-insertRows">insertRows()</code> and <code
+   title="dom-datagrid-deleteRows">deleteRows()</code>
+   methods.</p></dd>
+
+   <dt>Cells</dt>
+
+   <dd><p>The data that applies to this row. Cell data is discussed in
+   more detail below.</p></dd>
+
+  </dl>
+
+  <p>The <code>datagrid</code> itself also has a <dfn title="datagrid
+  child count">child count</dfn> and a <dfn title="datagrid row
+  count">row count</dfn>, which are analogous to the child counts and
+  row counts for rows. Initially these must be zero.</p>
+
+  <hr>
+
+  <p>The <dfn><code>datagrid</code> resort steps</dfn>, which are
+  invoked when the sort order changes as described in the previous
+  section, are as follows:</p>
+
+  <ol>
+
+   <li>
+
+    <p>Clear the <span>display order sparse data tree</span>
+    (i.e. mark the display order position of all the rows in the
+    <code>datagrid</code> as unknown).</p>
+
+    <p>User agents may cache the position information of rows for
+    various values of <code
+    title="dom-datagrid-sortColumn">sortColumn</code> and <code
+    title="dom-datagrid-sortAscending">sortAscending</code>, instead
+    of discarding the information altogether. If the user agent caches
+    this information, and has information that applies to the current
+    values of <code title="dom-datagrid-sortColumn">sortColumn</code>
+    and <code title="dom-datagrid-sortAscending">sortAscending</code>,
+    then the user agent may repopulate the <span>display order sparse
+    data tree</span> from this information.</p>
+
+   </li>
+
+   <li>
+
+    <p>Clear the <span>pending <code>datagrid</code> rows list</span>
+    and the <span>pending <code>datagrid</code> cells list</span>.</p>
+
+   </li>
+
+   <li>
+
+    <p>Invoke the <span><code>datagrid</code> update display
+    algorithm</span>.</p>
+
+   </li>
+
+   <!-- v2: queue a task to fire an event, or tell the listener the
+   sort order changed, or something -->
+
+  </ol>
+
+  <hr>
+
+  <p>The <dfn
+  title="dom-datagrid-renotify"><code>renotify()</code></dfn> method
+  must empty the <span>pending <code>datagrid</code> rows list</span>
+  and the <span>pending <code>datagrid</code> cells list</span>, and
+  invoke the <span><code>datagrid</code> update display
+  algorithm</span>.</p>
+
+  <hr>
+
+  <p>The <dfn title="dom-datagrid-setRowCount"><code>setRowCount(<var
+  title="">childCount</var>, <var
+  title="">rowCount</var>)</code></dfn> method must run the following
+  steps:</p>
+
+  <ol>
+
+   <li>
+
+    <p>Set the <span><code>datagrid</code> child count</span> to <var
+    title="">childCount</var>, the <span><code>datagrid</code> row
+    count</span> to <var title="">rowCount</var>.</p>
+
+   </li>
+
+   <li>
+
+    <p><span>Audit the <code>datagrid</code></span>. If this fails,
+    then revert the changes made in the previous step, throw a
+    <code>DATAGRID_MODEL_ERR</code> exception, and abort these
+    steps.</p>
+
+   </li>
+
+   <li>
+
+    <p>Invoke the <span><code>datagrid</code> update display
+    algorithm</span>.</p>
+
+   </li>
+
+  </ol>
+
+  <hr>
+
+  <p>The <dfn title="dom-datagrid-setRows"><code>setRows(<var
+  title="">rows</var>)</code></dfn> method must run the following
+  steps:</p>
+
+  <ol>
+
+   <li>
+
+    <p><span title="type-check a RowList object">Type-check the <var
+    title="">rows</var> argument</span>. If this fails, throw a
+    <code>TypeError</code> exception, and abort these steps.</p>
+
+   </li>
+
+   <li>
+
+    <p><span title="partially sort a RowList object">Partially sort
+    the <var title="">rows</var> argument</span>.</p>
+
+   </li>
+
+   <li>
+
+    <p>For each <code>Row</code> object in the <var
+    title="">rows</var> argument, in order, perform the appropriate
+    steps from the list below.</p>
+
+    <p class="note">The changes made to the <code>datagrid</code>'s
+    data structures in this step get reverted (as required below) if
+    any consistency errors are detected either in this step or the
+    next.</p>
+
+    <dl>
+
+     <dt>If there already exists a row in the <code>datagrid</code>'s
+     <span>natural order sparse data tree</span> with the same
+     identifier as given by the <code>Row</code> object's
+     <code>RowID</code> object, and that row and all its ancestors are
+     open</dt>
+
+     <dd>
+
+      <p>If one of the following conditions is true, then revert all
+      the changes done in this step, throw a
+      <code>DATAGRID_MODEL_ERR</code> exception, and abort these
+      steps:</p>
+
+      <ul>
+
+       <li>The value of the <code>Row</code> object's second entry is
+       neither &#x2212;1 nor equal to the child count of the
+       preexisting row.</li>
+
+       <li>The <code>Row</code> object has fewer than five entries, or
+       its fifth entry is false.</li>
+
+       <li>The <code>Row</code> object has fewer than six entries, or
+       its sixth entry is not equal to the row count of the
+       preexisting row.</li>
+
+      </ul>
+
+     </dd>
+
+     <dt>If there already exists a row in the <code>datagrid</code>'s
+     <span>natural order sparse data tree</span> with the same
+     identifier as given by the <code>Row</code> object's
+     <code>RowID</code> object, but either that row or one of its
+     ancestors is closed</dt>
+
+     <dd>
+
+      <p>Set the preexisting row's child count to the value of the
+      <code>Row</code> object's second entry.</p>
+
+      <p>If the <code>Row</code> object has five or more entries, and
+      either its fifth entry is true and the preexisting row is closed
+      but not opening, or its fifth entry is false and the preexisting
+      row is open, then: if the preexisting row has no ancestor row
+      that is closed, then revert all the changes done in this step,
+      throw a <code>DATAGRID_MODEL_ERR</code> exception, and abort
+      these steps; otherwise, if the fifth entry is false, then close
+      the row; otherwise, open the row.</p>
+
+      <p>If the <code>Row</code> object has six entries, set the
+      preexisting row's row count to the value of the <code>Row</code>
+      object's sixth entry.</p>
+
+      <p>If the preexisting row is opening, then: increase the
+      <span><code>datagrid</code> row count</span> and the row counts
+      of any ancestor rows by the number of rows that the preexisting
+      row now has in its row count, then open the row.</p> <!-- we
+      should also "update the <span>pending <code>datagrid</code> rows
+      list</span> and the <span>pending <code>datagrid</code> cells
+      list</span> accordingly" -->
+
+
+     </dd>
+
+     <dt>There does not exist a row in the <code>datagrid</code>'s
+     <span>natural order sparse data tree</span> with the same
+     identifier as given by the <code>Row</code> object's
+     <code>RowID</code> object</dt>
+
+     <dd>
+
+      <p>If the <code>RowID</code> object has a length greater than 1,
+      then verify that there is a row identified by the
+      <code>RowID</code> consisting of all but the last number in the
+      <code>Row</code> object's <code>RowID</code>. If there is no
+      such row present in the <span>natural order sparse data
+      tree</span>, then revert all the changes done in this step,
+      throw a <code>DATAGRID_MODEL_ERR</code> exception, and abort
+      these steps.</p>
+
+      <p>Create a row and insert it into the <span>natural order
+      sparse data tree</span>, such that its parent is the row
+      identified by the <code>RowID</code> consisting of all but the
+      last number in the <code>Row</code> object's <code>RowID</code>,
+      or the <code>datagrid</code> if the lenght of the
+      <code>Row</code> object's <code>RowID</code> is 1; with its
+      natural order position being the last number of the
+      <code>Row</code> object's <code>RowID</code>; with the child
+      count being the value of the third entry of the <code>Row</code>
+      object; with the row being marked closed unless the
+      <code>Row</code> object has five or more entries and its fifth
+      entry is true, in which case the row is open; and with its row
+      count being &#x2212;1 unless the <code>Row</code> object has six
+      entries, in which case the row count is equal to the value of
+      the <code>Row</code> object's sixth entry.</p>
+
+     </dd>
+
+    </dl>
+
+   </li>
+
+   <li>
+
+    <p><span>Audit the <code>datagrid</code></span>. If this fails,
+    then revert the changes made in the previous step, throw a
+    <code>DATAGRID_MODEL_ERR</code> exception, and abort these
+    steps.</p>
+
+   </li>
+
+   <li>
+
+    <p>For each <code>Row</code> object in the <var
+    title="">rows</var> argument, in order, <span title="apply a Row
+    object">apply the <code>Row</code> object</span>.</p>
+
+   </li>
+
+   <li>
+
+    <p>Invoke the <span><code>datagrid</code> update display
+    algorithm</span>.</p>
+
+   </li>
+
+  </ol>
+
+  <hr>
+
+  <p>The <dfn title="dom-datagrid-insertRows"><code>insertRows(<var
+  title="">rows</var>)</code></dfn> method must run the following
+  steps:</p>
+
+  <ol>
+
+   <li>
+
+    <p><span title="type-check a RowList object">Type-check the <var
+    title="">rows</var> argument</span>. If this fails, throw a
+    <code>TypeError</code> exception, and abort these steps.</p>
+
+   </li>
+
+   <li>
+
+    <p><span title="partially sort a RowList object">Partially sort
+    the <var title="">rows</var> argument</span>.</p>
+
+   </li>
+
+   <li>
+
+    <p>For each <code>Row</code> object in the <var
+    title="">rows</var> argument, in order, run the following
+    steps:</p>
+
+    <p class="note">The changes made to the <code>datagrid</code>'s
+    data structures in this step get reverted (as required below) if
+    any consistency errors are detected either in this step or the
+    next.</p>
+
     <ol>
 
-     <li>Remove the <code
-     title="datagrid-column-class-sorted">sorted</code> and <code
-     title="datagrid-column-class-reversed">reversed</code>
-     classes.</li>
+     <li>
 
-     <li>If the <code>table</code> element has a <code
-     title="attr-class">class</code> attribute that includes the <code
-     title="">sortable</code> class, add the <code
-     title="datagrid-column-class-sortable">sortable</code>
-     class.</li>
+      <p>Let <var title="">parent</var> be the row identified by the
+      <code>RowID</code> consisting of all but the last number in the
+      <code>Row</code> object's <code>RowID</code>, or the
+      <code>datagrid</code> itself it the <code>Row</code> object's
+      <code>RowID</code> has length 0.</p>
 
-     <li>If the column is the one currently being used to
-     sort the data, add the <code
-     title="datagrid-column-class-sorted">sorted</code> class.</li>
+      <p>If there is no such row present in the <span>natural order
+      sparse data tree</span>, then revert all the changes done in
+      this algorithm, throw a <code>DATAGRID_MODEL_ERR</code>
+      exception, and abort these steps.</p>
 
-     <li>If the column is the one currently being used to sort the
-     data, and it is sorted in descending order, add the <code
-     title="datagrid-column-class-reversed">reversed</code> class as
-     well.</li>
+     </li>
 
+     <li>
+
+      <p>Increment by one the natural order position of all rows whose
+      parent is <var title="">parent</var> and whose natural order
+      position is equal to or greater than the last number of the
+      <code>Row</code> object's <code>RowID</code>.</p>
+
+     </li>
+
+     <li>
+
+      <p>If the value of the <code>Row</code> object's second entry is
+      not &#x2212;1, then increment by one the display order position
+      of all rows whose parent is <var title="">parent</var> and whose
+      display order position is equal to or greater than the value of
+      the <code>Row</code> object's second entry.</p>
+
+     <!--(Not sure how to really say this.)
+      <p>Update the <span>pending <code>datagrid</code> rows
+      list</span> and the <span>pending <code>datagrid</code> cells
+      list</span> accordingly.</p>
+     -->
+
+     </li>
+ 
+     <li>
+
+      <p>Create a row and insert it into the <span>natural order
+      sparse data tree</span>, such that its parent is <var
+      title="">parent</var>; with its natural order position being the
+      last number of the <code>Row</code> object's <code>RowID</code>;
+      with the child count being the value of the third entry of the
+      <code>Row</code> object; with the row being marked closed unless
+      the <code>Row</code> object has five or more entries and its
+      fifth entry is true, in which case the row is open; and with its
+      row count being &#x2212;1 unless the <code>Row</code> object has
+      six entries, in which case the row count is equal to the value
+      of the <code>Row</code> object's sixth entry.</p>
+
+     </li>
+
     </ol>
 
-    <p>The various row- and cell- related methods operate relative to
-    a particular element, the element of the row or cell specified by
-    their arguments.</p>
+   </li>
 
-    <p><strong>For rows</strong>: Since the default data provider for
-    a <code>table</code> always returns 0 as the number of children
-    for any row other than the root, the path to the row passed to
-    these methods will always consist of a single number. In the prose
-    below, this number is referred to as <var title="">i</var>.</p>
+   <li>
 
-    <p>If the <code>table</code> has <code>tbody</code> element
-    children, the element for the <var title="">i</var>th row is the
-    <var title="">i</var>th <code>tr</code> element that is a child of
-    a <code>tbody</code> element that is a child of the
-    <code>table</code> element. If the <code>table</code> does not
-    have <code>tbody</code> element children, then the element for the
-    <var title="">i</var>th real row is the <var title="">i</var>th
-    <code>tr</code> element that is a child of the <code>table</code>
-    element.</p>
+    <p>For each <code>Row</code> object in the <var
+    title="">rows</var> argument, in order, <span title="apply a Row
+    object">apply the <code>Row</code> object</span>.</p>
 
-    <p><strong>For cells</strong>: Given a row and its element, the
-    row's <var title="">i</var>th cell's element is the <var
-    title="">i</var>th <code>td</code> element child of the row
-    element.</p>
+   </li>
 
-    <p class="note">The <code>colspan</code> and <code>rowspan</code>
-    attributes are <span title="ignore">ignored</span> by this
-    algorithm.</p>
+   <li>
 
-    <p><strong><code title="dom-provider-getRowImage">getRowImage(<var
-    title="">i</var>)</code></strong>: The <span>URL</span> of the
-    row's image is the <span>absolute URL</span> obtained by <span
-    title="resolve a url">resolving</span> the value of the <code
-    title="attr-img-src">src</code> attribute of the first
-    <code>img</code> element child of the row's first cell's element,
-    relative to that element, if there is one and resolving its
-    attribute is successful. Otherwise, the <span>URL</span> of the
-    row's image is the empty string.</p> <!-- note that if the base
-    URL has changed, this URL can be different than the one that the
-    <img> element fetched when it was created -->
+    <p>Invoke the <span><code>datagrid</code> update display
+    algorithm</span>.</p>
 
-    <p><strong><code title="dom-provider-getRowMenu">getRowMenu(<var
-    title="">i</var>)</code></strong>: If the row's first cell's
-    element has a <code>menu</code> element child, then the row's menu
-    is the first <code>menu</code> element child of the row's first
-    cell's element. Otherwise, the row has no menu.</p>
+   </li>
 
-    <p><strong><code
-    title="dom-provider-getRowClasses">getRowClasses(<var
-    title="">i</var>, <var title="">classes</var>)</code></strong>:
-    The default data provider must never add a class to the row's
-    classes.</p>
+  </ol>
 
-    <p id="defaultDataProviderTableSort"><strong><code
-    title="dom-provider-toggleColumnSortState">toggleColumnSortState(<var
-    title="">i</var>)</code></strong>: If the data is already being
-    sorted on the given column, then the user agent must change the
-    current sort mapping to be the inverse of the current sort
-    mapping; if the sort order was ascending before, it is now
-    descending, otherwise it is now ascending. Otherwise, if the
-    current sort column is another column, or the data model is
-    currently not sorted, the user agent must create a new mapping,
-    which maps rows in the data model to rows in the DOM so that the
-    rows in the data model are sorted by the specified column, in
-    ascending order. (Which sort comparison operator to use is left up
-    to the UA to decide.)</p>
+  <hr>
 
-    <p>When the sort mapping is changed, the values returned by the
-    <code
-    title="dom-provider-getChildAtPosition">getChildAtPosition()</code>
-    method for the default data provider <a
-    href="#defaultDataProviderTableMapper">will change
-    appropriately</a>.</p>
+  <p>When an algorithm requires the user agent to <dfn>type-check a
+  <code>RowList</code> object</dfn> (an array), each entry in the
+  object must be checked against the following requirements. If any
+  are false, then the type-check fails, otherwise it passes.</p>
 
-    <p><strong><code title="dom-provider-getCellData">getCellData(<var
-    title="">i</var>, <var title="">j</var>)</code>, <code
-    title="dom-provider-getCellClasses">getCellClasses(<var
-    title="">i</var>, <var title="">j</var>, <var
-    title="">classes</var>)</code>, <code
-    title="dom-provider-setCellCheckedState">getCellCheckedState(<var
-    title="">i</var>, <var title="">j</var>, <var
-    title="">state</var>)</code>, <code
-    title="dom-provider-cycleCell">cycleCell(<var title="">i</var>,
-    <var title="">j</var>)</code>, and <code
-    title="dom-provider-editCell">editCell(<var title="">i</var>,
-    <var title="">j</var>, <var title="">data</var>)</code></strong>:
-    See <a href="#commonDefaultDataGridMethodDefinitions">the common
-    definitions below</a>.</p>
+  <ul>
 
-    <p>The data provider must call the <code>datagrid</code>'s update
-    methods appropriately whenever the descendants of the
-    <code>datagrid</code> mutate. For example, if a <code>tr</code> is
-    removed, then the <code
-    title="dom-datagrid-updateRowsRemoved">updateRowsRemoved()</code>
-    methods would probably need to be invoked, and any change to a
-    cell or its descendants must cause the cell to be updated. If the
-    <code>table</code> element stops being the first child of the
-    <code>datagrid</code>, then the data provider must call the <code
-    title="dom-datagrid-updateEverything">updateEverything()</code>
-    method on the <code>datagrid</code>. Any change to a cell that is
-    in the column that the data provider is currently using as its
-    sort column must also cause the sort to be reperformed, with a
-    call to <code
-    title="dom-datagrid-updateEverything">updateEverything()</code> if
-    the change did affect the sort order.</p>
+   <li><p>The entry is a <code>Row</code> object (an
+   array).</p></li>
 
-   </dd>
+   <li><p>The first value in the <code>Row</code> is a
+   <code>RowID</code> object (also an array), whose length is at least
+   1, and whose values are all integers greater than or equal to
+   zero.</p></li>
 
+   <li><p>The numbers in the <code>RowID</code> object do not exactly
+   match any of the other entries in the <code>RowList</code> object
+   (i.e. no two <code>Row</code> objects have the same
+   identifier).</p></li>
 
-   <dt>While the first element child is a <code>select</code> or <code>datalist</code> element</dt>
+   <li><p>The second value in the <code>Row</code> is an integer that
+   is either &#x2212;1, zero, or a positive integer.</p></li>
 
-   <dd>
+   <li><p>The third value in the <code>Row</code> is an integer that
+   is either &#x2212;1, zero, or a positive integer.</p></li>
 
-    <p>The default data provider must return 1 for the column count,
-    the empty string for the column's caption, and must not add any
-    classes to the column's classes.</p>
+   <li><p>The fourth value in the <code>Row</code> is a
+   <code>CellList</code> object (yet another array).</p></li>
 
-    <p>For the rows, assume the existence of a node filter view of the
-    descendants of the first element child of the
-    <code>datagrid</code> element (the <code>select</code> or
-    <code>datalist</code> element), that skips all nodes other than
-    <code>optgroup</code> and <code>option</code> elements, as well as
-    any descendants of any <code>option</code> elements.</p>
+   <li><p>Each entry in the <span>CellList</span> object is a
+   <code>Cell</code> object (again, an array).</p></li>
 
-    <p>Given a path <var title="">row</var>, the corresponding element
-    is the one obtained by drilling into the view, taking the child
-    given by the path each time.</p>
+   <li><p>Each <code>Cell</code> object in the <span>CellList</span>
+   object has as its first value a <code>Column</code> object (a
+   string), and its value is the identifier of one of the columns in
+   the <span>column list</span>.</p></li>
 
-    <div class="example">
+   <li>
 
-     <p>Given the following XML markup:</p>
+    <p>Each <code>Cell</code> object in the <span>CellList</span>
+    object has as its second and subsequent entries values that match
+    the following requirements, as determined by the type of the
+    column identified by the first entry:</p>
 
-     <pre>&lt;datagrid>
- &lt;select>
-  &lt;!-- the options and optgroups have had their labels and values removed
-       to make the underlying structure clearer -->
-  &lt;optgroup>
-   &lt;option/>
-   &lt;option/>
-  &lt;/optgroup>
-  &lt;optgroup>
-   &lt;option/>
-   &lt;optgroup id="a">
-    &lt;option/>
-    &lt;option/>
-    &lt;bogus/>
-    &lt;option id="b"/>
-   &lt;/optgroup>
-   &lt;option/>
-  &lt;/optgroup>
- &lt;/select>
-&lt;/datagrid></pre>
+    <dl>
 
-     <p>The path "1,1,2" would select the element with ID "b". In the
-     filtered view, the text nodes, comment nodes, and bogus elements
-     are ignored; so for instance, the element with ID "a" (path
-     "1,1") has only 3 child nodes in the view.</p>
+     <dt>If the column's type is <code title="datagrid-type-text">text</code></dt>
+     <dd>
 
-    </div>
+      <p>The second entry's value is a string, and either there are
+      only two entries, or there are three, and the third entry is
+      an <code>img</code> element.</p>
 
-    <p><code title="dom-provider-getRowCount">getRowCount(<var
-    title="">row</var>)</code> must drill through the view to find the
-    element corresponding to the method's argument, and return the
-    number of child nodes in the filtered view that the corresponding
-    element has. (If the <var title="">row</var> is empty, the
-    corresponding element is the <code>select</code> element at the
-    root of the filtered view.)</p>
+      <p>If there is an <code>img</code> element specified, its <code
+      title="dom-img-complete">complete</code> attribute is true.</p>
 
-    <p><code
-    title="dom-provider-getChildAtPosition">getChildAtPosition(<var
-    title="">row</var>, <var title="">position</var>)</code> must
-    return <var title="">position</var>. (The
-    <code>select</code>/<code>datalist</code> default data provider
-    does not support sorting the data grid.)</p>
+     </dd>
 
-    <p><code title="dom-provider-getRowImage">getRowImage(<var
-    title="">i</var>)</code> must return the empty string, <code
-    title="dom-provider-getRowMenu">getRowMenu(<var
-    title="">i</var>)</code> must return null.</p>
+     <dt>If the column's type is <code title="datagrid-type-editable">editable</code></dt>
+     <dd>
 
-    <p><code title="dom-provider-getRowClasses">getRowClasses(<var
-    title="">row</var>, <var title="">classes</var>)</code> must add the
-    classes from the following list to <var title="">classes</var>
-    when their condition is met:</p>
+      <p>The second entry's value is a string, and either there are
+      only two entries, or the third entry is a
+      <code>datalist</code> element, and either there are only three
+      entries, or there are four, and the fourth entry is an
+      <code>img</code> element.</p>
 
-    <ul>
+      <p>If there is an <code>img</code> element specified, its <code
+      title="dom-img-complete">complete</code> attribute is true.</p>
 
-     <li>If the <var title="">row</var>'s corresponding element is an
-     <code>optgroup</code> element: <code
-     title="datagrid-row-class-header">header</code></li>
+     </dd>
 
-     <li>If the <var title="">row</var>'s corresponding element
-     contains other elements that are also in the view, and the
-     element's <code title="attr-class">class</code> attribute
-     contains the <code title="">closed</code> class: <code
-     title="datagrid-row-class-initially-closed">initially-closed</code></li>
+     <dt>If the column's type is <code title="datagrid-type-checkable">checkable</code></dt>
+     <dd>
 
-     <li>If the <var title="">row</var>'s corresponding element
-     contains other elements that are also in the view, and the
-     element's <code title="attr-class">class</code> attribute
-     contains the <code title="">open</code> class: <code
-     title="datagrid-row-class-initially-open">initially-open</code></li>
+      <p>The second entry's value is a string, the third entry is a
+      boolean, and either there are only three entries, or the
+      fourth entry is also a boolean, and either there are only four
+      entries, or there are five, and the fifth entry is an
+      <code>img</code> element.</p>
 
-    </ul>
+      <p>If there is an <code>img</code> element specified, its <code
+      title="dom-img-complete">complete</code> attribute is true.</p>
 
-    <p>The <code title="dom-provider-getCellData">getCellData(<var
-    title="">row</var>, <var title="">cell</var>)</code> method must
-    return the value of the <code
-    title="attr-optgroup-label">label</code> attribute if the <var
-    title="">row</var>'s corresponding element is an
-    <code>optgroup</code> element, otherwise, if the <var
-    title="">row</var>'s corresponding element is an
-    <code>option</code>element, its <code
-    title="attr-option-label">label</code> attribute if it has one,
-    otherwise the value of its <code>textContent</code> DOM
-    attribute.</p>
+     </dd>
 
-    <p>The <code
-    title="dom-provider-getCellClasses">getCellClasses(<var
-    title="">row</var>, <var title="">cell</var>, <var
-    title="">classes</var>)</code> method must add no classes.</p>
+     <dt>If the column's type is <code title="datagrid-type-list">list</code></dt>
+     <dd>
 
-    <p class="XXX"><!-- select-provider-selection
-    XXX-->autoselect some rows when initialized, reflect the selection
-    in the select, reflect the multiple attribute somehow.</p>
+      <p>The second entry's value is a string, the third entry is a
+      <code>select</code> element, and either there are only three
+      entries, or there are four, and the fourth entry is an
+      <code>img</code> element.</p>
 
-    <p>The data provider must call the <code>datagrid</code>'s update
-    methods appropriately whenever the descendants of the
-    <code>datagrid</code> mutate.</p>
+      <p>If there is an <code>img</code> element specified, its <code
+      title="dom-img-complete">complete</code> attribute is true.</p>
 
-   </dd>
+     </dd>
 
+     <dt>If the column's type is <code title="datagrid-type-progress">progress</code></dt>
+     <dd>
 
-   <dt>While the first element child is another element</dt>
+      <p>There are only two entries, the second entry's value is a
+      number, and the number's value is between 0.0 and 1.0
+      inclusive.</p>
 
-   <dd>
+     </dd>
 
-    <p>The default data provider must return 1 for the column count,
-    the empty string for the column's caption, and must not add any
-    classes to the column's classes.</p>
+     <dt>If the column's type is <code title="datagrid-type-meter">meter</code></dt>
+     <dd>
 
-    <p>For the rows, assume the existence of a node filter view of the
-    descendants of the <code>datagrid</code> that skips all nodes
-    other than <code>li</code>, <code>h1</code>&ndash;<code>h6</code>, and
-    <code>hr</code> elements, and skips any descendants of
-    <code>menu</code> elements.</p>
+      <p>There are at least two, but possibly up to seven, entries,
+      all entries but the first one are numbers, and the following
+      relationships hold:</p>
 
-    <p>Given this view, each element in the view represents a row in
-    the data model. The element corresponding to a path <var
-    title="">row</var> is the one obtained by drilling into the view,
-    taking the child given by the path each time. The element of the
-    row of a particular method call is the element given by drilling
-    into the view along the path given by the method's arguments.</p>
+      <ul class="brief">
 
-    <p><code title="dom-provider-getRowCount">getRowCount(<var
-    title="">row</var>)</code> must return the number of child
-    elements in this view for the given row, or the number of elements
-    at the root of the view if the <var title="">row</var> is
-    empty.</p>
+       <li>The second entry is less than the third, or less than 1.0
+       if the third is absent.</li>
 
-    <div class="example">
+       <li>The second entry is greater than the fourth, or greater
+       than 0.0 if the fourth is absent.</li>
 
-     <p>In the following example, the elements are identified by the
-     paths given by their child text nodes:</p>
+       <li>If there are at least three entries, the third entry is
+       greater than the fourth, or greater than zero if the fourth
+       is absent.</li>
 
-     <pre>&lt;datagrid>
- &lt;ol>
-  &lt;li> row 0 &lt;/li>
-  &lt;li> row 1
-   &lt;ol>
-    &lt;li> row 1,0 &lt;/li>
-   &lt;/ol>
-  &lt;/li>
-  &lt;li> row 2 &lt;/li>
- &lt;/ol>
-&lt;/datagrid></pre>
+       <li>If there are at least five entries, the fifth is not
+       greater than the third and not less than the fourth.</li>
 
-     <p>In this example, only the <code>li</code> elements actually
-     appear in the data grid; the <code>ol</code> element does not
-     affect the data grid's processing model.</p>
+       <li>If there are at least six entries, the sixth is not
+       greater than the third and not less than the fifth.</li>
 
-    </div>
+       <li>If there are at least seven entries, the fifth is not
+       greater than the third and not less than the fourth.</li>
 
-    <p><code
-    title="dom-provider-getChildAtPosition">getChildAtPosition(<var
-    title="">row</var>, <var title="">position</var>)</code> must
-    return <var title="">position</var>. (The generic default data
-    provider does not support sorting the data grid.)</p>
+      </ul>
 
-    <p><code title="dom-provider-getRowImage">getRowImage(<var
-    title="">i</var>)</code> must return the <span>absolute URL</span>
-    obtained from <span title="resolve a url">resolving</span> the
-    value of the <code title="attr-img-src">src</code> attribute of
-    the first <code>img</code> element descendant (in the real DOM) of
-    the row's element, that is not also a descendant of another
-    element in the filtered view that is a descendant of the row's
-    element, if such an element exists and resolving its attribute
-    relative to the element itself, is successful. Otherwise, it must
-    return the empty string.</p> <!-- note that if the base URL has
-    changed, this URL can be different than the one that the <img>
-    element fetched when it was created -->
+     </dd>
 
-    <div class="example">
+     <dt>If the column's type is <code title="datagrid-type-custom">custom</code></dt>
+     <dd>
 
-     <p>In the following example, the row with path "1,0" returns
-     "http://example.com/a" as its image URL, and the other rows
-     (including the row with path "1") return the empty string:</p>
+      <p>There are four entries, the second and third are numbers
+      that are integers greater than zero, and the fourth is a
+      <code>Rendering2DContextCallback</code> object (a
+      function).</p>
 
-     <pre>&lt;datagrid>
- &lt;ol>
-  &lt;li> row 0 &lt;/li>
-  &lt;li> row 1
-   &lt;ol>
-    &lt;li> row 1,0 &lt;img src="http://example.com/a" alt=""> &lt;/li>
-   &lt;/ol>
-  &lt;/li>
-  &lt;li> row 2 &lt;/li>
- &lt;/ol>
-&lt;/datagrid></pre>
+     </dd>
 
-    </div>
+    </dl>
 
-    <p><code title="dom-provider-getRowMenu">getRowMenu(<var
-    title="">i</var>)</code> must return the first <code>menu</code>
-    element descendant (in the real DOM) of the row's element, that is
-    not also a descendant of another element in the filtered view that
-    is a descendant of the row's element. (This is analogous to the
-    image case above.)</p>
+   </li>
 
-    <p><code title="dom-provider-getRowClasses">getRowClasses(<var
-    title="">i</var>, <var title="">classes</var>)</code> must add the
-    classes from the following list to <var title="">classes</var>
-    when their condition is met:</p>
+   <li><p>Either there are only four values in the <code>Row</code>,
+   or the fifth value in the <code>Row</code> is a boolean.</p></li>
 
-    <ul>
+   <li><p>Either there are only four or five values in the
+   <code>Row</code>, or there are six, and the sixth value in the
+   <code>Row</code> an integer that is greater than or equal to
+   zero.</p></li>
 
-     <li>If the row's element contains other elements that are also in
-     the view, and the element's <code title="attr-class">class</code>
-     attribute contains the <code title="">closed</code> class: <code
-     title="datagrid-row-class-initially-closed">initially-closed</code></li>
+  </ul>
 
-     <li>If the row's element contains other elements that are also in
-     the view, and the element's <code title="attr-class">class</code>
-     attribute contains the <code title="">open</code> class: <code
-     title="datagrid-row-class-initially-open">initially-open</code></li>
+  <p>Where the above requirements say that a value is to be a string,
+  the user agent must apply the ToString() conversion operator to the
+  value, assume that the value was indeed a string, and use the result
+  in the rest of the algorithm as if it had that had been the value
+  passed to the method. <a href="#refsECMA262">[ECMA262]</a></p>
 
-     <li>If the row's element is an <code>h1</code>&ndash;<code>h6</code>
-     element: <code
-     title="datagrid-row-class-header">header</code></li>
+  <p>Where the above requirements say that a value is to be a number,
+  the user agent must first apply the ToNumber() conversion operator
+  to the value, and then verify that the result is neither the
+  not-a-number NaN value nor an infinite value. If this result is
+  indeed acceptable (i.e. finite), the user agent must use the result
+  in the rest of the algorithm as if it had that had been the value
+  passed to the method. <a href="#refsECMA262">[ECMA262]</a></p>
 
-     <li>If the row's element is an <code>hr</code> element: <code
-     title="datagrid-row-class-separator">separator</code></li> <!--
-     XXX no way to get selectable-separator -->
+  <p>Where the above requirements say that a value is to be an
+  integer, the user agent must first apply the ToNumber() conversion
+  operator to the value, and then verify that the result is a finite
+  integer. If so, the user agent must use the result in the rest of
+  the algorithm as if it had that had been the value passed to the
+  method. <a href="#refsECMA262">[ECMA262]</a></p>
 
-    </ul>
+  <p>Where the above requirements say that a value is to be a boolean,
+  the user agent must apply the ToBoolean() conversion operator to the
+  value, assume that the value was indeed a boolean, and use the
+  result in the rest of the algorithm as if it had that had been the
+  value passed to the method. <a href="#refsECMA262">[ECMA262]</a></p>
 
-    <p>The <code title="dom-provider-getCellData">getCellData(<var
-    title="">i</var>, <var title="">j</var>)</code>, <code
-    title="dom-provider-getCellClasses">getCellClasses(<var
-    title="">i</var>, <var title="">j</var>, <var
-    title="">classes</var>)</code>, <code
-    title="dom-provider-setCellCheckedState">getCellCheckedState(<var
-    title="">i</var>, <var title="">j</var>, <var
-    title="">state</var>)</code>, <code
-    title="dom-provider-cycleCell">cycleCell(<var title="">i</var>,
-    <var title="">j</var>)</code>, and <code
-    title="dom-provider-editCell">editCell(<var title="">i</var>, <var
-    title="">j</var>, <var title="">data</var>)</code> methods must
-    act as described in <a
-    href="#commonDefaultDataGridMethodDefinitions">the common
-    definitions below</a>, treating the row's element as being the
-    cell's element.</p>
+  <hr>
 
-    <p class="XXX" id="generic-provider-selection">selection
-    handling?</p>
+  <p>When an algorithm requires the user agent to <dfn>audit the
+  <code>datagrid</code></dfn>, the <code>datagrid</code> must be
+  checked against the following requirements. If any are false, then
+  the audit fails, otherwise it passes.</p>
 
-    <p>The data provider must call the <code>datagrid</code>'s update
-    methods appropriately whenever the descendants of the
-    <code>datagrid</code> mutate.</p>
+  <ul>
 
-   </dd>
+   <li>There is no row whose natural order position is greater than or
+   equal to the child count of its parent row in the <span>natural
+   order sparse data tree</span>.</li>
 
+   <li>There is no row whose display order position is greater than or
+   equal to the child count of its parent row in the <span>display
+   order sparse data tree</span>.</li>
 
-   <dt>Otherwise, while there is no element child</dt>
+   <li>There is no row such that the sum of that row's child count and
+   the row counts all the open rows that are direct children of that
+   row in the <span>natural order sparse data tree</span> is less than
+   that row's row count.</li>
 
-   <dd>
+   <li>Of the rows whose child count is equal to the number of rows
+   that are direct children of that row in the <span>natural order
+   sparse data tree</span>, there is none such that the sum of that
+   row's child count and the row counts of all the open rows that are
+   direct children of that row in the <span>natural order sparse data
+   tree</span> is greater than that row's row count.</li>
 
-    <p>The data provider must return 0 for the number of rows, 1 for
-    the number of columns, the empty string for the first column's
-    caption, and must add no classes when asked for that column's
-    classes. If the <code>datagrid</code>'s child list changes such
-    that there is a first element child, then the data provider must
-    call the <code
-    title="dom-datagrid-updateEverything">updateEverything()</code>
-    method on the <code>datagrid</code>.</p>
+  </ul>
 
-   </dd>
+  <p>For the purposes of this audit, the <code>datagrid</code> must be
+  treated as the parent row of all the rows that are direct children
+  of the <code>datagrid</code> in the <span>natural order sparse data
+  tree</span> and the <span>display order sparse data tree</span>. The
+  child count of this implied row is the <span><code>datagrid</code>
+  child count</span>, and the row count of this implied row is the
+  <span><code>datagrid</code> row count</span>.</p>
 
-  </dl>
+  <hr>
 
-  <h6 id="commonDefaultDataGridMethodDefinitions">Common default data
-  provider method definitions for cells</h6>
+  <p>When an algorithm requires the user agent to <dfn>partially sort
+  a <code>RowList</code> object</dfn> (an array), the entries in the
+  object must be resorted such that <code>Row</code> objects are
+  listed after any of their ancestors and after any of their earlier
+  siblings. In other words, for any two <code>Row</code> objects <var
+  title="">a</var> and <var title="">b</var> in the
+  <code>RowList</code>, where <var title="">a</var> is before <var
+  title="">b</var> after the sort, the following conditions must
+  hold:</p>
 
-  <p>These definitions are used for the cell-specific methods of the
-  default data providers (other than in the
-  <code>select</code>/<code>datalist</code> case).  How they behave is
-  based on the contents of an element that represents the cell given
-  by their first two arguments. Which element that is is defined in
-  the previous section.</p>
+  <ul>
 
+   <li><p>If their <code>RowID</code> objects are the same length and
+   have values that are equal except for the last value, then the last
+   value of <var title="">a</var>'s <code>RowID</code>'s last value
+   must be less than <var title="">b</var>'s <code>RowID</code>'s last
+   value (i.e. earlier siblings must come before their later
+   siblings).</p></li>
+
+   <li><p>If their <code>RowID</code> objects are not the same length,
+   but the values in the shorter of the two are the same as the first
+   few values in the longer one, then <var title="">a</var>'s
+   <code>RowID</code> must be the shorter one (i.e. ancestors must
+   come before their descendants).</p></li>
+
+  </ul>
+
+  <hr>
+
+  <p>The <dfn title="dom-datagrid-deleteRows"><code>deleteRows(<var
+  title="">rows</var>)</code></dfn> method must run the following
+  steps:</p>
+
+  <ol>
+
+   <li>
+
+    <p>If any of the entries in <var title="">rows</var> are not
+    <code>RowID</code> objects consisting of one or more entries whose
+    values are all integers that are greater than or equal to zero,
+    then throw a <code>TypeError</code> exception and abort these
+    steps.</p>
+
+    <p>To check if a value is an integer, the user agent must first
+    apply the ToNumber() conversion operator to the value, and then
+    verify that the result is a finite integer. If so, the user agent
+    must use the result in the rest of the algorithm as if it had that
+    had been the value passed to the method. <a
+    href="#refsECMA262">[ECMA262]</a></p>
+
+   </li>
+
+   <li>
+
+    <p>If any of the <code>RowID</code> objects in the <var
+    title="">rows</var> argument identify a row that isn't present in
+    the <span>natural order sparse data tree</span>, then throw a
+    <code>DATAGRID_MODEL_ERR</code> exception and abort these
+    steps.</p>
+
+   </li>
+
+   <li>
+
+    <p>If any row is listed twice in the <var title="">rows</var>
+    argument, then throw a <code>DATAGRID_MODEL_ERR</code> exception
+    and abort these steps.</p>
+
+   </li>
+
+   <li>
+
+    <p>Sort the <var title="">rows</var> argument such that the
+    entries are given in the same order as the rows they identify
+    would be visited in a pre-order, depth first traversal of the
+    <span>natural order sparse data tree</span>.</p>
+
+   </li>
+
+   <li>
+
+    <p>For each row identified by entries in <var title="">rows</var>,
+    <em>in reverse order</em>, run the following steps:</p>
+
+    <ol>
+
+     <li>
+
+      <p>Decrement the child count of the row's parent row, if that
+      child count is greater than zero. If the row has no parent,
+      decrement the <span><code>datagrid</code> child
+      count</span>.</p>
+
+      <p>If the row has a parent row, and its child count is now zero,
+      then close that row.</p>
+
+     </li>
+
+     <li>
+
+      <p>Let <var title="">delta</var> be one more than the row's row
+      count if the row is open and its row count is greater than zero;
+      otherwise, let <var title="">delta</var> be one.</p>
+
+     </li>
+
+     <li>
+
+      <p>Let <var title="">ancestor</var> be the row.</p>
+
+     </li>
+
+     <li>
+
+      <p><i>Row count loop:</i> Let <var title="">ancestor</var> be
+      <var title="">ancestor</var>'s parent row, if any, or null if it
+      has none.</p>
+
+     </li>
+
+     <li>
+
+      <p>If <var title="">ancestor</var> is null, then decrement the
+      <span><code>datagrid</code> row count</span> by <var
+      title="">delta</var>. Otherwise, if <var title="">ancestor</var>
+      is open, then decrement its row count by <var
+      title="">delta</var>.</p>
+
+     </li>
+
+     <li>
+
+      <p>If <var title="">ancestor</var> is not null, then jump back
+      to the step labeled <i>row count loop</i> above.</p>
+
+     </li>
+
+     <li>
+
+      <p>Let <var title="">parent</var> be the row's parent, or the
+      <code>datagrid</code> if the row has no parent.</p>
+
+     </li>
+
+     <li>
+
+      <p>Decrement by one the natural order position of all rows whose
+      parent is <var title="">parent</var> and whose natural order
+      position is equal to or greater than the row's own natural order
+      position.</p>
+
+     </li>
+
+     <li>
+
+      <p>If the row is in the <span>display order sparse data
+      tree</span>, then decrement by one the display order position of
+      all rows whose parent is <var title="">parent</var> and whose
+      display order position is equal to or greater than the row's own
+      display order position.</p>
+
+     </li>
+
+     <li>
+
+      <p>Clear the row and its descendants from the
+      <code>Datagrid</code>.</p>
+
+     </li>
+
+    </ol>
+
+   </li>
+
+   <li>
+
+    <p>Invoke the <span><code>datagrid</code> update display
+    algorithm</span>.</p>
+
+   </li>
+
+  </ol>
+
+  <hr>
+
+  <p>The <dfn
+  title="dom-datagrid-clearRows"><code>clearRows()</code></dfn> method
+  must empty the <span>natural order sparse data tree</span>, reset
+  both the <span><code>datagrid</code> child count</span> and the
+  <span><code>datagrid</code> row count</span> to zero, and invoke the
+  <span><code>datagrid</code> update display algorithm</span>.</p>
+
+  <hr>
+
+  <p>The <dfn title="dom-datagrid-repaint"><code>repaint(<var
+  title="">row</var>, <var title="">column</var>)</code></dfn> method
+  must cause the user agent to clear its cache for the cell specified
+  by the identifier <var title="">row</var> and the column <var
+  title="">column</var>, if that column's type is <code
+  title="datagrid-type-custom">custom</code>. If the given column has
+  not been declared, or its type is not <code
+  title="datagrid-type-custom">custom</code>, then the user agent must
+  throw a <code>DATAGRID_MODEL_ERR</code> exception. If the given row
+  is not known, then the method must do nothing. If the cell is indeed
+  cleared, the user agent must reinvoke the previously registered
+  <code>RenderingContext2DCallback</code> callback when it needs to
+  repaint that row.</p>
+
+  <hr>
+
+  <p>If a row has a child count that isn't zero, then the user agent
+  should offer to the user the option of opening and closing the
+  row.</p>
+
+  <p>When a row is opened, if the row's row count is greater than
+  zero, then the user agent must increase the
+  <span><code>datagrid</code> row count</span> and the row counts of
+  any ancestor rows by the number of rows that the newly opened row
+  has in its row count<!-- we should also "update the <span>pending
+  <code>datagrid</code> rows list</span> and the <span>pending
+  <code>datagrid</code> cells list</span> accordingly" -->, then must
+  mark the row as open, then may fill in the <span>display order
+  sparse data tree</span> with any information that the user agent has
+  cached about the display order positions of descendants of the newly
+  opened row, and then must invoke the <code
+  title="dom-listener-rowOpened">rowOpened()</code> method on the
+  current <code title="dom-datagrid-listener">listener</code> with as
+  its first argument a <code>RowID</code> object identifying the row
+  that was opened and as its second argument the boolean false, and
+  then must invoke the <span><code>datagrid</code> update display
+  algorithm</span>.</p>
+
+  <p>On the other hand, when a row is opened and the row's row count
+  is &#x2212;1, then the user agent must mark the row as opening, and
+  then must invoke the <code
+  title="dom-listener-rowOpened">rowOpened()</code> method on the
+  current <code title="dom-datagrid-listener">listener</code> with as
+  its first argument a <code>RowID</code> object identifying the row
+  that was opened and as its second argument the boolean true.</p>
+
+  <p>When a row is closed, the user agent must decrease the
+  <span><code>datagrid</code> row count</span> and the row counts of
+  any ancestor rows by the number of rows that the newly closed row
+  has in its row count, and then must invoke the <code
+  title="dom-listener-rowOpened">rowOpened()</code> method on the
+  current <code title="dom-datagrid-listener">listener</code> with as
+  its first and only argument a <code>RowID</code> object identifying
+  the row that was opened.</p>
+
+
+
+  <h6>The cells</h6>
+
+  <p>Each row has one cell per column. Each cell has the same type as
+  its column. The <dfn>allowed <code>datagrid</code> column
+  types</dfn>, what they represent, and the requirements for when the
+  user interacts with them, are as follows:</p>
+
   <dl>
 
-   <dt>Cyclable cells</dt>
+   <dt><dfn title="datagrid-type-text"><code>text</code></dfn></dt>
+   <dd>
 
+    <p>The cell represents some text and an optional image.</p>
+
+   </dd>
+
+   <dt><dfn title="datagrid-type-editable"><code>editable</code></dfn></dt>
    <dd>
 
-    <p>If the first element child of a cell's element is a
-    <code>select</code> element that has a no <code
-    title="attr-select-multiple">multiple</code> attribute and has at
-    least one <code>option</code> element descendant, then the cell
-    acts as a cyclable cell.</p>
+    <p>The cells represents some editable text, an optional
+    <code>datalist</code> giving autocompletion hints, and an
+    optional image.</p>
 
-    <p>The "current" <code>option</code> element is the selected
-    <code>option</code> element, or the first <code>option</code>
-    element if none is selected.</p>
+    <p>If there is a <code>datalist</code> element, the user agent
+    should offer the suggestions represented by that element to the
+    user. The user agent may use the suggestion's <span
+    title="concept-option-label">label</span> to identify the
+    suggestion. If the user selects a suggestion, then the editable
+    text must be set to the selected suggestion's <span
+    title="concept-option-value">value</span>, as if the user had
+    written that value himself.</p>
 
-    <p>The <code title="dom-provider-getCellData">getCellData()</code>
-    method must return the <code>textContent</code> of the current
-    <code>option</code> element (the <code
-    title="attr-option-label">label</code> attribute is <span
-    title="ignore">ignored</span> in this context as the
-    <code>optgroup</code>s are not displayed).</p>
+    <p>When the user edits the value, either directly or using the
+    <code>datalist</code>, the user agent must invoke the <code
+    title="dom-listener-cellChanged">cellChanged()</code> method on
+    the current <code title="dom-datagrid-listener">listener</code>
+    with as its first argument a <code>RowID</code> identifying the
+    cell's row, as its second argument the identifier of the cell's
+    column, as its third argument the new value, and as its fourth
+    argument the previous value.</p>
 
-    <p>The <code
-    title="dom-provider-getCellClasses">getCellClasses()</code> method
-    must add the <code
-    title="datagrid-cell-class-cyclable">cyclable</code> class and
-    then all the classes of the current <code>option</code>
-    element.</p>
+   </dd>
 
-    <p>The <code title="dom-provider-cycleCell">cycleCell()</code>
-    method must change the selection of the <code>select</code>
-    element such that the next <code>option</code> element after the
-    current <code>option</code> element is the only one that is
-    selected (in <span>tree order</span>). If the current <code>option</code>
-    element is the last <code>option</code> element descendant of the
-    <code>select</code>, then the first <code>option</code> element
-    descendant must be selected instead.</p>
+   <dt><dfn title="datagrid-type-checkable"><code>checkable</code></dfn></dt>
+   <dd>
 
-    <p>The <code
-    title="dom-provider-setCellCheckedState">setCellCheckedState()</code>
-    and <code title="dom-provider-editCell">editCell()</code> methods
-    must do nothing.</p>
+    <p>The cell represents some text, a check box that optionally has
+    its value obscured as indeterminate, and an optional image.</p>
 
+    <p>When the user checks or unchecks the check box, the user agent
+    must change the check box's state appropriately and stop obscuring
+    the check box as indeterminate (if it is obscuring it), and then
+    must invoke the <code
+    title="dom-listener-cellChanged">cellChanged()</code> method on
+    the current <code title="dom-datagrid-listener">listener</code>
+    with as its first argument a <code>RowID</code> identifying the
+    cell's row, as its second argument the identifier of the cell's
+    column, as its third argument true if the check box is now checked
+    and false otherwise, and as its fourth argument true if the check
+    box was previously checked and false otherwise.</p>
+
    </dd>
 
-   <dt>Progress bar cells</dt>
-
+   <dt><dfn title="datagrid-type-list"><code>list</code></dfn></dt>
    <dd>
 
-    <p>If the first element child of a cell's element is a
-    <code>progress</code> element, then the cell acts as a progress
-    bar cell.</p>
+    <p>The cell represents some text giving the current value selected
+    from a dropdown list of options, a <code>select</code> element
+    giving the list of options, and an optional image.</p>
 
-    <p>The <code title="dom-provider-getCellData">getCellData()</code>
-    method must return the value returned by the <code>progress</code>
-    element's <code title="dom-progress-position">position</code> DOM
-    attribute.</p>
+    <p>The user agent should allow the user to change the value of the
+    cell from its current value to one of the <span
+    title="concept-option-value">values</span> given by
+    <code>option</code> elements in the <span
+    title="concept-select-option-list">list of options</span> (if
+    any). The user agent may use the <code>option</code> elements'
+    <span title="concept-option-label">labels</span> to annotate each
+    option.</p>
 
-    <p>The <code
-    title="dom-provider-getCellClasses">getCellClasses()</code> method
-    must add the <code
-    title="datagrid-cell-class-progress">progress</code> class.</p>
+    <p>When the user selects a new value from the <code>select</code>
+    element's <span title="concept-select-option-list">list of
+    options</span>, the user agent must invoke the <code
+    title="dom-listener-cellChanged">cellChanged()</code> method on
+    the current <code title="dom-datagrid-listener">listener</code>
+    with as its first argument a <code>RowID</code> identifying the
+    cell's row, as its second argument the identifier of the cell's
+    column, as its third argument the new value, and as its fourth
+    argument the previous value.</p>
 
-    <p>The <code
-    title="dom-provider-setCellCheckedState">setCellCheckedState()</code>,
-    <code title="dom-provider-cycleCell">cycleCell()</code>, and
-    <code title="dom-provider-editCell">editCell()</code> methods must
-    do nothing.</p>
+   </dd>
 
+   <dt><dfn title="datagrid-type-progress"><code>progress</code></dfn></dt>
+   <dd>
+
+    <p>The cell represents a (determinate) progress bar whose value is
+    between 0.0, indicating no progress, and 1.0, indicating the task
+    is complete.</p>
+
    </dd>
 
-   <dt>Checkbox cells</dt>
-
+   <dt><dfn title="datagrid-type-meter"><code>meter</code></dfn></dt>
    <dd>
 
-    <p>If the first element child of a cell's element is an
-    <code>input</code> element that has a <code
-    title="attr-input-type">type</code> attribute with the value <code
-    title="">checkbox</code>, then the cell acts as a check box
-    cell.</p>
+    <p>The cell represents a gauge, described by one to six
+    numbers.</p>
 
-    <p>The <code title="dom-provider-getCellData">getCellData()</code>
-    method must return the <code>textContent</code> of the cell
-    element.</p>
+    <p>The gauge's actual value is given by the first number.</p>
 
-    <p>The <code
-    title="dom-provider-getCellClasses">getCellClasses()</code> method
-    must add the <code
-    title="datagrid-cell-class-checked">checked</code> class if the
-    <code>input</code> element's <span
-    title="concept-fe-checked">checkedness</span> is true, and the
-    <code title="datagrid-cell-class-unchecked">unchecked</code> class
-    otherwise.</p>
+    <p>If there is a second number, then that number is the maximum
+    value. Otherwise, the maximum value is 1.0.</p>
 
-    <p>The <code
-    title="dom-provider-setCellCheckedState">setCellCheckedState()</code>
-    method must set the <code>input</code> element's checkbox <span
-    title="concept-fe-checked">checkedness</span> to true if the
-    method's third argument is 1, and to false otherwise.</p>
+    <p>If there is a third number, then that number is the minimum
+    value. Otherwise, the minimum value is 1.0.</p>
 
-    <p>The <code title="dom-provider-cycleCell">cycleCell()</code> and
-    <code title="dom-provider-editCell">editCell()</code> methods must
-    do nothing.</p>
+    <p>If there is a fourth number, then that number is the low
+    boundary. Otherwise, the low boundary is the minimum value.</p>
 
+    <p>If there is a fifth number, then that number is the high
+    boundary. Otherwise, the high boundary is the maximum value.</p>
+
+    <p>If there is a sixth number, then the optimal point is the sixth
+    number. Otherwise, the optimum point is the midpoint between the
+    minimum value and the maximum value.</p>
+
+    <!-- next two paragraphs copied from <meter>: -->
+
+    <p>If the optimum point is equal to the low boundary or the high
+    boundary, or anywhere in between them, then the region between the
+    low and high boundaries of the gauge must be treated as the
+    optimum region, and the low and high parts, if any, must be
+    treated as suboptimal. Otherwise, if the optimum point is less
+    than the low boundary, then the region between the minimum value
+    and the low boundary must be treated as the optimum region, the
+    region between the low boundary and the high boundary must be
+    treated as a suboptimal region, and the region between the high
+    boundary and the maximum value must be treated as an even less
+    good region. Finally, if the optimum point is higher than the high
+    boundary, then the situation is reversed; the region between the
+    high boundary and the maximum value must be treated as the optimum
+    region, the region between the high boundary and the low boundary
+    must be treated as a suboptimal region, and the remaining region
+    between the low boundary and the minimum value must be treated as
+    an even less good region.</p>
+
+    <p>User agents should indicate the relative position of the actual
+    actual to the minimum and maximum values, and the relationship
+    between the actual value and the three regions of the gauge.</p>
+
    </dd>
 
-   <dt>Editable cells</dt>
-
+   <dt><dfn title="datagrid-type-custom"><code>custom</code></dfn></dt>
    <dd>
 
-    <p>If the first element child of a cell's element is an
-    <code>input</code> element that has a <code
-    title="attr-input-type">type</code> attribute with the value <code
-    title="">text</code> or that has no <code
-    title="attr-input-type">type</code> attribute at all, then the
-    cell acts as an editable cell.</p>
+    <p>The cell represents a dynamically generated graphical image.</p>
 
-    <p>The <code title="dom-provider-getCellData">getCellData()</code>
-    method must return the <code title="dom-input-value">value</code>
-    of the <code>input</code> element.</p>
+    <p>The cell will have minimum dimensions (specified in CSS
+    pixels), and a callback (in the form of a
+    <code>RenderingContext2DCallback</code> object) to get a rendering
+    for the cell.</p>
 
-    <p>The <code
-    title="dom-provider-getCellClasses">getCellClasses()</code> method
-    must add the <code
-    title="datagrid-cell-class-editable">editable</code> class.</p>
+    <p>The user agent should not allow the cell to be rendered with
+    dimensions less than the given minimum width and height.</p>
 
-    <p>The <code title="dom-provider-editCell">editCell()</code>
-    method must set the <code>input</code> element's <code
-    title="dom-input-value">value</code> DOM attribute to the value of
-    the third argument to the method.</p>
+    <p>When the user agent needs to render the cell, the user agent
+    must <span>queue a task</span> to invoke the
+    <span>RenderingContext2DCallback</span> callback, passing it a
+    newly created <code>CanvasRenderingContext2D</code> object whose
+    <code title="dom-context-2d-canvas">canvas</code> DOM attribute is
+    null as the first argument, the actual cell width in CSS pixels as
+    the second argument, and the actual cell height in CSS pixels as
+    the third argument.</p>
 
-    <p>The <code
-    title="dom-provider-setCellCheckedState">setCellCheckedState()</code>
-    and <code title="dom-provider-cycleCell">cycleCell()</code>
-    methods must do nothing.</p>
+    <p>If the user agent is able to render graphics, then it must
+    render the graphics commands that the callback executed on the
+    provided <code>CanvasRenderingContext2D</code> object onto the
+    cell once the callback returns. The image must be clipped to the
+    dimensions of the cell. The coordinate space of the cell must be
+    aligned with that used by the 2D context such that the top left
+    corner of the cell is the 0,0 origin, with the coordinate space
+    increasing its <var title="">x</var> dimension towards the right
+    of the cell and its <var title="">y</var> axis towards the bottom
+    of the cell, and with the image not scaled (so that one CSS pixel
+    on the final rendering matches one CSS pixel in the coordinate
+    space usd by the 2D context).</p>
 
+    <p>The user agent must then decouple the
+    <code>CanvasRenderingContext2D</code> object and any objects that
+    it created (such as <code>CanvasPattern</code> objects or
+    <code>ImageData</code> objects) from any real drawing surface.</p>
+
+    <p>If the user agent is unable to render graphics, then it must
+    render the text string returned by the callback instead.</p>
+
    </dd>
 
   </dl>
 
-  <!-- XXX Calculated cells, like in spreadsheets? -->
+  <hr>
 
+  <p>When an algorithm requires the user agent to <dfn>apply a
+  <code>Row</code> object</dfn>, the user agent must run the following
+  steps:</p>
 
-  <h5>Populating the <code>datagrid</code> element</h5>
+  <ol>
 
-  <p>A <code>datagrid</code> must be disabled until its end tag has
-  been parsed<!-- XXX do we define that? what if the end tag is never
-  seen, but the element is popped off the stack?--> (in the case of a
-  <code>datagrid</code> element in the original document markup) or
-  until it has been <span title="insert an element into a
-  document">inserted into the document</span> (in the case of a
-  dynamically created element). After that point, the element must
-  fire a single <code title="event-load">load</code> event at itself,
-  which doesn't bubble and cannot be canceled.</p>
+   <li>
 
-  <p class="XXX">The end-tag parsing thing should be moved to
-  the parsing section.</p>
+    <p>If the value of the <code>Row</code> object's second entry is
+    not &#x2212;1, then run these substeps:</p>
 
-  <p>The <code>datagrid</code> must then populate itself using the
-  data provided by the data provider assigned to the <code
-  title="dom-datagrid-data">data</code> DOM attribute. After the view
-  is populated (using the methods described below), the
-  <code>datagrid</code> must invoke the <code
-  title="dom-provider-initialize">initialize()</code> method on the
-  data provider specified by the <code
-  title="dom-datagrid-data">data</code> attribute, passing itself (the
-  <code>HTMLDataGridElement</code> object) as the only argument.</p>
+    <ol>
 
-  <p>When the <code title="dom-datagrid-data">data</code> attribute is
-  null, the <code>datagrid</code> must use the default data provider
-  described in the previous section.</p>
+     <li><p>If there is a row with the same parent as the row
+     specified by the <code>Row</code> object's <code>RowID</code>
+     object, whose display order position is currently the same as the
+     value of the <code>Row</code> object's second entry, then remove
+     that row from the <span>display order sparse data
+     tree</span>.</p></li>
 
-  <p>To obtain data from the data provider, the element must invoke
-  methods on the data provider object in the following ways:</p>
+     <li><p>Set the display order position of the row specified by the
+     <code>Row</code> object's <code>RowID</code> to the value of the
+     <code>Row</code> object's second entry, updating its position in
+     the <span>display order sparse data tree</span>
+     accordingly.</p></li>
 
-  <dl>
+     <li><p>If the row is in the the <span>pending
+     <code>datagrid</code> rows list</span>, remove it.</p></li>
 
-   <dt>To determine the total number of columns</dt>
+    </ol>
 
-   <dd>Invoke the <code
-   title="dom-provider-getColumnCount">getColumnCount()</code> method
-   with no arguments. The return value is the number of columns. If
-   the return value is zero or negative, not an integer, or simply not
-   a numeric type, or if the method is not defined, then 1 must be
-   used instead.</dd>
+   </li>
 
-   <dt>To get the captions to use for the columns</dt>
+   <li>
 
-   <dd>Invoke the <code
-   title="dom-provider-getCaptionText">getCaptionText()</code> method
-   with the index of the column in question. The index <var
-   title="">i</var> must be in the range 0 &le; <var title="">i</var>
-   &lt; <var title="">N</var>, where <var title="">N</var> is the
-   total number of columns. The return value is the string to use when
-   referring to that column. If the method returns null or the empty
-   string, the column has no caption. If the method is not defined,
-   then none of the columns have any captions.</dd>
+    <p>If the fourth entry in the <code>Row</code> object (a
+    <code>CellList</code> object, an array) is not empty, then for
+    each <code>Cell</code> object in that array update the cell that
+    corresponds to the column identified by the value of the first
+    entry of the <code>Cell</code> object, by using the appropriate
+    set of steps given below as determined by the type of the
+    column. Then, if the cell is in the the <span>pending
+    <code>datagrid</code> cells list</span>, remove it.</p>
 
-   <dt>To establish what classes apply to a column</dt>
+    <dl>
 
-   <dd>Invoke the <code
-   title="dom-provider-getCaptionClasses">getCaptionClasses()</code>
-   method with the index of the column in question, and an object
-   implementing the <code>DOMTokenList</code> interface, associated
-   with an anonymous empty string. The index <var title="">i</var>
-   must be in the range 0 &le; <var title="">i</var> &lt; <var
-   title="">N</var>, where <var title="">N</var> is the total number
-   of columns. The tokens contained in the string underlying
-   <code>DOMTokenList</code> object when the method returns represent
-   the classes that apply to the given column. If the method is not
-   defined, no classes apply to the column.</dd>
+     <dt>If the column's type is <code title="datagrid-type-text">text</code></dt>
+     <dd>
 
-   <dt>To establish whether a column should be initially included in
-   the visible columns</dt>
+      <p>Update the cell's text to the value given in the
+      <code>Cell</code> object's second entry.</p>
 
-   <dd>Check whether the <code
-   title="datagrid-column-class-initially-hidden">initially-hidden</code>
-   class applies to the column. If it does, then the column should not
-   be initially included; if it does not, then the column should be
-   initially included.</dd>
+      <p>If the <code>Cell</code> object has three entries, then copy
+      the image data from the <code>img</code> element given in the
+      third entry, and let the cell's image be given by that image
+      data. Otherwise, update the cell to have no image.</p>
 
-   <dt id="columnType2">To establish whether the data can be sorted
-   relative to a particular column</dt>
+     </dd>
 
-   <dd>Check whether the <code
-   title="datagrid-column-class-sortable">sortable</code> class
-   applies to the column. If it does, then the user agent should offer
-   the user the option to have the data displayed sorted by that
-   column; if it does not, then the user agent must not allow the user
-   to ask for the data to be sorted by that column.</dd>
+     <dt>If the column's type is <code title="datagrid-type-editable">editable</code></dt>
+     <dd>
 
-   <dt>To establish if a column is a sorted column</dt>
+      <p>Update the cell's text to the value given in the
+      <code>Cell</code> object's second entry.</p>
 
-   <dd>If the user agent can handle multiple columns being marked as
-   sorted simultaneously: Check whether the <code
-   title="datagrid-column-class-sorted">sorted</code> class applies to
-   the column. If it does, then that column is the sorted column,
-   otherwise it is not.</dd>
+      <p>If the <code>Cell</code> object has three entries, then let
+      the <code>datalist</code> element given in the third entry be
+      the <code>datalist</code> element giving autocompletion
+      hints. Otherwise, update the cell to have no
+      <code>datalist</code> element.</p>
 
-   <dd>If the user agent can only handle one column being marked as
-   sorted at a time: Check each column in turn, starting with the
-   first one, to see whether the <code
-   title="datagrid-column-class-sorted">sorted</code> class applies to
-   that column. The first column that has that class, if any, is the
-   sorted column. If none of the columns have that class, there is no
-   sorted column.</dd>
+      <p>If the <code>Cell</code> object has four entries, then copy
+      the image data from the <code>img</code> element given in the
+      fourth entry, and let the cell's image be given by that image
+      data. Otherwise, update the cell to have no image.</p>
 
-   <dt>To establish the sort direction of a sorted column</dt>
+     </dd>
 
-   <dd>Check whether the <code
-   title="datagrid-column-class-reversed">reversed</code> class
-   applies to the column. If it does, then the sort direction is
-   descending (down; first rows have the highest values), otherwise it
-   is ascending (up; first rows have the lowest values).</dd>
+     <dt>If the column's type is <code title="datagrid-type-checkable">checkable</code></dt>
+     <dd>
 
-   <dt>To determine the total number of rows</dt>
+      <p>Update the cell's text to the value given in the
+      <code>Cell</code> object's second entry.</p>
 
-   <dd>Determine the number of rows for the root of the data grid, and
-   determine the number of child rows for each open row. The total
-   number of rows is the sum of all these numbers.</dd>
+      <p>Update the cell's checked state to match the value of the
+      third entry: checked if true, unchecked otherwise.</p>
 
-   <dt>To determine the number of rows for the root of the data grid</dt>
+      <p>If the <code>Cell</code> object has four entries and the
+      fourth entry is true, then update the cell to be obscured as
+      indeterminate. Otherwise, the cell's state is not obscured.</p>
 
-   <dd>Invoke the <code
-   title="dom-provider-getRowCount">getRowCount()</code> method with a
-   <code>RowSpecification</code> object representing the empty path as
-   its only argument. The return value is the number of rows at the
-   top level of the data grid. If the return value of the method is
-   negative, not an integer, or simply not a numeric type, or if the
-   method is not defined, then zero must be used instead.</dd>
+      <p>If the <code>Cell</code> object has five entries, then copy
+      the image data from the <code>img</code> element given in the
+      fifth entry, and let the cell's image be given by that image
+      data. Otherwise, update the cell to have no image.</p>
 
-   <dt>To determine the number of child rows for a row</dt>
+     </dd>
 
-   <dd>Invoke the <code
-   title="dom-provider-getRowCount">getRowCount()</code> method with a
-   <code>RowSpecification</code> object representing the path to the
-   row in question. The return value is the number of child rows for
-   the given row. If the return value of the method is negative, not
-   an integer, or simply not a numeric type, or if the method is not
-   defined, then zero must be used instead.</dd>
+     <dt>If the column's type is <code title="datagrid-type-list">list</code></dt>
+     <dd>
 
-   <dt>To determine what order to render rows in</dt>
+      <p>Update the cell's text to the value given in the
+      <code>Cell</code> object's second entry, and the
+      <code>select</code> element to be the one given in the
+      <code>Cell</code> object's third entry</p>
 
-   <dd>
+      <p>If the <code>Cell</code> object has four entries, then copy
+      the image data from the <code>img</code> element given in the
+      fourth entry, and let the cell's image be given by that image
+      data. Otherwise, update the cell to have no image.</p>
 
-    <p>Invoke the <code
-    title="dom-provider-getChildAtPosition">getChildAtPosition()</code>
-    method with a <code>RowSpecification</code> object representing
-    the path to the parent of the rows that are being rendered as the
-    first argument, and the position that is being rendered as the
-    second argument. The return value is the index of the row to
-    render in that position.</p>
+     </dd>
 
-    <div class="example">
+     <dt>If the column's type is <code title="datagrid-type-progress">progress</code></dt>
+     <dd>
 
-     <p>If the rows are:</p>
+      <p>Update the cell to be a progress bar whose progress, on the
+      scale of 0.0 (no progress) to 1.0 (task complete) is given by
+      the value in the <code>Cell</code> object's second entry.</p>
 
-     <ol>
-      <li> Row "0"
-       <ol>
-        <li> Row "0,0"
-        <li> Row "0,1"
-       </ol>
-      </li>
-      <li> Row "1"
-       <ol>
-        <li> Row "1,0"
-        <li> Row "1,1"
-       </ol>
-      </li>
-     </ol>
+     </dd>
 
-     <p>...and the <code
-    title="dom-provider-getChildAtPosition">getChildAtPosition()</code>
-    method is implemented as follows:</p>
+     <dt>If the column's type is <code title="datagrid-type-meter">meter</code></dt>
+     <dd>
 
-    <pre>function getChildAtPosition(parent, child) {
-  // always return the reverse order
-  return getRowCount(parent)-child-1;
-}</pre>
+      <p>Update the cell to be a gauge configured with the numbers
+      given by the second and subsequent entries of the
+      <code>Cell</code> object.</p>
 
-     <p>...then the rendering would actually be:</p>
+     </dd>
 
-     <ol>
-      <li> Row "1"
-       <ol>
-        <li> Row "1,1"
-        <li> Row "1,0"
-       </ol>
-      </li>
-      <li> Row "0"
-       <ol>
-        <li> Row "0,1"
-        <li> Row "0,0"
-       </ol>
-      </li>
-     </ol>
+     <dt>If the column's type is <code title="datagrid-type-custom">custom</code></dt>
+     <dd>
 
-    </div>
+      <p>Update the cell's minimum width to be the length in CSS
+      pixels given by the <code>Cell</code> object's second entry.</p>
 
-    <p>If the return value of the method is negative, larger than the
-    number of rows that the <code
-    title="dom-provider-getRowCount">getRowCount()</code> method
-    reported for that parent, not an integer, or simply not a numeric
-    type, then the entire data grid should be disabled. Similarly, if
-    the method returns the same value for two or more different values
-    for the second argument (with the same first argument, and
-    assuming that the data grid hasn't had relevant update methods
-    invoked in the meantime), then the data grid should be
-    disabled. Instead of disabling the data grid, the user agent may
-    act as if the <code
-    title="dom-provider-getChildAtPosition">getChildAtPosition()</code>
-    method was not defined on the data provider (thus disabling
-    sorting for that data grid, but still letting the user interact
-    with the data). If the method is not defined, then the return
-    value must be assumed to be the same as the second argument (an
-    identity transform; the data is rendered in its natural
-    order).</p>
+      <p>Update the cell's minimum height to be the length in CSS
+      pixels given by the <code>Cell</code> object's third entry.</p>
 
-   </dd>
+      <p>Update the cell's callback to be the
+      <code>RenderingContext2DCallback</code> object given by the
+      <code>Cell</code> object's fourth entry.</p>
 
-   <dt>To establish what classes apply to a row</dt>
+     </dd>
 
-   <dd>Invoke the <code
-   title="dom-provider-getRowClasses">getRowClasses()</code> method
-   with a <code>RowSpecification</code> object representing the row in
-   question, and a <code>DOMTokenList</code> associated with an empty
-   string. The tokens contained in the <code>DOMTokenList</code>
-   object's underlying string when the method returns represent the
-   classes that apply to the row in question. If the method is not
-   defined, no classes apply to the row.</dd>
+    </dl>
 
-   <dt>To establish whether a row is a data row or a special row</dt>
+   </li>
 
-   <dd>Examine the classes that apply to the row. If the <code
-   title="datagrid-row-class-header">header</code> class applies to
-   the row, then it is not a data row, it is a subheading. The data
-   from the first cell of the row is the text of the subheading, the
-   rest of the cells must be ignored. Otherwise, if the <code
-   title="datagrid-row-class-separator">separator</code> class applies
-   to the row, then in the place of the row, a separator should be
-   shown. Otherwise, if the <code
-   title="datagrid-row-class-selectable-separator">selectable-separator</code>
-   class applies to the row, then the row should be a data row, but
-   represented as a separator. (The difference between a <code
-   title="datagrid-row-class-separator">separator</code> and a <code
-   title="datagrid-row-class-selectable-separator">selectable-separator</code>
-   is that the former is not an item that can be actually selected,
-   whereas the second can be selected and thus has a context menu that
-   applies to it, and so forth.) For both kinds of separator rows, the
-   data of the rows' cells must all be ignored. If none of those three
-   classes apply then the row is a simple data row.</dd>
+  </ol>
 
-   <dt id="rowType1">To establish whether a row is openable</dt>
+  <hr>
 
-   <dd>Determine the number of child rows for that row. If there are
-   one or more child rows, then the row is openable.</dd>
+  <p>When the user agent is to run the <dfn><code>datagrid</code>
+  update display algorithm</dfn>, the user agent must invoke the <code
+  title="dom-listener-getRows">getRows()</code> and <code
+  title="dom-listener-getCells">getCells()</code> methods on the
+  current <code title="dom-datagrid-listener">listener</code> such
+  that all the current visible rows in the <span>display order sparse
+  data list</span>, and all the cells in the currently visible columns
+  on all the currently visible rows, have been covered.</p>
 
-   <dt>To establish whether a row should be initially open or closed</dt>
+  <p>A row is considered covered if it is present in the <span>pending
+  <code>datagrid</code> rows list</span>, or if the <code
+  title="dom-listener-getRows">getRows()</code> method is invoked with
+  a range that includes the row in question.</p>
 
-   <dd>If <a href="#rowType1">the row is openable</a>, examine the
-   classes that apply to the row. If the <code
-   title="datagrid-row-class-initially-open">initially-open</code>
-   class applies to the row, then it should be initially
-   open. Otherwise, if the <code
-   title="datagrid-row-class-initially-closed">initially-closed</code>
-   class applies to the row, then it must be initially
-   closed. Otherwise, if neither class applies to the row, or if the
-   row is not openable, then the initial state of the row should be
-   based on platform conventions.</dd>
+  <p>A cell is considered covered if it is present in the
+  <span>pending <code>datagrid</code> cells list</span>, or if the
+  <code title="dom-listener-getRows">getRows()</code> method is
+  invoked with a range that includes the row in question and a list of
+  columns that includes the cell's column, or if the <code
+  title="dom-listener-getCells">getCells()</code> method is invoked
+  with a list of rows and columns that intersects the cell in
+  question. However, the <code
+  title="dom-listener-getCells">getCells()</code> method can only be
+  used if the row is already present in the <span>display order sparse
+  data list</span>.</p>
 
-<!-- XXXPA
-   <dt>To establish whether a row is deletable</dt>
+  <p>The <code title="dom-listener-getRows">getRows()</code> method,
+  if used, must be invoked with five arguments. The first argument
+  must be the index in the <span>display order sparse data list</span>
+  to the first row that the the user agent is requesting, known as the
+  <i>anchor row</i>. The second argument must be the number of
+  consecutive cells for which the user agent is requesting
+  information. The third argument must be the <code>RowID</code> of
+  the row that is the nearest ancestor in the <span>display order
+  sparse data <em>tree</em></span> of the anchor row. If this is the
+  <code>datagrid</code>, then the <code>RowID</code> object must be an
+  empty array. The fourth argument must be the display order position
+  of the anchor row in the <span>display order sparse data
+  tree</span>, assuming that the row identified in the third argument
+  is indeed the anchor row's parent row. The fifth and final argument
+  must be an array of the identifiers of the columns for which the
+  user agent is requesting information, in the order they were added
+  to the <code>datagrid</code>.</p>
 
-   <dd>Check whether the <code
-   title="datagrid-row-class-deletable">deletable</code> class applies
-   to the row. If it does, the row is deletable, and interactive user
-   agents should provide a way for the user to request that the row be
-   deleted. (See the <code
-   title="dom-provider-performActionOnRow">performActionOnRow()</code>
-   method for more details.) Otherwise, the user agent should not
-   provide the user with a method for requesting that the row be
-   deleted.</dd>
--->
+  <p>As the <code title="dom-listener-getRows">getRows()</code> method
+  is invoked, the <span>pending <code>datagrid</code> rows list</span>
+  must be updated to include the rows for which information has been
+  requested, excluding rows for which information is already
+  available; and the <span>pending <code>datagrid</code> cells
+  list</span> must be updated to include the cells for which
+  information has been requested on those rows.</p>
 
-   <dt>To obtain a <span>URL</span> identifying an image representing a row</dt>
+  <p>The <code title="dom-listener-getCells">getCells()</code> method,
+  if used, must be invoked with two arguments. The first argument must
+  be an array of <code>RowID</code> objects identifying the rows for
+  which information is being requested. The second argument must be an
+  array of the identifiers of the columns for which the user agent is
+  requesting information, in the order they were added to the
+  <code>datagrid</code>.</p>
 
-   <dd>Invoke the <code
-   title="dom-provider-getRowImage">getRowImage()</code> method with a
-   <code>RowSpecification</code> object representing the row in
-   question. The return value is a <span>URL</span>. Immediately <span
-   title="resolve a url">resolve</span> that URL, relative to the
-   <code>datagrid</code> element, to obtain an <span>absolute
-   URL</span> identifying the image that represents the row. If the
-   method returns the empty string, null, or if the method is not
-   defined, then the row has no associated image.</dd> <!-- changing
-   the base URL doesn't change the image used later -->
+  <p>As the <code title="dom-listener-getCells">getCells()</code>
+  method is invoked, the <span>pending <code>datagrid</code> cells
+  list</span> must be updated to include the cells for which
+  information has been requested.</p>
 
-   <dt>To obtain a context menu appropriate for a particular row</dt>
+  <p>Calls to these methods should be batched so that the rows and
+  cells to be covered are handled by the fewest number of calls to
+  these methods as possible. To this end, user agents may invoke the
+  <code title="dom-listener-getRows">getRows()</code> method for a set
+  of rows that includes some rows that are already in the
+  <span>display order sparse data list</span>, and similarly may
+  invoke the <code title="dom-listener-getCells">getCells()</code>
+  method with row/column combinations that cover some cells for which
+  data is already known. Generally, however, user agents should avoid
+  invoking these methods with arguments that cause information to be
+  requested when it has already been requested or is already
+  known.</p>
 
-   <dd>Invoke the <code
-   title="dom-provider-getRowMenu">getRowMenu()</code> method with a
-   <code>RowSpecification</code> object representing the row in
-   question. The return value is a reference to an object implementing
-   the <code>HTMLMenuElement</code> interface, i.e. a
-   <code>menu</code> element DOM node. (This element must then be
-   interpreted as described in the section on context menus to obtain
-   the actual context menu to use.<!-- XXX update once menu section
-   works; with xrefs -->) If the method returns something that is not
-   an <code>HTMLMenuElement</code>, or if the method is not defined,
-   then the row has no associated context menu. User agents may
-   provide their own default context menu, and may add items to the
-   author-provided context menu. For example, such a menu could allow
-   the user to change the presentation of the <code>datagrid</code>
-   element.</dd>
+  <div class="example">
 
-   <dt>To establish the value of a particular cell</dt>
+   <p>For example, consider a case represented by the following table,
+   where the cells marked "Yes" indicate that the data has already
+   been obtained, the cells marked "Pending" indicate that the data
+   has been previously requested but not yet obtained, and the cells
+   with just a dash indicate that no information has ever been
+   obtained, or any information that had been obtained has now been
+   discarded.</p>
 
-   <dd>Invoke the <code
-   title="dom-provider-getCellData">getCellData()</code> method with
-   the first argument being a <code>RowSpecification</code> object
-   representing the row of the cell in question and the second
-   argument being the index of the cell's column. The second argument
-   must be a non-negative integer less than the total number of
-   columns. The return value is the value of the cell. If the return
-   value is null or the empty string, or if the method is not defined,
-   then the cell has no data. (For progress bar cells, the cell's
-   value must be further interpreted, as described below.)</dd>
+   <table>
+    <tr> <td>        <th> Row   <th> Column A  <th> Column B
+    <tr> <th> Row 1  <td> -     <td> -         <td> -
+    <tr> <th> Row 2  <td> Yes   <td> Yes       <td> Yes
+    <tr> <th> Row 3  <td> Yes   <td> Yes       <td> Yes
+    <tr> <th> Row 4  <td> Yes   <td> Yes       <td> Yes
+    <tr> <th> Row 5  <td> -     <td> -         <td> -
+    <tr> <th> Row 6  <td> -     <td> -         <td> -
+    <tr> <th> Row 7  <td> Yes   <td> Pending   <td> -
+    <tr> <th> Row 8  <td> Yes   <td> Pending   <td> Pending
+   </table>
 
-   <dt>To establish what classes apply to a cell</dt>
+   <p>Thus, rows 2, 3, 4, 7, and 8 are already covered, as are the
+   cells from those rows except for the cell in column B of row 7.</p>
 
-   <dd>Invoke the <code
-   title="dom-provider-getCellClasses">getCellClasses()</code> method
-   with the first argument being a <code>RowSpecification</code>
-   object representing the row of the cell in question, the second
-   argument being the index of the cell's column, and the third being
-   an object implementing the <code>DOMTokenList</code> interface,
-   associated with an empty string. The second argument must be a
-   non-negative integer less than the total number of columns. The
-   tokens contained in the <code>DOMTokenList</code> object's
-   underlying string when the method returns represent the classes
-   that apply to that cell. If the method is not defined, no classes
-   apply to the cell.</dd>
+   <p>Now consider what happens if all of these rows become visible at
+   once. The user agent has several choices, including (but not
+   limited to) the following:</p>
 
-   <dt id="cellType1">To establish the type of a cell</dt>
+   <ul>
 
-   <dd>Examine the classes that apply to the cell. If the <code
-   title="datagrid-cell-class-progress">progress</code> class applies
-   to the cell, it is a progress bar. Otherwise, if the <code
-   title="datagrid-cell-class-cyclable">cyclable</code> class applies
-   to the cell, it is a cycling cell whose value can be cycled between
-   multiple states. Otherwise, none of these classes apply, and the
-   cell is a simple text cell.</dd>
+    <li>Fire the <code title="dom-listener-getRows">getRows()</code>
+    method for rows 1 through 8 and columns A and B all at once.</li>
 
-   <dt>To establish the value of a progress bar cell</dt>
+    <li>Fire the <code title="dom-listener-getRows">getRows()</code>
+    method for row 1, then fire it again for rows 5 through 7.</li>
 
-   <dd>If the value <var title="">x</var> of the cell is a string that
-   can be <span title="rules for parsing floating point number
-   values">converted to a floating-point number</span> in the range
-   0.0&nbsp;&le;&nbsp;<var title="">x</var>&nbsp;&le;&nbsp;1.0, then
-   the progress bar has that value (0.0 means no progress, 1.0 means
-   complete). Otherwise, the progress bar is an indeterminate progress
-   bar.</dd>
+    <li>Fire the <code title="dom-listener-getRows">getRows()</code>
+    method for row 1, then fire it again for rows 5 and 6, and then
+    fire the <code title="dom-listener-getCells">getCells()</code>
+    method for row 7 column B.</li>
 
-   <dt id="cellType2">To establish how a simple text cell should be presented</dt>
+   </ul>
 
-   <dd>Check whether one of the <code
-   title="datagrid-cell-class-checked">checked</code>, <code
-   title="datagrid-cell-class-unchecked">unchecked</code>, or <code
-   title="datagrid-cell-class-indeterminate">indeterminate</code>
-   classes applies to the cell. If any of these are present, then the
-   cell has a checkbox, otherwise none are present and the cell does
-   not have a checkbox. If the cell has no checkbox, check whether the
-   <code title="datagrid-cell-class-editable">editable</code> class
-   applies to the cell. If it does, then the cell value is editable,
-   otherwise the cell value is static.</dd>
+   <p>All three options are allowed, but the latter two are preferable
+   to the former, as they minimise the amount of redundant information
+   requested.</p>
 
-   <dt>To establish the state of a cell's checkbox, if it has one</dt>
+   <p>In any case, the data model now looks like this:</p>
 
-   <dd>Check whether the <code
-   title="datagrid-cell-class-checked">checked</code> class applies to
-   the cell. If it does, the cell is checked. Otherwise, check whether
-   the <code title="datagrid-cell-class-unchecked">unchecked</code>
-   class applies to the cell. If it does, the cell is unchecked.
-   Otherwise, the <code
-   title="datagrid-cell-class-indeterminate">indeterminate</code>
-   class applies to the cell and the cell's checkbox is in an
-   indeterminate state. When the <code
-   title="datagrid-cell-class-indeterminate">indeterminate</code>
-   class applies to the cell, the checkbox is a tristate checkbox,
-   and the user can set it to the indeterminate state. Otherwise, only
-   the <code title="datagrid-cell-class-checked">checked</code> and/or
-   <code title="datagrid-cell-class-unchecked">unchecked</code>
-   classes apply to the cell, and the cell can only be toggled between
-   those two states.</dd>
+   <table>
+    <tr> <td>        <th> Row     <th> Column A  <th> Column B  <th> Column C
+    <tr> <th> Row 1  <td> Pending <td> Pending   <td> Pending   <td> -
+    <tr> <th> Row 2  <td> Yes     <td> Yes       <td> Yes       <td> -
+    <tr> <th> Row 3  <td> Yes     <td> Yes       <td> Yes       <td> -
+    <tr> <th> Row 4  <td> Yes     <td> Yes       <td> Yes       <td> -
+    <tr> <th> Row 5  <td> Pending <td> Pending   <td> Pending   <td> -
+    <tr> <th> Row 6  <td> Pending <td> Pending   <td> Pending   <td> -
+    <tr> <th> Row 7  <td> Yes     <td> Pending   <td> Pending   <td> -
+    <tr> <th> Row 8  <td> Yes     <td> Pending   <td> Pending   <td> -
+   </table>
 
-  </dl>
+   <p>Now consider the case where a third column, column C, is added
+   to the data model. The user agent once again has several choices,
+   including (but not limited to) the following:</p>
 
-  <p>If the data provider ever raises an exception while the
-  <code>datagrid</code> is invoking one of its methods, the
-  <code>datagrid</code> must act, for the purposes of that particular
-  method call, as if the relevant method had not been defined.</p>
+   <ul>
 
-  <p>A <code>RowSpecification</code> object <var title="">p</var> with
-  <var title="">n</var> path components passed to a method of the data
-  provider must fulfill the constraint <span>0&nbsp;&le;&nbsp;<var
-  title="">p<sub title=""><var
-  title="">i</var></sub></var>&nbsp;&lt;&nbsp;<var
-  title="">m</var>-1</span> for all integer values of <var
-  title="">i</var> in the range <span>0&nbsp;&le;&nbsp;<var
-  title="">i</var>&nbsp;&lt;&nbsp;<var title="">n</var>-1</span>,
-  where <var title="">m</var> is the value that was last returned by
-  the <code title="dom-provider-getRowCount">getRowCount()</code>
-  method when it was passed the <code>RowSpecification</code> object
-  <var title="">q</var> with <span title=""><var title="">i</var>-1</span>
-  items, where <span title=""><var title="">p<sub title=""><var
-  title="">i</var></sub></var>&nbsp;=&nbsp;<var title="">q<sub
-  title=""><var title="">i</var></sub></var></span> for all integer
-  values of <var title="">i</var> in the range
-  <span>0&nbsp;&le;&nbsp;<var title="">i</var>&nbsp;&lt;&nbsp;<var
-  title="">n</var>-1</span>, with any changes implied by the update
-  methods taken into account.</p>
+    <li>Fire the <code title="dom-listener-getRows">getRows()</code>
+    method for rows 1 through 8 again, this time listing just column
+    C.</li>
 
-  <p id="inconsistentDataProvider">The data model is considered
-  stable: user agents may assume that subsequent calls to the data
-  provider methods will return the same data, until one of the update
-  methods is called on the <code>datagrid</code> element. If a user
-  agent is returned inconsistent data, for example if the number of
-  rows returned by <code
-  title="dom-provider-getRowCount">getRowCount()</code> varies in ways
-  that do not match the calls made to the update methods, the user
-  agent may disable the <code>datagrid</code>. User agents that do not
-  disable the <code>datagrid</code> in inconsistent cases must honor
-  the most recently returned values.</p>
+    <li>Fire the <code title="dom-listener-getRows">getRows()</code>
+    method for row 1, then fire it again for rows 5 and 6, and then
+    fire the <code title="dom-listener-getCells">getCells()</code>
+    method for the other rows (in all three cases, listing just column
+    C).</li>
 
-  <p>User agents may cache returned values so that the data provider
-  is never asked for data that could contradict earlier data. User
-  agents must not cache the return value of the <code
-  title="dom-provider-getRowMenu">getRowMenu</code> method.</p>
+   </ul>
 
-  <p>The exact algorithm used to populate the data grid is not defined
-  here, since it will differ based on the presentation used. However,
-  the behavior of user agents must be consistent with the
-  descriptions above. For example, it would be non-conformant for a
-  user agent to make cells have both a checkbox and be editable, as
-  the descriptions above state that cells that have a checkbox cannot
-  be edited.</p> <!-- XXX speaking of which, do we actually want that
-  limitation? -->
+   <p>The two options here are as bad as each other; the former
+   involves a lot of overlap, but the latter involves a lot of method
+   calls. Unfortunately the user agent can't do the obvious thing,
+   namely just to invoke the <code
+   title="dom-listener-getCells">getCells()</code> method for all the
+   rows listing just column C, because it doesn't have the row
+   information for all the rows yet (rows 1, 5 and 6 are still
+   pending).</p>
 
+   <p>In any case, the data model now looks like this:</p>
 
-  <h5>Updating the <code>datagrid</code></h5>
+   <table>
+    <tr> <td>        <th> Row     <th> Column A  <th> Column B  <th> Column C
+    <tr> <th> Row 1  <td> Pending <td> Pending   <td> Pending   <td> Pending
+    <tr> <th> Row 2  <td> Yes     <td> Yes       <td> Yes       <td> Pending
+    <tr> <th> Row 3  <td> Yes     <td> Yes       <td> Yes       <td> Pending
+    <tr> <th> Row 4  <td> Yes     <td> Yes       <td> Yes       <td> Pending
+    <tr> <th> Row 5  <td> Pending <td> Pending   <td> Pending   <td> Pending
+    <tr> <th> Row 6  <td> Pending <td> Pending   <td> Pending   <td> Pending
+    <tr> <th> Row 7  <td> Yes     <td> Pending   <td> Pending   <td> Pending
+    <tr> <th> Row 8  <td> Yes     <td> Pending   <td> Pending   <td> Pending
+   </table>
 
-  <p>Whenever the <code title="dom-datagrid-data">data</code>
-  attribute is set to a new value, the <code>datagrid</code> must
-  clear the current selection, remove all the displayed rows, and plan
-  to repopulate itself using the information from the new data
-  provider at the earliest opportunity.</p>
+   <p>If at this point the user scrolls around anywhere within this
+   <code>datagrid</code>, the user agent won't fire the <code
+   title="dom-listener-getRos">getRos()</code> and <code
+   title="dom-listener-getCells">getCells()</code> methods, because
+   all of the rows and cells are covered.</p>
 
-  <p>There are a number of update methods that can be invoked on the
-  <code>datagrid</code> element to cause it to refresh itself in
-  slightly less drastic ways:</p>
+   <p>Now consider the case where the user agent receives row
+   information, but no cell information, for rows 1, 5, and 6:</p>
 
-  <p>When the <dfn
-  title="dom-datagrid-updateEverything"><code>updateEverything()</code></dfn>
-  method is called, the user agent must repopulate the entire
-  <code>datagrid</code>. If the number of rows decreased, the
-  selection must be updated appropriately. If the number of rows
-  increased, the new rows should be left unselected.</p>
+   <table>
+    <tr> <td>        <th> Row     <th> Column A  <th> Column B  <th> Column C
+    <tr> <th> Row 1  <td> Yes     <td> Pending   <td> Pending   <td> Pending
+    <tr> <th> Row 2  <td> Yes     <td> Yes       <td> Yes       <td> Pending
+    <tr> <th> Row 3  <td> Yes     <td> Yes       <td> Yes       <td> Pending
+    <tr> <th> Row 4  <td> Yes     <td> Yes       <td> Yes       <td> Pending
+    <tr> <th> Row 5  <td> Yes     <td> Pending   <td> Pending   <td> Pending
+    <tr> <th> Row 6  <td> Yes     <td> Pending   <td> Pending   <td> Pending
+    <tr> <th> Row 7  <td> Yes     <td> Pending   <td> Pending   <td> Pending
+    <tr> <th> Row 8  <td> Yes     <td> Pending   <td> Pending   <td> Pending
+   </table>
 
-  <p>When the <dfn
-  title="dom-datagrid-updateRowsChanged"><code>updateRowsChanged(<var
-  title="">row</var>, <var title="">count</var>)</code></dfn> method
-  is called, the user agent must refresh the rendering of the rows
-  starting from the row specified by <var title="">row</var>, and
-  including the <var title="">count</var> next siblings of the row (or
-  as many next siblings as it has, if that is less than <var
-  title="">count</var>), including all descendant rows.</p>
+   <p>The user agent still won't fire any methods when the user
+   scrolls, because the data is still covered. But if the script then
+   calls the <code title="dom-datagrid-renotify">renotify()</code>
+   method, the "Pending" flags would get reset, and the model would
+   now look like this:</p>
 
-  <p>When the <dfn
-  title="dom-datagrid-updateRowsInserted"><code>updateRowsInserted(<var
-  title="">row</var>, <var title="">count</var>)</code></dfn> method
-  is called, the user agent must assume that <var title="">count</var>
-  new rows have been inserted, such that the first new row is
-  identified by <var title="">row</var>. The user agent must update
-  its rendering and the selection accordingly. The new rows should not
-  be selected.</p>
+   <table>
+    <tr> <td>        <th> Row     <th> Column A  <th> Column B  <th> Column C
+    <tr> <th> Row 1  <td> Yes     <td> -         <td> -         <td> -      
+    <tr> <th> Row 2  <td> Yes     <td> Yes       <td> Yes       <td> -      
+    <tr> <th> Row 3  <td> Yes     <td> Yes       <td> Yes       <td> -      
+    <tr> <th> Row 4  <td> Yes     <td> Yes       <td> Yes       <td> -      
+    <tr> <th> Row 5  <td> Yes     <td> -         <td> -         <td> -      
+    <tr> <th> Row 6  <td> Yes     <td> -         <td> -         <td> -      
+    <tr> <th> Row 7  <td> Yes     <td> -         <td> -         <td> -      
+    <tr> <th> Row 8  <td> Yes     <td> -         <td> -         <td> -      
+   </table>
 
-  <p>When the <dfn
-  title="dom-datagrid-updateRowsRemoved"><code>updateRowsRemoved(<var
-  title="">row</var>, <var title="">count</var>)</code></dfn> method
-  is called, the user agent must assume that <var title="">count</var>
-  rows have been removed starting from the row that used to be
-  identifier by <var title="">row</var>.  The user agent must update
-  its rendering and the selection accordingly.</p>
+   <p>Now, assuming that all eight rows and all three columns are
+   still visible, the user agent has the following choices (amongst
+   others):</p>
 
-  <p>The <dfn
-  title="dom-datagrid-updateRowChanged"><code>updateRowChanged(<var
-  title="">row</var>)</code></dfn> method must be exactly equivalent
-  to calling <code
-  title="dom-datagrid-updateRowsChanged">updateRowsChanged(<var
-  title="">row</var>, 1)</code>.</p>
+   <ul>
 
-  <p>When the <dfn
-  title="dom-datagrid-updateColumnChanged"><code>updateColumnChanged(<var
-  title="">column</var>)</code></dfn> method is called, the user agent
-  must refresh the rendering of the specified column <var
-  title="">column</var>, for all rows.</p>
+    <li>Fire the <code title="dom-listener-getRows">getCells()</code>
+    method for rows 1 through 8, listing all three columns.</li>
 
-  <p>When the <dfn
-  title="dom-datagrid-updateCellChanged"><code>updateCellChanged(<var
-  title="">row</var>, <var title="">column</var>)</code></dfn> method
-  is called, the user agent must refresh the rendering of the cell on
-  row <var title="">row</var>, in column <var
-  title="">column</var>.</p>
+    <li>Fire the <code title="dom-listener-getRows">getCells()</code>
+    method for rows 1 and 5 through 8, listing all three columns, and
+    then fire the method for rows 2 through 4, listing just column
+    C.</li>
 
-  <p>Any effects the update methods have on the
-  <code>datagrid</code>'s selection is not considered a change to the
-  selection, and must therefore not fire the <code
-  title="event-select">select</code> event.</p>
+    <li>Fire the <code title="dom-listener-getRows">getCells()</code>
+    method for rows 1 and 5 through 8, listing just columns A abd B,
+    and then fire the method for rows 1 through 8, listing just column
+    C.</li>
 
-  <p>These update methods should be called only by the data provider,
-  or code acting on behalf of the data provider. In particular,
-  calling the <code
-  title="dom-datagrid-updateRowsInserted">updateRowsInserted()</code>
-  and <code
-  title="dom-datagrid-updateRowsRemoved">updateRowsRemoved()</code>
-  methods without actually inserting or removing rows from the data
-  provider is <a href="#inconsistentDataProvider">likely to result in
-  inconsistent renderings</a>, and the user agent is likely to disable
-  the data grid.</p>
+   </ul>
 
+   <p>Here the latter two are preferable because they result in less
+   overlap than the first.</p>
 
-  <h5>Requirements for interactive user agents</h5>
+  </div>
 
-  <p><em>This section only applies to interactive user agents.</em></p>
+  <hr>
 
-  <p>If the <code>datagrid</code> element has a <dfn
-  title="attr-datagrid-disabled"><code>disabled</code></dfn>
-  attribute, then the user agent must disable the
-  <code>datagrid</code>, preventing the user from interacting with it.
-  The <code>datagrid</code> element should still continue to update
-  itself when the data provider signals changes to the data, though.
-  Obviously, conformance requirements stating that
-  <code>datagrid</code> elements must react to users in particular
-  ways do not apply when one is disabled.</p>
+  <p>The <span>task source</span> for tasks queued on behalf of a
+  <code>datagrid</code> is the <span>DOM manipulation task
+  source</span>.</p>
 
-  <p>If <a href="#rowType1">a row is openable</a>, then the user agent
-  should offer to the user the option of toggling the row's
-  open/closed state. When a row's open/closed state changes, the user
-  agent must update the rendering to match the new state.</p>
+  </div>
 
-  <p>If a cell is a cell whose value <a href="#cellType1">can be
-  cycled between multiple states</a>, then the user agent should allow
-  the user to activate the cell to cycle its value. When the user
-  activates this "cycling" behavior of a cell, then the
-  <code>datagrid</code> must invoke the data provider's <code
-  title="dom-provider-cycleCell">cycleCell()</code> method, with a
-  <code>RowSpecification</code> object representing the cell's row as
-  the first argument and the cell's column index as the second. The
-  <code>datagrid</code> must then act as if the
-  <code>datagrid</code>'s <code
-  title="dom-datagrid-updateCellChanged">updateCellChanged()</code>
-  method had been invoked with those same arguments.</p>
 
-  <p>When a cell <a href="#cellType2">has a checkbox</a>, the user
-  agent should allow the user to set the checkbox's state. When the
-  user changes the state of a checkbox in such a cell, the
-  <code>datagrid</code> must invoke the data provider's <code
-  title="dom-provider-setCellCheckedState">setCellCheckedState()</code>
-  method, with a <code>RowSpecification</code> object representing the
-  cell's row as the first argument, the cell's column index as the
-  second, and the checkbox's new state as the third. The state should
-  be represented by the number 1 if the new state is checked, 0 if the
-  new state is unchecked, and &#x2212;1 if the new state is
-  indeterminate (which must be possible only if the cell has the <code
-  title="datagrid-cell-class-indeterminate">indeterminate</code> class
-  set). The <code>datagrid</code> must then act as if the
-  <code>datagrid</code>'s <code
-  title="dom-datagrid-updateCellChanged">updateCellChanged()</code>
-  method had been invoked, specifying the same cell.</p>
+  <h5>Listening to notifications from the <code>datagrid</code></h5>
 
-  <p>If a cell <a href="#cellType2">is editable</a>, the user agent
-  should allow the user to edit the data for that cell, and doing so
-  must cause the user agent to invoke the <code
-  title="dom-provider-editCell">editCell()</code> method of the data
-  provider with three arguments: a <code>RowSpecification</code>
-  object representing the cell's row, the cell's column's index, and
-  the new text entered by the user. The user agent must then act as if
-  the <code
-  title="dom-datagrid-updateCellChanged">updateCellChanged()</code>
-  method had been invoked, with the same row and column specified.</p>
+  <p><em>The conformance criteria in this section apply to any
+  implementation of the <code>DataGridListener</code> interface,
+  including (and most commonly) the content author's
+  implementation(s).</em></p>
 
-  <!-- XXXPA <p class="XXX">define actions (performAction(), etc)</p> -->
+  <pre class="idl">// To be implemented by Web authors as a JS object
+[NoInterfaceObject] interface <dfn>DataGridListener</dfn> {
+  void <span title="dom-listener-initialize">initialize</span>(in <span>HTMLDataGridElement</span> datagrid);
 
+  void <span title="dom-listener-getRows">getRows</span>(in unsigned long rowIndex, in unsigned long rowCount, in <span>RowID</span> parentRow, in unsigned long position, in <span>ColumnList</span> columns);
+  void <span title="dom-listener-getCells">getCells</span>(in <span>RowIDList</span> rows, in <span>ColumnList</span> columns);
+  void <span title="dom-listener-rowOpened">rowOpened</span>(in <span>RowID</span> row, in boolean rowCountNeeded);
+  void <span title="dom-listener-rowClosed">rowClosed</span>(in <span>RowID</span> row);
+
+  void <span title="dom-listener-cellChanged">cellChanged</span>(in <span>RowID</span> row, in <span>Column</span> column, in any newValue, in any prevValue);
+  <span>HTMLMenuElement</span> <span title="dom-listener-getRowMenu">getRowMenu</span>(in <span>RowID</span> row);
+<!--vsDGDND
+  boolean <span title="dom-listener-canDrop">canDrop</span>(in <span>RowID</span> row, in <span>RowID</span> position, data);
+  boolean <span title="dom-listener-dropped">dropped</span>(in <span>RowID</span> row, in <span>RowID</span> position, data);
+--><!--v2DGPA
+  void <span title="dom-listener-performAction">performAction</span>(in <span>RowID</span> row, in DOMString action);
+-->};</pre>
+
+  <p>The <code>DataGridDataProvider</code> interface, once implemented
+  by an object in a script and hooked up to a <code>datagrid</code>
+  using the <dfn title="dom-datagrid-data"><code>data</code></dfn> DOM
+  attribute, receives notifications when the <code>datagrid</code>
+  needs information (such as which rows exist) for display.</p>
+
+  <p>The following methods may be usefully implemented:</p>
+
+  <dl>
+
+   <dt><dfn title="dom-listener-initialize"><code>initialize(<var title="">datagrid</var>)</code></dfn></dt>
+
+   <dd>
+
+    <p>Called by the <code>datagrid</code> element (the one given by
+    the <var title="">datagrid</var> argument) when the <code
+    title="dom-datagrid-listener">listener</code> attribute is
+    set.</p>
+
+   </dd>
+
+   <dt><dfn title="dom-listener-getRows"><code>getRows(<var title="">rowIndex</var>, <var title="">rowCount</var>, <var title="">parentRow</var>, <var title="">position</var>, <var title="">columns</var>)</code></dfn></dt>
+
+   <dd>
+
+    <p>Called by the <code>datagrid</code> element when the user agent
+    finds itself needing to render rows for which it is lacking
+    information.</p>
+
+    <p>The <var title="">rowIndex</var> argument gives the flattened
+    index of the first row for which it needs information, ignoring
+    the tree structure of the <code>datagrid</code> model, where zero
+    is the first row of the entire tree.</p>
+
+    <p>The <var title="">rowCount</var> argument gives the number of
+    rows for which the user agent would like information.</p>
+
+    <p>The <var title="">parentRow</var> argument gives the
+    <code>RowID</code> object identifying the nearest ancestor of the
+    first row that the user agent is aware of. After the sort order
+    has changed, this will typically be the root of the tree
+    (identified by a <code>RowID</code> object consisting of an empty
+    array).
+
+    <p>The <var title="">columns</var> argument gives the columns for
+    which the user agent is lacking information, as an array of column
+    identifiers (as passed to <code
+    title="dom-datagrid-addColumn">addColumn()</code>).</p>
+
+   </dd>
+
+   <dt><dfn title="dom-listener-getCells"><code>getCells(<var title="">rows</var>, <var title="">columns</var>)</code></dfn></dt>
+
+   <dd>
+
+    <p>Called by the <code>datagrid</code> element when the user agent
+    finds itself needing to render cells for which it is lacking
+    information in rows that it does know about.</p>
+
+    <p>The <var title="">rows</var> argument gives an array of
+    <code>RowID</code> objects identifying the various rows for which
+    the user agent is lacking information.</p>
+
+    <p>The <var title="">columns</var> argument gives the columns for
+    which the user agent is lacking information, as an array of column
+    identifiers (as passed to <code
+    title="dom-datagrid-addColumn">addColumn()</code>).</p>
+
+   </dd>
+
+   <dt><dfn title="dom-listener-rowOpened"><code>rowOpened(<var title="">row</var>, <var title="">rowCountNeeded</var>)</code></dfn></dt>
+
+   <dd>
+
+    <p>Called by the <code>datagrid</code> element when the user has
+    opened a row.</p>
+
+    <p>The <var title="">row</var> argument gives an
+    <code>RowID</code> object identifying the row that was opened.</p>
+
+    <p>If the user agent also knows how many children that row has,
+    then the <var title="">rowCountNeeded</var> argument will be
+    false. Otherwise, the argument will be true, and the row will
+    remain closed until the <code
+    title="dom-datagrid-setRows">setRows()</code> method is called
+    with an accurate row count.</p>
+
+   </dd>
+
+   <dt><dfn title="dom-listener-rowClosed"><code>rowClosed(<var title="">row</var>)</code></dfn></dt>
+
+   <dd>
+
+    <p>Called by the <code>datagrid</code> element when the user has
+    opened a row.</p>
+
+    <p>The <var title="">row</var> argument gives an
+    <code>RowID</code> object identifying the row that was closed.</p>
+
+   </dd>
+
+   <dt><dfn title="dom-listener-cellChanged"><code>cellChanged(<var title="">row</var>, <var title="">column</var>, <var title="">newValue</var>, <var title="">prevValue</var>)</code></dfn></dt>
+
+   <dd>
+
+    <p>Called by the <code>datagrid</code> element when the user has
+    edited a cell or checked a check box in a cell.</p>
+
+    <p>The <var title="">row</var> argument gives an
+    <code>RowID</code> object identifying the row of the cell, and the
+    <var title="">column</var> argument gives the identifier of the
+    cell's column.</p>
+
+    <p>The <var title="">newValue</var> argument gives the new value,
+    and the <var title="">prevValue</var> argument gives the previous
+    value.</p>
+
+   </dd>
+
+   <dt><dfn title="dom-listener-getRowMenu"><code>getRowMenu(<var title="">row</var>)</code></dfn></dt>
+
+   <dd>Must return an <code>HTMLMenuElement</code> object that is to
+   be used as a context menu for row <var title="">row</var>, or null
+   if there is no particular context menu. May be omitted if none of
+   the rows have a special context menu. As this method is called
+   immediately before showing the menu in question, no precautions
+   need to be taken if the return value of this method changes.</dd>
+
+   <!--v2DGDND, v2DFPA-->
+
+  </dl>
+
+  <div class="impl">
+
+  <p>Objects that implement the <code>DataGridListener</code>
+  interface may omit any or all of the methods. When a method is
+  omitted, a user agent intending to call that method must instead
+  skip the method call, and must assume that the method's return value
+  is null.</p>
+
+  </div>
+
+
+
+<!-- v2DGS: <datagrid> selection (search for the bits marked "..." to see what needs filling in, at a minimum)
+
   <h5>The selection</h5>
 
-  <p><em>This section only applies to interactive user agents. For
-  other user agents, the <code
-  title="dom-datagrid-selection">selection</code> attribute must
-  return null.</em></p>
-
   <pre class="idl">interface <dfn>DataGridSelection</dfn> {
-  readonly attribute unsigned long <span title="dom-DataGridSelection-count">length</span>;
-  [IndexGetter] <span>RowSpecification</span> <span title="dom-DataGridSelection-item">item</span>(in unsigned long index);
-  boolean <span title="dom-DataGridSelection-isSelected">isSelected</span>(in <span>RowSpecification</span> row);
-  void <span title="dom-DataGridSelection-setSelected">setSelected</span>(in <span>RowSpecification</span> row, in boolean selected);
-<!--  void <span title="dom-DataGridSelection-addRange">addRange</span>(in <span>RowSpecification</span> first, in <span>RowSpecification</span> last);
-  void <span title="dom-DataGridSelection-removeRange">removeRange</span>(in <span>RowSpecification</span> first, in <span>RowSpecification</span> last);
-XXX selection ranges -->
+  readonly attribute unsigned long <span title="dom-DataGridSelection-length">length</span>;
+  [IndexGetter] <span>RowID</span> <span title="dom-DataGridSelection-item">item</span>(in unsigned long index);
+  boolean <span title="dom-DataGridSelection-isSelected">isSelected</span>(in <span>RowID</span> row);
+  void <span title="dom-DataGridSelection-setSelected">setSelected</span>(in <span>RowID</span> row, in boolean selected);
   void <span title="dom-DataGridSelection-selectAll">selectAll</span>();
-  void <span title="dom-DataGridSelection-invert">invert</span>();
   void <span title="dom-DataGridSelection-clear">clear</span>();
 };</pre>
 
+  <dl class="domintro">
+
+   ...
+
+  </dl>
+
+  <div class="impl">
+
   <p>Each <code>datagrid</code> element must keep track of which rows
   are currently selected. Initially no rows are selected, but this can
-  be changed via the methods described in this section. <!--XXX
-  select-provider-selection The default data provider, for instance,
-  changes which rows are selected when it is first initialized.--></p>
+  be changed via the methods described in this section.</p>
 
   <p>The selection of a <code>datagrid</code> is represented by its
   <dfn title="dom-datagrid-selection"><code>selection</code></dfn> DOM
   attribute, which must be a <code>DataGridSelection</code> object.</p>
 
   <p><code>DataGridSelection</code> objects represent the rows in the
-  selection. In the selection the rows must be ordered in the natural
-  order of the data provider (and not, e.g., the rendered order). Rows
-  that are not rendered because one of their ancestors is closed must
-  share the same selection state as their nearest rendered
-  ancestor. Such rows are not considered part of the selection for the
-  purposes of iterating over the selection.</p>
+  selection. In the selection the rows must be ordered in their
+  natural order (and not, e.g., the display order). A row with an
+  ancestor that is closed cannot be selected.</p>
 
-  <p class="note">This selection API doesn't allow for hidden rows to
-  be selected because it is trivial to create a data provider that has
-  infinite depth, which would then require the selection to be
-  infinite if every row, including every hidden row, was selected.</p>
-
   <p>The <dfn
   title="dom-DataGridSelection-length"><code>length</code></dfn>
   attribute must return the number of rows currently present in the
@@ -41997,7 +42668,8 @@
   properties</span>.</p>
 
   <p>The <dfn title="dom-DataGridSelection-item"><code>item(<var
-  title="">index</var>)</code></dfn> method must return the <var
+  title="">index</var>)</code></dfn> method must return a
+  <code>RowID</code> object identifying the <var
   title="">index</var>th row in the selection. If the argument is out
   of range (less than zero or greater than the number of selected rows
   minus one), then it must raise an <code>INDEX_SIZE_ERR</code>
@@ -42006,8 +42678,9 @@
   <p>The <dfn
   title="dom-DataGridSelection-isSelected"><code>isSelected()</code></dfn>
   method must return the selected state of the row specified by its
-  argument. If the specified row exists and is selected, it must
-  return true, otherwise it must return false.</p>
+  argument. If the specified row is in the <span>natural order sparse
+  data tree</span> and is selected, the method must return true,
+  otherwise it must return false.</p>
 
   <p>The <dfn
   title="dom-DataGridSelection-setSelected"><code>setSelected()</code></dfn>
@@ -42015,116 +42688,51 @@
   title="">selected</var>. When invoked, it must set the selection
   state of row <var title="">row</var> to selected if <var
   title="">selected</var> is true, and unselected if it is false. If
-  <var title="">row</var> is not a row in the data grid, the method
-  must raise an <code>INDEX_SIZE_ERR</code> exception. If the
-  specified row is not rendered because one of its ancestors is
-  closed, the method must do nothing.</p>
+  <var title="">row</var> does not specify a row in the <span>natural
+  order sparse data tree</span> ...
 
   <p>The <dfn
   title="dom-DataGridSelection-selectAll"><code>selectAll()</code></dfn>
-  method must mark all the rows in the data grid as selected. After a
-  call to <code
-  title="dom-DataGridSelection-selectAll">selectAll()</code>, the
-  <code title="dom-DataGridSelection-length">length</code> attribute
-  will return the number of rows in the data grid, not counting
-  children of closed rows.</p>
+  method must ...
 
   <p>The <dfn
-  title="dom-DataGridSelection-invert"><code>invert()</code></dfn>
-  method must cause all the rows in the selection that were marked as
-  selected to now be marked as not selected, and vice versa.</p>
-
-  <p>The <dfn
   title="dom-DataGridSelection-clear"><code>clear()</code></dfn>
-  method must mark all the rows in the data grid to be marked as not
-  selected.  After a call to <code
+  method must mark all the rows in the <code>datagrid</code> as not
+  selected. After a call to <code
   title="dom-DataGridSelection-clear">clear()</code>, the <code
   title="dom-DataGridSelection-length">length</code> attribute will
   return zero.</p>
 
-  <p>If the <code>datagrid</code> element has a <dfn
-  title="attr-datagrid-multiple"><code>multiple</code></dfn>
-  attribute, then the user agent should allow the user to select any
-  number of rows (zero or more). If the attribute is not present, then
-  the user agent must not allow the user to select more than a single
-  row at a time, and selecting another one must unselect all the other
-  rows.</p>
+  <p>If the <code>datagrid</code> element has a <code
+  title="attr-datagrid-multiple">multiple</code> attribute, then the
+  user agent should allow the user to select any number of rows (zero
+  or more). If the attribute is not present, then the user agent
+  should allow the user to select a row, and must not allow the user
+  to select more than a single row at a time; selecting another one
+  must unselect all the other rows.</p>
 
   <p class="note">This only applies to the user. Scripts can select
   multiple rows even when the <code
   title="attr-datagrid-multiple">multiple</code> attribute is
   absent.</p>
 
-  <p>Whenever the selection of a <code>datagrid</code> changes,
-  whether due to the user interacting with the element, or as a result
-  of calls to methods of the <code
-  title="dom-datagrid-selection">selection</code> object, a <dfn
-  title="event-select"><code>select</code></dfn><!-- XXX check if we
-  really should be DFNing this here. It's a DOM3 Core event. What's
-  our story going to be regarding events and defining them? --> event
-  that bubbles but is not cancelable must be fired on the
-  <code>datagrid</code> element. If changes are made to the selection
-  via calls to the object's methods during the execution of a
-  script<!-- XXX should xref to a better explanation -->, then the
-  <code title="event-select">select</code> events must be coalesced
-  into one, which must then be fired<!--XXX xref again--> when the
-  script execution has completed<!-- XXX xref -->.</p>
+  ...event on selection change?...
 
+  </div>
+
   <p class="note">The <code>DataGridSelection</code> interface has no
   relation to the <code>Selection</code> interface.</p>
 
+-->
 
-  <h5>Columns and captions</h5>
 
-  <p><em>This section only applies to interactive user agents.</em></p>
-
-  <p>Each <code>datagrid</code> element must keep track of which
-  columns are currently being rendered. User agents should initially
-  show all the columns except those with the <code
-  title="datagrid-column-class-initially-hidden">initially-hidden</code>
-  class, but may allow users to hide or show columns. User agents
-  should initially display the columns in the order given by the data
-  provider, but may allow this order to be changed by the user.</p>
-
-  <p>If columns are not being used, as might be the case if the data
-  grid is being presented in an icon view, or if an overview of data
-  is being read in an aural context, then the text of the first column
-  of each row should be used to represent the row.</p>
-
-  <p>If none of the columns have any captions (i.e. if the data
-  provider does not provide a <code
-  title="dom-provider-getCaptionText">getCaptionText()</code> method),
-  then user agents may avoid showing the column headers at all. This
-  may prevent the user from performing actions on the columns (such as
-  reordering them, changing the sort column, and so on).</p>
-
-  <p class="note">Whatever the order used for rendering, and
-  irrespective of what columns are being shown or hidden, the "first
-  column" as referred to in this specification is always the column
-  with index zero, and the "last column" is always the column with the
-  index one less than the value returned by the <code
-  title="dom-provider-getcolumnCount">getColumnCount()</code> method
-  of the data provider.</p>
-
-  <p>If <a href="#columnType2">a column is sortable</a>, then the user
-  agent should allow the user to request that the data be sorted using
-  that column. When the user does so, then the <code>datagrid</code>
-  must invoke the data provider's <code
-  title="dom-provider-toggleColumnSortState">toggleColumnSortState()</code>
-  method, with the column's index as the only argument. The
-  <code>datagrid</code> must <em>then</em> act as if the
-  <code>datagrid</code>'s <code
-  title="dom-datagrid-updateEverything">updateEverything()</code>
-  method had been invoked.</p>
-
-<!--XXXDND
+<!--vsDGDND
   <h5>Drag and drop in <code>datagrid</code>s</h5>
 
   <p><em>This section only applies to interactive user agents.</em></p>
 
-  <p class="XXX">define drag and drop in datagrids; selectiondraggable, etc.</p>
+  ...define drag and drop in datagrids; selectiondraggable...
 -->
-</div>
 
 
   <h4 id="the-command">The <dfn><code>command</code></dfn> element</h4>
@@ -74606,6 +75214,7 @@
  XXX * should check all cases of 'active document' and change the
        relevant ones to 'fully active document'.
  XXX * use <code>Document</code> consistently instead of 'document'.
+ XXX * s/raise/throw/g
 -->
 
  </body>

|