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

Sugar for one-time listeners #10

Open
appsforartists opened this issue Feb 11, 2014 · 5 comments
Open

Sugar for one-time listeners #10

appsforartists opened this issue Feb 11, 2014 · 5 comments

Comments

@appsforartists
Copy link

It would be nice for the Gator standard library to include sugar for one-time listeners, namely onFirst and onNth. Here's a sample implementation of onFirst:

Gator.prototype.onFirst = function (events, selector, callback) {
    /*  Useful abstraction for making sure something is only called
     *  once, even if the event is fired repeatedly.  For instance,
     *  onFirst('transitionend', ...) can be used to clean up a host of
     *  parallel transitions that each fire their own 'transitionend'.
     */
    var self = this;

    var listener = function (event) {
        self.off(events, selector, listener);
        callback(event);
    }

    self.on(events, selector, listener);
};

If @ccampbell approves of this sugar, I'll open a pull request.

@thelinuxlich
Copy link

It would be better if it didn't remove the event of all elements of the selector, just from the element which triggered the event.

@lazd
Copy link

lazd commented Nov 5, 2014

@appsforartists, this is more complex than your code sample lets on. Let's say you do this:

var myElement = document.createElement('div');
var handleClick = function(event) {
  console.log('Clicked!');
};

// Let's handle only the first click to myElement
Gator(myElement).onFirst('click', handleClick);

// We've changed our mind, we don't want to handle that click anymore
Gator(myElement).off('click', handleClick);

// But alas, when the user clicks, handleClick is still called!

It doesn't work, because handleClick is not the listener that was passed to on(). With the approach you've outlined, it's impossible for the user to remove that event listener because they don't have a reference to the listener function created inside of onFirst.

One solution to this problem would be to maintain a WeakMap so you could find the actual function given the user-provided function. However, I don't think this is a feature that Gator should be concerned with -- this is not event delegation, -1.

With Gator in its current form, users can implement this functionality very easily using named functions:

var myElement = document.createElement('div');

// Pass a named function to on()
Gator(myElement).on('click', function handleClick(event) {
  console.log('Clicked!');
  // handleClick will refer to this function, so we can easily remove the listener
  Gator(myElement).off('click', handleClick);
});

@englishextra
Copy link

englishextra commented Apr 21, 2017

@lazd That's because the handleClick handler should be defined in Gator, not outside. This is a common thing when you face problems with removing one-time listeners.

@lazd
Copy link

lazd commented Apr 21, 2017

@englishextra I think we're talking about two different things. Look at the code in the original issue, it passes listener to gator.on(), not the user-provided callback. As such, you cannot pass callback to gator.off() to remove it, you would have to pass listener, which obviously you don't have access to as it was created inside of gator.onFirst() and never returned. Because of this, it is impossible to remove a listener added with gator.onFirst() if it is implemented as described in the issue.

@englishextra
Copy link

englishextra commented Apr 21, 2017

@lazd Oh yeah

Then I guess this has to be established as a good rule for that issue:

It doesn't work, because handleClick is not the listener that was passed to on(). With the approach you've outlined, it's impossible for the user to remove that event listener because they don't have a reference to the listener function created inside of onFirst.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants