W3C

HTML 5

A vocabulary and associated APIs for HTML and XHTML

← 4.10 FormsTable of contents5 Web browsers →

4.11 Interactive elements

4.11.1 The details element

Categories
Flow content.
Interactive content.
Contexts in which this element may be used:
Where flow content is expected.
Content model:
One legend element followed by flow content.
Content attributes:
Global attributes
open
DOM interface:
interface HTMLDetailsElement : HTMLElement {
           attribute boolean open;
};

The details element represents additional information or controls which the user can obtain on demand.

The details element is not appropriate for footnotes. Please see the section on footnotes for details on how to mark up footnotes.

The first element child of a details element, if it is a legend element, represents the summary of the details.

If the first element is not a legend element, the UA should provide its own legend (e.g. "Details").

The open content attribute is a boolean attribute. If present, it indicates that the details are to be shown to the user. If the attribute is absent, the details are not to be shown.

If the attribute is removed, then the details should be hidden. If the attribute is added, the details should be shown.

The user agent should allow the user to request that the details be shown or hidden. To honor a request for the details to be shown, the user agent must set the open attribute on the element to the value open. To honor a request for the details to be hidden, the user agent must remove the open attribute from the element.

The open attribute must reflect the open content attribute.

4.11.2 The datagrid element

Categories
Flow content.
Interactive content.
Sectioning root.
Contexts in which this element may be used:
Where flow content is expected.
Content model:
Either: Nothing.
Or: Flow content, but where the first element child node, if any, is not a table, select, or datalist element.
Or: A single table element.
Or: A single select element.
Or: A single datalist element.
Content attributes:
Global attributes
disabled
DOM interface:
interface HTMLDataGridElement : HTMLElement {
           attribute boolean multiple;
           attribute boolean disabled;
           attribute DataGridListener listener;

  // columns
  void addColumn(in Column id, in DOMString label, in DOMString type, [Optional] in HTMLImageElement icon, [Optional] in boolean sortable, [Optional] in boolean visible);
           attribute DOMString sortColumn;
           attribute boolean sortAscending;
  void clearColumns();

  // rows
  void renotify();
  void setRowCount(in long childCount, in long rowCount);
  void setRows(in RowList rows);
  void insertRows(in RowList rows);
  void deleteRows(in RowIDList rows);
  void repaint(in RowID row, in DOMString column);
  void clearRows();

};

typedef DOMString Column;
typedef sequence<Column> ColumnList;
typedef sequence<any> Cell; // Column, [Variadic] any (exact types expected depend on the column type)
typedef sequence<Cell> CellList;
typedef sequence<any> Row; // RowID, long, long, CellList, [Optional] boolean, [Optional] long
typedef sequence<Row> RowList;
typedef sequence<unsigned long> RowID;
typedef sequence<RowID> RowIDList;

[Callback=FunctionOnly, NoInterfaceObject]
interface RenderingContext2DCallback {
  DOMString handleEvent(in CanvasRenderingContext2D context, in unsigned long width, in unsigned long height);
};

The datagrid element represents an interactive representation of tree, list, or tabular data.

The data being presented is provided by script using the methods described in the following sections.

The disabled attribute is a boolean attribute used to disable the control. When the attribute is set, the user agent must disable the datagrid, preventing the user from interacting with it. The datagrid 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 datagrid elements must react to users in particular ways do not apply when the datagrid is disabled.

The disabled DOM attribute must reflect the content attribute of the same name.

4.11.2.1 Introduction

This section is non-normative.

In the datagrid 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 might be hidden in the presentation.


Each row can have child rows. Child rows may be hidden or shown, by closing or opening (respectively) the parent row.

Rows are referred to by the path along the tree that one would take to reach the row, using zero-based indices. Thus, the first row of a list is row "0", the second row is row "1"; the first child row of the first row is row "0,0", the second child row of the first row 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.

The chains of numbers that give a row's path, or identifier, are represented by arrays of positions, represented in IDL by the RowID interface.

The root of the tree is represented by an empty array.


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.

The possible types are as follows:

Keyword Description
text Simple text.
editable Editable text.
checkable Text with a check box.
list A list of values that the user can switch between.
progress A progress bar.
meter A gauge.
custom A canvas onto which arbitrary content can be drawn.

Each column can be flagged as sortable, in which case the user will be able to sort the view using that column.

Columns are not necessarily visible. A column can be created invisible by default. The user can select which columns are to be shown.

When no columns have been added to the datagrid, a column with no name, whose identifier is the empty string, whose type is text, and which is not sortable, is implied. This column is removed if any explicit columns are declared.

Each cell uses the type given for its column, so all cells in a column present the same type of information.

4.11.2.1.1 Example: a datagrid backed by a static table element

...

4.11.2.1.2 Example: a datagrid backed by nested ol elements

...

4.11.2.1.3 Example: a datagrid backed by a server

...

4.11.2.2 Populating the datagrid
datagrid . listener [ = value ]

Return the current object that is configured as the datagrid listener, if any. Returns null if there is none.

The listener is an object provided by the script author that receives notifications when the datagrid 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 DataGridListener interface used for this purpose is described in the next section.)

Can be set, to change the current listener.

datagrid . renotify()

Causes the datagrid to resend notifications to the listener (if any) for any rows or cells that the datagrid does not yet have information for.

datagrid . addColumn(id, label, type [, icon [, sortable [, visible ] ] ] )

Adds a column to the datagrid.

If a column with the given identifier has already been added, it just replaces the information for that column.

The possible types are enumerated in the previous section.

datagrid . sortColumn [ = value ]

Returns the identifier of the column by which the data is to be sorted.

Can be set, to indicate that the sort order has changed. This will cause the datagrid to clear its position information for rows, so setRows() will have to be called again with the new sort order.

The columns are not actually sorted by the datagrid; the data has to be sorted by the script that adds the rows to the datagrid.

datagrid . sortAscending [ = value ]

Returns true if the data is to be sorted with smaller values first; otherwise, returns false, indicating that bigger values are to be put first.

Can be set, to indicate that the order is about to change.

datagrid . clearColumns()

Removes all the columns in the datagrid, reinstating the implied column.

datagrid . setRowCount(childCount, rowCount)

Sets the numbers of rows in the datagrid, excluding rows that are descendants of rows that are closed.

Throws a DATAGRID_MODEL_ERR exception if the arguments contradict each other or previously declared information (e.g. declaring that the datagrid has three rows when the 12th row has been declared).

datagrid . setRows(rows)

Updates data for rows in the datagrid, or fills in data for rows previously implied by a call to setRowCount() but not previously declared.

The rows argument is an array of rows, each represented by a further array consisting of:

  1. A RowID object identifying the row.
  2. An integer giving the position of the row in its parent, given the current sort order, or −1 to set other row data without setting a position or changing a previously declared position.
  3. An integer giving the number of children of the row, or 0 if the row has no children, or −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 −1 leaves the previous count unchanged.
  4. An array giving the data for zero or more cells in the row, as described below.
  5. 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.
  6. 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.

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:

text
  1. A string giving the cell's value.
  2. Optionally, an img element giving an icon for the cell.
editable
  1. A string giving the cell's value.
  2. Optionally, a datalist element giving a set of predefined options.
  3. Optionally, an img element giving an icon for the cell.
checkable
  1. A string giving the cell's value.
  2. A boolean, indicating whether the cell is checked (true) or not (false).
  3. Optionally, a boolean indicating whether the value of the cell is obscured as indeterminate (true), or not (false).
  4. Optionally, an img element giving an icon for the cell.
list
  1. A string giving the cell's current value.
  2. A select element giving the list of options.
  3. Optionally, an img element giving an icon for the cell.
