useful-observer

useful Observer pattern implementation

useful-Observer

useful Observer pattern implementation

Install with component(1):

$ component install muigui/useful-Observer

Install with npm:

$ npm install useful-Observer

Observer provides the core functionality required to create event-driven applications by allowing you to observe and broadcast custom events within the JavaScript space.

Observer is best utilised as a base class you can extend your own classes with or as a mixin.

An Object of observers to observe. See the observe instance method for details on adding event listeners.

Returns false if no event is currently being broadcast, otherwise it will be set to the name of the event currently being broadcast.

Returns true if the Observer instance was destroyed, false otherwise.

Returns true if the Observer instance is currently being destroyed, false otherwise.

The Observer's event listener store.

Returns true if the Observer has been suspended from broadcasting events, false otherwise.

Broadcasts the passed event – firing any event listener callbacks observing the event being broadcast – and passes any extra arguments to the callback Functions.

IMPORTANT: The Observer instance broadcasting the event will always be the first argument passed to each callback Function; UNLESS The callback Function is a method on the Observer instance.

 
    var Observer = require( 'useful-Observer' );
 
    function log() { console.log( 'log function: ', arguments ); }
 
    var observer = new Observer();
 
    observer.log = function() { console.log( 'log method:   ', arguments ); }
 
    observer.observe( 'foo', log )
            .observe( 'foo', observer.log, observer )
            .broadcast( 'foo', 1, 2, 3 );
 
    // logs => log function: [observer, 1, 2, 3]; <- Observer instance that broadcast the event is the first argument as log function does not exist on observer 
    // logs => log method:   [1, 2, 3];           <- Observer instance omitted, as log method exists on observer 
 

Destroys the Observer instance, purging all event listeners and disabling the Observer instance from broadcasting any more events.

Returns true if the Observer instance is successfully destroyed, false otherwise.

IMPORTANT: If you are extending Observer it is best practice to override the _destroy method rather than the destroy method, to ensure the before:destroy & destroy events are broadcast at the correct times.

 
    var Observer = require( 'useful-Observer' );
 
    function log() { console.log( arguments ); }
 
    var observer = new Observer( { foo : log } );
 
    observer.broadcast( 'foo', 1, 2, 3 ); // logs    => log function: [observer, 1, 2, 3]; 
 
    observer.destory();                   // returns => true 
 
    observer.broadcast( 'foo', 1, 2, 3 ); // does nothing, observer is destoryed 
 
    observer.observe( 'foo', log );            // throws  => TypeError: this.listeners is undefined. 
 

Removes the passed callback' Function from the listener queue, so that it is no longer fired when the Observer broadcasts the passedevent`.

 
    var Observer = require( 'useful-Observer' );
 
    function log() { console.log( arguments ); }
 
    var observer = new Observer( { foo : log } );
 
    observer.broadcast( 'foo', 1, 2, 3 ); // logs => [observer, 1, 2, 3]; 
 
    observer.ignore( 'foo', log );
 
    observer.broadcast( 'foo', 1, 2, 3 ); // does nothing, the observer was removed; 
 

An alias for ignore above.

Observes the Observer instance based on the passed parameters.

Allows you to add a single event listener callback – or multiple callbacks – for a single event; or an Object containing a number of event listeners for multiple events and multiple event listener callbacks.

When adding event listeners you can also give an optional options Object, the optional parameters it accepts are:

optiontypedescription
argsArrayIf supplied, these arguments will be prepended to the arguments passed to each event listener callback.
bufferNumberIf supplied, the event listener callback will only be executed once during the specified number of milliseconds.
This is handy for events that could fire hundreds or thousands of times in a second – but do not need to be executed each time – ensuring your application's performance does not suffer because of this.
delayNumberIf supplied, the event listener will be executed after being delayed by the specified number of milliseconds.
singleBooleanIf supplied, the event listener callbackk will only be executed once and then removed.

This is all best explained by examples. First let us define an example Observer class and a couple of instances:

 
    var Class    = require( 'useful-Class' ),
        Observer = require( 'useful-Observer' );
 
    Class( 'ObserverExample', {
       constructor : function( idobservers ) {
          this.id = id;
          this.parent( observers );
       },
       extend      : Observer,
       log         : function() { console.log( this.id, '', arguments ); },
       foo         : function() { console.log( this.id, ': foo' ); },
       bar         : function() { console.log( this.id, ': bar' ); }
    } );
 
    var observer_1 = Class.new( 'ObserverExample' ),
        observer_2 = ObserverExample.create();
 

Now let's observe an event:

 
// adding a single event listener and maintaining the correct context 
    observer_1.observe( 'foo', observer_2.log );             // <- WRONG: context (this) Object of observer_2.log will be observer_1 
 
    observer_1.observe( 'foo', observer_2.log, observer_2 ); // <- RIGHT: context (this) Object of observer_2.log will be observer_2 
 

A little bit smarter, observing an event with multiple listeners:

 
// add multiple event listener callbacks for one event 
    observer_1.observe( 'foo', [observer_2.log, observer_2.foo, observer_2.bar], observer_2 );
 
    observer_1.observe( 'foo', ['log', 'foo', 'bar'], observer_2 );             // <- same as above 
 

Adding options into the mix:

 
// fire an event listener once only 
    observer_1.observe( 'foo', 'log', observer_2, true );                       // <- can simply pass true if there are no other options 
    observer_1.observe( 'foo', observer_2.log, observer_2, { single : true } ); // <- will do same as above 
 
// delay the event listener from firing by the specified number of milliseconds 
    observer_1.observe( 'foo', 'log', observer_2, 500 );                        // <- can simply pass the number of milliseconds if there are no other options 
    observer_1.observe( 'foo', observer_2.log, observer_2, { delay : 500 } );   // <- will do the same as above 
 
// buffer an event listener to only fire once during the specified number of milliseconds 
    observer_1.observe( 'foo', observer_2.log, observer_2, { buffer : 500 } );  // <- only one way to do this one, sorry. 
 

Adding event listeners for multiple events using an Object, and whole lot more!

 
// add multiple event listener callbacks for multiple events 
    observer_1.observe( {
       foo        : {
          fn      : 'foo',
          ctx     : observer_2,                                      // <- overrides the top level ctx 
          options : { args : [1, 2, 3], delay : 250, single : true } // <- overrides the top level options 
       },
       bar        : [observer_2.bar, 'log'],                         // <- can still add multiple callbacks for one event 
       log        : observer_2.log,
       ctx        : observer_2,                                      // <- top level ctx for all callbacks which don't have one specified 
       options    : { args : [4, 5, 6 ] }                            // <- top level options for all callbacks which don't have any specified 
    } );
 

NOTE: you can also supply wildcard (*) event listeners:

 
   observer_1.observe( '*foo*', console.log, console );
 
   observer_1.broadcast( 'foo', 1, 2, 3 );          // <= fires *foo* listener callback 
 
   observer_1.broadcast( 'ipitythefool', 1, 2, 3 ); // <= fires *foo* listener callback 
 
   observer_1.broadcast( 'foomanchu', 1, 2, 3 );    // <= fires *foo* listener callback 
 
   observer_1.broadcast( 'foomanchu', 1, 2, 3 );    // <= fires *foo* listener callback 
 
   observer_1.broadcast( 'boofuu', 1, 2, 3 );       // <= DOES NOT fire *foo* listener callback 
 

An alias for observe above.

Removes all an Observer instance's event listeners. If an event is passed, only the event listeners for that event will be removed.

Relays the passed events from the Observer instance to the passed observer, as if the events are also being broadcast by the passed observer.

Handy for implementing "event bubbling" like functionality.

Enables the Observer instance's ability to broadcast events.

See suspendEvent example below.

Disables the Observer instance's ability to broadcast events.

 
    var Observer = require( 'useful-Observer' );
 
    function log() { console.log( arguments ); }
 
    var observer = new Observer( { foo : log } );
 
    observer.broadcast( 'foo', 1, 2, 3 ); // logs => [observer, 1, 2, 3]; 
 
    observer.suspendEvents();
 
    observer.broadcast( 'foo', 1, 2, 3 ); // does nothing, events are suspended 
 
    observer.resumeEvents();
 
    observer.broadcast( 'foo', 1, 2, 3 ); // logs => [observer, 1, 2, 3]; 
 

(The MIT License)

Copyright (c) 2011 christos "constantology" constandinou http://muigui.com

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.