Coder Social home page Coder Social logo

ampersand-events's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

ampersand-events's Issues

Consider augmenting EventEmitter

Given that most projects of moderate size are likely to have a transitive dependency on events.EventEmitter, would it make sense to reimplement ampersand-events as an augmentation thereof? I imagine this would reduce both code size and cognitive load (dealing with subtly different event emitters is surprisingly problematic).

Allow listening to DOM events

Implementing, for example, a draggable element would be so nice like this:

const DraggableView = AmpersandView.extend ({
  ...
  events: {
    'mousedown': 'down', // start dragging and set listeners
  },
  down: function (ev) {
    ...
    // we need to listen on window to handle panning outside the browser
    this.listenTo (window, 'mousemove', this.move)
    this.listenTo (window, 'mouseup', this.up)
  },
  move: function (ev) {
    ...
  },
  up: function (ev) {
    ...
    // this is way elegant!
    this.stopListening (window, 'mousemove')
    this.stopListening (window, 'mouseup')
  },
})

Being able to do this would have huge advantages over other solutions:

  • Defining mousemove and mouseup in the events hash causes atrocities like the element being left behind if the mouse if moved too fast, or being stuck dragging if the mouse is moved outside the window.
  • Using .listenTo preserves the context for this in the callback function.
  • The event listeners would be removed when the view was destroyed.
  • The .stopListening is way more elegant than the DOM's .removeEventListener

I think implementing this should be just as simple as modifying ampersand-events to allow .listenTo and .stopListening on DOM elements. I think the code to stop listening on destruction is already in place and wouldn't need modification.

What do you think? Surely you cannot deny the awesomeness of what this would allow you to do; is this as simple to implement as it seems?

Feature idea: onlyOnce method

I recently ran into a small but confusing bug in my app while using ampersand-events (or rather, one of its dependents). I was using the once method to listen to two event names with one callback, expecting it to work like this:

var count = 0;
model.once("error success", function() {
    //I assumed, incorrectly, that this callback would fire only once, ever.
    count++;
});
model.trigger("error");
model.trigger("success");
assert.equal(count, 1); // nope. count actually equals `2`

see live example on TonicDev

But I misunderstood the functionality. There were rare cases where both success and error events could happen while those listeners were in place causing unexpected results based on the callback being called multiple times.


While this behaviour is by design –as a convenience method for calling once for multiple event names–, and while this could be achieved by wrapping the callback function using lodash.once, I believe there is room in this library for a method that only ever triggers for a group of events. It can be called onlyOnce or firstOnce or similar. The implementation would be minimal: simply wrap the callback in lodash.once and calling the regular once with the newly wrapped callback.

Thoughts?

Should we ship this?

I think it's pretty much ready to go. Can I get some review from @AmpersandJS/core-team so we can ship it?

`.emit ()` as an alias for `.trigger ()`

What do you think about adding .emit () as an alias for .trigger (). This would allow it to have a signature very similar to NodeJS's EventEmitter class which would be nice for server-side code.

Along with this might come aliasing .removeListener () to .off ().

What do you &yet-ers think about this? Is this kind of uniformity worth doing for you?

P.S. I'm LOVING AmpersandJS, using it everywhere from my API on Node to the app in the browser. Keep up the good work!

passing a context argument to `once` does not apply context to callback

Here is a proof of the behaviour (or see this notebook on TonicDev)

const AmpersandState = require("ampersand-state");

const Model = AmpersandState.extend({});

const model = new Model();
const someObject = {};

//passing a context argument to `on` correctly applies the context to the callback
model.on("foo", function testThisEqualsModel2() {
    console.log("foo event via `on`; this === someObject");
    console.log(this === someObject);
}, someObject);

//... but doing the same for `once` doesn't work.
model.once("bar", function testThisEqualsModel2() {
    console.log("bar event via `once`; this === someObject")
    console.log(this === someObject);
}, someObject);

model.trigger("foo");
// "foo event via `on`; this === someObject"
// true

model.trigger("bar");
// "bar event via `once`; this === someObject"
// false

The potential problem code in ampersand-events.js (L24):

   once: function (name, callback, context) {
        if (!utils.eventsApi(this, 'once', name, [callback, context]) || !callback) return this;
        var self = this;
        var once = runOnce(function () {
            self.off(name, once);
            callback.apply(self, arguments);
        });
        once._callback = callback;
        return this.on(name, once, context);
    },

Note the callback is being called via apply(self, arguments), instead of something like apply(context, arguments).


This currently affects AmpersandJS/ampersand-view-switcher#35

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.