progress
  1. A value in the range 0.0 (no progress) to 1.0 (task complete).
meter
  1. A number giving the cell's value.
  2. Optionally, a number giving the maximum value, if it's not 1.
  3. Optionally, a number giving the minimum value, if it's not 0.
  4. Optionally, a number giving the highest value that is considered "low".
  5. Optionally, a number giving the lowest value that is considered "high".
  6. Optionally, a number giving the value that is considered optimal.
custom
  1. A number giving the minimum width of the cell, in CSS pixels, that is desired.
  2. A number giving the minimum height of the cell, in CSS pixels, that is desired.
  3. A function that is passed a CanvasRenderingContext2D object, along with the width and height (in CSS pixels) of the cell that the context will draw on.

While the rows in a single call to the setRows() 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.

Throws a DATAGRID_MODEL_ERR 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).

datagrid . insertRows(rows)

Inserts the given rows into the datagrid, increasing the numbers of rows that the datagrid assumes are present.

The rows argument is an array of rows in the same structure as the argument to the setRows() 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 setRows() 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 rows argument will increase its parent's counts automatically.

Throws a DATAGRID_MODEL_ERR exception if the arguments contradict each other or previously declared information.

datagrid . deleteRows(rows)

Removes the given rows from the datagrid, and updates the number of rows known to be in the datagrid accordingly. The argument is an array of RowID objects identifying the rows to remove.

Throws a DATAGRID_MODEL_ERR exception if the argument includes a row the datagrid doesn't know about.

datagrid . repaint(row, column)

If the given column's type is custom, then causes the datagrid to reinvoke the function that obtains the desired rendering.

datagrid . clearRows()

Clears the datagrid of all row data, resetting it to empty.

4.11.2.2.1 The listener

The listener DOM attribute allows authors to specify an object that will receive all the notifications from the datagrid. 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 queue a task to call the initalize() method with the datagrid element as its only argument.

4.11.2.2.2 The columns

The columns are represented by the column list, an ordered list of entries for columns, each of which consists of:

An identifier
A string used to identify the column in the API.
A label
A string used in the user interface.
A type
One of the types described below.
An icon
An image, copied from an img element when the column was declared.
Whether the column is sortable
A boolean indicating whether the user can request that the data be sorted by this column (true), or not (false).
Whether the column is visible
A boolean indicating whether the column is part of the datagrid's rendering.

Initially, the column list must have a single column, the default column, whose identifier is the empty string, whose label is the empty string, whose type is text, with no icon, which is not sortable, and which is visible.


The addColumn(id, label, type, icon, sortable, visible) method must run the following steps:

  1. If there is already an entry in column list, other than the default column, whose identifier is id, throw a DATAGRID_MODEL_ERR exception and abort these steps.

  2. If type is not a string equal to one of the allowed datagrid column types, then throw a DATAGRID_MODEL_ERR exception and abort these steps.

  3. If the icon argument is present and not null, and the given img element's complete attribute is false, then throw an INVALID_STATE_ERR exception and abort these steps.

  4. If the icon argument is present and not null, then copy the image data from that img element, and let image be the copy of that image data. Otherwise, let image be nothing.

  5. Append a new entry to the column list, with id as its identifier, label as its label, type as its type, and image as its icon. Let the column be sortable if the sortable argument is present and true, and make it visible if the visible argument is absent or true.

  6. If the column list contains the default column, then remove the default column from the column list, discard any data for cells in that column in any rows in the datagrid, set sortColumn to id, set sortAscending to true, and run the datagrid resort steps.


The sortColumn 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 column list, then the user agent must throw a DATAGRID_MODEL_ERR 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 datagrid resort steps.

The sortAscending 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 datagrid resort steps.

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.

When the user changes the sort order in this manner, the user agent must update the sortColumn and sortAscending attributes appropriately, and then run the datagrid resort steps.

The datagrid resort steps are described in the next section.


The clearColumns() method, if the column list doesn't contain the default column, must empty the column list, append the default column to the now empty column list, discard any data for cells in all rows in the datagrid, set sortColumn to the empty string, set sortAscending to true, and run the datagrid resort steps. (If the column list is already just the default column, then the method does nothing.)

4.11.2.2.3 The rows

A datagrid 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.

To make this efficient, the datagrid element actually shows a small part of a sparse 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.

Conceptually, therefore, a datagrid has a number of related sparse data structures backing it.

The first is the natural order sparse data tree. 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 natural order sparse data tree, 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 deleteRows() and clearRows() 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.

The second structure is the display order sparse data tree. This is a similar structure that contains a subset of the rows in the natural order sparse data tree, ordered in the order given by the sortAscending and sortColumn attributes, and excluding rows with one or more ancestors that are closed. This tree is cleared whenever the sortAscending and sortColumn attributes change.

The third structure is the display order sparse data list. This structure is a flattened representation of the display order sparse data tree.

At any time, a number of consecutive rows in the display order sparse data list are physically visible to the user. The datagrid fires notifications to a listener (provided by script), and the listener, or other some script, is expected to feed the datagrid with the information needed to render the control.

A datagrid has a pending datagrid rows list, which is a list of rows in the display order sparse data list for which the datagrid has sent notifications requesting information but not yet received information about.

A datagrid also has a pending datagrid cells list, which is a list of row/column pairs (cells) for which the datagrid has sent notifications requesting information but not yet received information about.

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.


These structures are different views of the collection of rows that form the datagrid. Each row has the following information associated with it:

A parent

Either another row, or the datagrid itself. This is the parent of the row in the natural order sparse data tree and the display order sparse data tree for the datagrid.

A natural order position relative to the other rows with the same parent

This is the number of rows that precede this row under the same parent in the natural order sparse data tree. This number can't be changed relative to other rows in the same parent; to change the relative natural order of data in the datagrid, 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.)

A row can be identified by a RowID 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 datagrid would be identified by a RowID object whose value is [1, 0, 3]. A row's identifier changes if rows are inserted before it in the datagrid.

A display order position relative to the other rows with the same parent

This is the number of rows that precede this row under the same parent in the display order sparse data tree. This number can be unknown. If the sort order changes, then this information is lost (as the display order sparse data tree is cleared).

A child count

The number of rows that have this row as a parent. If this is zero, the row cannot be opened. If this is −1, then the child count is unknown but the row can be opened. This value can be changed by the setRows() method only if the current value is −1 or if the row or one of its ancestors is closed. Otherwise, it can only be changed indirectly using the insertRows() and deleteRows() methods.

An open flag

A boolean indicating whether the row is open (true) or closed (false). Once set, the flag can only be changed by the user or while 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.

A row count

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 −1, then the row count is unknown. This value can be changed by the setRows() 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 insertRows() and deleteRows() methods.

Cells

The data that applies to this row. Cell data is discussed in more detail below.

The datagrid itself also has a child count and a row count, which are analogous to the child counts and row counts for rows. Initially, these must be zero.


The datagrid resort steps, which are invoked when the sort order changes as described in the previous section, are as follows:

  1. Clear the display order sparse data tree (i.e. mark the display order position of all the rows in the datagrid as unknown).

    User agents may cache the position information of rows for various values of sortColumn and sortAscending, instead of discarding the information altogether. If the user agent caches this information, and has information that applies to the current values of sortColumn and sortAscending, then the user agent may repopulate the display order sparse data tree from this information.

  2. Clear the pending datagrid rows list and the pending datagrid cells list.

  3. Invoke the datagrid update display algorithm.


The renotify() method must empty the pending datagrid rows list and the pending datagrid cells list, and invoke the datagrid update display algorithm.


