diff --git a/Gruntfile.js b/Gruntfile.js index 5761eed..5dbc67b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -71,9 +71,12 @@ module.exports = function(grunt) { vendor : [ 'public/javascripts/json2.js', 'public/javascripts/jquery.js', - 'public/javascripts/underscore.js', - 'public/javascripts/backbone.js' + 'node_modules/underscore/underscore.js', + 'node_modules/backbone/backbone.js', + 'node_modules/sinon/pkg/sinon.js', + 'node_modules/jasmine-sinon/lib/jasmine-sinon.js', ], + keepRunner: true, }, coverage : { src : '<%= jasmine.wreqr.src %>', diff --git a/package.json b/package.json index cff50a5..87c8bdb 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,9 @@ "grunt-contrib-connect": "0.2.0", "grunt-template-jasmine-istanbul": "0.2.0", "grunt-preprocess": "2.0.0", - "grunt-plato": "0.1.5" + "grunt-plato": "0.1.5", + "sinon": "1.9.0", + "jasmine-sinon": "0.3.1" }, "jam":{ "dependencies": { diff --git a/readme.md b/readme.md index 5b2bea4..7b84556 100644 --- a/readme.md +++ b/readme.md @@ -72,6 +72,42 @@ var result = reqres.request("foo"); console.log(result); ``` +### Radio + +Radio is a convenient way for emitting events through channels. Radio can be used to either retrieve a channel, or talk through a channel with either command, reqres, or vent. + +```js +// channels +var globalChannel = Backbone.Wreqr.radio.channel('global'); +var userChannel = Backbone.Wreqr.radio.channel('user'); + +// Wreqr events +Backbone.Wreqr.radio.commands.execute( 'global', 'shutdown' ); +Backbone.Wreqr.radio.reqres.request( 'global', 'current-user' ); +Backbone.Wreqr.radio.vent.trigger( 'global', 'game-over'); + +``` + +### Channel +Channel is an object that wraps EventAggregator, Commands, and Reqres. Channels provide a convenient way for the objects in your system to talk to one another without the global channel becoming too noisy. + +```js +// global channel +var globalChannel = Backbone.Wreqr.radio.channel('global'); +globalChannel.commands.execute('shutdown' ); +globalChannel.reqres.request('current-user' ); +globalChannel.vent.trigger('game-over'); + +// user channel +var userChannel = Backbone.Wreqr.radio.channel('user'); +userChannel.commands.execute('punnish'); +userChannel.reqres.request('user-avatar'); +userChannel.vent.trigger('win', { + level: 2, + stars: 3 +}); +``` + ### Adding Multiple Handlers Multiple handlers can be set on the Commands and RequestResponse diff --git a/spec/javascripts/channel/connect-commands.spec.js b/spec/javascripts/channel/connect-commands.spec.js new file mode 100644 index 0000000..956c9e2 --- /dev/null +++ b/spec/javascripts/channel/connect-commands.spec.js @@ -0,0 +1,41 @@ +describe('Executing `connectCommands` with a hash as the first argument', function() { + + var + ch, + label1 = 'one', + label2 = 'two', + cbOne, + cbTwo, + p, + ret, + commandsHash; + + beforeEach(function() { + + cbOne = function() {}; + cbTwo = function() {}; + ch = Wreqr.radio.channel('foo'); + + commandsHash = {}; + commandsHash[label2] = cbOne; + commandsHash[label1] = cbTwo; + + ret = ch.connectCommands( commandsHash ); + + p = ch.commands._wreqrHandlers || {}; + + }); + + afterEach(function() { + ch.reset(); + }); + + it( 'should attach the listeners to the Channel', function() { + expect(_.keys(p)).toEqual( [label2, label1] ); + }); + + it( 'should return the Channel', function() { + expect( ret ).toBe( ch ); + }); + +}); diff --git a/spec/javascripts/channel/connect-events.spec.js b/spec/javascripts/channel/connect-events.spec.js new file mode 100644 index 0000000..479b10e --- /dev/null +++ b/spec/javascripts/channel/connect-events.spec.js @@ -0,0 +1,41 @@ +describe('Executing `connectEvents` with a hash as the first argument', function() { + + var + ch, + label1 = 'one', + label2 = 'two', + cbOne, + cbTwo, + p, + ret, + eventsHash; + + beforeEach(function() { + + cbOne = function() {}; + cbTwo = function() {}; + ch = Wreqr.radio.channel('test'); + + eventsHash = {}; + eventsHash[label2] = cbOne; + eventsHash[label1] = cbTwo; + + ret = ch.connectEvents( eventsHash ); + + p = ch.vent._events || {}; + + }); + + afterEach(function() { + ch.reset(); + }); + + it( 'should attach the listeners to the Channel', function() { + expect(_.keys(p)).toEqual( [label2, label1] ); + }); + + it( 'should return the Channel', function() { + expect( ret ).toBe( ch ); + }); + +}); diff --git a/spec/javascripts/channel/connect-requests.spec.js b/spec/javascripts/channel/connect-requests.spec.js new file mode 100644 index 0000000..6375c1a --- /dev/null +++ b/spec/javascripts/channel/connect-requests.spec.js @@ -0,0 +1,41 @@ +describe('Executing `connectRequests` with a hash as the first argument', function() { + + var + ch, + label1 = 'one', + label2 = 'two', + cbOne, + cbTwo, + p, + ret, + requestsHash; + + beforeEach(function() { + + cbOne = function() {}; + cbTwo = function() {}; + ch = Wreqr.radio.channel('test'); + + requestsHash = {}; + requestsHash[label2] = cbOne; + requestsHash[label1] = cbTwo; + + ret = ch.connectRequests( requestsHash ); + + p = ch.reqres._wreqrHandlers || {}; + + }); + + afterEach(function() { + ch.reset(); + }); + + it( 'should attach the listeners to the Channel', function() { + expect(_.keys(p)).toEqual( [label2, label1] ); + }); + + it( 'should return the Channel', function() { + expect( ret ).toBe( ch ); + }); + +}); diff --git a/spec/javascripts/channel/create.spec.js b/spec/javascripts/channel/create.spec.js new file mode 100644 index 0000000..b0ccce1 --- /dev/null +++ b/spec/javascripts/channel/create.spec.js @@ -0,0 +1,23 @@ +describe('Creating a Channel', function() { + + var + ch, + chName, + name = 'test', + v, c, r; + + beforeEach(function() { + ch = new Wreqr.Channel( name ); + }); + + it( 'should set the name', function() { + expect( ch.channelName ).toEqual( name ); + }); + + it( 'should instantiate a new instance of each messaging system', function() { + expect( ch.vent instanceof Backbone.Wreqr.EventAggregator ).toBeTruthy(); + expect( ch.commands instanceof Backbone.Wreqr.Commands ).toBeTruthy(); + expect( ch.reqres instanceof Backbone.Wreqr.RequestResponse ).toBeTruthy(); + }); + +}); diff --git a/spec/javascripts/channel/reset.spec.js b/spec/javascripts/channel/reset.spec.js new file mode 100644 index 0000000..3ca2bf0 --- /dev/null +++ b/spec/javascripts/channel/reset.spec.js @@ -0,0 +1,44 @@ +describe('Running `resetChannel`', function() { + + var + ch, + v1Stub, v2Stub, cStub, rStub, + v, c, r, + ret; + + beforeEach(function() { + + ch = new Wreqr.Channel( 'test' ); + v = ch.vent; + c = ch.commands; + r = ch.reqres; + v1Stub = sinon.spy( v, "off"); + v2Stub = sinon.spy( v, "stopListening"); + cStub = sinon.spy( c, "removeAllHandlers"); + rStub = sinon.spy( r, "removeAllHandlers"); + + ret = ch.reset(); + + }); + + afterEach(function() { + + v1Stub.restore(); + v2Stub.restore(); + cStub.restore(); + rStub.restore(); + + }); + + it( 'should call the reset functions for each messaging system', function() { + expect( v1Stub ).toHaveBeenCalledOnce(); + expect( v2Stub ).toHaveBeenCalledOnce(); + expect( cStub ).toHaveBeenCalledOnce(); + expect( rStub ).toHaveBeenCalledOnce(); + }); + + it( 'should return the Channel', function() { + expect( ret ).toBe( ch ); + }); + +}); diff --git a/spec/javascripts/radio/channel.spec.js b/spec/javascripts/radio/channel.spec.js new file mode 100644 index 0000000..cdf60d1 --- /dev/null +++ b/spec/javascripts/radio/channel.spec.js @@ -0,0 +1,42 @@ +describe('radio.channel', function () { + + var channel, channelName; + + describe('with no arguments', function() { + + it( 'should throw an exception', function() { + expect( function() { Wreqr.radio.channel()} ).toThrow(); + }); + + }); + + describe('for a nonexistent channel', function() { + + beforeEach(function() { + channel = Wreqr.radio.channel('lala'); + }); + + it( 'should return an instance of the default channel', function() { + expect( channel.channelName ).toEqual( 'lala' ); + }); + + }); + + describe('twice with the same name', function() { + + var chOne, chTwo; + + beforeEach(function() { + + chOne = Wreqr.radio.channel( 'lala' ); + chTwo = Wreqr.radio.channel( 'lala' ); + + }); + + it( 'should return the same channel', function() { + expect( chOne ).toBe( chTwo ); + }); + + }); + +}); diff --git a/spec/javascripts/radio/commands.spec.js b/spec/javascripts/radio/commands.spec.js new file mode 100644 index 0000000..d3eec1b --- /dev/null +++ b/spec/javascripts/radio/commands.spec.js @@ -0,0 +1,156 @@ +describe('radio.commands', function() { + + describe('.execute', function() { + + var ch, chName, commandName, stub; + + beforeEach(function() { + + chName = 'test'; + commandName = 'some:command'; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.commands, 'execute' ); + Wreqr.radio.commands.execute( chName, commandName ); + + }); + + afterEach(function() { + stub.restore(); + }); + + it( 'should forward the call to the Channel\'s commands execute function', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + it( 'should pass the correct arguments to commands.execute', function() { + expect( stub ).toHaveBeenCalledWith( commandName ); + }); + + }); + + describe('.setHandler', function() { + + var ch, chName, fn, commandName, stub; + + beforeEach(function() { + + chName = 'test'; + fn = function() {}; + commandName = 'some:command'; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.commands, 'setHandler' ); + Wreqr.radio.commands.setHandler( chName, commandName, fn ); + + }); + + afterEach(function() { + stub.restore(); + }); + + it( 'should forward the call to the Channel\'s commands object', function() { + expect( stub ).toHaveBeenCalledOnce; + }); + + it( 'should pass the correct arguments to commands.setHandler', function() { + expect( stub ).toHaveBeenCalledWith( commandName, fn ); + }); + + }); + + describe('.setHandlers', function() { + + var ch, chName, obj, commandName, stub; + + beforeEach(function() { + + chName = 'test'; + obj = { + some1: function() {}, + some2: function() {} + }; + commandName = 'some:command'; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.commands, 'setHandlers' ); + Wreqr.radio.commands.setHandlers( chName, commandName, obj ); + + }); + + afterEach(function() { + + stub.restore(); + + }); + + it( 'should forward the call to the Channel\'s commands object', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + it( 'should pass the correct arguments to commands.setHandlers', function() { + expect( stub ).toHaveBeenCalledWith( commandName, obj ); + }); + + }); + + describe('.removeHandlers', function() { + + var ch, chName, commandName, stub; + + beforeEach(function() { + + chName = 'test'; + commandName = 'some:command'; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.commands, 'removeHandler' ); + Wreqr.radio.commands.removeHandler( chName, commandName ); + + }); + + afterEach(function() { + stub.restore(); + }); + + it( 'should forward the call to the Channel\'s commands object', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + it( 'should pass the correct arguments to commands.removeHandler', function() { + expect( stub ).toHaveBeenCalledWith( commandName ); + }); + + }); + + describe('.removeAllHandlers', function() { + + var ch, chName, stub; + + beforeEach(function() { + + chName = 'test'; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.commands, 'removeAllHandlers' ); + Wreqr.radio.commands.removeAllHandlers( chName ); + + }); + + afterEach(function() { + + stub.restore(); + + }); + + it( 'should forward the call to the Channel\'s commands object', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + }); +}); diff --git a/spec/javascripts/radio/reqres.spec.js b/spec/javascripts/radio/reqres.spec.js new file mode 100644 index 0000000..e3c23a2 --- /dev/null +++ b/spec/javascripts/radio/reqres.spec.js @@ -0,0 +1,160 @@ +describe('radio.reqres', function() { + + describe('.request`', function() { + + var ch, chName, reqName, stub; + + beforeEach(function() { + + chName = 'test'; + reqName = 'some:request'; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.reqres, 'request' ); + Wreqr.radio.reqres.request( chName, reqName ); + + }); + + afterEach(function() { + stub.restore(); + }); + + it( 'should forward the call to the Channel\'s reqres request function', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + it( 'should pass the correct arguments to reqres.request', function() { + expect( stub ).toHaveBeenCalledWith( reqName ); + }); + + }); + + describe('.setHandler` ', function() { + + var ch, chName, fn, commandName, stub; + + beforeEach(function() { + + chName = 'test'; + fn = function() {}; + commandName = 'some:command'; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.reqres, 'setHandler' ); + Wreqr.radio.reqres.setHandler( chName, commandName, fn ); + + }); + + afterEach(function() { + + stub.restore(); + + }); + + it( 'should forward the call to the Channel\'s reqres object', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + it( 'should pass the correct arguments to reqres.setHandler', function() { + expect( stub ).toHaveBeenCalledWith( commandName, fn ); + }); + + }); + + describe('.setHandlers', function() { + + var ch, chName, obj, commandName, stub; + + beforeEach(function() { + + chName = 'test'; + obj = { + some1: function() {}, + some2: function() {} + }; + commandName = 'some:command'; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.reqres, 'setHandlers' ); + Wreqr.radio.reqres.setHandlers( chName, commandName, obj ); + + }); + + afterEach(function() { + + stub.restore(); + + }); + + it( 'should forward the call to the Channel\'s reqres object', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + it( 'should pass the correct arguments to reqres.setHandlers', function() { + expect( stub ).toHaveBeenCalledWith( commandName, obj ); + }); + + }); + + describe('.removeHandler', function() { + + var ch, chName, commandName, stub; + + beforeEach(function() { + + chName = 'test'; + commandName = 'some:command'; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.reqres, 'removeHandler' ); + Wreqr.radio.reqres.removeHandler( chName, commandName ); + + }); + + afterEach(function() { + + stub.restore(); + + }); + + it( 'should forward the call to the Channel\'s reqres object', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + it( 'should pass the correct arguments to reqres.removeHandler', function() { + expect( stub ).toHaveBeenCalledWith( commandName ); + }); + + }); + + describe('.removeAllHandlers', function() { + + var ch, chName, stub; + + beforeEach(function() { + + chName = 'test'; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.reqres, 'removeAllHandlers' ); + Wreqr.radio.reqres.removeAllHandlers( chName ); + + }); + + afterEach(function() { + + stub.restore(); + + }); + + it( 'should forward the call to the Channel\'s reqres object', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + }); +}) diff --git a/spec/javascripts/radio/vent.spec.js b/spec/javascripts/radio/vent.spec.js new file mode 100644 index 0000000..375355c --- /dev/null +++ b/spec/javascripts/radio/vent.spec.js @@ -0,0 +1,283 @@ +describe('radio.vent', function() { + + describe('.off', function() { + + var ch, chName, obj, fn, eventName, stub; + + beforeEach(function() { + + chName = 'test'; + fn = function() {}; + eventName = 'some:event'; + obj = { test: true, testTwo: false }; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.vent, 'on' ); + Wreqr.radio.vent.on( chName, eventName, fn, obj ); + + }); + + afterEach(function() { + + stub.restore(); + + }); + + it( 'should forward the call to the corresponding Channel vent method', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + it( 'should pass the correct arguments to vent.on', function() { + expect( stub ).toHaveBeenCalledWith( eventName, fn, obj ); + }); + + }); + + describe('.off with no additional arguments', function() { + + var ch, chName, stub; + + beforeEach(function() { + + chName = 'test'; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.vent, 'off' ); + Wreqr.radio.vent.off( chName ); + + }); + + afterEach(function() { + + stub.restore(); + + }); + + it( 'should forward the call to the Channel vent `off` method', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + }); + + describe('Passing additional arguments to the `off` function', function() { + + var ch, chName, obj, fn, eventName, stub; + + beforeEach(function() { + + chName = 'test'; + fn = function() {}; + eventName = 'some:event'; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.vent, 'off' ); + Wreqr.radio.vent.off( chName, eventName, fn ); + + }); + + afterEach(function() { + + stub.restore(); + + }); + + it( 'should pass them along to vent.off', function() { + expect( stub ).toHaveBeenCalledWith( eventName, fn ); + }); + + }); + + describe('.once', function() { + + var ch, chName, obj, fn, eventName, stub; + + beforeEach(function() { + + chName = 'test'; + fn = function() {}; + eventName = 'some:event'; + obj = { test: true, testTwo: false }; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.vent, 'once' ); + Wreqr.radio.vent.once( chName, eventName, fn, obj ); + + }); + + afterEach(function() { + stub.restore(); + }); + + it( 'should forward the call to the Channel vent `once`', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + it( 'should pass the correct arguments to vent.once', function() { + expect( stub ).toHaveBeenCalledWith( eventName, fn, obj ); + }); + + }); + + describe('.trigger', function() { + + var ch, chName, obj, fn, eventName, stub; + + beforeEach(function() { + + chName = 'test'; + fn = function() {}; + eventName = 'some:event'; + obj = { test: true, testTwo: false }; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.vent, 'trigger' ); + Wreqr.radio.vent.trigger( chName, eventName, fn, obj, true, '2' ); + + }); + + afterEach(function() { + + stub.restore(); + + }); + + it( 'should forward the call to the Channel vent `trigger`', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + it( 'should pass the correct arguments to vent.trigger', function() { + expect( stub ).toHaveBeenCalledWith( eventName, fn, obj, true, '2' ); + }); + + }); + + describe('.stopListening with no extra arguments', function() { + + var ch, chName, stub; + + beforeEach(function() { + + chName = 'test'; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.vent, 'stopListening' ); + Wreqr.radio.vent.stopListening( chName ); + + }); + + afterEach(function() { + + stub.restore(); + + }); + + it( 'should forward the call to the Channel vent `stopListening`', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + }); + + describe('.stopListening with additional arguments', function() { + + var ch, chName, obj, fn, eventName, stub; + + beforeEach(function() { + + chName = 'test'; + fn = function() {}; + eventName = 'some:event'; + obj = { test: true, testTwo: false }; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.vent, 'stopListening' ); + Wreqr.radio.vent.stopListening( chName, eventName, fn, obj ); + + }); + + afterEach(function() { + + stub.restore(); + + }); + + it( 'should pass the correct arguments to vent.trigger', function() { + expect( stub ).toHaveBeenCalledWith( eventName, fn, obj ); + }); + + }); + + describe('.listenTo', function() { + + var ch, chName, obj, fn, eventName, stub; + + beforeEach(function() { + + chName = 'test'; + fn = function() {}; + eventName = 'some:event'; + obj = { test: true, testTwo: false }; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.vent, 'listenTo' ); + Wreqr.radio.vent.listenTo( chName, eventName, fn, obj, true, '2' ); + + }); + + afterEach(function() { + + stub.restore(); + + }); + + it( 'should forward the call to the Channel vent `trigger`', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + it( 'should pass the correct arguments to vent.trigger', function() { + expect( stub ).toHaveBeenCalledWith( eventName, fn, obj, true, '2' ); + }); + + }); + + describe('.listenToOnce', function() { + + var ch, chName, obj, fn, eventName, stub; + + beforeEach(function() { + + chName = 'test'; + fn = function() {}; + eventName = 'some:event'; + obj = { test: true, testTwo: false }; + + ch = Wreqr.radio.channel( chName ); + + stub = sinon.stub( ch.vent, 'listenToOnce' ); + Wreqr.radio.vent.listenToOnce( chName, eventName, fn, obj, true, '2' ); + + }); + + afterEach(function() { + + stub.restore(); + + }); + + it( 'should forward the call to the Channel vent `listenToOnce`', function() { + expect( stub ).toHaveBeenCalledOnce(); + }); + + it( 'should pass the correct arguments to vent.listenToOnce', function() { + expect( stub ).toHaveBeenCalledWith( eventName, fn, obj, true, '2' ); + }); + + }); +}) diff --git a/src/wreqr.channel.js b/src/wreqr.channel.js new file mode 100644 index 0000000..cf9d27a --- /dev/null +++ b/src/wreqr.channel.js @@ -0,0 +1,60 @@ +// Wreqr.Channel +// -------------- +// +// An object that wraps the three messaging systems: +// EventAggregator, RequestResponse, Commands +Wreqr.Channel = (function(Wreqr){ + "use strict"; + + var Channel = function(channelName) { + this.vent = new Backbone.Wreqr.EventAggregator(); + this.reqres = new Backbone.Wreqr.RequestResponse(); + this.commands = new Backbone.Wreqr.Commands(); + this.channelName = channelName; + }; + + _.extend(Channel.prototype, { + + // Remove all handlers from the messaging systems of this channel + reset: function() { + this.vent.off(); + this.vent.stopListening(); + this.reqres.removeAllHandlers(); + this.commands.removeAllHandlers(); + return this; + }, + + // Connect a hash of events; one for each messaging system + connectEvents: function(hash, context) { + this._connect('vent', hash, context); + return this; + }, + + connectCommands: function(hash, context) { + this._connect('commands', hash, context); + return this; + }, + + connectRequests: function(hash, context) { + this._connect('reqres', hash, context); + return this; + }, + + // Attach the handlers to a given message system `type` + _connect: function(type, hash, context) { + if (!hash) { + return; + } + + context = context || this; + var method = (type === 'vent') ? 'on' : 'setHandler'; + + _.each(hash, function(fn, eventName) { + this[type][method](eventName, _.bind(fn, context)); + }, this); + } + }); + + + return Channel; +})(Wreqr); diff --git a/src/wreqr.js b/src/wreqr.js index 3c06ba8..7605472 100644 --- a/src/wreqr.js +++ b/src/wreqr.js @@ -7,6 +7,8 @@ Backbone.Wreqr = (function(Backbone, Marionette, _){ // @include wreqr.commands.js // @include wreqr.requestresponse.js // @include wreqr.eventaggregator.js + // @include wreqr.channel.js + // @include wreqr.radio.js return Wreqr; })(Backbone, Backbone.Marionette, _); diff --git a/src/wreqr.radio.js b/src/wreqr.radio.js new file mode 100644 index 0000000..e14ba43 --- /dev/null +++ b/src/wreqr.radio.js @@ -0,0 +1,86 @@ +// Wreqr.Radio +// -------------- +// +// An object that lets you communicate with many channels. +Wreqr.radio = (function(Wreqr){ + "use strict"; + + var Radio = function() { + this._channels = {}; + this.vent = {}; + this.commands = {}; + this.reqres = {}; + this._proxyMethods(); + }; + + _.extend(Radio.prototype, { + + channel: function(channelName) { + if (!channelName) { + throw new Error('Channel must receive a name'); + } + + return this._getChannel( channelName ); + }, + + _getChannel: function(channelName) { + var channel = this._channels[channelName]; + + if(!channel) { + channel = new Wreqr.Channel(channelName); + this._channels[channelName] = channel; + } + + return channel; + }, + + _proxyMethods: function() { + _.each(['vent', 'commands', 'reqres'], function(system) { + _.each( messageSystems[system], function(method) { + this[system][method] = proxyMethod(this, system, method); + }, this); + }, this); + } + }); + + + var messageSystems = { + vent: [ + 'on', + 'off', + 'trigger', + 'once', + 'stopListening', + 'listenTo', + 'listenToOnce' + ], + + commands: [ + 'execute', + 'setHandler', + 'setHandlers', + 'removeHandler', + 'removeAllHandlers' + ], + + reqres: [ + 'request', + 'setHandler', + 'setHandlers', + 'removeHandler', + 'removeAllHandlers' + ] + }; + + var proxyMethod = function(radio, system, method) { + return function(channelName) { + var messageSystem = radio._getChannel(channelName)[system]; + var args = Array.prototype.slice.call(arguments, 1); + + messageSystem[method].apply(messageSystem, args); + }; + }; + + return new Radio(); + +})(Wreqr);