Skip to content
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

Change when button has activation behavior #10032

Open
vinhill opened this issue Jan 2, 2024 · 7 comments
Open

Change when button has activation behavior #10032

vinhill opened this issue Jan 2, 2024 · 7 comments
Labels
topic: events topic: forms topic: popover The popover attribute and friends

Comments

@vinhill
Copy link
Contributor

vinhill commented Jan 2, 2024

What is the issue with the HTML Standard?

The specification is currently phrased such that a button always has activation behavior. According to the dispatch algorithm, there is at a maximum one activation target for every dispatch of an activation event.

Problem

This does not fully correspond to browser implementations. Specifically, there are issues around

  1. Anchor with child button, issue <button> shouldn't have activation behavior when it is not in a form #1567
    • <a href="link"><form><button type="button">click</button></form></a>. When a button with type=button is nested within an anchor and clicked, the link will be followed in Chrome, Firefox and Safari.
    • <a href="link"><button type="reset">click</button></a>. For a button that is not type=button, an ancestor link is followed if the button has no form owner in Chrome, Firefox and Safari.
  2. button that has a popovertarget
    • <a href="#link"><button popovertarget="foo">click</button></a><article id="foo">article</article> In Chrome but not in Firefox, clicking the button will activate the popover and follow the link. This corresponds to both the link and button being activation target. I'm unable to test on Safari.

I'm unsure whether 2. is intended behavior. When replacing the anchor with a form, the popover won't be activated. Maybe someone from Chromium can comment?

Consequences if button does not always have activation behavior

We should make sure that clicking a button nested within a summary will not toggle a details element. Maybe by stating that the activation behavior of a summary element is to do nothing if the event is targeted at an interactive content descendant. Gecko already does something similar.

The behavior around activation should be conserved. Although a button might not have activation behavior, it should be able to activate it via e.g. the keyboard.

If a button within a form changes from type=button to type=submit during an click handler, the button will not submit the form anymore. See issue #1568.

Possible solutions

We could state that a button has activation behavior if

  • it is disabled, or
  • has a form owner and is not of type=button, or
  • has a popovertarget specified.

We would need to mitigate above consequences and collect data on whether there are use cases for switching the button type during a click handler.

Or, under certain conditions, button activation behavior could be to activate an anchor ancestor. Between step 3 and 4 of button activation behavior, we could insert something like

  • Otherwise, or if the element's type attribute is in the button state, and the element has an anchor element ancestor:
    • fire an event named click at the anchor element

Or, we could specify the behavior of Chromium and Safari.

@whatwg/forms @zcorpan

@zcorpan zcorpan added topic: forms topic: events topic: popover The popover attribute and friends labels Jan 2, 2024
@annevk
Copy link
Member

annevk commented Jan 9, 2024

#1567 (comment) has a suggested way to write this down a lot clearer. And then the outcome needs to meet these criteria:

  • well-defined
  • tested
  • web compatible.

@EdgarChen
Copy link
Member

2. button that has a `popovertarget`
   
   * `<a href="#link"><button popovertarget="foo">click</button></a><article id="foo">article</article>` In Chrome but not in Firefox, clicking the button will activate the popover and follow the link. This corresponds to both the link and button being activation target. I'm unable to test on Safari.

I update the test a bit,

data:text/html,<a href="javascript:alert('link%20followed');"><button popovertarget=foo>click</button></a><div id=foo popover>popover</div>

Safari behaves the same as Chrome.

@EdgarChen
Copy link
Member

<input type=button> has a similar issue,

Test with

data:text/html,<a id=link href="javascript:alert('link%20followed');"><input type=button value=click></a>

a's activate behavior is triggered.

And test with input type button with popovertarget

data:text/html,<a href="javascript:alert('link%20followed');"><input type=button value=click popovertarget=foo></a><div id=foo popover>popover</div>

Chrome and Safari triggers both a's activate behavior and the popover.

@vinhill
Copy link
Contributor Author

vinhill commented Jan 23, 2024

Another issue

data:text/html,<a href="javascript:alert('link')"><form action="javascript:alert('submit')"><input type=submit onclick="this.type='button'"></form></a>

According to the spec, the input element is activation target. But Firefox as well as Chrome trigger the link. Introducing a has-activation-behavior algorithm as described in #1567 (comment) probably would not mitigate this.

@annevk
Copy link
Member

annevk commented Jan 23, 2024

@vinhill It seems a simpler version of that would be data:text/html,<form%20action="javascript:alert('submit')"><input%20type=submit%20onclick="this.type='button'"></form>. Something with activation behavior makes itself ineligible for activation behavior (and therefore we end up looking at the parent in the complicated case). But yeah, addressing that might require some heavier restructuring. And it's definitely broken in both its simple and complex forms today.

@vinhill
Copy link
Contributor Author

vinhill commented Mar 5, 2024

Both of my proposed solutions are probably not a good idea.

  • Idea 1, introduce a has activation behavior algorithm. This would change the behavior of buttons changing their type on click in a way that is visible to the web.
  • Idea 2, have buttons activate ancestor links. I think this is a bit ugly and more importantly, elements in the event chain between button and anchor cannot stop the navigation through preventing default.

I read the code from Blink and WebKit, maybe we can align the specification to their implementation through the following changes

  • In dispatch, activationTarget becomes legacyActivationTarget and is only used for legacy-pre- and legacy-canceled-activation behavior
  • Introduce a new default handled flag for events
  • After step 11, walk the event's path and invoke each element's activation behavior until the event is canceled or default handled
  • The activation behavior algorithms are changed to set the default handled flag accordingly.

For comparison, here is the corresponding code for default handling the event in Blink and WebKit.

An open question for me is whether popover should cause the default handled flag to be set. It doesn't seem to be the case in Chromium (see here), but as stated above, I'm unsure if this is intended.

@annevk
Copy link
Member

annevk commented Mar 5, 2024

cc @rniwa @nt1m @mfreed7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: events topic: forms topic: popover The popover attribute and friends
Development

No branches or pull requests

4 participants