The setRowCount(childCount, rowCount) method must run the following steps:

  1. Set the datagrid child count to childCount, the datagrid row count to rowCount.

  2. Audit the datagrid. If this fails, then revert the changes made in the previous step, throw a DATAGRID_MODEL_ERR exception, and abort these steps.

  3. Invoke the datagrid update display algorithm.


The setRows(rows) method must run the following steps:

  1. Type-check the rows argument. If this fails, throw a TypeError exception, and abort these steps.

  2. Partially sort the rows argument.

  3. For each Row object in the rows argument, in order, perform the appropriate steps from the list below.

    The changes made to the datagrid's data structures in this step get reverted (as required below) if any consistency errors are detected either in this step or the next.

    If there already exists a row in the datagrid's natural order sparse data tree with the same identifier as given by the Row object's RowID object, and that row and all its ancestors are open

    If one of the following conditions is true, then revert all the changes done in this step, throw a DATAGRID_MODEL_ERR exception, and abort these steps:

    • The value of the Row object's second entry is neither −1 nor equal to the child count of the preexisting row.
    • The Row object has fewer than four entries or more than six entries.
    • The Row object has five or more entries, and its fifth entry is false.
    • The Row object has six entries, and its sixth entry is not equal to the row count of the preexisting row.
    If there already exists a row in the datagrid's natural order sparse data tree with the same identifier as given by the Row object's RowID object, but either that row or one of its ancestors is closed

    Set the preexisting row's child count to the value of the Row object's second entry.

    If the Row 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 DATAGRID_MODEL_ERR exception, and abort these steps; otherwise, if the fifth entry is false, then close the row; otherwise, open the row.

    If the Row object has six entries, set the preexisting row's row count to the value of the Row object's sixth entry.

    If the preexisting row is opening, then: increase the datagrid row count 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.

    There does not exist a row in the datagrid's natural order sparse data tree with the same identifier as given by the Row object's RowID object

    If the RowID object has a length greater than 1, then verify that there is a row identified by the RowID consisting of all but the last number in the Row object's RowID. If there is no such row present in the natural order sparse data tree, then revert all the changes done in this step, throw a DATAGRID_MODEL_ERR exception, and abort these steps.

    Create a row and insert it into the natural order sparse data tree, such that its parent is the row identified by the RowID consisting of all but the last number in the Row object's RowID, or the datagrid if the length of the Row object's RowID is 1; with its natural order position being the last number of the Row object's RowID; with the child count being the value of the third entry of the Row object; with the row being marked closed unless the Row 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 −1 unless the Row object has six entries, in which case the row count is equal to the value of the Row object's sixth entry.

  4. Audit the datagrid. If this fails, then revert the changes made in the previous step, throw a DATAGRID_MODEL_ERR exception, and abort these steps.

  5. For each Row object in the rows argument, in order, apply the Row object.

  6. Invoke the datagrid update display algorithm.


The insertRows(rows) method must run the following steps:

  1. Type-check the rows argument. If this fails, throw a TypeError exception, and abort these steps.

  2. Partially sort the rows argument.

  3. For each Row object in the rows argument, in order, run the following steps:

    The changes made to the datagrid's data structures in this step get reverted (as required below) if any consistency errors are detected either in this step or the next.

    1. Let parent be the row identified by the RowID consisting of all but the last number in the Row object's RowID, or the datagrid itself if the Row object's RowID has length 0.

      If there is no such row present in the natural order sparse data tree, then revert all the changes done in this algorithm, throw a DATAGRID_MODEL_ERR exception, and abort these steps.

    2. Increment by one the natural order position of all rows whose parent is parent and whose natural order position is equal to or greater than the last number of the Row object's RowID.

    3. If the value of the Row object's second entry is not −1, then increment by one the display order position of all rows whose parent is parent and whose display order position is equal to or greater than the value of the Row object's second entry.

    4. Create a row and insert it into the natural order sparse data tree, such that its parent is parent; with its natural order position being the last number of the Row object's RowID; with the child count being the value of the third entry of the Row object; with the row being marked closed unless the Row 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 −1 unless the Row object has six entries, in which case the row count is equal to the value of the Row object's sixth entry.

  4. For each Row object in the rows argument, in order, apply the Row object.

  5. Invoke the datagrid update display algorithm.


When an algorithm requires the user agent to type-check a RowList object (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.

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. [ECMA262]

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. [ECMA262]

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. [ECMA262]

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. [ECMA262]


When an algorithm requires the user agent to audit the datagrid, the datagrid must be checked against the following requirements. If any are false, then the audit fails, otherwise it passes.

For the purposes of this audit, the datagrid must be treated as the parent row of all the rows that are direct children of the datagrid in the natural order sparse data tree and the display order sparse data tree. The child count of this implied row is the datagrid child count, and the row count of this implied row is the datagrid row count.


When an algorithm requires the user agent to partially sort a RowList object (an array), the entries in the object must be resorted such that Row objects are listed after any of their ancestors and after any of their earlier siblings. In other words, for any two Row objects a and b in the RowList, where a is before b after the sort, the following conditions must hold:


The deleteRows(rows) method must run the following steps:

  1. If any of the entries in rows are not RowID objects consisting of one or more entries whose values are all integers that are greater than or equal to zero, then throw a TypeError exception and abort these steps.

    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. [ECMA262]

  2. If any of the RowID objects in the rows argument identify a row that isn't present in the natural order sparse data tree, then throw a DATAGRID_MODEL_ERR exception and abort these steps.

  3. If any row is listed twice in the rows argument, then throw a DATAGRID_MODEL_ERR exception and abort these steps.

  4. Sort the rows 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 natural order sparse data tree.

  5. For each row identified by entries in rows, in reverse order, run the following steps:

    1. 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 datagrid child count.

      If the row has a parent row, and its child count is now zero, then close that row.

    2. Let delta be one more than the row's row count if the row is open and its row count is greater than zero; otherwise, let delta be one.

    3. Let ancestor be the row.

    4. Row count loop: Let ancestor be ancestor's parent row, if any, or null if it has none.

    5. If ancestor is null, then decrement the datagrid row count by delta. Otherwise, if ancestor is open, then decrement its row count by delta.

    6. If ancestor is not null, then jump back to the step labeled row count loop above.

    7. Let parent be the row's parent, or the datagrid if the row has no parent.

    8. Decrement by one the natural order position of all rows whose parent is parent and whose natural order position is equal to or greater than the row's own natural order position.

    9. If the row is in the display order sparse data tree, then decrement by one the display order position of all rows whose parent is parent and whose display order position is equal to or greater than the row's own display order position.

    10. Clear the row and its descendants from the Datagrid.

  6. Invoke the datagrid update display algorithm.


The clearRows() method must empty the natural order sparse data tree, reset both the datagrid child count and the datagrid row count to zero, and invoke the datagrid update display algorithm.


The repaint(row, column) method must cause the user agent to clear its cache for the cell specified by the identifier row and the column column, if that column's type is custom. If the given column has not been declared, or its type is not custom, then the user agent must throw a DATAGRID_MODEL_ERR 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 RenderingContext2DCallback callback when it needs to repaint that row.


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.

When a row is opened, if the row's row count is greater than zero, then the user agent must increase the datagrid row count and the row counts of any ancestor rows by the number of rows that the newly opened row has in its row count, then must mark the row as open, then may fill in the display order sparse data tree 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 rowOpened() method on the current listener with as its first argument a RowID object identifying the row that was opened and as its second argument the boolean false, and then must invoke the datagrid update display algorithm.

On the other hand, when a row is opened and the row's row count is −1, then the user agent must mark the row as opening, and then must invoke the rowOpened() method on the current listener with as its first argument a RowID object identifying the row that was opened and as its second argument the boolean true.

When a row is closed, the user agent must decrease the datagrid row count 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 rowOpened() method on the current listener with as its first and only argument a RowID object identifying the row that was opened.

4.11.2.2.4 The cells

Each row has one cell per column. Each cell has the same type as its column. The allowed datagrid column types, what they represent, and the requirements for when the user interacts with them, are as follows:

text

The cell represents some text and an optional image.

editable

The cells represents some editable text, an optional datalist giving autocompletion hints, and an optional image.

If there is a datalist element, the user agent should offer the suggestions represented by that element to the user. The user agent may use the suggestion's label to identify the suggestion. If the user selects a suggestion, then the editable text must be set to the selected suggestion's value, as if the user had written that value himself.

When the user edits the value, either directly or using the datalist, the user agent must invoke the cellChanged() method on the current listener with as its first argument a RowID 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.

checkable

The cell represents some text, a check box that optionally has its value obscured as indeterminate, and an optional image.

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 cellChanged() method on the current listener with as its first argument a RowID 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.

list

The cell represents some text giving the current value selected from a dropdown list of options, a select element giving the list of options, and an optional image.

The user agent should allow the user to change the value of the cell from its current value to one of the values given by option elements in the list of options (if any). The user agent may use the option elements' labels to annotate each option.

When the user selects a new value from the select element's list of options, the user agent must invoke the cellChanged() method on the current listener with as its first argument a RowID 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.

progress

The cell represents a (determinate) progress bar whose value is between 0.0, indicating no progress, and 1.0, indicating the task is complete.

meter

The cell represents a gauge, described by one to six numbers.

The gauge's actual value is given by the first number.

If there is a second number, then that number is the maximum value. Otherwise, the maximum value is 1.0.

If there is a third number, then that number is the minimum value. Otherwise, the minimum value is 1.0.

If there is a fourth number, then that number is the low boundary. Otherwise, the low boundary is the minimum value.

If there is a fifth number, then that number is the high boundary. Otherwise, the high boundary is the maximum value.

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.

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.

User agents should indicate the relative position of the actual value to the minimum and maximum values, and the relationship between the actual value and the three regions of the gauge.

custom

The cell represents a dynamically generated graphical image.

The cell will have minimum dimensions (specified in CSS pixels), and a callback (in the form of a RenderingContext2DCallback object) to get a rendering for the cell.

The user agent should not allow the cell to be rendered with dimensions less than the given minimum width and height.

When the user agent needs to render the cell, the user agent must queue a task to invoke the RenderingContext2DCallback callback, passing it a newly created CanvasRenderingContext2D object whose canvas 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.

If the user agent is able to render graphics, then it must render the graphics commands that the callback executed on the provided CanvasRenderingContext2D 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 x dimension towards the right of the cell and its y 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 used by the 2D context).

