open-ui
open-ui copied to clipboard
[Invokers] Expose API for default `invokeaction` handlers
Addressing the need for polyfills, including support for any future elements or actions, we'll need adequate means of progressive enhancement for this. Namely, I think elements will need methods for listing actions/checking for a handled action, as well as to register new handlers for actions.
I'm currently experimenting with the API in Firefox by toggling dom.element.invokers.enabled
, and I'm finding that, while it does dispatch invoke
events, it does not currently provide any default handling for various actions. And I find myself lacking the means of detecting if some given action for an element has a default handler or if I need to manually handle it. This is obviously just a problem of an incomplete implementation in this case, but I can see the same issue arising whenever the defaults are expanded upon.
So, I propose the following methods:
-
HTMLElement.hasInvokeAction(action)
-> Boolean -
HTMLElement.addInvokeAction(action, callback)
-> Boolean (if there was previously and invoke action handler) -
HTMLElement.getAllInvokeActions()
-> Array or Set (not strictly necessary) -
HTMLElement.getInvokeAction(action)
-> Function (not necessary, but helpful for polyfills)
I'm not set on the method names, and only hasInvokeAction()
and addInvokeAction()
are strictly necessary. But I am thinking these would be best as static methods, and where eg HTMLDialogElement
overrides the methods on HTMLElement
. At least the hasInvokeAction()
and addInvokeAction()
would need to be static since they apply to all such elements rather than a particular instance.
Alternatively, this could be exposed via a map-like static actions
property and Element.actions.has(action)
and Element.actions.set(action, handler)
.
Example Usage:
if (! HTMLDialogElement.hasInvokeAction('showModal')) {
HTMLDialogElement.addInvokeAction('showModal', (invokeEvent) => {
if (! invokeEvent.target.open) {
invokeEvent.target.showModal();
}
});
}
if (! HTMLFooElement.hasInvokeAction('bar')) {
// Allow for adding new default invoke handlers on new tags and actions
HTMLFooElement.addInvokeAction('bar', function({ target, action, invoker {) {
HTMLBarElement.getInvokeAction('bar').call(null, { target, action, invoker });
});
}
Example of getInvokeAction()
in Polyfill:
someEl.addEventListener('invoke', event => {
// Static methods do make it a bit clunky to add invoke listeners
// But it does provide a convenient way of using added action handlers
if (event.target.constructor.hasInvokeAction(event.action)) {
event.target.constructor.getInvokeAction(event.action).call(null, event);
}
});