Skip to content

Commit

Permalink
Allow top layer elements to be nested within popovers
Browse files Browse the repository at this point in the history
This allows top layer elements, including the dialog element, to be nested inside of an open popover, by not closing the popover when the new top layer element is opened. Without this patch, opening a modal dialog inside of a popover will make the page inert and make the dialog invisible.

Fixes #9998. See also whatwg/fullscreen#237.
  • Loading branch information
josepharhar committed Mar 26, 2024
1 parent cf95931 commit ae5a7ec
Showing 1 changed file with 63 additions and 24 deletions.
87 changes: 63 additions & 24 deletions source
Expand Up @@ -61305,8 +61305,14 @@ interface <dfn interface>HTMLDialogElement</dfn> : <span>HTMLElement</span> {
<li><p>Set <span>this</span>'s <span>previously focused element</span> to the
<span>focused</span> element.</p></li>

<li><p>Run <span>hide all popovers</span> given <span>this</span>'s <span>node
document</span>.</p></li>
<li><p>Let <var>hideUntil</var> be the result of running <span>topmost popover ancestor</span>
given <span>this</span>, null, and false.</p></li>

<li><p>If <var>hideUntil</var> is null, then set <var>hideUntil</var> to <span>this</span>'s
<span>node document</span>.</p></li>

<li><p>Run <span data-x="hide-all-popovers-until">hide all popovers until</span> given
<var>hideUntil</var>, false, and true.</p></li>

<li><p>Run the <span>dialog focusing steps</span> given <span>this</span>.</p></li>
</ol>
Expand Down Expand Up @@ -61368,8 +61374,14 @@ interface <dfn interface>HTMLDialogElement</dfn> : <span>HTMLElement</span> {
<li><p>Set <span>this</span>'s <span>previously focused element</span> to the
<span>focused</span> element.</p></li>

<li><p>Run <span>hide all popovers</span> given <span>this</span>'s <span>node
document</span>.</p></li>
<li><p>Let <var>hideUntil</var> be the result of running <span>topmost popover ancestor</span>
given <span>this</span>, null, and false.</p></li>

<li><p>If <var>hideUntil</var> is null, then set <var>hideUntil</var> to <span>this</span>'s
<span>node document</span>.</p></li>

<li><p>Run <span data-x="hide-all-popovers-until">hide all popovers until</span> given
<var>hideUntil</var>, false, and true.</p></li>

<li><p>Run the <span>dialog focusing steps</span> given <span>this</span>.</p></li>
</ol>
Expand Down Expand Up @@ -84844,7 +84856,7 @@ dictionary <dfn dictionary>DragEventInit</dfn> : <span>MouseEventInit</span> {
data-x="attr-popover">popover</code> attribute.</p></li>

<li><p>Let <var>ancestor</var> be the result of running the <span>topmost popover
ancestor</span> algorithm given <var>element</var> and <var>invoker</var>.</p></li>
ancestor</span> algorithm given <var>element</var>, <var>invoker</var>, and true.</p></li>

<li><p>If <var>ancestor</var> is null, then set <var>ancestor</var> to
<var>document</var>.</p></li>
Expand Down Expand Up @@ -85117,7 +85129,7 @@ dictionary <dfn dictionary>DragEventInit</dfn> : <span>MouseEventInit</span> {
data-x="popover-showing-state">showing</span>; otherwise false.</p></li>
</ol>

<p>To <dfn data-x="hide-all-popovers-until">hide all popovers until</dfn>, given an <span
<p>To <dfn export data-x="hide-all-popovers-until">hide all popovers until</dfn>, given an <span
data-x="HTML elements">HTML element</span> or <code>Document</code> <var>endpoint</var>, a boolean
<var>focusPreviousElement</var>, and a boolean <var>fireEvents</var>:</p>

Expand Down Expand Up @@ -85209,21 +85221,17 @@ dictionary <dfn dictionary>DragEventInit</dfn> : <span>MouseEventInit</span> {
happens. For example, during light-dismiss of a popover, this algorithm ensures that we close only
the popovers that aren't related to the node clicked by the user.</p>

<p>To <dfn export>hide all popovers</dfn>, given a <code>Document</code> <var>document</var>, run
<span data-x="hide-all-popovers-until">hide all popovers until</span> given <var>document</var>,
false, and false.</p>

<p>To find the <dfn>topmost popover ancestor</dfn>, given a <code>Node</code>
<var>newPopover</var>, and an <span data-x="HTML elements">HTML element</span> or null
<var>invoker</var>, perform the following steps. They return an <span data-x="HTML
elements">HTML element</span> or null.</p>
<p>To find the <dfn export>topmost popover ancestor</dfn>, given a <code>Node</code>
<var>newPopoverOrTopLayerElement</var>, an <span data-x="HTML elements">HTML element</span> or
null <var>invoker</var>, and a boolean <var>isPopover</var>, perform the following steps. They
return an <span data-x="HTML elements">HTML element</span> or null.</p>

<div class="note">
<p>The <span>topmost popover ancestor</span> algorithm will return the topmost (latest in the
<span>showing auto popover list</span>) ancestor popover for the provided popover. Popovers can
be related to each other in several ways, creating a tree of popovers. There are two paths
through which one popover (call it the "child" popover) can have a topmost ancestor popover (call
it the "parent" popover):</p>
<span>showing auto popover list</span>) ancestor popover for the provided popover or top layer
element. Popovers can be related to each other in several ways, creating a tree of popovers.
There are two paths through which one popover (call it the "child" popover) can have a topmost
ancestor popover (call it the "parent" popover):</p>

<ol>
<li><p>The popovers are nested within each other in the node tree. In this case, the descendant
Expand All @@ -85241,14 +85249,45 @@ dictionary <dfn dictionary>DragEventInit</dfn> : <span>MouseEventInit</span> {
containing an invoking element that points back to the containing popover), and it allows for the
construction of a well-formed tree from the (possibly cyclic) graph of connections. Only <span
data-x="attr-popover-auto-state">auto</span> popovers are considered.</p>

<p>If the provided element is a top layer element such as a <code>dialog</code> which is not
showing as a popover, then <span>topmost popover ancestor</span> will only look in the node tree
to find the first popover.</p>
</div>

<ol>
<li>
<p>If <var>isPopover</var> is true:</p>

<ol>
<li><p><span>Assert</span>: <var>newPopoverOrTopLayerElement</var> is an <span data-x="HTML
elements">HTML element</span>.</p></li>

<li><p><span>Assert</span>: <var>newPopoverOrTopLayerElement</var>'s <code
data-x="attr-popover">popover</code> attribute is not in the <span
data-x="attr-popover-none-state">no popover state</span> or the <span
data-x="attr-popover-manual-state">manual</span> state.</p></li>

<li><p><span>Assert</span>: <var>newPopoverOrTopLayerElement</var>'s <span>popover visibility
state</span> is not in the <span data-x="popover-showing-state">popover showing
state</span>.</p></li>
</ol>
</li>

<li>
<p>Otherwise:</p>

<ol>
<li><p><span>Assert</span>: <var>invoker</var> is null.</p></li>
</ol>
</li>

<li><p>Let <var>popoverPositions</var> be an empty <span>ordered map</span>.</p></li>

<li><p>Let <var>index</var> be 0.</p></li>

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

<li>
<p>For each <var>popover</var> of <var>document</var>'s <span>showing auto popover
Expand All @@ -85262,8 +85301,8 @@ dictionary <dfn dictionary>DragEventInit</dfn> : <span>MouseEventInit</span> {
</ol>
</li>

<li><p><span data-x="map set">Set</span> <var>popoverPositions</var>[<var>newPopover</var>] to
<var>index</var>.</p></li>
<li><p>If <var>isPopover</var> is true, then <span data-x="map set">set</span>
<var>popoverPositions</var>[<var>newPopoverOrTopLayerElement</var>] to <var>index</var>.</p></li>

<li><p>Increment <var>index</var> by 1.</p></li>

Expand Down Expand Up @@ -85291,12 +85330,12 @@ dictionary <dfn dictionary>DragEventInit</dfn> : <span>MouseEventInit</span> {
</ol>
</li>

<li><p>Run <var>checkAncestor</var> given <var>newPopover</var>'s parent node within the
<span>flat tree</span>.</p></li>
<li><p>Run <var>checkAncestor</var> given <var>newPopoverOrTopLayerElement</var>'s parent node
within the <span>flat tree</span>.</p></li>

<li><p>Run <var>checkAncestor</var> given <var>invoker</var>.</p></li>

<li><p>return <var>topmostPopoverAncestor</var>.</p></li>
<li><p>Return <var>topmostPopoverAncestor</var>.</p></li>
</ol>

<p>To find the <dfn>nearest inclusive open popover</dfn> given a <code>Node</code>
Expand Down

0 comments on commit ae5a7ec

Please sign in to comment.