The user agent must then decouple the CanvasRenderingContext2D object and any objects that it created (such as CanvasPattern objects or ImageData objects) from any real drawing surface.

If the user agent is unable to render graphics, then it must render the text string returned by the callback instead.


When an algorithm requires the user agent to apply a Row object, the user agent must run the following steps:

  1. If the value of the Row object's second entry is not −1, then run these substeps:

    1. If there is a row with the same parent as the row specified by the Row object's RowID object, whose display order position is currently the same as the value of the Row object's second entry, then remove that row from the display order sparse data tree.

    2. Set the display order position of the row specified by the Row object's RowID to the value of the Row object's second entry, updating its position in the display order sparse data tree accordingly.

    3. If the row is in the pending datagrid rows list, remove it.

  2. If the fourth entry in the Row object (a CellList object, an array) is not empty, then for each Cell object in that array update the cell that corresponds to the column identified by the value of the first entry of the Cell 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 pending datagrid cells list, remove it.

    If the column's type is text

    Update the cell's text to the value given in the Cell object's second entry.

    If the Cell object has three entries, then copy the image data from the img 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.

    If the column's type is editable

    Update the cell's text to the value given in the Cell object's second entry.

    If the Cell object has three entries, then let the datalist element given in the third entry be the datalist element giving autocompletion hints. Otherwise, update the cell to have no datalist element.

    If the Cell object has four entries, then copy the image data from the img 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.

    If the column's type is checkable

    Update the cell's text to the value given in the Cell object's second entry.

    Update the cell's checked state to match the value of the third entry: checked if true, unchecked otherwise.

    If the Cell 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.

    If the Cell object has five entries, then copy the image data from the img 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.

    If the column's type is list

    Update the cell's text to the value given in the Cell object's second entry, and the select element to be the one given in the Cell object's third entry

    If the Cell object has four entries, then copy the image data from the img 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.

    If the column's type is progress

    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 Cell object's second entry.

    If the column's type is meter

    Update the cell to be a gauge configured with the numbers given by the second and subsequent entries of the Cell object.

    If the column's type is custom

    Update the cell's minimum width to be the length in CSS pixels given by the Cell object's second entry.

    Update the cell's minimum height to be the length in CSS pixels given by the Cell object's third entry.

    Update the cell's callback to be the RenderingContext2DCallback object given by the Cell object's fourth entry.


When the user agent is to run the datagrid update display algorithm, the user agent must invoke the getRows() and getCells() methods on the current listener such that all the current visible rows in the display order sparse data list, and all the cells in the currently visible columns on all the currently visible rows, have been covered.

A row is considered covered if it is present in the pending datagrid rows list, or if the getRows() method is invoked with a range that includes the row in question.

A cell is considered covered if it is present in the pending datagrid cells list, or if the getRows() 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 getCells() method is invoked with a list of rows and columns that intersects the cell in question. However, the getCells() method can only be used if the row is already present in the display order sparse data list.

The getRows() method, if used, must be invoked with five arguments. The first argument must be the index in the display order sparse data list to the first row that the user agent is requesting, known as the anchor row. The second argument must be the number of consecutive cells for which the user agent is requesting information. The third argument must be the RowID of the row that is the nearest ancestor in the display order sparse data tree of the anchor row. If this is the datagrid, then the RowID object must be an empty array. The fourth argument must be the display order position of the anchor row in the display order sparse data tree, 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 datagrid.

As the getRows() method is invoked, the pending datagrid rows list must be updated to include the rows for which information has been requested, excluding rows for which information is already available; and the pending datagrid cells list must be updated to include the cells for which information has been requested on those rows.

The getCells() method, if used, must be invoked with two arguments. The first argument must be an array of RowID 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 datagrid.

As the getCells() method is invoked, the pending datagrid cells list must be updated to include the cells for which information has been requested.

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 getRows() method for a set of rows that includes some rows that are already in the display order sparse data list, and similarly may invoke the getCells() 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.

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.

Row Column A Column B
Row 1 - - -
Row 2 Yes Yes Yes
Row 3 Yes Yes Yes
Row 4 Yes Yes Yes
Row 5 - - -
Row 6 - - -
Row 7 Yes Pending -
Row 8 Yes Pending Pending

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.

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:

All three options are allowed, but the latter two are preferable to the former, as they minimise the amount of redundant information requested.

In any case, the data model now looks like this:

Row Column A Column B Column C
Row 1 Pending Pending Pending -
Row 2 Yes Yes Yes -
Row 3 Yes Yes Yes -
Row 4 Yes Yes Yes -
Row 5 Pending Pending Pending -
Row 6 Pending Pending Pending -
Row 7 Yes Pending Pending -
Row 8 Yes Pending Pending -

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:

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 getCells() 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).

In any case, the data model now looks like this:

