Re: Re: Better way to maintain this reference on event listener functions

2016-05-09 Thread Mark Kennedy
Haha, no problem, Andrea. I think I may have not explained the scenario as
clearly in my original post so I apologize for that. But like Boris
mentioned, removing the event listeners in a much easier way is also a part
of my goal here.

I do like passing context in an argument and if using the third argument is
a possibility, that would be nice. I would vote for:

```js
el.addEventListener('click', this.onClick, {context: this});
```

which would decrease the amount of code necessary imo.
-- 

mark

Sent while riding a hoverboard...
heyimmark.com :)
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Better way to maintain this reference on event listener functions

2016-05-09 Thread Mark Kennedy
Sorry maybe I'm not explaining this the right way. My original intent is to
lessen the code that I would have to write to achieve multiple event
handlers which do different things on multiple DOM elements when
constructing a class and also REMOVING the event listeners manually. I am
assuming this is a scenario where the DOM elements are outliving their
event listeners (for single page web applications for instance) so they
must be removed manually. Let's say I have five buttons on a page and I
want them all to do something different when they are clicked.

```html
button 1
button 2
button 3
```

With your approach, I would have to do this, right?

```js
class SomeClass {
  constructor() {
let button1 = document.getElementById('button1');
button1.addEventListener('click', this);
let button2 = document.getElementById('button2');
button2.addEventListener('click', this);
let button3 = document.getElementById('button3');
button3.addEventListener('mouseover', this);
  },

  onclick(e) {
   // if e.target is button1,
  // show modal
   // if e.target is button2,
  // navigate backwards
   // i f e.target is button 3,
  // do something else
  },

onmouseover (e) {
  // if e.target is button 3
  // do something else different from the above
}

  handleEvent(e) {
this['on' + e.type](e);
}
```
It may just be me confused here, but the above code is much more
overwhelming and much less intuitive than the solutions I've proposed above.

Hopefully this helps clarify a few things.


