-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add "check and possibly close popover stack" algorithm #9048
Conversation
The "auto popover list" is constructed by attributes set on buttons. When those buttons are modified, it can break connections in the list. This patch adds checks to spots where buttons can be modified in order to fix up the list by closing all popovers when a connection has been broken.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I have a few questions.
source
Outdated
<li><p>If <var>localName</var> is <code data-x="attr-fe-disabled">disabled</code> or <code | ||
data-x="attr-fae-form">form</code>, then run <span>check and possibly close popover stack</span> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If someone changes the popovertarget to a different element, should we run the algorithm? We're also effectively breaking the ancestor relationship in that case.
Though the algorithm below would probably no longer work, since the popovertarget attribute is used to get the topmost popover ancestor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree! I pushed a commit to add popovertarget here, and I started on chromium and WPT changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though the algorithm below would probably no longer work, since the popovertarget attribute is used to get the topmost popover ancestor.
I don't understand, the rest of this algorithm only cares if the popover attribute is changed, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if "check and possibly close popover stack" runs before or after the attribute change, but this bit relies on checking the invokers:
If the result of running topmost popover ancestor
So if the popovertarget changes, the tree will end up different depending on when this runs, but disabled/form are also similarly affected (since we use the popover target element algorithm).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if "check and possibly close popover stack" runs before or after the attribute change
In chromium we are definitely doing it after the attribute has been changed. After reading https://dom.spec.whatwg.org/#concept-element-attributes-change it looks like these steps actually run before the attribute has been changed! Maybe we should create an alternative in the DOM spec which runs after the attribute is changed instead of before.
Is that the extent of your concern?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that the extent of your concern?
Yep :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. Do engines have callbacks before and after or is the DOM Standard wrong here in doing it before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on my brief searching, it looks like in chromium we only look at attribute changes after they happen, not before they happen. I'd be in favor of just changing element attribute changes to run after instead of having two algorithms/definitions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created a PR here: whatwg/dom#1176
source
Outdated
<p>If the result of running <span>topmost popover ancestor</span> given | ||
<var>stack</var>[<var>index</var>] is not <var>stack</var>[<var>index</var> - 1], then:</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we can do something more simple, like pass the popoverTargetElement then run hide all popovers until popoverTargetElement if it's an auto popover.
I'm having a bit of trouble understanding why this is the right thing to do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@josepharhar Can you explain what this "check and possibly close popover stack" algorithm does in terms of user experience? Like which cases it will be no-op, which cases it will hide all popovers, this is mostly the part I have trouble wrapping my head around.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain what this "check and possibly close popover stack" algorithm does in terms of user experience?
Check and possibly close popover stack recalculates the popover stack being built from the relationships of the popovers to each other in the DOM and from the popover target attributes and reconciles it with the currently open popovers. If they don't match up, it closes all popovers because something must have been modified which messed up the relationships.
Like which cases it will be no-op, which cases it will hide all popovers, this is mostly the part I have trouble wrapping my head around.
When setting disabled
in this case, check and possibly close popover stack will be called but no popovers will be closed because outerpopover and innerpopover are associated by their parent-child relationship in the DOM.
<div id=outerpopover popover=auto>
<div id=innerpopover popover=auto>hello world</div>
</div>
<button id=mybutton>button</button>
<script>
outerpopover.showPopover();
innerpopover.showPopover(); // both can be open since outerpopover is an ancestor
mybutton.disabled = true; // doesn't close any popovers
</script>
However, if we make the button the thing which creates the relationship between outerpopover and innerpopover and allows them to both be open at the same time and then take that away, it will close all popovers:
<div id=outerpopover popover=auto>
<button id=mybutton popovertarget=innerpopover>toggle popover</button>
</div>
<div id=innerpopover popover=auto>hello world</div>
<script>
outerpopover.showPopover();
innerpopover.showPopover(); // both can be open thanks to mybutton
mybutton.removeAttribute('popovertarget'); // all popovers will be closed since we broke the connection
</script>
There are additional test cases in the WPT. Does this help?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, thanks! seems like this is symmetric with the auto popovers hidden by the show popover algo as well, perhaps a note linking the two would be helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok I added a note, how does it look?
If the popovertarget attribute is changed on an element in a way which breaks the connection keeping multiple popovers open, then this patch will close all open popovers. This was pointed out here: whatwg/html#9048 (comment) Bug: 1307772, 1408546 Change-Id: I0a42260e97b7ef3fde01f416ef090b50994b8c5d
If the popovertarget attribute is changed on an element in a way which breaks the connection keeping multiple popovers open, then this patch will close all open popovers. This was pointed out here: whatwg/html#9048 (comment) Bug: 1307772, 1408546 Change-Id: I0a42260e97b7ef3fde01f416ef090b50994b8c5d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4354171 Commit-Queue: Joey Arhar <jarhar@chromium.org> Reviewed-by: Mason Freed <masonf@chromium.org> Cr-Commit-Position: refs/heads/main@{#1120013}
If the popovertarget attribute is changed on an element in a way which breaks the connection keeping multiple popovers open, then this patch will close all open popovers. This was pointed out here: whatwg/html#9048 (comment) Bug: 1307772, 1408546 Change-Id: I0a42260e97b7ef3fde01f416ef090b50994b8c5d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4354171 Commit-Queue: Joey Arhar <jarhar@chromium.org> Reviewed-by: Mason Freed <masonf@chromium.org> Cr-Commit-Position: refs/heads/main@{#1120013}
If the popovertarget attribute is changed on an element in a way which breaks the connection keeping multiple popovers open, then this patch will close all open popovers. This was pointed out here: whatwg/html#9048 (comment) Bug: 1307772, 1408546 Change-Id: I0a42260e97b7ef3fde01f416ef090b50994b8c5d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4354171 Commit-Queue: Joey Arhar <jarhar@chromium.org> Reviewed-by: Mason Freed <masonf@chromium.org> Cr-Commit-Position: refs/heads/main@{#1120013}
Looks good to me, will leave it to @annevk for a final look, and for the before attribute change vs after attribute change issue. |
WebKit implementation bug: https://bugs.webkit.org/show_bug.cgi?id=254382 |
At least in chromium, synchronous internal listeners for attribute changes which are run as "attribute change steps" are run after the attribute is actually changed, not before. This affects popover attribute related algorithms in HTML: whatwg/html#9048 (comment)
If the popovertarget attribute is changed on an element in a way which breaks the connection keeping multiple popovers open, then this patch will close all open popovers. This was pointed out here: whatwg/html#9048 (comment) Bug: 1307772, 1408546 Change-Id: I0a42260e97b7ef3fde01f416ef090b50994b8c5d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4354171 Commit-Queue: Joey Arhar <jarhar@chromium.org> Reviewed-by: Mason Freed <masonf@chromium.org> Cr-Commit-Position: refs/heads/main@{#1120013}
If the popovertarget attribute is changed on an element in a way which breaks the connection keeping multiple popovers open, then this patch will close all open popovers. This was pointed out here: whatwg/html#9048 (comment) Bug: 1307772, 1408546 Change-Id: I0a42260e97b7ef3fde01f416ef090b50994b8c5d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4354171 Commit-Queue: Joey Arhar <jarhar@chromium.org> Reviewed-by: Mason Freed <masonf@chromium.org> Cr-Commit-Position: refs/heads/main@{#1120013}
https://bugs.webkit.org/show_bug.cgi?id=254382 Reviewed by Tim Nguyen. Implement "check and possibly close popover stack" algorithm as specified here: whatwg/html#9048 This patch also imports the latest version of popover-target-element-disabled.html. * LayoutTests/imported/w3c/web-platform-tests/html/semantics/popovers/popover-target-element-disabled-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/popovers/popover-target-element-disabled.html: * Source/WebCore/html/HTMLElement.cpp: (WebCore::HTMLElement::checkAndPossiblyClosePopoverStackInternal): * Source/WebCore/html/HTMLElement.h: (WebCore::HTMLElement::checkAndPossiblyClosePopoverStack): * Source/WebCore/html/HTMLFormControlElement.cpp: (WebCore::HTMLFormControlElement::removedFromAncestor): (WebCore::HTMLFormControlElement::parseAttribute): (WebCore::HTMLFormControlElement::disabledStateChanged): (WebCore::HTMLFormControlElement::didChangeForm): * Source/WebCore/html/HTMLFormControlElement.h: * Source/WebCore/html/HTMLInputElement.cpp: (WebCore::HTMLInputElement::updateType): Canonical link: https://commits.webkit.org/262440@main
If the popovertarget attribute is changed on an element in a way which breaks the connection keeping multiple popovers open, then this patch will close all open popovers. This was pointed out here: whatwg/html#9048 (comment) Bug: 1307772, 1408546 Change-Id: I0a42260e97b7ef3fde01f416ef090b50994b8c5d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4354171 Commit-Queue: Joey Arhar <jarhar@chromium.org> Reviewed-by: Mason Freed <masonf@chromium.org> Cr-Commit-Position: refs/heads/main@{#1120013}
…ttribute changes, a=testonly Automatic update from web-platform-tests Close popover stack when popovertarget attribute changes If the popovertarget attribute is changed on an element in a way which breaks the connection keeping multiple popovers open, then this patch will close all open popovers. This was pointed out here: whatwg/html#9048 (comment) Bug: 1307772, 1408546 Change-Id: I0a42260e97b7ef3fde01f416ef090b50994b8c5d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4354171 Commit-Queue: Joey Arhar <jarhar@chromium.org> Reviewed-by: Mason Freed <masonf@chromium.org> Cr-Commit-Position: refs/heads/main@{#1120013} -- wpt-commits: 699803ffbe61479119ee4dd8622635b6b0ef715e wpt-pr: 39083
Fixes whatwg#9160 If this patch is merged, then whatwg#9048 is obsolete and can be closed without merging. Rationale (copied from [masons patch](https://chromium-review.googlesource.com/c/chromium/src/+/4429412)): Instead of using just the DOM structure to establish the popover hierarchy, the user's behavior should matter. For example, if one popover contains a popover invoker pointing to another popover, it should matter whether that invoker is *actually used* to open the second popover. An example: - Component 1 is a third party widget, which uses popover - Component 2 is another third party widget, also using popover - A page wants to use both components separately, from separate invoking buttons. - Component 1 also wants to be able to use Component 2, via a button within Component 1. In this example, the page should be able to still independently use these components. So a user clicking the page's button for Component 2 is expected to close Component 1 if it's open, because that's a direct invocation of Component 2. However, if the user clicks the button within Component 1 to get Component 2, it is natural to leave Component 1 open because this is a nested call. Important note: this often happens to be the behavior even before this change, since the user clicking on the page-level Component 2 invoking button represents a light dismiss signal for Component 1, so it closes either way. But this patch simplifies the implementation, removing the need to track all invokers on the page, and also removing the need to continuously check whether invoker relationships have changed.
If #9171 gets merged, then it will make this PR obsolete and I will close this |
<li><p>If <var>localName</var> is <code data-x="attr-fe-disabled">disabled</code>, <code | ||
data-x="attr-fae-form">form</code>, or <code data-x="attr-popovertarget">popovertarget</code>, | ||
then run <span>check and possibly close popover stack</span> given <var>element</var>'s | ||
<span>node document</span>.</p></li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is correct for form
and possibly popovertarget
. This algorithm runs whenever the value is set, even when it's set to the same value. Presumably when it's set to the same value we don't want to invalidate.
In all implementations, internal listeners for attribute changes which are run as "attribute change steps" are run after the attribute is actually changed, not before. This affects popover attribute related algorithms in HTML: whatwg/html#9048 (comment).
The "auto popover list" is constructed by attributes set on buttons. When those buttons are modified, it can break connections in the list. This patch adds checks to spots where buttons can be modified in order to fix up the list by closing all popovers when a connection has been broken.
Fixes #8991
/infrastructure.html ( diff )
/input.html ( diff )
/popover.html ( diff )