Row Column A Column B Column C
Row 1 Pending Pending Pending Pending
Row 2 Yes Yes Yes Pending
Row 3 Yes Yes Yes Pending
Row 4 Yes Yes Yes Pending
Row 5 Pending Pending Pending Pending
Row 6 Pending Pending Pending Pending
Row 7 Yes Pending Pending Pending
Row 8 Yes Pending Pending Pending

If at this point the user scrolls around anywhere within this datagrid, the user agent won't fire the getRos() and getCells() methods, because all of the rows and cells are covered.

Now consider the case where the user agent receives row information, but no cell information, for rows 1, 5, and 6:

Row Column A Column B Column C
Row 1 Yes Pending Pending Pending
Row 2 Yes Yes Yes Pending
Row 3 Yes Yes Yes Pending
Row 4 Yes Yes Yes Pending
Row 5 Yes Pending Pending Pending
Row 6 Yes Pending Pending Pending
Row 7 Yes Pending Pending Pending
Row 8 Yes Pending Pending Pending

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 renotify() method, the "Pending" flags would get reset, and the model would now look like this:

Row Column A Column B Column C
Row 1 Yes - - -
Row 2 Yes Yes Yes -
Row 3 Yes Yes Yes -
Row 4 Yes Yes Yes -
Row 5 Yes - - -
Row 6 Yes - - -
Row 7 Yes - - -
Row 8 Yes - - -

Now, assuming that all eight rows and all three columns are still visible, the user agent has the following choices (amongst others):

Here the latter two are preferable because they result in less overlap than the first.


The task source for tasks queued on behalf of a datagrid is the DOM manipulation task source.

4.11.2.3 Listening to notifications from the datagrid

The conformance criteria in this section apply to any implementation of the DataGridListener interface, including (and most commonly) the content author's implementation(s).

// To be implemented by Web authors as a JS object
[NoInterfaceObject] interface DataGridListener {
  void initialize(in HTMLDataGridElement datagrid);

  void getRows(in unsigned long rowIndex, in unsigned long rowCount, in RowID parentRow, in unsigned long position, in ColumnList columns);
  void getCells(in RowIDList rows, in ColumnList columns);
  void rowOpened(in RowID row, in boolean rowCountNeeded);
  void rowClosed(in RowID row);

  void cellChanged(in RowID row, in Column column, in any newValue, in any prevValue);
  HTMLMenuElement getRowMenu(in RowID row);
};

The DataGridDataProvider interface, once implemented by an object in a script and hooked up to a datagrid using the data DOM attribute, receives notifications when the datagrid needs information (such as which rows exist) for display.

The following methods may be usefully implemented:

initialize(datagrid)

Called by the datagrid element (the one given by the datagrid argument) when the listener attribute is set.

getRows(rowIndex, rowCount, parentRow, position, columns)

Called by the datagrid element when the user agent finds itself needing to render rows for which it is lacking information.

The rowIndex argument gives the flattened index of the first row for which it needs information, ignoring the tree structure of the datagrid model, where zero is the first row of the entire tree.

The rowCount argument gives the number of rows for which the user agent would like information.

The parentRow argument gives the RowID 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 RowID object consisting of an empty array).

The columns argument gives the columns for which the user agent is lacking information, as an array of column identifiers (as passed to addColumn()).

getCells(rows, columns)

Called by the datagrid element when the user agent finds itself needing to render cells for which it is lacking information in rows that it does know about.

The rows argument gives an array of RowID objects identifying the various rows for which the user agent is lacking information.

The columns argument gives the columns for which the user agent is lacking information, as an array of column identifiers (as passed to addColumn()).

rowOpened(row, rowCountNeeded)

Called by the datagrid element when the user has opened a row.

The row argument gives an RowID object identifying the row that was opened.

If the user agent also knows how many children that row has, then the rowCountNeeded argument will be false. Otherwise, the argument will be true, and the row will remain closed until the setRows() method is called with an accurate row count.

rowClosed(row)

Called by the datagrid element when the user has opened a row.

The row argument gives an RowID object identifying the row that was closed.

cellChanged(row, column, newValue, prevValue)

Called by the datagrid element when the user has edited a cell or checked a check box in a cell.

The row argument gives an RowID object identifying the row of the cell, and the column argument gives the identifier of the cell's column.

The newValue argument gives the new value, and the prevValue argument gives the previous value.

getRowMenu(row)
Must return an HTMLMenuElement object that is to be used as a context menu for row row, 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.

Objects that implement the DataGridListener 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.

4.11.3 The command element

Categories
Metadata content.
Flow content.
Phrasing content.
Contexts in which this element may be used:
Where metadata content is expected.
Where phrasing content is expected.
Content model:
Empty.
Content attributes:
Global attributes
type
label
icon
disabled
checked
radiogroup
default
Also, the title attribute has special semantics on this element.
DOM interface:
interface HTMLCommandElement : HTMLElement {
           attribute DOMString type;
           attribute DOMString label;
           attribute DOMString icon;
           attribute boolean disabled;
           attribute boolean checked;
           attribute DOMString radiogroup;
           attribute boolean default;
 void click(); // shadows HTMLElement.click()
};

The Command interface must also be implemented by this element.

The command element represents a command that the user can invoke.

The type attribute indicates the kind of command: either a normal command with an associated action, or a state or option that can be toggled, or a selection of one item from a list of items.

The attribute is an enumerated attribute with three keywords and states. The keyword "command" maps to the Command state, the checkbox" maps to the Checkbox, and the "radio" keyword maps to the Radio state. The missing value default is the Command state.

The Command state

The element represents a normal command with an associated action.

The Checkbox state

The element represents a state or option that can be toggled.

The Radio state

The element represents a selection of one item from a list of items.

The label attribute gives the name of the command, as shown to the user.

The title attribute gives a hint describing the command, which might be shown to the user to help him.

The icon attribute gives a picture that represents the command. If the attribute is specified, the attribute's value must contain a valid URL. To obtain the absolute URL of the icon, the attribute's value must be resolved relative to the element.

The disabled attribute is a boolean attribute that, if present, indicates that the command is not available in the current state.

The distinction between disabled and hidden is subtle. A command would be disabled if, in the same context, it could be enabled if only certain aspects of the situation were changed. A command would be marked as hidden if, in that situation, the command will never be enabled. For example, in the context menu for a water faucet, the command "open" might be disabled if the faucet is already open, but the command "eat" would be marked hidden since the faucet could never be eaten.

The checked attribute is a boolean attribute that, if present, indicates that the command is selected. The attribute must be omitted unless the type attribute is in either the Checkbox state or the Radio state.

The radiogroup attribute gives the name of the group of commands that will be toggled when the command itself is toggled, for commands whose type attribute has the value "radio". The scope of the name is the child list of the parent element. The attribute must be omitted unless the type attribute is in the Radio state.

If the command element is used when generating a context menu, then the default attribute indicates, if present, that the command is the one that would have been invoked if the user had directly activated the menu's subject instead of using its context menu. The default attribute is a boolean attribute. The attribute must be omitted unless the type attribute is in the Command state.

Need an example that shows an element that, if double-clicked, invokes an action, but that also has a context menu, showing the various command attributes off, and that has a default command.

The type, label, icon, disabled, checked, radiogroup, and default DOM attributes must reflect the respective content attributes of the same name.

The click() method's behavior depends on the value of the type attribute of the element, as follows:

If the type attribute is in the Checkbox state

If the element has a checked attribute, the UA must remove that attribute. Otherwise, the UA must add a checked attribute, with the literal value checked. The UA must then fire a click event at the element.

If the type attribute is in the Radio state