On Mon, May 9, 2016 at 12:20 PM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> Hi Mark, not sure I understand. What you are doing is exactly the same,
> there is no difference whatsoever with what I've shown to you.
>
> > Yes but what happens when you have multiple event targets using the
> same `type` of event? You're going to require a lot of extra conditionals
> in `onclick` method. Again this approach is cumbersome and, imo, not the
> most efficient.
>
> conditionals what? the onclick is called only when the node where you
> attached the listener as instance gets invoked. It never triggers in any
> other cases.
> Or better, it is exactly the same as `someNode.addEventListener('click',
> (e) => this.onClick(e))` ... really, PRECISELY the same.
>
> Whenever your `click` gets triggered, the `handleEvent` would behave
> **exactly** the same. Not sure I've stressed the *exactly* part enough so
> nothing is cumbersome, maybe you don't understand or you've never used this
> approach before.
>
> Otherwise, please show me a single example where adding a listener as
> callback, or bound callback, would be triggered differently from adding an
> instance with an inherited, or own, handleEvent.
>
> Going on ...
>
> > 1. When an arrow function is used as the second parameter to
> `addEventListener`, the language can evaluate and use its scoped context
>  ...
>
> This is not going to happen. It's an exception to the arrow that would
> confuse even more about its context.
>
> > 2. Another solution would be if we could maybe pass a method string as
> the second parameter and then an optional context as the fourth parameter
> ...
>
> This is DOM land, since it's about `addEventListener` signature, and I
> would personally vote -1 to that variant.
>
>
> You should really try to understand how `handleEvent` works, IMO. It's the
> sugar you're looking for already since it makes you set any listener you
> want *without* needing to store upfront the bound method: fast, clean,
> simple.
>
> To remove a listener at any time, you don't need to store upfront a bound
> version of the method.
>
> Best Regards
>
>
>
>
> On Mon, May 9, 2016 at 5:05 PM, Mark Kennedy  wrote:
>
>> Yes but what happens when you have multiple event targets using the same
>> `type` of event? You're going to require a lot of extra conditionals in
>> `onclick` method. Again this approach is cumbersome and, imo, not the most
>> efficient.
>>
>> These may not be the best solutions but here are a few options I've
>> thought of:
>>
>> 1. When an arrow function is used as the second parameter to
>> `addEventListener`, the language can evaluate and use its scoped context
>> when the same function is used with a subsequent `removeEventListener call,
>> so essentially the following code would work when calling destroy.
>>
>>
>> ```js
>> class MyClass {
>> constructor () {
>> someNode.addEventListener('click', (e) => this.onClick(e))
>> }
>>
>> onClick (e) {
>> // do something here
>> }
>>
>> destroy () {
>> someNode.removeEventListener('click', (e) => this.onClick(e))
>> }
>> }
>>
>> ```
>>
>> 2. Another solution would be if we could maybe pass a method string as
>> the second parameter and then an optional context as the fourth parameter
>> to addEventListener and removeEventListener as follows:
>>
>>
>> ```js
>> class MyClass {
>> constructor () {
>> someNode.addEventListener('click', 'onClick', 

Re: Re: Better way to maintain this reference on event listener functions

2016-05-09 Thread Andrea Giammarchi
Hi Mark, not sure I understand. What you are doing is exactly the same,
there is no difference whatsoever with what I've shown to you.

> Yes but what happens when you have multiple event targets using the same
`type` of event? You're going to require a lot of extra conditionals in
`onclick` method. Again this approach is cumbersome and, imo, not the most
efficient.

conditionals what? the onclick is called only when the node where you
attached the listener as instance gets invoked. It never triggers in any
other cases.
Or better, it is exactly the same as `someNode.addEventListener('click',
(e) => this.onClick(e))` ... really, PRECISELY the same.

Whenever your `click` gets triggered, the `handleEvent` would behave
**exactly** the same. Not sure I've stressed the *exactly* part enough so
nothing is cumbersome, maybe you don't understand or you've never used this
approach before.

Otherwise, please show me a single example where adding a listener as
callback, or bound callback, would be triggered differently from adding an
instance with an inherited, or own, handleEvent.

Going on ...

> 1. When an arrow function is used as the second parameter to
`addEventListener`, the language can evaluate and use its scoped context ...

This is not going to happen. It's an exception to the arrow that would
confuse even more about its context.

> 2. Another solution would be if we could maybe pass a method string as
the second parameter and then an optional context as the fourth parameter
...

This is DOM land, since it's about `addEventListener` signature, and I
would personally vote -1 to that variant.


You should really try to understand how `handleEvent` works, IMO. It's the
sugar you're looking for already since it makes you set any listener you
want *without* needing to store upfront the bound method: fast, clean,
simple.

To remove a listener at any time, you don't need to store upfront a bound
version of the method.

Best Regards




On Mon, May 9, 2016 at 5:05 PM, Mark Kennedy  wrote:

> Yes but what happens when you have multiple event targets using the same
> `type` of event? You're going to require a lot of extra conditionals in
> `onclick` method. Again this approach is cumbersome and, imo, not the most
> efficient.
>
> These may not be the best solutions but here are a few options I've
> thought of:
>
> 1. When an arrow function is used as the second parameter to
> `addEventListener`, the language can evaluate and use its scoped context
> when the same function is used with a subsequent `removeEventListener call,
> so essentially the following code would work when calling destroy.
>
>
> ```js
> class MyClass {
> constructor () {
> someNode.addEventListener('click', (e) => this.onClick(e))
> }
>
> onClick (e) {
> // do something here
> }
>
> destroy () {
> someNode.removeEventListener('click', (e) => this.onClick(e))
> }
> }
>
> ```
>
> 2. Another solution would be if we could maybe pass a method string as the
> second parameter and then an optional context as the fourth parameter to
> addEventListener and removeEventListener as follows:
>
>
> ```js
> class MyClass {
> constructor () {
> someNode.addEventListener('click', 'onClick', {}, this)
> }
>
> onClick (e) {
> // do something here
> }
>
> destroy () {
> someNode.removeEventListener('click', 'onClick', {}, this)
> }
> }
>
> ```
>
>
> On Mon, May 9, 2016 at 9:52 AM Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> uhm, I've used commas ... anyway, the sugar is desugaring to old methods,
>> this is working example:
>>
>> ```js
>> class SomeClass {
>>   constructor(someNode) {
>> someNode.addEventListener('click', this);
>>   }
>>   onclick(e) {
>> alert(this.constructor.name); // SomeClass
>>   }
>>   handleEvent(e) {
>> this['on' + e.type](e);
>>   }
>> }
>>
>> new SomeClass(document.documentElement);
>> ```
>>
>> The difference with your example is that you will always be able to
>> remove the instance without needing to store upfront every bound listener.
>>
>> To know where the `addEventListener` was set you always have the
>> `e.currentTarget` so basically you have a weakmap between a node and an
>> object where you can always retrieve the initial node that used the object
>> through the event, keeping the node clean from "expando" links.
>>
>> More sugar than this, I'm not sure what would be.
>>
>> You could also have a simple naming convention where every method that
>> starts with `on` will be set as listener using the current instance, and do
>> the same, if necessary, on teardown/destroy.
>>
>> What kind of sugar would you use otherwise?
>>
>> The only proposal discussed so far is `el.addEventListener('click', ::
>> this.onClick)`, unfortunately that doesn't solve anything because AFAIK
>> they don't see any advantage in having `::this.onClick === ::this.onClick`
>> which is what I've raised already as "that's what developers would expect"
>> but apparently it's too costy or complicated or ... 

RE: Subject=Re: Re: Better way to maintain this reference on event listener functions

2016-05-09 Thread Domenic Denicola
To give some clarity to "whose concern is it", the idea of it being an ES 
concern is that this is a concern for all APIs that accept a callback. 
addEventListener is a simple example.

I think ES has already given an answer to this question: 
`Function.prototype.bind`. I'm not sure what the OP was hoping to accomplish 
that could not already be accomplished with bind. Any possible mechanism (e.g. 
syntactic sugar for a (thisArg, function) pair) would essentially duplicate 
what bind does under the hood.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Better way to maintain this reference on event listener functions

2016-05-09 Thread Andrea Giammarchi
uhm, I've used commas ... anyway, the sugar is desugaring to old methods,
this is working example:

```js
class SomeClass {
  constructor(someNode) {
someNode.addEventListener('click', this);
  }
  onclick(e) {
alert(this.constructor.name); // SomeClass
  }
  handleEvent(e) {
this['on' + e.type](e);
  }
}

new SomeClass(document.documentElement);
```

The difference with your example is that you will always be able to remove
the instance without needing to store upfront every bound listener.

To know where the `addEventListener` was set you always have the
`e.currentTarget` so basically you have a weakmap between a node and an
object where you can always retrieve the initial node that used the object
through the event, keeping the node clean from "expando" links.

More sugar than this, I'm not sure what would be.

You could also have a simple naming convention where every method that
starts with `on` will be set as listener using the current instance, and do
the same, if necessary, on teardown/destroy.

What kind of sugar would you use otherwise?

The only proposal discussed so far is `el.addEventListener('click', ::
this.onClick)`, unfortunately that doesn't solve anything because AFAIK
they don't see any advantage in having `::this.onClick === ::this.onClick`
which is what I've raised already as "that's what developers would expect"
but apparently it's too costy or complicated or ... dunno.

¯\_(ツ)_/¯

Best Regards










On Mon, May 9, 2016 at 2:41 PM, Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> Raising a concern about `addEventListener` and its context probably made
> me think it was rather a WHATWG concern.
>
> Anyway, I don't know why you had to point out the `class` keyword ... I
> mean 
>
> ```js
> class SomeClass {
>   constructor(someNode) {
> someNode.addEventListener('click', this);
>   },
>   onclick(e) {
> alert(this.constructor.name); // SomeClass
>   },
>   handleEvent(e) {
> this['on' + e.type](e);
>   }
> }
> ```
>
> There you go
>
> Best Regards
>
>
> On Mon, May 9, 2016 at 2:38 PM, Mark Kennedy  wrote:
>
>> Wow that's so ironic because [I posted this same idea](
>> https://github.com/whatwg/dom/issues/245#issuecomment-217816301)
>> (literally
>> copied and pasted) in WHATWG's "DOM land" and they told me this was an
>> es-discuss issue. So which is it?
>> Oh and thanks for the code sample but it uses the old prototypical method
>> of replicating a class by creating a function which is now not the most
>> efficient way (there's the `class` keyword). And I don't see how what
>> you're doing isn't any different from a roundabout way of what I did. I
>> already know about the `handleEvent()` stuff, I like that it's available
>> and its polyfills. They are great, but my original question is to
>> implement
>> sugar so that you don't have to use polyfills or the `handleEvent()`.
>> --
>>
>> mark
>>
>> Sent while riding a hoverboard...
>> heyimmark.com :)
>>
>> ___
>> 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


Re: Re: Better way to maintain this reference on event listener functions

2016-05-09 Thread Andrea Giammarchi
Raising a concern about `addEventListener` and its context probably made me
think it was rather a WHATWG concern.

Anyway, I don't know why you had to point out the `class` keyword ... I
mean 

```js
class SomeClass {
  constructor(someNode) {
someNode.addEventListener('click', this);
  },
  onclick(e) {
alert(this.constructor.name); // SomeClass
  },
  handleEvent(e) {
this['on' + e.type](e);
  }
}
```

There you go

Best Regards


On Mon, May 9, 2016 at 2:38 PM, Mark Kennedy  wrote:

> Wow that's so ironic because [I posted this same idea](
> https://github.com/whatwg/dom/issues/245#issuecomment-217816301)
> (literally
> copied and pasted) in WHATWG's "DOM land" and they told me this was an
> es-discuss issue. So which is it?
> Oh and thanks for the code sample but it uses the old prototypical method
> of replicating a class by creating a function which is now not the most
> efficient way (there's the `class` keyword). And I don't see how what
> you're doing isn't any different from a roundabout way of what I did. I
> already know about the `handleEvent()` stuff, I like that it's available
> and its polyfills. They are great, but my original question is to implement
> sugar so that you don't have to use polyfills or the `handleEvent()`.
> --
>
> mark
>
> Sent while riding a hoverboard...
> heyimmark.com :)
>
> ___
> 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


Re: Subject=Re: Re: Better way to maintain this reference on event listener functions

2016-05-09 Thread Andrea Giammarchi
Raising a concern about `addEventListener` and its context probably made me
think it was rather a WHATWG concern.

Anyway, I don't know why you had to point out the `class` keyword ... I
mean 

```js
class SomeClass {
  constructor(someNode) {
someNode.addEventListener('click', this);
  },
  onclick(e) {
alert(this.constructor.name); // SomeClass
  },
  handleEvent(e) {
this['on' + e.type](e);
  }
}
```

There you go

Best Regards



On Mon, May 9, 2016 at 2:28 PM, Mark Kennedy  wrote:

> Wow that's so ironic because [I posted this same idea](
> https://github.com/whatwg/dom/issues/245#issuecomment-217816301)
> (literally copied and pasted) in WHATWG's "DOM land" and they told me this
> was an es-discuss issue. So which is it?
> Oh and thanks for the code sample but it uses the old prototypical method
> of replicating a class by creating a function which is now not the most
> efficient way (there's the `class` keyword). And I don't see how what
> you're doing isn't any different from a roundabout way of what I did. I
> already know about the `handleEvent()` stuff, I like that it's available
> and its polyfills. They are great, but my original question is to implement
> sugar so that you don't have to use polyfills or the `handleEvent()`.
>
>
> ___
> 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


Re: Re: Better way to maintain this reference on event listener functions

2016-05-09 Thread Mark Kennedy
Wow that's so ironic because [I posted this same idea](
https://github.com/whatwg/dom/issues/245#issuecomment-217816301) (literally
copied and pasted) in WHATWG's "DOM land" and they told me this was an
es-discuss issue. So which is it?
Oh and thanks for the code sample but it uses the old prototypical method
of replicating a class by creating a function which is now not the most
efficient way (there's the `class` keyword). And I don't see how what
you're doing isn't any different from a roundabout way of what I did. I
already know about the `handleEvent()` stuff, I like that it's available
and its polyfills. They are great, but my original question is to implement
sugar so that you don't have to use polyfills or the `handleEvent()`.
-- 

mark

Sent while riding a hoverboard...
heyimmark.com :)
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Subject=Re: Re: Better way to maintain this reference on event listener functions

2016-05-09 Thread Mark Kennedy
Wow that's so ironic because [I posted this same idea](
https://github.com/whatwg/dom/issues/245#issuecomment-217816301) (literally
copied and pasted) in WHATWG's "DOM land" and they told me this was an
es-discuss issue. So which is it?
Oh and thanks for the code sample but it uses the old prototypical method
of replicating a class by creating a function which is now not the most
efficient way (there's the `class` keyword). And I don't see how what
you're doing isn't any different from a roundabout way of what I did. I
already know about the `handleEvent()` stuff, I like that it's available
and its polyfills. They are great, but my original question is to implement
sugar so that you don't have to use polyfills or the `handleEvent()`.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss