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

Event disaptching. #40

Merged
merged 3 commits into from
Mar 21, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 95 additions & 9 deletions permission-element.bs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ time providing implementations with a better signal of user intent.
<dd>{{HTMLPermissionElement/type}} — Type of permission this element applies to.</dd>
<dd>{{HTMLPermissionElement/isValid}} — query whether the element can currently be activated.</dd>
<dd>{{HTMLPermissionElement/invalidReason}} — Return a string representation of why the element currently cannot be activated.</dd>
<dd>{{HTMLPermissionElement/ondismiss}} — notifies when the user has dismissed the permission prompt.</dd>
<dd>{{HTMLPermissionElement/onresolve}} — notifies when a permission prompt has been answered by the user (positively or negatively).</dd>
<dd>{{HTMLPermissionElement/onpromptdismiss}} — notifies when the user has dismissed the permission prompt.</dd>
<dd>{{HTMLPermissionElement/onpromptaction}} — notifies when a permission prompt has been answered by the user (positively or negatively).</dd>
<dd>{{HTMLPermissionElement/onvalidationstatuschange}} — notifies when the validation status changes.</dd>
<dt>[=Accessibility considerations=]:</dt>
<dd></dd>
Expand All @@ -134,8 +134,8 @@ time providing implementations with a better signal of user intent.
readonly attribute boolean isValid;
readonly attribute PermissionElementBlockerReason invalidReason;

attribute EventHandler onresolve;
attribute EventHandler ondismiss;
attribute EventHandler onpromptaction;
attribute EventHandler onpromptdismiss;
attribute EventHandler onvalidationstatuschange;
};
</pre>
Expand Down Expand Up @@ -168,8 +168,8 @@ observed by the <{permission}> element to select localized text.
The following are the [=event handlers=] (and their corresponding [=event handler event types=]) that must be supported on <{permission}> elements [=event handler IDL attributes=]:

<pre class=simpledef>
onresolve: Event
ondismiss: Event
onpromptaction: Event
onpromptdismiss: Event
onvalidationstatuschange: Event
</pre>

Expand Down Expand Up @@ -208,6 +208,18 @@ The <{permission}> element has the following internal slots:
{{DOMRectReadOnly}} that stores the most recently seen intersection, i.e.
the position of the <{permission}> relative to the [=viewport=].

* <dfn attribute for="HTMLPermissionElement">\[[LastNotifiedValidState]]</dfn>
is a [=boolean=] that stores the most recently notified state of
{{HTMLPermissionElement/isValid}}.

* <dfn attribute for="HTMLPermissionElement">\[[LastNotifiedInvalidReason]]</dfn>
is a [=string=] that stores the most recently notified state of
{{HTMLPermissionElement/invalidReason}}.
{{[[LastNotifiedValidState]]}} and {{[[LastNotifiedInvalidReason]]}} are
used to determine whether an
{{HTMLPermissionElement/onvalidationstatuschange}} event needs to be
dispatches.

## <{permission}>-supporting state at the [=/navigable=] ## {#permission-element-external-state}

In order to support the <{permission}> element, the [=/navigable=] maintains
Expand Down Expand Up @@ -464,6 +476,9 @@ The {{HTMLPermissionElement}} constructor steps are:

1. Initialize the internal {{[[Types]]}} slot to null.
1. Initialize the internal {{[[BlockerList]]}} to &laquo;[]&raquo;.
1. Initialize the internal {{[[LastNotifiedValidState]]}} with false.
1. Initialize the internal {{[[LastNotifiedInvalidReason]]}} with the empty
string.

</div>

Expand All @@ -488,6 +503,7 @@ The {{HTMLPermissionElement}} [=insertion steps=] are:
[=this=]
is a [=fenced navigable=], then [=add a permanent blocker=]
with {{PermissionElementBlockerReason/illegal_subframe}}.
1. [=Maybe dispatch onvalidstatechange=] on [=this=].

</div>

Expand All @@ -496,6 +512,7 @@ The {{HTMLPermissionElement}} [=removing steps=] are:

1. [=list/Remove=] [=this=] from [=node navigable=]'s {{[[PermissionElements]]}}.
1. [=Recheck type permissibility=] for [=this=]'s [=node navigable=].
1. [=Maybe dispatch onvalidstatechange=] on [=this=].

</div>

Expand All @@ -521,10 +538,23 @@ A <{permission}> |element|'s [=EventTarget/activation behavior=] given |event| i
1. If |element|'s {{[[Types]]}} [=list/is empty=], then return.
1. If |event|.{{Event/isTrusted}} is false, then return.
1. If |element|.{{HTMLPermissionElement/isValid}} is false, then return.
1. [=Request permission to use=] the [=powerful features=] named in |element|'s
{{[[Types]]}}.
1. [=Request permission to use=] the [=powerful features=] named in
|element|'s {{[[Types]]}}.
1. If the previous step was cancelled or dismissed by the user, then
[=dispatch onpromptdismiss=] on [=this=] and return.

Issue: The [[PERMISSIONS]] spec assumes that [=request permission to use=]
will always succeed. That is, it assumes that the user will always make a
choice and that the algorithm will always deliver a `grant`/`deny`
answer corresponding to that choice. But you can't force a user to do that.
Some [=user agents=] may have different UI affordances for an explicit
denial (e.g. a "deny" button) on one hand, and cancelling or dismissing the
request dialog (e.g. an "X" button in the top right corner). Here, we
distinguish between these two actions, despite no clear hook for this
in the underlying specification.

1. [=Dispatch onpromptaction=] on [=this=].

Issue: What about event handlers?
</div>

<div algorithm="HTMLPermissionElement/IntersectionObserver callback">
Expand All @@ -551,6 +581,7 @@ The HTMLPermissionElement's <dfn for="HTMLPermissionElement">IntersectionObserve
{{PermissionElementBlockerReason/intersection_changed}}.
1. Set {{[[IntersectionRect]]}} to
|entry|.{{IntersectionObserverEntry/intersectionRect}}
1. [=Maybe dispatch onvalidstatechange=] on [=this=].

ISSUE: Do I need to define dictionary equality?
</div>
Expand Down Expand Up @@ -583,6 +614,61 @@ To <dfn for="HTMLPermissionElement">recheck type permissibility</dfn> for a

</div>

## <{permission}> element event algorithms ## {#events}

<div algorithm>
To <dfn for=HTMLPermissionElement>maybe dispatch onvalidstatechange</dfn> for |element|:

1. Let |oldState| be {{[[LastNotifiedValidState]]}}.
1. Let |newState| be whether |element|’s [=blocker=] is Nothing.
1. Set {{[[LastNotifiedValidState]]}} to |newState|.
1. Let |oldReason| be {{[[LastNotifiedInvalidReason]]}}.
1. Let |newReason| be whether |element|’s
{{HTMLPermissionElement/invalidReason}}.
1. Set {{[[LastNotifiedInvalidReason]]}} to |newReason|.
1. If |oldState| != |newState| or |oldReason| != |newReason|, then:
1. Let |event| be a new {{Event}}.
1. [=Event/Initialize=] |event| with
<a argument for="Event/initEvent(type, bubbles, cancelable)">type</a>
"{{HTMLPermissionElement/onvalidationstatuschange}}",
<a argument for="Event/initEvent(type, bubbles, cancelable)">bubbles</a>
true, and
<a argument for="Event/initEvent(type, bubbles, cancelable)">cancelable</a>
true.
1. [=/Dispatch=] |event| to |element|.

</div>

<div algorithm>
To <dfn for=HTMLPermisssionElement>dispatch onpromptaction</dfn> for |element|:

1. Let |event| be a new {{Event}}.
1. [=Event/Initialize=] |event| with
<a argument for="Event/initEvent(type, bubbles, cancelable)">type</a>
"{{HTMLPermissionElement/onpromptaction}}",
<a argument for="Event/initEvent(type, bubbles, cancelable)">bubbles</a>
true, and
<a argument for="Event/initEvent(type, bubbles, cancelable)">cancelable</a>
true.
1. [=/Dispatch=] |event| to |element|.

</div>

<div algorithm>
To <dfn for=HTMLPermisssionElement>dispatch onpromptdismiss</dfn> for |element|:

1. Let |event| be a new {{Event}}.
1. [=Event/Initialize=] |event| with
<a argument for="Event/initEvent(type, bubbles, cancelable)">type</a>
"{{HTMLPermissionElement/onpromptdismiss}}",
<a argument for="Event/initEvent(type, bubbles, cancelable)">bubbles</a>
true, and
<a argument for="Event/initEvent(type, bubbles, cancelable)">cancelable</a>
true.
1. [=/Dispatch=] |event| to |element|.

</div>

# Rendering the <{permission}> Element # {#rendering}

The <{permission}> element is a [=non-devolvable widget=] and is chiefly
Expand Down