If the element has a parent, then the UA must walk the list of child nodes of that parent element, and for each node that is a command element, if that element has a radiogroup attribute whose value exactly matches the current element's (treating missing radiogroup attributes as if they were the empty string), and has a checked attribute, must remove that attribute and fire a click event at the element.

Then, the element's checked attribute attribute must be set to the literal value checked and a click event must be fired at the element.

Otherwise

The UA must fire a click event at the element.

Firing a synthetic click event at the element does not cause any of the actions described above to happen.

command elements are not rendered unless they form part of a menu.

4.11.4 The bb element

Categories
Flow content.
Phrasing content.
Interactive content.
Contexts in which this element may be used:
Where phrasing content is expected.
Content model:
Phrasing content, but there must be no interactive content descendant.
Content attributes:
Global attributes
type
DOM interface:
interface HTMLBrowserButtonElement : HTMLElement {
           attribute DOMString type;
  readonly attribute boolean supported;
  readonly attribute boolean disabled;
};

The Command interface must also be implemented by this element.

The bb element represents a user agent command that the user can invoke.

The type attribute indicates the kind of command. The type attribute is an enumerated attribute. The following table lists the keywords and states for the attribute — the keywords in the left column map to the states listed in the cell in the second column on the same row as the keyword.

Keyword State
makeapp make application

The missing value default state is the null state.

Each state has an action and a relevance, defined in the following sections.

When the attribute is in the null state, the action is to not do anything, and the relevance is unconditionally false.

A bb element whose type attribute is in a state whose relevance is true must be enabled. Conversely, a bb element whose type attribute is in a state whose relevance is false must be disabled.

If a bb element is enabled, it will match the :enabled pseudo-class; otherwise, it will match the :disabled pseudo-class.

User agents should allow users to invoke bb elements when they are enabled. When a user invokes a bb element, its type attribute's state's action must be invoked.

When the element has no descendant element children and has no descendant text node children of non-zero length, the element represents a browser button with a user-agent-defined icon or text representing the type attribute's state's action and relevance (enabled vs disabled). Otherwise, the element represents its children.

bb . supported

Returns true if the value in the type attribute is a value that the user agent supports. Otherwise, returns false.

bb . disabled

Returns false if the user can invoke the element's action (i.e. if the element's relevance is true). Otherwise, returns true.

The type DOM attribute must reflect the content attribute of the same name.

The supported DOM attribute must return true if the type attribute is in a state other than the null state and the user agent supports that state's action (i.e. when the attribute's value is one that the user agent recognizes and supports), and false otherwise.

The disabled DOM attribute must return true if the element is disabled, and false otherwise (i.e. it returns the opposite of the type attribute's state's relevance).

4.11.4.1 Browser button types
4.11.4.1.1 The make application state

Some user agents support making sites accessible as independent applications, as if they were not Web sites at all. The make application state exists to allow Web pages to offer themselves to the user as targets for this mode of operation.

The action of the make application state is to confirm the user's intent to use the current site in a standalone fashion, and, provided the user's intent is confirmed, offer the user a way to make the resource identified by the document's address available in such a fashion.

The confirmation is needed because it is relatively easy to trick users into activating buttons. The confirmation could, e.g. take the form of asking the user where to "save" the application, or non-modal information panel that is clearly from the user agent and gives the user the opportunity to drag an icon to their system's application launcher.

The relevance of the make application state is false if the user agent is already handling the site in such a fashion, or if the user agent doesn't support making the site available in that fashion, and true otherwise.

In the following example, a few links are listed on an application's page, to allow the user perform certain actions, including making the application standalone:

<menu>
 <li><a href="settings.html" onclick="panels.show('settings')">Settings</a>
 <li><bb type="makeapp">Download standalone application</bb>
 <li><a href="help.html" onclick="panels.show('help')">Help</a>
 <li><a href="logout.html" onclick="panels.show('logout')">Sign out</a>
</menu>

With the following stylesheet, it could be make to look like a single line of text with vertical bars separating the options, with the "make app" option disappearing when it's not supported or relevant:

menu li { display: none; }
menu li:enabled { display: inline; }
menu li:not(:first-child)::before { content: ' | '; }

This could look like this:

"Settings | Download standalone application | Help | Sign out"

The following example shows another way to do the same thing as the previous one, this time not relying on CSS support to hide the "make app" link if it doesn't apply:

<menu>
 <a href="settings.html" onclick="panels.show('settings')">Settings</a> |
 <bb type="makeapp" id="makeapp"> </bb>
 <a href="help.html" onclick="panels.show('help')">Help</a> |
 <a href="logout.html" onclick="panels.show('logout')">Sign out</a>
</menu>
<script>
 var bb = document.getElementById('makeapp');
 if (bb.supported && bb.enabled) {
   bb.parentNode.nextSibling.textContent = ' | ';
   bb.textContent = 'Download standalone application';
 } else {
   bb.parentNode.removeChild(bb);
 }
</script>
Categories
Flow content.
If the element's type attribute is in the tool bar state: Interactive content.
Contexts in which this element may be used:
Where flow content is expected.
Content model:
Either: Zero or more li elements.
Or: Flow content.
Content attributes:
Global attributes
type
label
DOM interface:
interface HTMLMenuElement : HTMLElement {
           attribute DOMString type;
           attribute DOMString label;
};

The menu element represents a list of commands.

The type attribute is an enumerated attribute indicating the kind of menu being declared. The attribute has three states. The context keyword maps to the context menu state, in which the element is declaring a context menu. The toolbar keyword maps to the tool bar state, in which the element is declaring a tool bar. The attribute may also be omitted. The missing value default is the list state, which indicates that the element is merely a list of commands that is neither declaring a context menu nor defining a tool bar.

If a menu element's type attribute is in the context menu state, then the element represents the commands of a context menu, and the user can only interact with the commands if that context menu is activated.

If a menu element's type attribute is in the tool bar state, then the element represents a list of active commands that the user can immediately interact with.

If a menu element's type attribute is in the list state, then the element either represents an unordered list of items (each represented by an li element), each of which represents a command that the user can perform or activate, or, if the element has no li element children, flow content describing available commands.

The label attribute gives the label of the menu. It is used by user agents to display nested menus in the UI. For example, a context menu containing another menu would use the nested menu's label attribute for the submenu's menu label.

The type and label DOM attributes must reflect the respective content attributes of the same name.

This section is non-normative.

...

4.11.5.2 Building menus and tool bars

A menu (or tool bar) consists of a list of zero or more of the following components:

The list corresponding to a particular menu element is built by iterating over its child nodes. For each child node in tree order, the required behavior depends on what the node is, as follows:

An element that defines a command
Append the command to the menu, respecting its facets. If the element is a command element with a default attribute, mark the command as being a default command.
An hr element
An option element that has a value attribute set to the empty string, and has a disabled attribute, and whose textContent consists of a string of one or more hyphens (U+002D HYPHEN-MINUS)
Append a separator to the menu.
An li element
Iterate over the children of the li element.
A menu element with no label attribute
A select element
Append a separator to the menu, then iterate over the children of the menu or select element, then append another separator.
A menu element with a label attribute
An optgroup element
Append a submenu to the menu, using the value of the element's label attribute as the label of the menu. The submenu must be constructed by taking the element and creating a new menu for it using the complete process described in this section.
Any other node
Ignore the node.

We should support label in the algorithm above -- just iterate through the contents like with li, to support input elements in label elements. Also, optgroup elements without labels should be ignored (maybe? or at least should say they have no label so that they are dropped below), and select elements inside label elements may need special processing.

Once all the nodes have been processed as described above, the user agent must the post-process the menu as follows:

  1. Any menu item with no label, or whose label is the empty string, must be removed.
  2. Any sequence of two or more separators in a row must be collapsed to a single separator.
  3. Any separator at the start or end of the menu must be removed.
