beforescroll and using DOM events for extensibility

Jonas and Anne raised some good concerns (
https://www.w3.org/Bugs/Public/show_bug.cgi?id=12230) with the way we're
thinking of using DOM events for beforescroll (
https://docs.google.com/a/chromium.org/document/d/1oEVWIVdMZ2OlVZMvcZZ3IgaT6RAUNSKAzpzb9AlVeLw/edit#).
Moving the discussion here (independent from the other thread about the
performance tradeoffs of enabling JS customization of scrolling).

> Jonas Sicking:
> >
> > Enabling pages to trigger actions that are triggered by other larger
features is indeed usually a good idea,
> > for the reasons enumerated in the extensible web manifest.
> >
> > However enabling pages to trigger those actions by creating an event
and calling dispatchEvent is very
> > awkward.
> >
> > Normally JS APIs are built using functions. Like "window.doStuff(5)".
While possible to use a pattern like
> >
> > event = new CustomEvent("stuff");
> > event.detail = 5;
> > window.dispatchEvent(event);
> >
> > it is quite awkward.
> > Instead define a JS function, and then define that this function is
called as default action in response to some particular event.
> >
> Anne van Kesteren:
>
> It's not just awkward, it doesn't match the prescribed events model.
Which is that dispatchEvent() returns
> a boolean and based on that you might initiate a default > action (or
not). So the polyfill would always be
> along the lines of
>
>   var ev = ...
>  if(obj.dispatchEvent(ev))
>    obj.defaultAction()
>
> That just dispatching the event invokes obj.defaultAction() breaks the
event model and is a
> longstanding bug for some events in browsers (this bug, indeed).

This makes perfect sense when the browser behavior for an event should come
strictly after any behavior on the page (i.e. it's really the final
"default action" - coupled with the thing that generated the event in the
first place).  But that strict "JS before browser" pattern isn't always
consistent with the extensible web ideas of some browser behavior being
built on the same primitives available to the application.  For full
composition of built-in and JS behavior, there may be cases where some JS
behavior happens only after some built-in behavior has been given a chance
to run.

In particular, for scrolling, consider the case of a scrollable DIV nested
inside a scrollable document.  We want to allow the scrolling behavior of
the DIV to either be supplied by the browser or by some JS library.  In
either case, when the DIV has reached its scroll extent, further scrolling
chains up to the document.

In our efforts to make this behavior extensible, it seemed most natural to
model the scroll request as a DOM event, and the chaining as bubbling of
that event.  But for proper composition, this implies that browser behavior
must act as just an event handler - not a default action that occurs
strictly after event processing.

Personally I really like the idea of the browser relying on the same
addEventListener mechanism available to applications in order to trigger
certain behavior.  It ensures natural / seamless composition between JS and
native behavior, similar to what you see in traditional OO UI frameworks
(where the framework relies on the same OO design principles for
composition as are available to the application for extensibility).  We
actually already have a number of places that do this in blink and webkit
(most commonly in shadowDOM components, eg. for form elements).

Thoughts?
   Rick

Received on Friday, 3 October 2014 13:15:37 UTC