From e0cf31887ea2321d7fcb6681b17dbcc2af0fda9d Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Mon, 2 Oct 2023 17:39:31 -0400 Subject: [PATCH] Add name attribute for grouping details elements This allows grouping into exclusive accordions. See https://open-ui.org/components/accordion.explainer/. --- source | 277 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 261 insertions(+), 16 deletions(-) diff --git a/source b/source index 5d08a2dbbb0..16bc29ba628 100644 --- a/source +++ b/source @@ -10698,6 +10698,14 @@ partial interface Document {

This is only populated for "about:"-schemed Documents.

+

Each Document has a fire + mutation events flag, which is a boolean, initially true.

+ +

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. + UIEVENTS

+

The DocumentOrShadowRoot interface

DOM defines the Content attributes:

Global attributes
+
name
open
Accessibility considerations:
@@ -59922,6 +59931,7 @@ dictionary FormDataEventInit : EventInit { interface HTMLDetailsElement : HTMLElement { [HTMLConstructor] constructor(); + [CEReactions] attribute DOMString name; [CEReactions] attribute boolean open; };
@@ -59942,6 +59952,31 @@ interface HTMLDetailsElement : HTMLElement {

The rest of the element's contents represents the additional information or controls.

+

The name content + attribute gives the name of the group of related details 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.

+ +

A document must not contain more than one details element in the same + details name group that has the open + attribute present. Authors must not use script to add details elements to a document + in a way that would cause a details name group to have more than one + details element with the open attribute + present.

+ +

The group of elements that is created by a common name attribute is exclusive, meaning that at most one of the + details elements can be open at once. While this exclusivity is enforced by user + agents, the resulting enforcement immediately changes the open attributes in the markup. This requirement on authors + forbids such misleading markup.

+ +

Documents that use the name attribute to group multiple + related details elements should keep those related elements together in a containing + element (such as a section element).

+ +

Keeping related elements together can be important for accessibility.

+

The open content attribute is a boolean attribute. 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 @@ -59968,25 +60003,68 @@ interface HTMLDetailsElement : HTMLElement { exists, user agents can still provide this ability through some other user interface affordance.

+

The details name group that contains a details element a + also contains all the other details elements b that fulfill all of the + following conditions:

+ + +

Every details element has a details toggle task tracker, which is a toggle task tracker or null, initially null.

-

Whenever the open attribute is added to or removed from - a details element, the user agent must run the following steps, which are known as - the details notification task steps, for this details element:

- -

When the open attribute is toggled several - times in succession, the resulting tasks essentially get coalesced so that only one event is - fired.

+

The following attribute change + steps, given element, localName, oldValue, + value, and namespace, are used for all details elements:

    -
  1. If the open attribute is added, queue a - details toggle event task given the details element, "closed", and "open".

  2. +
  3. If namespace is not null, then return.

  4. + +
  5. If localName is name, then ensure + details exclusivity by closing the given element if needed given + element.

  6. -
  7. Otherwise, queue a details toggle event task given the details - element, "open", and "closed".

  8. +
  9. If localName is open, then: +

      +
    1. +

      If one of oldValue or value is null and the other is not null, + run the following steps, which are known as the details notification task steps, for + this details element:

      +

      When the open attribute is toggled + several times in succession, the resulting tasks essentially get coalesced so that only one + event is fired.

      + +
        +
      1. If oldValue is null, queue a details toggle event task given + the details element, "closed", and "open".

      2. + +
      3. Otherwise, queue a details toggle event task given the + details element, "open", and "closed".

      4. +
      +
    2. + +
    3. If oldValue is null and value is not null, then ensure + details exclusivity by closing other elements if needed given + element.

    4. +
    +
  10. +
+ +

The details HTML element insertion + steps, given insertedNode, are:

+ +
    +
  1. Ensure details exclusivity by closing the given element if needed given + insertedNode.

To queue a details toggle event task given a details element @@ -60028,9 +60106,105 @@ interface HTMLDetailsElement : HTMLElement { to oldState.

-

The open - IDL attribute must reflect the open content - attribute.

+

To ensure details exclusivity by closing other elements if needed given a + details element element:

+ +
    +
  1. Assert: element has an open attribute.

  2. + + +
  3. If element does not have a name + attribute, or its name attribute is the empty string, + then return.

  4. + +
  5. Let document be element's node document.

  6. + +
  7. Let oldFlag be the value of document's fire mutation events flag.

  8. + +
  9. Set document's fire + mutation events flag to false.

  10. + +
  11. Let groupMembers be a list of elements, containing all elements in + element's details name group except for element, in tree + order.

  12. + +
  13. +

    For each element otherElement of + groupMembers:

    +
      +
    1. +

      If the open attribute is set on + otherElement, then:

      + +
        +
      1. Assert: otherElement is the only element in + groupMembers that has the open attribute + set.

      2. + +
      3. Remove the open attribute on otherElement.

      4. + +
      5. Break.

      6. +
      +
    +
  14. + +
  15. Set document's fire + mutation events flag to oldFlag.

  16. +
+ +

To ensure details exclusivity by closing the given element if needed given a + details element element:

+ +
    +
  1. If element does not have an open + attribute, then return.

  2. + + +
  3. If element does not have a name + attribute, or its name attribute is the empty string, + then return.

  4. + +
  5. Let document be element's node document.

  6. + +
  7. Let oldFlag be the value of document's fire mutation events flag.

  8. + +
  9. Set document's fire + mutation events flag to false.

  10. + +
  11. Let groupMembers be a list of elements, containing all elements in + element's details name group except for element, in tree + order.

  12. + +
  13. +

    For each element otherElement of + groupMembers:

    + +
      +
    1. +

      If the open attribute is set on + otherElement, then:

      + +
        +
      1. Remove the open attribute on element.

      2. + +
      3. Break.

      4. +
      +
    2. +
    +
  14. + +
  15. Set document's fire + mutation events flag to oldFlag.

  16. +
+ +

The name + and open + IDL attributes must reflect the respective content attributes of the same name.

@@ -60107,6 +60281,62 @@ interface HTMLDetailsElement : HTMLElement { +
+

The following example shows the name attribute of the + details element being used to create an exclusive accordion, a set of + details elements where a user action to open one details element causes + any open details to close.

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

The following example shows what happens when the open + attribute is set on a details element that is part of a set of elements using the + name attribute to create an exclusive accordion.

+ +

Given the initial markup:

+ +
<section class="characteristics">
+ <details name="frame-characteristics" id="d1" open>...</details>
+ <details name="frame-characteristics" id="d2">...</details>
+ <details name="frame-characteristics" id="d3">...</details>
+</section>
+ +

and the script:

+ +
document.getElementById("d2").setAttribute("open", "");
+ +

then the resulting tree after the script executes will be equivalent to the markup:

+ +
<section class="characteristics">
+ <details name="frame-characteristics" id="d1">...</details>
+ <details name="frame-characteristics" id="d2" open>...</details>
+ <details name="frame-characteristics" id="d3">...</details>
+</section>
+ +

because setting the open attribute on d2 removes it from d1.

+ +

The same happens when the user activates the summary element inside of d2.

+
+

Because the open attribute is added and removed @@ -108878,8 +109108,17 @@ document.body.appendChild(frame) erase all event listeners and handlers given document's relevant global object.

+
  • Let oldFlag be the value of document's fire mutation events flag.
  • + +
  • Set document's fire + mutation events flag to false.
  • +
  • Replace all with null within - document, without firing any mutation events.

  • + document.

    + +
  • Set document's fire + mutation events flag to oldFlag.
  • If document is fully active, then:

    @@ -134246,6 +134485,7 @@ interface External { summary*; flow globals; + name; open HTMLDetailsElement @@ -136517,6 +136757,11 @@ interface External { form-associated custom elements Name of the element to use for form submission and in the form.elements API Text* + + name + details + Name of group of mutually-exclusive details elements + Text* name form