4.11.5.3 Context menus

The contextmenu attribute gives the element's context menu. The value must be the ID of a menu element in the DOM. If the node that would be obtained by the invoking the getElementById() method using the attribute's value as the only argument is null or not a menu element, then the element has no assigned context menu. Otherwise, the element's assigned context menu is the element so identified.

When an element's context menu is requested (e.g. by the user right-clicking the element, or pressing a context menu key), the UA must fire a contextmenu event on the element for which the menu was requested.

Typically, therefore, the firing of the contextmenu event will be the default action of a mouseup or keyup event. The exact sequence of events is UA-dependent, as it will vary based on platform conventions.

The default action of the contextmenu event depends on whether the element has a context menu assigned (using the contextmenu attribute) or not. If it does not, the default action must be for the user agent to show its default context menu, if it has one.

Context menus should inherit (so clicking on a span in a paragraph with a context menu should show the menu).

If the element does have a context menu assigned, then the user agent must fire a show event on the relevant menu element.

The default action of this event is that the user agent must show a context menu built from the menu element.

The user agent may also provide access to its default context menu, if any, with the context menu shown. For example, it could merge the menu items from the two menus together, or provide the page's context menu as a submenu of the default menu.

If the user dismisses the menu without making a selection, nothing in particular happens.

If the user selects a menu item that represents a command, then the UA must invoke that command's Action.

Context menus must not, while being shown, reflect changes in the DOM; they are constructed as the default action of the show event and must remain like that until dismissed.

User agents may provide means for bypassing the context menu processing model, ensuring that the user can always access the UA's default context menus. For example, the user agent could handle right-clicks that have the Shift key depressed in such a way that it does not fire the contextmenu event and instead always shows the default context menu.

The contextMenu attribute must reflect the contextmenu content attribute.

4.11.5.4 Tool bars

When a menu element has a type attribute in the tool bar state, then the user agent must build the menu for that menu element, and use the result in the rendering.

The user agent must reflect changes made to the menu's DOM, by immediately rebuilding the menu.

4.11.6 Commands

A command is the abstraction behind menu items, buttons, and links. Once a command is defined, other parts of the interface can refer to the same command, allowing many access points to a single feature to share aspects such as the disabled state.

Commands are defined to have the following facets:

Type
The kind of command: "command", meaning it is a normal command; "radio", meaning that triggering the command will, amongst other things, set the Checked State to true (and probably uncheck some other commands); or "checkbox", meaning that triggering the command will, amongst other things, toggle the value of the Checked State.
ID
The name of the command, for referring to the command from the markup or from script. If a command has no ID, it is an anonymous command.
Label
The name of the command as seen by the user.
Hint
A helpful or descriptive string that can be shown to the user.
Icon
An absolute URL identifying a graphical image that represents the action. A command might not have an Icon.
Hidden State
Whether the command is hidden or not (basically, whether it should be shown in menus).
Disabled State
Whether the command is relevant and can be triggered or not.
Checked State
Whether the command is checked or not.
Action
The actual effect that triggering the command will have. This could be a scripted event handler, a URL to which to navigate, or a form submission.

Commands are represented by elements in the DOM. Any element that can define a command also implements the Command interface:

Actually even better would be to just mix it straight into those interfaces somehow.

[NoInterfaceObject] interface Command {
  readonly attribute DOMString commandType;          
  readonly attribute DOMString id;
  readonly attribute DOMString label;
  readonly attribute DOMString title;
  readonly attribute DOMString icon;
  readonly attribute boolean hidden;
  readonly attribute boolean disabled;              
  readonly attribute boolean checked;              
  void click();
};

The Command interface must be implemented by any element capable of defining a command. All the attributes of the Command interface are read-only. Elements implementing this interface might implement other interfaces that have attributes with identical names but that are mutable; in bindings that flatten all supported interfaces on the object, the mutable attributes must shadow the readonly attributes defined in the Command interface.

element . commandType

Exposes the Type facet of the command.

element . id

Exposes the ID facet of the command.

element . label

Exposes the Label facet of the command.

element . title

Exposes the Hint facet of the command.

element . icon

Exposes the Icon facet of the command.

element . hidden

Exposes the Hidden State facet of the command.

element . disabled

Exposes the Disabled State facet of the command.

element . checked

Exposes the Checked State facet of the command.

element . click

Triggers the Action of the command.

The commandType attribute must return a string whose value is either "command", "radio", or "checked", depending on whether the Type of the command defined by the element is "command", "radio", or "checked" respectively. If the element does not define a command, it must return null.

The id attribute must return the command's ID, or null if the element does not define a command or defines an anonymous command. This attribute will be shadowed by the id DOM attribute on the HTMLElement interface.

The label attribute must return the command's Label, or null if the element does not define a command or does not specify a Label. This attribute will be shadowed by the label DOM attribute on option and command elements.

The title attribute must return the command's Hint, or null if the element does not define a command or does not specify a Hint. This attribute will be shadowed by the title DOM attribute on the HTMLElement interface.

The icon attribute must return the absolute URL of the command's Icon. If the element does not specify an icon, or if the element does not define a command, then the attribute must return null. This attribute will be shadowed by the icon DOM attribute on command elements.

The hidden attribute must return true if the command's Hidden State is that the command is hidden, and false if it is that the command is not hidden. If the element does not define a command, the attribute must return false. This attribute will be shadowed by the hidden DOM attribute on the HTMLElement interface.

The disabled attribute must return true if the command's Disabled State is that the command is disabled, and false if the command is not disabled. This attribute is not affected by the command's Hidden State. If the element does not define a command, the attribute must return false. This attribute will be shadowed by the disabled attribute on button, input, option, and command elements.

The checked attribute must return true if the command's Checked State is that the command is checked, and false if it is that the command is not checked. If the element does not define a command, the attribute must return false. This attribute will be shadowed by the checked attribute on input and command elements.

The click() method must trigger the Action for the command. If the element does not define a command, this method must do nothing. This method will be shadowed by the click() method on HTML elements, and is included only for completeness.

The commands attribute of the document's HTMLDocument interface must return an HTMLCollection rooted at the Document node, whose filter matches only elements that define commands and have IDs.

The following elements can define commands: a, button, input, option, command, bb.

4.11.6.1 Using the a element to define a command

An a element with an href attribute defines a command.

The Type of the command is "command".

The ID of the command is the value of the id attribute of the element, if the attribute is present and not empty. Otherwise the command is an anonymous command.

The Label of the command is the string given by the element's textContent DOM attribute.

The Hint of the command is the value of the title attribute of the element. If the attribute is not present, the Hint is the empty string.

The Icon of the command is the absolute URL obtained from resolving the value of the src attribute of the first img element descendant of the element, relative to that element, if there is such an element and resolving its attribute is successful. Otherwise, there is no Icon for the command.

The Hidden State of the command is true (hidden) if the element has a hidden attribute, and false otherwise.

The Disabled State facet of the command is always false. (The command is always enabled.)

The Checked State of the command is always false. (The command is never checked.)

The Action of the command is to fire a click event at the element.

4.11.6.2 Using the button element to define a command

A button element always defines a command.

The Type, ID, Label, Hint, Icon, Hidden State, Checked State, and Action facets of the command are determined as for a elements (see the previous section).

The Disabled State of the command mirrors the disabled state of the button.

4.11.6.3 Using the input element to define a command

An input element whose type attribute is in one of the Submit Button, Reset Button, Button, Radio Button, or Checkbox states defines a command.

The Type of the command is "radio" if the type attribute is in the Radio Button state, "checkbox" if the type attribute is in the Checkbox state, and "command" otherwise.

