Skip to content

Commit

Permalink
Add name attribute for grouping details elements
Browse files Browse the repository at this point in the history
This allows grouping into exclusive accordions. See https://open-ui.org/components/accordion.explainer/.
  • Loading branch information
dbaron authored Oct 2, 2023
1 parent 85547bd commit e0cf318
Showing 1 changed file with 261 additions and 16 deletions.
277 changes: 261 additions & 16 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -10698,6 +10698,14 @@ partial interface <dfn id="document" data-lt="">Document</dfn> {
<p class="note">This is only populated for "<code data-x="">about:</code>"-schemed
<code>Document</code>s.</p>

<p>Each <code>Document</code> has a <dfn data-x="concept-document-fire-mutation-events-flag">fire
mutation events flag</dfn>, which is a boolean, initially true.</p>

<p class="note">This is intended to suppress firing of DOM Mutation Events in cases when they
would normally fire. The specification describing mutation events is not actively maintained so
it does not look at this flag, but implementations are expected to act as though it did.
<ref>UIEVENTS</ref></p>

<h4>The <code>DocumentOrShadowRoot</code> interface</h4>

<p><cite>DOM</cite> defines the <code data-x="DOM
Expand Down Expand Up @@ -59911,6 +59919,7 @@ dictionary <dfn dictionary>FormDataEventInit</dfn> : <span>EventInit</span> {
<dd>One <code>summary</code> element followed by <span>flow content</span>.</dd>
<dt><span data-x="concept-element-attributes">Content attributes</span>:</dt>
<dd><span>Global attributes</span></dd>
<dd><code data-x="attr-details-name">name</code></dd>
<dd><code data-x="attr-details-open">open</code></dd>
<dt><span
data-x="concept-element-accessibility-considerations">Accessibility considerations</span>:</dt>
Expand All @@ -59922,6 +59931,7 @@ dictionary <dfn dictionary>FormDataEventInit</dfn> : <span>EventInit</span> {
interface <dfn interface>HTMLDetailsElement</dfn> : <span>HTMLElement</span> {
[<span>HTMLConstructor</span>] constructor();

[<span>CEReactions</span>] attribute DOMString <span data-x="dom-details-name">name</span>;
[<span>CEReactions</span>] attribute boolean <span data-x="dom-details-open">open</span>;
};</code></pre>
</dd>
Expand All @@ -59942,6 +59952,31 @@ interface <dfn interface>HTMLDetailsElement</dfn> : <span>HTMLElement</span> {
<p>The rest of the element's contents <span>represents</span> the additional information or
controls.</p>

<p>The <dfn element-attr for="details"><code data-x="attr-details-name">name</code></dfn> content
attribute gives the name of the group of related <code>details</code> elements that the element is
a member of. Opening one member of this group causes other members of the group to close. If the
attribute is specified, its value must not be the empty string.</p>

<p>A document must not contain more than one <code>details</code> element in the same
<span>details name group</span> that has the <code data-x="attr-details-open">open</code>
attribute present. Authors must not use script to add <code>details</code> elements to a document
in a way that would cause a <span>details name group</span> to have more than one
<code>details</code> element with the <code data-x="attr-details-open">open</code> attribute
present.</p>

<p class="note">The group of elements that is created by a common <code
data-x="attr-details-name">name</code> attribute is exclusive, meaning that at most one of the
<code>details</code> elements can be open at once. While this exclusivity is enforced by user
agents, the resulting enforcement immediately changes the <code
data-x="attr-details-open">open</code> attributes in the markup. This requirement on authors
forbids such misleading markup.</p>

<p>Documents that use the <code data-x="attr-details-name">name</code> attribute to group multiple
related <code>details</code> elements should keep those related elements together in a containing
element (such as a <code>section</code> element).</p>

<p class="note">Keeping related elements together can be important for accessibility.</p>

<p>The <dfn element-attr for="details"><code data-x="attr-details-open">open</code></dfn> content
attribute is a <span>boolean attribute</span>. If present, it indicates that both the summary and
the additional information is to be shown to the user. If the attribute is absent, only the
Expand All @@ -59968,25 +60003,68 @@ interface <dfn interface>HTMLDetailsElement</dfn> : <span>HTMLElement</span> {
exists, user agents can still provide this ability through some other user interface
affordance.</p>

<p>The <dfn>details name group</dfn> that contains a <code>details</code> element <var>a</var>
also contains all the other <code>details</code> elements <var>b</var> that fulfill all of the
following conditions:</p>

<ul>
<li>Both <var>a</var> and <var>b</var> are in the same <span>tree</span>.</li>

<li>They both have a <code data-x="attr-details-name">name</code> attribute, their <code
data-x="attr-details-name">name</code> attributes are not the empty string, and the value of
<var>a</var>'s <code data-x="attr-details-name">name</code> attribute equals the value of
<var>b</var>'s <code data-x="attr-details-name">name</code> attribute.</li>
</ul>

<p>Every <code>details</code> element has a <dfn>details toggle task tracker</dfn>, which is a
<span>toggle task tracker</span> or null, initially null.</p>

<p>Whenever the <code data-x="attr-details-open">open</code> attribute is added to or removed from
a <code>details</code> element, the user agent must run the following steps, which are known as
the <dfn>details notification task steps</dfn>, for this <code>details</code> element:</p>

<p class="note">When the <code data-x="attr-details-open">open</code> attribute is toggled several
times in succession, the resulting tasks essentially get coalesced so that only one event is
fired.</p>
<p>The following <span data-x="concept-element-attributes-change-ext">attribute change
steps</span>, given <var>element</var>, <var>localName</var>, <var>oldValue</var>,
<var>value</var>, and <var>namespace</var>, are used for all <code>details</code> elements:</p>

<ol>
<li><p>If the <code data-x="attr-details-open">open</code> attribute is added, <span>queue a
details toggle event task</span> given the <code>details</code> element, "<code
data-x="">closed</code>", and "<code data-x="">open</code>".</p></li>
<li><p>If <var>namespace</var> is not null, then return.</p></li>

<li><p>If <var>localName</var> is <code data-x="attr-details-name">name</code>, then <span>ensure
details exclusivity by closing the given element if needed</span> given
<var>element</var>.</p></li>

<li><p>Otherwise, <span>queue a details toggle event task</span> given the <code>details</code>
element, "<code data-x="">open</code>", and "<code data-x="">closed</code>".</p></li>
<li><p>If <var>localName</var> is <code data-x="attr-details-open">open</code>, then:
<ol>
<li>
<p>If one of <var>oldValue</var> or <var>value</var> is null and the other is not null,
run the following steps, which are known as the <dfn>details notification task steps</dfn>, for
this <code>details</code> element:</p>

<p class="note">When the <code data-x="attr-details-open">open</code> attribute is toggled
several times in succession, the resulting tasks essentially get coalesced so that only one
event is fired.</p>

<ol>
<li><p>If <var>oldValue</var> is null, <span>queue a details toggle event task</span> given
the <code>details</code> element, "<code data-x="">closed</code>", and "<code
data-x="">open</code>".</p></li>

<li><p>Otherwise, <span>queue a details toggle event task</span> given the
<code>details</code> element, "<code data-x="">open</code>", and "<code
data-x="">closed</code>".</p></li>
</ol>
</li>

<li><p>If <var>oldValue</var> is null and <var>value</var> is not null, then <span>ensure
details exclusivity by closing other elements if needed</span> given
<var>element</var>.</p></li>
</ol>
</li>
</ol>

<p>The <code>details</code> <span data-x="html element insertion steps">HTML element insertion
steps</span>, given <var>insertedNode</var>, are:</p>

<ol>
<li><p><span>Ensure details exclusivity by closing the given element if needed</span> given
<var>insertedNode</var>.</p></li>
</ol>

<p>To <dfn>queue a details toggle event task</dfn> given a <code>details</code> element
Expand Down Expand Up @@ -60028,9 +60106,105 @@ interface <dfn interface>HTMLDetailsElement</dfn> : <span>HTMLElement</span> {
to <var>oldState</var>.</p></li>
</ol>

<p>The <dfn attribute for="HTMLDetailsElement"><code data-x="dom-details-open">open</code></dfn>
IDL attribute must <span>reflect</span> the <code data-x="attr-details-open">open</code> content
attribute.</p>
<p>To <dfn>ensure details exclusivity by closing other elements if needed</dfn> given a
<code>details</code> element <var>element</var>:</p>

<ol>
<li><p><span>Assert</span>: <var>element</var> has an <code
data-x="attr-details-open">open</code> attribute.</p></li>

<!-- This step is an optimization, but it may also make things clearer. -->
<li><p>If <var>element</var> does not have a <code data-x="attr-details-name">name</code>
attribute, or its <code data-x="attr-details-name">name</code> attribute is the empty string,
then return.</p></li>

<li><p>Let <var>document</var> be <var>element</var>'s <span>node document</span>.</p></li>

<li><p>Let <var>oldFlag</var> be the value of <var>document</var>'s <span
data-x="concept-document-fire-mutation-events-flag">fire mutation events flag</span>.</p></li>

<li><p>Set <var>document</var>'s <span data-x="concept-document-fire-mutation-events-flag">fire
mutation events flag</span> to false.</p></li>

<li><p>Let <var>groupMembers</var> be a list of elements, containing all elements in
<var>element</var>'s <span>details name group</span> except for <var>element</var>, in <span>tree
order</span>.</p></li>

<li>
<p><span data-x="list iterate">For each</span> element <var>otherElement</var> of
<var>groupMembers</var>:</p>
<ol>
<li>
<p>If the <code data-x="attr-details-open">open</code> attribute is set on
<var>otherElement</var>, then:</p>

<ol>
<li><p><span>Assert</span>: <var>otherElement</var> is the only element in
<var>groupMembers</var> that has the <code data-x="attr-details-open">open</code> attribute
set.</p></li>

<li><p><span data-x="concept-element-attributes-remove">Remove</span> the <code
data-x="attr-details-open">open</code> attribute on <var>otherElement</var>.</p></li>

<li><p><span>Break</span>.</p></li>
</ol>
</ol>
</li>

<li><p>Set <var>document</var>'s <span data-x="concept-document-fire-mutation-events-flag">fire
mutation events flag</span> to <var>oldFlag</var>.</p></li>
</ol>

<p>To <dfn>ensure details exclusivity by closing the given element if needed</dfn> given a
<code>details</code> element <var>element</var>:</p>

<ol>
<li><p>If <var>element</var> does not have an <code data-x="attr-details-open">open</code>
attribute, then return.</p></li>

<!-- This step is an optimization, but it may also make things clearer. -->
<li><p>If <var>element</var> does not have a <code data-x="attr-details-name">name</code>
attribute, or its <code data-x="attr-details-name">name</code> attribute is the empty string,
then return.</p></li>

<li><p>Let <var>document</var> be <var>element</var>'s <span>node document</span>.</p></li>

<li><p>Let <var>oldFlag</var> be the value of <var>document</var>'s <span
data-x="concept-document-fire-mutation-events-flag">fire mutation events flag</span>.</p></li>

<li><p>Set <var>document</var>'s <span data-x="concept-document-fire-mutation-events-flag">fire
mutation events flag</span> to false.</p></li>

<li><p>Let <var>groupMembers</var> be a list of elements, containing all elements in
<var>element</var>'s <span>details name group</span> except for <var>element</var>, in <span>tree
order</span>.</p></li>

<li>
<p><span data-x="list iterate">For each</span> element <var>otherElement</var> of
<var>groupMembers</var>:</p>

<ol>
<li>
<p>If the <code data-x="attr-details-open">open</code> attribute is set on
<var>otherElement</var>, then:</p>

<ol>
<li><p><span data-x="concept-element-attributes-remove">Remove</span> the <code
data-x="attr-details-open">open</code> attribute on <var>element</var>.</p></li>

<li><p><span>Break</span>.</p></li>
</ol>
</li>
</ol>
</li>

<li><p>Set <var>document</var>'s <span data-x="concept-document-fire-mutation-events-flag">fire
mutation events flag</span> to <var>oldFlag</var>.</p></li>
</ol>

<p>The <dfn attribute for="HTMLDetailsElement"><code data-x="dom-details-name">name</code></dfn>
and <dfn attribute for="HTMLDetailsElement"><code data-x="dom-details-open">open</code></dfn>
IDL attributes must <span>reflect</span> the respective content attributes of the same name.</p>

</div>

Expand Down Expand Up @@ -60107,6 +60281,62 @@ interface <dfn interface>HTMLDetailsElement</dfn> : <span>HTMLElement</span> {

</div>

<div class="example" id="example-details-exclusive-accordion">
<p>The following example shows the <code data-x="attr-details-name">name</code> attribute of the
<code>details</code> element being used to create an exclusive accordion, a set of
<code>details</code> elements where a user action to open one <code>details</code> element causes
any open <code>details</code> to close.</p>

<pre><code class="html">&lt;section class="characteristics">
&lt;details name="frame-characteristics">
&lt;summary>Material&lt;/summary>
The picture frame is made of solid oak wood.
&lt;/details>
&lt;details name="frame-characteristics">
&lt;summary>Size&lt;/summary>
The picture frame fits a photo 40cm tall and 30cm wide.
The frame is 45cm tall, 35cm wide, and 2cm thick.
&lt;/details>
&lt;details name="frame-characteristics">
&lt;summary>Color&lt;/summary>
The picture frame is available in its natural wood
color, or with black stain.
&lt;/details>
&lt;/section></code></pre>
</div>

<div class="example" id="example-details-exclusive-accordion-setting-open">
<p>The following example shows what happens when the <code data-x="attr-details-open">open</code>
attribute is set on a <code>details</code> element that is part of a set of elements using the
<code data-x="attr-details-name">name</code> attribute to create an exclusive accordion.</p>

<p>Given the initial markup:</p>

<pre><code class="html">&lt;section class="characteristics">
&lt;details name="frame-characteristics" id="d1" open>...&lt;/details>
&lt;details name="frame-characteristics" id="d2">...&lt;/details>
&lt;details name="frame-characteristics" id="d3">...&lt;/details>
&lt;/section></code></pre>

<p>and the script:</p>

<pre><code class="js">document.getElementById("d2").setAttribute("open", "");</code></pre>

<p>then the resulting tree after the script executes will be equivalent to the markup:</p>

<pre><code class="html">&lt;section class="characteristics">
&lt;details name="frame-characteristics" id="d1">...&lt;/details>
&lt;details name="frame-characteristics" id="d2" open>...&lt;/details>
&lt;details name="frame-characteristics" id="d3">...&lt;/details>
&lt;/section></code></pre>

<p>because setting the <code data-x="attr-details-open">open</code> attribute on <code
data-x="">d2</code> removes it from <code data-x="">d1</code>.</p>

<p>The same happens when the user activates the <code>summary</code> element inside of <code
data-x="">d2</code>.</p>
</div>

<div class="example">

<p>Because the <code data-x="attr-details-open">open</code> attribute is added and removed
Expand Down Expand Up @@ -108878,8 +109108,17 @@ document.body.appendChild(frame)</code></pre>
<span>erase all event listeners and handlers</span> given <var>document</var>'s <span>relevant
global object</span>.</p></li>

<li>Let <var>oldFlag</var> be the value of <var>document</var>'s <span
data-x="concept-document-fire-mutation-events-flag">fire mutation events flag</span>.</li>

<li>Set <var>document</var>'s <span data-x="concept-document-fire-mutation-events-flag">fire
mutation events flag</span> to false.</li>

<li><p><span data-x="concept-node-replace-all">Replace all</span> with null within
<var>document</var>, without firing any mutation events.</p></li>
<var>document</var>.</p></li>

<li>Set <var>document</var>'s <span data-x="concept-document-fire-mutation-events-flag">fire
mutation events flag</span> to <var>oldFlag</var>.</li>

<li>
<p>If <var>document</var> is <span>fully active</span>, then:</p>
Expand Down Expand Up @@ -134246,6 +134485,7 @@ interface <dfn interface>External</dfn> {
<td><code>summary</code>*;
<span data-x="Flow content">flow</span></td>
<td><span data-x="global attributes">globals</span>;
<code data-x="attr-details-name">name</code>;
<code data-x="attr-details-open">open</code></td>
<td><code>HTMLDetailsElement</code></td>
</tr>
Expand Down Expand Up @@ -136517,6 +136757,11 @@ interface <dfn interface>External</dfn> {
<span data-x="attr-fe-name">form-associated custom elements</span>
<td> Name of the element to use for <span>form submission</span> and in the <code data-x="dom-form-elements">form.elements</code> API <!--or: Name of the element to use in the <code data-x="dom-form-elements">form.elements</code> API. -->
<td> <a href="#attribute-text">Text</a>*
<tr>
<th> <code data-x="">name</code>
<td> <code data-x="attr-details-name">details</code>
<td> Name of group of mutually-exclusive <code>details</code> elements
<td> <a href="#attribute-text">Text</a>*
<tr>
<th> <code data-x="">name</code>
<td> <code data-x="attr-form-name">form</code>
Expand Down

0 comments on commit e0cf318

Please sign in to comment.