# EventMixer

[![npm version](https://badge.fury.io/js/event-mixer.svg)](https://badge.fury.io/js/event-mixer)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/49f721b9e3e648bf9545475bec6d1446)](https://www.codacy.com/app/bdraper/event-mixer?utm_source=captison@bitbucket.org&amp;utm_medium=referral&amp;utm_content=captison/event-mixer&amp;utm_campaign=Badge_Grade)
[![Coverage Status](https://coveralls.io/repos/bitbucket/captison/event-mixer/badge.svg?branch=master)](https://coveralls.io/bitbucket/captison/event-mixer?branch=master)

## What is this?

Just another event-emitter implementation.  Nothin' special.

### Features

- Manage custom events in your application easily
- Listener registration and emitter functionality can be mixed-in to existing objects
- Listener functions can
    - opt-out of future notification
    - stop continued propagation of an event
    - request event cancellation (like 'preventDefault')


## Mmm... Ok. How do I get it?

### npm

```
npm install event-mixer --save
```

### bower

```
bower install event-mixer --save
```

## What's the Setup?

Simple.

For node

```js
var eventMixer = require('event-mixer');
```

In a browser

```html
<script src=".../dist/event-mixer.js"></script>
// or, minified
<script src=".../dist/event-mixer.min.js"></script>
```

## How Does This Work?

You have an object.  It needs some pub-sub functionality.

You want it to manage its own event subscriptions.

You want it (or some other object) to manage the event publishing.

```js
var mySubber = {}, myPubber = {};
var mixer = eventMixer.mixer(mySubber, myPubber);
```

Now `mySubber ` has `.on()`/`.off()` methods to register/unregister listener functions, and `myPubber` has a `.fire()` method to trigger event notifications.

Now, we need some events

```js
var twist = mixer.create('twist'),
    mangle = mixer.create('mangle'),
    scratch = mixer.create('scratch');
```

At this point `mySubber` has `.onTwist()`, `.offTwist()`, `.onMangle()`, etc.

And `myPubber` now has `.fireTwist()`, `.fireMangle()`, etc.

Also, event handlers have been returned.  More on those in a sec.

Register some listeners!

```js
mySubber.onTwist([eo => console.log('dog'), eo => console.log('cat')]);
mySubber.onMangle(eo => console.log('mangled!'));
mySubber.on('scratch', eo => console.log('scratched!'));
```

So we've created events and registered some listeners.

Now we want to fire them. We can use the emitter object,

```js
myPubber.fireTwist();     // => dog => cat
myPubber.fireMangle();    // => mangled!
myPubber.fireScratch();   // => scratched!
```

or the handlers we got earlier.

```js
twist.fire();   
mangle.fire();
scratch.fire();
```

--

Now, let's talk about the event listener functions.

`listener(eo:object):object`

As you likely noticed earlier, listener functions are passed an event object (`eo`).

- `eo.target`  
The target object the mixer was created with.

- `eo.name`  
The name of the event that was triggered.

- `eo.data`  
Any additional data attached to the event.  This will be data used to create the handler merged with any provided when the event was fired.  Any changes made by a listener will also be available to subsequent listeners.

The listener object return value has some flags you can use.

If the listener wants to opt out of future event notifications:

```js
return { remove: true };
```

If the listener wants to be the last one called for this event:

```js
return { stop: true };
```

If the listener wants to stop whatever happens next (like `.preventDefault()`):

```js
return { prevent: true };
```

Use whatever combination of these flags you like:

```js
return { prevent: true, remove: true, stop: false };
```

Beyond this, listener return values are ignored.

## Nice. Can I Get an API Quick-Ref?

Yep. Here you go!

**module**

- `mixer(target:object, emitter:object):mixer`  
Returns an event manager object that mixes listener registration methods into target object and event trigger methods into emitter object.  Both arguments are optional.

- `handler(target:object, name:string, data:object):handler`   
Returns an event handler object that passes triggered events on to its listeners.  Data provided here will be passed to each listener.  (**Note:** Listeners are _not_ managed as a Set so a handler can add the same listener function multiple times.)

**mixer**

- `create(name:string, data:object):handler`  
Creates a new event handler. This adds on/off methods to target object and a fire method to emitter object.

- `destroy(name:string):handler`  
Destroys an event handler. This removes on/off methods from target object and the fire method from emitter object.

- `emitter():object`  
Returns the emitter for this mixer.

- `event(name:string):handler`  
Returns the named handler object.

- `fire(name:string, data:object):boolean`  
Fires the named event.  This method is also added directly to the emitter object.

- `has(name:string):boolean`  
Returns `true` if there is an event handler for the given name.

- `names():array`  
Returns the names of all event handlers.

- `off(name:string|array, listener:function|array):this`  
Removes listener(s) from named event(s).  This method is also added directly to the target object.

- `on(name:string|array, listener:function|array):this`  
Adds listener(s) to named event(s).  This method is also added directly to the target object.

- `target():object`  
Returns the target of this mixer.

**handler**

- `add(listener:function|array):this`  
Alias for `.append()`.

- `append(listener:function|array):this`  
Appends listener function(s) to end of listener list.

- `at(index:number):listener`  
Returns the listener at the given index or `null` if not found.

- `clear():this`  
Removes all listeners.

- `count():number`  
Returns the number of listeners in this event handler.

- `cut(index:number):listener`  
Removes and returns the listener at the given index or `null` if not found.

- `each(callback:function):this`  
Filters the listener array.  Each listener (and its index) is passed to 'callback' and replaced by its return value.  If the callback does not return a function the listener will be omitted.

- `fire(data:object):boolean`  
Triggers the event (with optional data).  The returned boolean value indicates if the event should continue normally (`true`) or not (`false`).

- `has(listener:function):boolean`  
Returns `true` if this handler has the given listener function.

- `indexOf(listener:function, start:number):number`  
Returns the index of given listener in the listener list or `-1` if not found.  Specify 'start' to begin the search at a specific index.

- `prepend(listener:function|array):this`  
Prepends listener function(s) to beginning of listener list.

- `remove(listener:function|array):this`  
Removes listener function(s).

**target**

- `off(name:string|array, listener:function|array):this`  
Removes listener(s) from named event handler(s).  Added from mixer.

- `on(name:string|array, listener:function|array):this`  
Adds listener(s) to named event handler(s).  Added from mixer.

- `offXxx(listener:function|array):this`  
Removes listener(s) from event handler 'Xxx'.  Added via `mixer.create()`.

- `onXxx(listener:function|array):this`  
Adds listener(s) to event handler 'Xxx'.  Added via `mixer.create()`.

**emitter**

- `fire(name:string, data:object):boolean`  
Fires the named event.  Added from mixer.

- `fireXxx(data:object):boolean`  
Fires the event named 'Xxx'.  Added via `mixer.create()`.

## Anything Else I Should Know?

### Links

{ [distrib](https://bitbucket.org/captison/event-mixer/src/master/dist) }
{ [updates](https://bitbucket.org/captison/event-mixer/src/master/CHANGELOG.md) }
{ [feedback](https://bitbucket.org/captison/event-mixer/issues) }
{ [license](https://bitbucket.org/captison/event-mixer/src/master/LICENSE) }
{ [versioning](http://semver.org/) }

Please be sure to check 'updates' link when upgrading to a new version.

### Tests

_EventMixer_ uses [Jasmine](https://jasmine.github.io) for testing and [Istanbul](https://www.npmjs.com/package/istanbul) for coverage analysis.

```
npm test
```

[![Codeship Status for captison/event-mixer](https://app.codeship.com/projects/32a4db50-0263-0135-865e-561ac1403276/status?branch=master)](https://app.codeship.com/projects/213071)

### Finally

Don't Get Triggered! Happy Eventing!