The ID of the command is the value of the id attribute of the element, if the attribute is present and not empty. Otherwise the command is an anonymous command.

The Label of the command depends on the Type of the command:

If the Type is "command", then it is the string given by the value attribute, if any, and a UA-dependent value that the UA uses to label the button itself if the attribute is absent.

Otherwise, the Type is "radio" or "checkbox". If the element is a labeled control, the textContent of the first label element in tree order whose labeled control is the element in question is the Label (in DOM terms, this the string given by element.labels[0].textContent). Otherwise, the value of the value attribute, if present, is the Label. Otherwise, the Label is the empty string.

The Hint of the command is the value of the title attribute of the input element. If the attribute is not present, the Hint is the empty string.

There is no Icon for the command.

The Hidden State of the command is true (hidden) if the element has a hidden attribute, and false otherwise.

The Disabled State of the command mirrors the disabled state of the control.

The Checked State of the command is true if the command is of Type "radio" or "checkbox" and the element is checked attribute, and false otherwise.

The Action of the command is to fire a click event at the element.

4.11.6.4 Using the option element to define a command

An option element with an ancestor select element and either no value attribute or a value attribute that is not the empty string defines a command.

The Type of the command is "radio" if the option's nearest ancestor select element has no multiple attribute, and "checkbox" if it does.

The ID of the command is the value of the id attribute of the element, if the attribute is present and not empty. Otherwise the command is an anonymous command.

The Label of the command is the value of the option element's label attribute, if there is one, or the value of the option element's textContent DOM attribute if there isn't.

The Hint of the command is the string given by the element's title attribute, if any, and the empty string if the attribute is absent.

There is no Icon for the command.

The Hidden State of the command is true (hidden) if the element has a hidden attribute, and false otherwise.

The Disabled State of the command is true (disabled) if the element is disabled or if its nearest ancestor select element is disabled, and false otherwise.

The Checked State of the command is true (checked) if the element's selectedness is true, and false otherwise.

The Action of the command depends on its Type. If the command is of Type "radio" then it must pick the option element. Otherwise, it must toggle the option element.

4.11.6.5 Using the command element to define a command

A command element defines a command.

The Type of the command is "radio" if the command's type attribute is "radio", "checkbox" if the attribute's value is "checkbox", and "command" otherwise.

The ID of the command is the value of the id attribute of the element, if the attribute is present and not empty. Otherwise the command is an anonymous command.

The Label of the command is the value of the element's label attribute, if there is one, or the empty string if it doesn't.

The Hint of the command is the string given by the element's title attribute, if any, and the empty string if the attribute is absent.

The Icon for the command is the absolute URL obtained from resolving the value of the element's icon attribute, relative to the element, if it has such an attribute and resolving it is successful. Otherwise, there is no Icon for the command.

The Hidden State of the command is true (hidden) if the element has a hidden attribute, and false otherwise.

The Disabled State of the command is true (disabled) if the element has a disabled attribute, and false otherwise.

The Checked State of the command is true (checked) if the element has a checked attribute, and false otherwise.

The Action of the command is to invoke the behavior described in the definition of the click() method of the HTMLCommandElement interface.

4.11.6.6 Using the bb element to define a command

A bb element always defines a command.

The Type of the command is "command".

The ID of the command is the value of the id attribute of the element, if the attribute is present and not empty. Otherwise the command is an anonymous command.

The Label of the command is the string given by the element's textContent DOM attribute, if that is not the empty string, or a user-agent-defined string appropriate for the bb element's type attribute's state.

The Hint of the command is the value of the title attribute of the element. If the attribute is not present, the Hint is a user-agent-defined string appropriate for the bb element's type attribute's state.

The Icon of the command is the absolute URL obtained from resolving the value of the src attribute of the first img element descendant of the element, relative to that element, if there is such an element and resolving its attribute is successful. Otherwise, the Icon is a user-agent-defined image appropriate for the bb element's type attribute's state.

The Hidden State facet of the command is true (hidden) if the bb element's type attribute's state is null or if the element has a hidden attribute, and false otherwise.

The Disabled State facet of the command is true if the bb element's type attribute's state's relevance is false, and true otherwise.

The Checked State of the command is always false. (The command is never checked.)

The Action of the command is to perform the action of the bb element's type attribute's state.

4.12 Miscellaneous elements

4.12.1 The legend element

Categories
None.
Contexts in which this element may be used:
As the first child of a fieldset element.
As the first child of a details element.
As a child of a figure element, if there are no other legend element children of that element.
Content model:
Phrasing content.
Content attributes:
Global attributes
DOM interface:
interface HTMLLegendElement : HTMLElement {
  readonly attribute HTMLFormElement form;
};

The legend element represents a title or explanatory caption for the rest of the contents of the legend element's parent element.

legend . form

Returns the element's form element, if any, or null otherwise.

The form DOM attribute's behavior depends on whether the legend element is in a fieldset element or not. If the legend has a fieldset element as its parent, then the form DOM attribute must return the same value as the form DOM attribute on that fieldset element. Otherwise, it must return null.

4.12.2 The div element

Categories
Flow content.
Contexts in which this element may be used:
Where flow content is expected.
Content model:
Flow content.
Content attributes:
Global attributes
DOM interface:
Uses HTMLElement.

The div element has no special meaning at all. It represents its children. It can be used with the class, lang/xml:lang, and title attributes to mark up semantics common to a group of consecutive elements.

Allowing div elements to contain phrasing content makes it easy for authors to abuse div, using it with the class="" attribute to the point of not having any other elements in the markup. This is a disaster from an accessibility point of view, and it would be nice if we could somehow make such pages non-compliant without preventing people from using divs as the extension mechanism that they are, to handle things the spec can't otherwise do (like making new widgets).

4.13 Matching HTML elements using selectors

There are a number of dynamic selectors that can be used with HTML. This section defines when these selectors match HTML elements.

:link
:visited

All a elements that have an href attribute, all area elements that have an href attribute, and all link elements that have an href attribute, must match one of :link and :visited.

:active

The :active pseudo-class must match the following elements between the time the user begins to activate the element and the time the users stops activating the element:

For example, if the user is using a keyboard to push a button element by pressing the space bar, the element would match this pseudo-class in between the time that the element received the keydown event and the time the element received the keyup event.

:enabled

The :enabled pseudo-class must match the following elements:

:disabled

The :disabled pseudo-class must match the following elements:

:checked

The :checked pseudo-class must match the following elements:

:indeterminate

The :indeterminate pseudo-class must match input elements whose type attribute is in the Checkbox state and whose indeterminate DOM attribute is set to true.

:default

The :default pseudo-class must match the following elements:

:valid

The :valid pseudo-class must match all elements that are candidates for constraint validation and that satisfy their constraints.

:invalid

The :invalid pseudo-class must match all elements that are candidates for constraint validation but that do not satisfy their constraints.

:in-range

The :in-range pseudo-class must match all elements that are candidates for constraint validation and that are neither suffering from an underflow nor suffering from an overflow.

:out-of-range

The :out-of-range pseudo-class must match all elements that are candidates for constraint validation and that are suffering from an underflow or suffering from an overflow.

:required

The :required pseudo-class must match the following elements:

:optional

The :optional pseudo-class must match the following elements:

:read-only
:read-write

The :read-write pseudo-class must match the following elements:

The :read-only pseudo-class must match all other HTML elements.

Another section of this specification defines the target element used with the :target pseudo-class.

This specification does not define when an element matches the :hover, :focus, or :lang() dynamic pseudo-classes, as those are all defined in sufficient detail in a language-agnostic fashion in the Selectors specification. [SELECTORS]