W3C home > Mailing lists > Public > www-dom@w3.org > January to March 2013

Re: Better event listeners

From: Benoit Marchant <marchant@mac.com>
Date: Mon, 07 Jan 2013 09:12:41 -0800
Cc: François REMY <francois.remy.dev@outlook.com>, DOM WG <www-dom@w3.org>, es-discuss <es-discuss@mozilla.org>
Message-id: <6ED4FB05-B703-4C4C-90EC-F379338C8123@mac.com>
To: Andrea Giammarchi <andrea.giammarchi@gmail.com>
Hi there

I have to say I'm really surprised that efforts are spent offering an alternative to addEventListener/removeEventListener. I've been doing JavaScript development for almost 13 years and I never felt these 2 api were that bad.

What is the rationale behind trying to offer an alternative syntax? As Francois mentioned, where did capture flag go?

Also we spent years explaining people to not use inline onclick="function(e){}" and now it's suddenly ok to do an element.on({click: ….) . That's muddying the waters to say the least.

There are other issues that I'm not sure are being worked on:
	- How about a better way when your handlers are objects and not functions? The big problem with functions is removing the listeners, it has to be the same function object and there are countless leaks today of people not realizing that their removeEventListener, when they thought of doing it actually doesn't do anything.
	Using an object as a listener typically doesn't have that problem in a well organized code like MVC. An object has a role, it's here to stay, it's typically "this" in addEventListener/removeEventListener. But "handleEvent" is insufficient because then your handleEvent becomes a big switch. In our framework we adopted a very intuitive convention and do some event distribution ourselves:
	if anObject listen for a "click" in bubble mode for an event target with an identifier property of "submitButton" then we look for a method on the listener: handleSubmitButtonClick. We shift the routing out of everyone else's code, and reading your own code tells you exactly what's going on.
	A more generic way to do that would be to allow the listener registration to provide the name of the method he wants as a callback instead of "handleEvent".

	- Perfornance. Event Delegation as a concept has been pushed because it's slow to install all these listeners upfront. Is that being worked on?

	- Registering the same listener for multiple different events could be useful sometimes

	- the API for creating and dispatching events are quite bad in the other hand, these need work.


Thanks,

Benoit

On Jan 7, 2013, at 9:05 AM, Andrea Giammarchi <andrea.giammarchi@gmail.com> wrote:

> element.on.{EventType} doesn't scale much with custom events where prefixes are in place, i.e. "jquery:transform" or whatever other string used to create unobtrusive custom events or ... will it? Same is for element.on({EventType:cb|handler})
> 
> My best version of on follows same addEventListener signature except it returns the element itself and accepts an array of types as overload
> 
> element.on(
>   type:string|string[],
>   handler:Function|Object (with handleEvent),
>   capture:Boolean (false by default)
> ):element
> 
> the counter part is semantically easy to remember ...
> 
> element.off(
>   ... same as above ...
> ):element
> 
> the ability to reuse a single callback or object with handleEvent together with the ability to use arrays of event types makes state machine like event driven interaction a piece of cake, IMHO.
> 
> 
> My 2 cents
> 
> 
> 
> 
> 
> 
> 
> 
> 
> On Mon, Jan 7, 2013 at 8:42 AM, François REMY <francois.remy.dev@outlook.com> wrote:
> Hi Anne,
> 
> Thanks for bringing the case of event registration, this has been a pain in DOM/JavaScript for some time already and it's quite clear we can do better in this area.
> 
> However, I've a few issues with your latest proposal:
> 
>    - how do you register more than one handlers for an event?
>    - how do you unregister an handler with this proposal?
>    - how do you specify properties for your handlers (like shouldCapture)?
> and
>    - isn't creating an object bag a too high cost for an event registration?
>    - how do you deal with private names and inherited properties?
> 
> What about resurrecting .{} instead?
> 
>    element.on.{
>        click.{
>            remove(oldCallback1)
>            add(newCallback1)
>        }
>        resize.add(newCallback2)
>    }
> 
> Even if .{} isn't resurrected, I think an 'on' proxy still leaves you with a fairly good syntax:
> 
>    element.on.DOMContentLoaded.remove(...).add(...).add(...);
> 
> If we define "element.on" as a proxy, we can event make it support unknown event names by returning an "event handler object" for the event whose name as been specified as property name.
> 
> That would leave us with two new WebIDL interfaces, and an updated one:
> 
>    interface EventTarget {
>        readonly EventRegistrationHub on;
>    }
> 
>    interface EventRegistrationHub {
>        readonly EventTarget target;
>        /* proxy, returns an event handler for unknown properties whose target is 'target' and whose 'name' is the required property name */
>    }
> 
>    interface EventHandler {
>        readonly DOMString name; // the name of the event
>        readonly EventTarget target; // the target of the event
>        add(callback, options...) // ...
>        remove(callback...) // ...
>    }
> 
> Another benefit is that you could pass an event to a function (now, you have to pass the target and the name, and use target.addEventListener/removeEventListenee(name, ...)).
> 
> Another benefit could be that now you can check for the existence of an event by doing if("EventName" in target.on), if we configure the proxy correctly (ie return true only if the event is builtin). New events always come with an uppercase first-letter name so that we can be sure there will be no conflict with future Object.prototype.* builtin properties (if there's not one already with the current names, which I believe is not the case).
> 
> Last but not least, you can get intellisense (autocompletion) once you typed "element.on." in any sufficiently good IDE/dev tool.
> 
> Best regards,
> François
> 
> 
> 
> 
> -----Message d'origine----- From: Anne van Kesteren
> Sent: Monday, January 07, 2013 2:25 PM
> To: es-discuss
> Subject: Object iteration order
> 
> In "DOM-land" we're designing new APIs that take objects as arguments.
> Unless objects meet the criteria in
> https://mail.mozilla.org/pipermail/es-discuss/2010-December/012469.html
> invocation of the API method might result in implementation-specific
> behavior. See also
> https://www.w3.org/Bugs/Public/show_bug.cgi?id=20158
> 
> Given the convenience of being able to do something like
> 
>  element.on({click: callback1, resize: callback2})
> 
> we're probably going to run with it, but I thought I'd give a heads
> up. Maybe someone here has a better idea or maybe iteration order will
> finally be settled on? :-)
> 
> 
> -- 
> http://annevankesteren.nl/
> _______________________________________________
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss 
> _______________________________________________
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
> 
> _______________________________________________
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
Received on Monday, 7 January 2013 22:53:27 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Monday, 7 January 2013 22:53:31 GMT