1
0
mirror of https://github.com/2ec0b4/kaamelott-soundboard.git synced 2025-12-10 16:35:34 +00:00

(master) Ajoute les dépendances manquantes

This commit is contained in:
Antoine
2023-10-30 08:04:13 +01:00
parent dca241fc0b
commit 8930cd2dc7
268 changed files with 83121 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
{
"name": "backbone.radio",
"version": "1.0.5",
"homepage": "https://github.com/marionettejs/backbone.radio",
"authors": [
"Jmeas <jellyes2@gmail.com>"
],
"description": "Messaging patterns for Backbone applications.",
"main": "build/backbone.radio.js",
"keywords": [
"backbone",
"marionette",
"decoupled",
"pubsub",
"publish",
"subscribe",
"messaging",
"architecture",
"spa"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"backbone": "1.0.0 - 1.3.x",
"underscore": "1.4.4 - 1.8.3"
},
"_release": "1.0.5",
"_resolution": {
"type": "version",
"tag": "v1.0.5",
"commit": "277936bb207583b64bdc3b71f039bf170ea0a393"
},
"_source": "https://github.com/marionettejs/backbone.radio.git",
"_target": "^1.0.5",
"_originalSource": "backbone.radio"
}

View File

@@ -0,0 +1,119 @@
### [1.0.5](https://github.com/marionettejs/backbone.radio/releases/tag/1.0.5)
- Updated Backbone dep to allow v1.3.3
### [1.0.4](https://github.com/marionettejs/backbone.radio/releases/tag/1.0.4)
- **Bug fix**: The UMD generated from rollup was setting `global` to `undefined`.
### [1.0.3](https://github.com/marionettejs/backbone.radio/releases/tag/1.0.3)
- Updated Backbone dep to allow v1.3.2
### [1.0.2](https://github.com/marionettejs/backbone.radio/releases/tag/1.0.2)
- Updated Backbone dep to allow v1.2.3
### [1.0.1](https://github.com/marionettejs/backbone.radio/releases/tag/1.0.1)
- Updated Backbone dep to allow v1.2.2
### [1.0.0](https://github.com/jmeas/backbone.radio/releases/tag/v1.0.0)
- **Breaking change**: Commands have been removed. ([see explanation](https://github.com/marionettejs/backbone.radio/pull/221#issuecomment-104782925))
### [0.9.1](https://github.com/jmeas/backbone.radio/releases/tag/v0.9.1)
- **Refactor**: Structure and build using babel-boilerplate
- Update Underscore and Backbone dependencies to 1.8.3 and 1.2.1 respectively to match Marionette.
### [0.9.0](https://github.com/jmeas/backbone.radio/releases/tag/v0.9.0)
- **Breaking change**: Space-separated requests no longer return an Array. Instead, an Object is returned.
```js
// old
myChannel.request('thingOne thingTwo');
// => [replyOne, replyTwo]
// new
myChannel.request('thingOne thingTwo');
// => { thingOne: replyOne, thingTwo: replyTwo }
```
- **New feature**: `Radio.reset()` is now a top-level API method that can be used to reset a channel, or all channels. Do note that channels continue to have their own `reset` method.
- **New feature**: `Radio.debugLog()` is now exposed...go forth and customize how Radio logs potential errors!
### [0.8.2](https://github.com/jmeas/backbone.radio/releases/tag/v0.8.2)
- **Refactor**: A small refactor to support Underscore 1.4.4 (the lowest version that Marionette supports)
### [0.8.1](https://github.com/jmeas/backbone.radio/releases/tag/v0.8.1)
- **Bug fix**: Fixes bug where `stopComplying` and `stopReplying` would not remove the correct
callbacks in certain situations
### [0.8.0](https://github.com/jmeas/backbone.radio/releases/tag/v0.8.0)
- **Feature**: DEBUG now warns when an already-registered Command or Request is overwritten
- **Feature**: `stopComplying` and `stopReplying` now accept the same arguments as `off`
### [0.7.2](https://github.com/jmeas/backbone.radio/releases/tag/v0.7.2)
- Corrects Underscore dependency in bower.json.
### [0.7.1](https://github.com/jmeas/backbone.radio/releases/tag/v0.7.1)
- Corrects Underscore dependency.
### [0.7.0](https://github.com/jmeas/backbone.radio/releases/tag/v0.7.0)
- **Feature**: All API methods of Commands ands Requests now support the space-separated syntax.
- **Enhancement**: Only Channels created through Radio's factory method will register themselves on the internal
store of Channels
- **Enhancement**: Callback execution has been optimized
### [0.6.0](https://github.com/jmeas/backbone.radio/releases/tag/v0.6.0)
*This update is not backwards compatible.*
- **Feature:** `channelName` is now a public property on each Channel.
- **Feature:** Requests and Commands can now have `"default"` handlers which will be called when the specified event isn't registered.
- **API Change:** The convenience connectX methods have been removed. In their place, the object syntax can be used for registering
multiple events on channels. This makes the API of Radio more consistent with Backbone.Events. For instance,
```js
myChannel.reply({
oneRequest: myCallback,
anotherRequest: myCallback
}, myContext);
```
### [0.5.2](https://github.com/jmeas/backbone.radio/releases/tag/v0.5.2)
- Fixes a bug where the top-level API would not pass the correct arguments to the underlying methods.
### [0.5.1](https://github.com/jmeas/backbone.radio/releases/tag/v0.5.1)
- Fixes Radio.VERSION in the built library
### [0.5.0](https://github.com/jmeas/backbone.radio/releases/tag/v0.5.0)
- Commands.react has been renamed to Commands.comply
### [0.4.1](https://github.com/jmeas/backbone.radio/releases/tag/v0.4.1)
- The Channel convenience methods no longer bind the context, instead deferring that
responsibility to the wrapped methods themselves. This aids in stack traces and gives you
the ability to unregister the methods individually.
### [0.4.0](https://github.com/jmeas/backbone.radio/releases/tag/v0.4.0)
- Debug mode now informs you when you attempt to unregister an event that was never registered. This is to help prevent memory leaks.
- `respond` has been renamed to `reply`
- More methods now return `this`, making the API more consistent internally, and with Backbone.Events
### [0.3.0](https://github.com/jmeas/backbone.radio/releases/tag/v0.3.0)
- More test coverage
- Tests completely rewritten
- Numerous bug fixes; more work on the library

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 James Smith
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.

View File

@@ -0,0 +1,351 @@
# Backbone.Radio
[![Travis Build Status](http://img.shields.io/travis/marionettejs/backbone.radio.svg?style=flat)](https://travis-ci.org/marionettejs/backbone.radio)
[![Coverage](http://img.shields.io/codeclimate/coverage/github/marionettejs/backbone.radio.svg?style=flat)](https://codeclimate.com/github/marionettejs/backbone.radio)
[![Dependency Status](http://img.shields.io/david/marionettejs/backbone.radio.svg?style=flat)](https://david-dm.org/marionettejs/backbone.radio)
[![Gitter chat room](https://img.shields.io/badge/gitter-backbone.radio-brightgreen.svg?style=flat)](https://gitter.im/marionettejs/backbone.radio)
Backbone.Radio provides additional messaging patterns for Backbone applications.
Backbone includes an event system, Backbone.Events, which is an implementation of the publish-subscribe pattern. Pub-sub is by far the most
common event pattern in client-side applications, and for good reason: it is incredibly useful. It should also be familiar to web developers
in particular, because the DOM relies heavily on pub-sub. Consider, for instance, registering a handler on an element's `click` event. This isn't
so much different than listening to a Model's `change` event, as both of these situations are using pub-sub.
Backbone.Radio adds two additional messaging-related features. The first is Requests, an implementation of the request-reply pattern. Request-reply
should also be familiar to web developers, as it's the messaging pattern that backs HTTP communications. The other feature are Channels: explicit
namespaces to your communications.
## Installation
Clone this repository or install via [Bower](http://bower.io/) or [npm](https://www.npmjs.org/).
```
bower install backbone.radio
npm install backbone.radio
```
## Documentation
- [Getting Started](#getting-started)
- [Backbone.Events](#backboneevents)
- [Radio.Requests](#backboneradiorequests)
- [Channels](#channels)
- [Using With Marionette](#using-with-marionette)
- [API](#api)
- [Radio.Requests](#requests)
- [Channel](#channel)
- [Radio](#radio)
- [Top-level API](#top-level-api)
## Getting Started
### Backbone.Events
Anyone who has used Backbone should be quite familiar with Backbone.Events. Backbone.Events is what facilitates
communications between objects in your application. The quintessential example of this is listening in on a
Model's change event.
```js
// Listen in on a model's change events
this.listenTo(someModel, 'change', myCallback);
// Later on, the model triggers a change event when it has been changed
someModel.trigger('change');
```
Let's look at a diagram for Backbone.Events:
<p align='center'>
<img src='https://cloud.githubusercontent.com/assets/10248067/11762943/5a927e54-a0bd-11e5-8aa5-e0fafae0e559.png' alt='Backbone.Events diagram'>
</p>
It goes without saying that Backbone.Events is incredibly useful when you mix it into instances of Classes. But what
if you had a standalone Object with an instance of Backbone.Events on it? This gives you a powerful message bus to utilize.
```js
// Create a message bus
var myBus = _.extend({}, Backbone.Events);
// Listen in on the message bus
this.listenTo(myBus, 'some:event', myCallback);
// Trigger an event on the bus
myBus.trigger('some:event');
```
As long as there was an easy way to access this message bus throughout your entire application, then you would have a central
place to store a collection of events. This is the idea behind Channels. But before we go more into that, let's take a look at Requests.
### Backbone.Radio.Requests
Requests is similar to Events in that it's another event system. And it has a similar API, too. For this reason, you *could* mix
it into an object.
```js
_.extend(myView, Backbone.Radio.Requests);
```
Although this works, I wouldn't recommend it. Requests are most useful, I think, when they're used with a Channel.
Perhaps the biggest difference between Events and Requests is that Requests have *intention*. Unlike Events, which notify
nothing in particular about an occurrence, Requests are asking for a very specific thing to occur. As a consequence of this,
requests are 'one-to-one,' which means that you cannot have multiple 'listeners' to a single request.
Let's look at a basic example.
```js
// Set up an object to reply to a request. In this case, whether or not its visible.
myObject.reply('visible', this.isVisible);
// Get whether it's visible or not.
var isViewVisible = myObject.request('visible');
```
The handler in `reply` can either return a flat value, like `true` or `false`, or a function to be executed. Either way, the value is sent back to
the requester.
Here's a diagram of the Requests pattern:
<p align='center'>
<img src='https://cloud.githubusercontent.com/assets/10248067/11762945/5c302a36-a0bd-11e5-8e4e-0eee7cacbef1.png' alt='Backbone.Requests diagram'>
</p>
Although the name is 'Requests,' you can just as easily request information as you can request that an action be completed. Just like HTTP,
where you can both make GET requests for information, or DELETE requests to order than a resource be deleted, Requests can be used for a variety
of purposes.
One thing to note is that this pattern is **identical** to a simple method call. One can just as easily rewrite the above example as:
```js
// Set up a method...
myObject.isVisible = function() {
return this.viewIsVisible;
}
// Call that method
var isViewVisible = myObject.isVisible();
```
This is why mixing Requests into something like a View or Model does not make much sense. If you have access to the View or Model, then
you might as well just use methods.
### Channels
The real draw of Backbone.Radio are Channels. A Channel is simply an object that has Backbone.Events and Radio.Requests mixed into it:
it's a standalone message bus comprised of both systems.
Getting a handle of a Channel is easy.
```js
// Get a reference to the channel named 'user'
var userChannel = Backbone.Radio.channel('user');
```
Once you've got a channel, you can attach handlers to it.
```js
userChannel.on('some:event', function() {
console.log('An event has happened!');
});
userChannel.reply('some:request', 'food is good');
```
You can also use the 'trigger' methods on the Channel.
```js
userChannel.trigger('some:event');
userChannel.request('some:request');
```
You can have as many channels as you'd like
```js
// Maybe you have a channel for the profile section of your app
var profileChannel = Backbone.Radio.channel('profile');
// And another one for settings
var settingsChannel = Backbone.Radio.channel('settings');
```
The whole point of Channels is that they provide a way to explicitly namespace events in your application, and a means to easily access
any of those namespaces.
### Using With Marionette
[Marionette](https://github.com/marionettejs/backbone.marionette) does not use Radio by default, although it will in the next major release: v3. However, you can use Radio today by including a small shim after you load Marionette, but before you load your application's code. To get the shim, refer to [this Gist](https://gist.github.com/jmeas/7992474cdb1c5672d88b).
## API
Like Backbone.Events, **all** of the following methods support both the object-syntax and space-separated syntax. For the sake of brevity,
I only provide examples for these alternate syntaxes in the most common use cases.
### Requests
#### `request( requestName [, args...] )`
Make a request for `requestName`. Optionally pass arguments to send along to the callback. Returns the reply, if one
exists. If there is no reply registered then `undefined` will be returned.
You can make multiple requests at once by using the space-separated syntax.
```js
myChannel.request('requestOne requestTwo');
```
When using the space-separated syntax, the responses will be returned to you as an object, where
the keys are the name of the request, and the values are the replies.
#### `reply( requestName, callback [, context] )`
Register a handler for `requestName` on this object. `callback` will be executed whenever the request is made. Optionally
pass a `context` for the callback, defaulting to `this`.
To register a default handler for Requests use the `default` requestName. The unhandled `requestName` will be passed as the first argument.
```js
myChannel.reply('default', function(requestName) {
console.log('No reply exists for this request: ' + requestName);
});
// This will be handled by the default request
myChannel.request('someUnhandledRequest');
```
To register multiple requests at once you may also pass in a hash.
```js
// Connect all of the replies at once
myChannel.reply({
'some:request': myCallback,
'some:other:request': someOtherCallback
}, context);
```
Returns the instance of Requests.
#### `replyOnce( requestName, callback [, context] )`
Register a handler for `requestName` that will only be called a single time.
Like `reply`, you may also pass a hash of replies to register many at once. Refer to the `reply` documentation above
for an example.
Returns the instance of Requests.
#### `stopReplying( [requestName] [, callback] [, context] )`
If `context` is passed, then all replies with that context will be removed from the object. If `callback` is
passed then all requests with that callback will be removed. If `requestName` is passed then this method will
remove that reply. If no arguments are passed then all replies are removed from the object.
You may also pass a hash of replies or space-separated replies to remove many at once.
Returns the instance of Requests.
### Channel
#### `channelName`
The name of the channel.
#### `reset()`
Destroy all handlers from Backbone.Events and Radio.Requests from the channel. Returns the channel.
### Radio
#### `channel( channelName )`
Get a reference to a channel by name. If a name is not provided an Error will be thrown.
```js
var authChannel = Backbone.Radio.channel('auth');
```
#### `DEBUG`
This is a Boolean property. Setting it to `true` will cause console warnings to be issued
whenever you interact with a `request` that isn't registered. This is useful in development when you want to
ensure that you've got your event names in order.
```js
// Turn on debug mode
Backbone.Radio.DEBUG = true;
// This will log a warning to the console if it goes unhandled
myChannel.request('show:view');
// Likewise, this will too, helping to prevent memory leaks
myChannel.stopReplying('startTime');
```
#### `debugLog(warning, eventName, channelName)`
A function executed whenever an unregistered request is interacted with on a Channel. Only
called when `DEBUG` is set to `true`. By overriding this you could, for instance, make unhandled
events throw Errors.
The warning is a string describing the type of problem, such as:
> Attempted to remove the unregistered request
while the `eventName` and `channelName` are what you would expect.
#### `tuneIn( channelName )`
Tuning into a Channel is another useful tool for debugging. It passes all
triggers and requests made on the channel to
[`Radio.log`](https://github.com/jmeas/backbone.radio#log-channelname-eventname--args-).
Returns `Backbone.Radio`.
```js
Backbone.Radio.tuneIn('calendar');
```
#### `tuneOut( channelName )`
Once you're done tuning in you can call `tuneOut` to stop the logging. Returns `Backbone.Radio`.
```js
Backbone.Radio.tuneOut('calendar');
```
#### `log( channelName, eventName [, args...] )`
When tuned into a Channel, this method will be called for all activity on
a channel. The default implementation is to `console.log` the following message:
```js
'[channelName] "eventName" args1 arg2 arg3...'
```
where args are all of the arguments passed with the message. It is exposed so that you
may overwrite it with your own logging message if you wish.
### 'Top-level' API
If you'd like to execute a method on a channel, yet you don't need to keep a handle of the
channel around, you can do so with the proxy functions directly on the `Backbone.Radio` object.
```js
// Trigger 'some:event' on the settings channel
Backbone.Radio.trigger('settings', 'some:event');
```
All of the methods for both messaging systems are available from the top-level API.
#### `reset( [channelName] )`
You can also reset a single channel, or all Channels, from the `Radio` object directly. Pass a
`channelName` to reset just that specific channel, or call the method without any arguments
to reset every channel.
```js
// Reset all channels
Radio.reset();
```

View File

@@ -0,0 +1,33 @@
{
"name": "backbone.radio",
"version": "1.0.4",
"homepage": "https://github.com/marionettejs/backbone.radio",
"authors": [
"Jmeas <jellyes2@gmail.com>"
],
"description": "Messaging patterns for Backbone applications.",
"main": "build/backbone.radio.js",
"keywords": [
"backbone",
"marionette",
"decoupled",
"pubsub",
"publish",
"subscribe",
"messaging",
"architecture",
"spa"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"backbone": "1.0.0 - 1.3.x",
"underscore": "1.4.4 - 1.8.3"
}
}

View File

@@ -0,0 +1,352 @@
// Backbone.Radio v1.0.4
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('underscore'), require('backbone')) :
typeof define === 'function' && define.amd ? define(['underscore', 'backbone'], factory) :
(global.Backbone = global.Backbone || {}, global.Backbone.Radio = factory(global._,global.Backbone));
}(this, function (_,Backbone) { 'use strict';
_ = 'default' in _ ? _['default'] : _;
Backbone = 'default' in Backbone ? Backbone['default'] : Backbone;
var babelHelpers = {};
babelHelpers.typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;
};
babelHelpers;
var previousRadio = Backbone.Radio;
var Radio = Backbone.Radio = {};
Radio.VERSION = '1.0.4';
// This allows you to run multiple instances of Radio on the same
// webapp. After loading the new version, call `noConflict()` to
// get a reference to it. At the same time the old version will be
// returned to Backbone.Radio.
Radio.noConflict = function () {
Backbone.Radio = previousRadio;
return this;
};
// Whether or not we're in DEBUG mode or not. DEBUG mode helps you
// get around the issues of lack of warnings when events are mis-typed.
Radio.DEBUG = false;
// Format debug text.
Radio._debugText = function (warning, eventName, channelName) {
return warning + (channelName ? ' on the ' + channelName + ' channel' : '') + ': "' + eventName + '"';
};
// This is the method that's called when an unregistered event was called.
// By default, it logs warning to the console. By overriding this you could
// make it throw an Error, for instance. This would make firing a nonexistent event
// have the same consequence as firing a nonexistent method on an Object.
Radio.debugLog = function (warning, eventName, channelName) {
if (Radio.DEBUG && console && console.warn) {
console.warn(Radio._debugText(warning, eventName, channelName));
}
};
var eventSplitter = /\s+/;
// An internal method used to handle Radio's method overloading for Requests.
// It's borrowed from Backbone.Events. It differs from Backbone's overload
// API (which is used in Backbone.Events) in that it doesn't support space-separated
// event names.
Radio._eventsApi = function (obj, action, name, rest) {
if (!name) {
return false;
}
var results = {};
// Handle event maps.
if ((typeof name === 'undefined' ? 'undefined' : babelHelpers.typeof(name)) === 'object') {
for (var key in name) {
var result = obj[action].apply(obj, [key, name[key]].concat(rest));
eventSplitter.test(key) ? _.extend(results, result) : results[key] = result;
}
return results;
}
// Handle space separated event names.
if (eventSplitter.test(name)) {
var names = name.split(eventSplitter);
for (var i = 0, l = names.length; i < l; i++) {
results[names[i]] = obj[action].apply(obj, [names[i]].concat(rest));
}
return results;
}
return false;
};
// An optimized way to execute callbacks.
Radio._callHandler = function (callback, context, args) {
var a1 = args[0],
a2 = args[1],
a3 = args[2];
switch (args.length) {
case 0:
return callback.call(context);
case 1:
return callback.call(context, a1);
case 2:
return callback.call(context, a1, a2);
case 3:
return callback.call(context, a1, a2, a3);
default:
return callback.apply(context, args);
}
};
// A helper used by `off` methods to the handler from the store
function removeHandler(store, name, callback, context) {
var event = store[name];
if ((!callback || callback === event.callback || callback === event.callback._callback) && (!context || context === event.context)) {
delete store[name];
return true;
}
}
function removeHandlers(store, name, callback, context) {
store || (store = {});
var names = name ? [name] : _.keys(store);
var matched = false;
for (var i = 0, length = names.length; i < length; i++) {
name = names[i];
// If there's no event by this name, log it and continue
// with the loop
if (!store[name]) {
continue;
}
if (removeHandler(store, name, callback, context)) {
matched = true;
}
}
return matched;
}
/*
* tune-in
* -------
* Get console logs of a channel's activity
*
*/
var _logs = {};
// This is to produce an identical function in both tuneIn and tuneOut,
// so that Backbone.Events unregisters it.
function _partial(channelName) {
return _logs[channelName] || (_logs[channelName] = _.bind(Radio.log, Radio, channelName));
}
_.extend(Radio, {
// Log information about the channel and event
log: function log(channelName, eventName) {
if (typeof console === 'undefined') {
return;
}
var args = _.toArray(arguments).slice(2);
console.log('[' + channelName + '] "' + eventName + '"', args);
},
// Logs all events on this channel to the console. It sets an
// internal value on the channel telling it we're listening,
// then sets a listener on the Backbone.Events
tuneIn: function tuneIn(channelName) {
var channel = Radio.channel(channelName);
channel._tunedIn = true;
channel.on('all', _partial(channelName));
return this;
},
// Stop logging all of the activities on this channel to the console
tuneOut: function tuneOut(channelName) {
var channel = Radio.channel(channelName);
channel._tunedIn = false;
channel.off('all', _partial(channelName));
delete _logs[channelName];
return this;
}
});
/*
* Backbone.Radio.Requests
* -----------------------
* A messaging system for requesting data.
*
*/
function makeCallback(callback) {
return _.isFunction(callback) ? callback : function () {
return callback;
};
}
Radio.Requests = {
// Make a request
request: function request(name) {
var args = _.toArray(arguments).slice(1);
var results = Radio._eventsApi(this, 'request', name, args);
if (results) {
return results;
}
var channelName = this.channelName;
var requests = this._requests;
// Check if we should log the request, and if so, do it
if (channelName && this._tunedIn) {
Radio.log.apply(this, [channelName, name].concat(args));
}
// If the request isn't handled, log it in DEBUG mode and exit
if (requests && (requests[name] || requests['default'])) {
var handler = requests[name] || requests['default'];
args = requests[name] ? args : arguments;
return Radio._callHandler(handler.callback, handler.context, args);
} else {
Radio.debugLog('An unhandled request was fired', name, channelName);
}
},
// Set up a handler for a request
reply: function reply(name, callback, context) {
if (Radio._eventsApi(this, 'reply', name, [callback, context])) {
return this;
}
this._requests || (this._requests = {});
if (this._requests[name]) {
Radio.debugLog('A request was overwritten', name, this.channelName);
}
this._requests[name] = {
callback: makeCallback(callback),
context: context || this
};
return this;
},
// Set up a handler that can only be requested once
replyOnce: function replyOnce(name, callback, context) {
if (Radio._eventsApi(this, 'replyOnce', name, [callback, context])) {
return this;
}
var self = this;
var once = _.once(function () {
self.stopReplying(name);
return makeCallback(callback).apply(this, arguments);
});
return this.reply(name, once, context);
},
// Remove handler(s)
stopReplying: function stopReplying(name, callback, context) {
if (Radio._eventsApi(this, 'stopReplying', name)) {
return this;
}
// Remove everything if there are no arguments passed
if (!name && !callback && !context) {
delete this._requests;
} else if (!removeHandlers(this._requests, name, callback, context)) {
Radio.debugLog('Attempted to remove the unregistered request', name, this.channelName);
}
return this;
}
};
/*
* Backbone.Radio.channel
* ----------------------
* Get a reference to a channel by name.
*
*/
Radio._channels = {};
Radio.channel = function (channelName) {
if (!channelName) {
throw new Error('You must provide a name for the channel.');
}
if (Radio._channels[channelName]) {
return Radio._channels[channelName];
} else {
return Radio._channels[channelName] = new Radio.Channel(channelName);
}
};
/*
* Backbone.Radio.Channel
* ----------------------
* A Channel is an object that extends from Backbone.Events,
* and Radio.Requests.
*
*/
Radio.Channel = function (channelName) {
this.channelName = channelName;
};
_.extend(Radio.Channel.prototype, Backbone.Events, Radio.Requests, {
// Remove all handlers from the messaging systems of this channel
reset: function reset() {
this.off();
this.stopListening();
this.stopReplying();
return this;
}
});
/*
* Top-level API
* -------------
* Supplies the 'top-level API' for working with Channels directly
* from Backbone.Radio.
*
*/
var channel;
var args;
var systems = [Backbone.Events, Radio.Requests];
_.each(systems, function (system) {
_.each(system, function (method, methodName) {
Radio[methodName] = function (channelName) {
args = _.toArray(arguments).slice(1);
channel = this.channel(channelName);
return channel[methodName].apply(channel, args);
};
});
});
Radio.reset = function (channelName) {
var channels = !channelName ? this._channels : [this._channels[channelName]];
_.each(channels, function (channel) {
channel.reset();
});
};
return Radio;
}));
//# sourceMappingURL=./backbone.radio.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
// Backbone.Radio v1.0.4
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n(require("underscore"),require("backbone")):"function"==typeof define&&define.amd?define(["underscore","backbone"],n):(e.Backbone=e.Backbone||{},e.Backbone.Radio=n(e._,e.Backbone))}(this,function(e,n){"use strict";function t(e,n,t,r){var o=e[n];return t&&t!==o.callback&&t!==o.callback._callback||r&&r!==o.context?void 0:(delete e[n],!0)}function r(n,r,o,i){n||(n={});for(var s=r?[r]:e.keys(n),u=!1,a=0,c=s.length;c>a;a++)r=s[a],n[r]&&t(n,r,o,i)&&(u=!0);return u}function o(n){return l[n]||(l[n]=e.bind(a.log,a,n))}function i(n){return e.isFunction(n)?n:function(){return n}}e="default"in e?e["default"]:e,n="default"in n?n["default"]:n;var s={};s["typeof"]="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};var u=n.Radio,a=n.Radio={};a.VERSION="1.0.4",a.noConflict=function(){return n.Radio=u,this},a.DEBUG=!1,a._debugText=function(e,n,t){return e+(t?" on the "+t+" channel":"")+': "'+n+'"'},a.debugLog=function(e,n,t){a.DEBUG&&console&&console.warn&&console.warn(a._debugText(e,n,t))};var c=/\s+/;a._eventsApi=function(n,t,r,o){if(!r)return!1;var i={};if("object"===("undefined"==typeof r?"undefined":s["typeof"](r))){for(var u in r){var a=n[t].apply(n,[u,r[u]].concat(o));c.test(u)?e.extend(i,a):i[u]=a}return i}if(c.test(r)){for(var l=r.split(c),f=0,h=l.length;h>f;f++)i[l[f]]=n[t].apply(n,[l[f]].concat(o));return i}return!1},a._callHandler=function(e,n,t){var r=t[0],o=t[1],i=t[2];switch(t.length){case 0:return e.call(n);case 1:return e.call(n,r);case 2:return e.call(n,r,o);case 3:return e.call(n,r,o,i);default:return e.apply(n,t)}};var l={};e.extend(a,{log:function(n,t){if("undefined"!=typeof console){var r=e.toArray(arguments).slice(2);console.log("["+n+'] "'+t+'"',r)}},tuneIn:function(e){var n=a.channel(e);return n._tunedIn=!0,n.on("all",o(e)),this},tuneOut:function(e){var n=a.channel(e);return n._tunedIn=!1,n.off("all",o(e)),delete l[e],this}}),a.Requests={request:function(n){var t=e.toArray(arguments).slice(1),r=a._eventsApi(this,"request",n,t);if(r)return r;var o=this.channelName,i=this._requests;if(o&&this._tunedIn&&a.log.apply(this,[o,n].concat(t)),i&&(i[n]||i["default"])){var s=i[n]||i["default"];return t=i[n]?t:arguments,a._callHandler(s.callback,s.context,t)}a.debugLog("An unhandled request was fired",n,o)},reply:function(e,n,t){return a._eventsApi(this,"reply",e,[n,t])?this:(this._requests||(this._requests={}),this._requests[e]&&a.debugLog("A request was overwritten",e,this.channelName),this._requests[e]={callback:i(n),context:t||this},this)},replyOnce:function(n,t,r){if(a._eventsApi(this,"replyOnce",n,[t,r]))return this;var o=this,s=e.once(function(){return o.stopReplying(n),i(t).apply(this,arguments)});return this.reply(n,s,r)},stopReplying:function(e,n,t){return a._eventsApi(this,"stopReplying",e)?this:(e||n||t?r(this._requests,e,n,t)||a.debugLog("Attempted to remove the unregistered request",e,this.channelName):delete this._requests,this)}},a._channels={},a.channel=function(e){if(!e)throw new Error("You must provide a name for the channel.");return a._channels[e]?a._channels[e]:a._channels[e]=new a.Channel(e)},a.Channel=function(e){this.channelName=e},e.extend(a.Channel.prototype,n.Events,a.Requests,{reset:function(){return this.off(),this.stopListening(),this.stopReplying(),this}});var f,h,d=[n.Events,a.Requests];return e.each(d,function(n){e.each(n,function(n,t){a[t]=function(n){return h=e.toArray(arguments).slice(1),f=this.channel(n),f[t].apply(f,h)}})}),a.reset=function(n){var t=n?[this._channels[n]]:this._channels;e.each(t,function(e){e.reset()})},a});
//# sourceMappingURL=backbone.radio.min.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,233 @@
import gulp from 'gulp';
import loadPlugins from 'gulp-load-plugins';
import del from 'del';
import glob from 'glob';
import path from 'path';
import {Instrumenter} from 'isparta';
import webpack from 'webpack';
import webpackStream from 'webpack-stream';
import _ from 'underscore';
import rollup from 'rollup';
import babel from 'rollup-plugin-babel';
import preset from 'babel-preset-es2015-rollup';
import fs from 'fs';
import mkdirp from 'mkdirp';
import mochaGlobals from './test/setup/.globals';
import manifest from './package.json';
// Load all of our Gulp plugins
const $ = loadPlugins();
// Gather the library data from `package.json`
const config = manifest.babelBoilerplateOptions;
const mainFile = manifest.main;
const destinationFolder = path.dirname(mainFile);
const exportFileName = path.basename(mainFile, path.extname(mainFile));
function cleanDist(done) {
del([destinationFolder]).then(() => done());
}
function cleanTmp(done) {
del(['tmp']).then(() => done());
}
function onError() {
$.util.beep();
}
// Lint a set of files
function lint(files) {
return gulp.src(files)
.pipe($.plumber())
.pipe($.eslint())
.pipe($.eslint.format())
.pipe($.eslint.failOnError())
.pipe($.jscs())
.pipe($.jscs.reporter())
.pipe($.jscs.reporter('fail'))
.on('error', onError);
}
function lintSrc() {
return lint('src/**/*.js');
}
function lintTest() {
return lint('test/**/*.js');
}
function lintGulpfile() {
return lint('gulpfile.babel.js');
}
function getBanner() {
var banner = '// Backbone.Radio v<%= version %>\n';
return _.template(banner)(manifest);
}
function build(done) {
rollup.rollup({
entry: path.join('src', config.entryFileName),
plugins: [
babel({
sourceMaps: true,
presets: [preset],
babelrc: false
})
]
}).then(function(bundle) {
var banner = getBanner();
var result = bundle.generate({
banner: banner,
format: 'umd',
sourceMap: 'inline',
sourceMapSource: config.entryFileName + '.js',
sourceMapFile: exportFileName + '.js',
moduleName: config.mainVarName
});
var code = _.template(result.code.toString())(manifest) +
`\n//# sourceMappingURL=./${exportFileName}.js.map`;
// Write the generated sourcemap
mkdirp.sync(destinationFolder);
fs.writeFileSync(path.join(destinationFolder, exportFileName + '.js'), code);
fs.writeFileSync(path.join(destinationFolder, `${exportFileName}.js.map`), result.map.toString());
$.file(exportFileName + '.js', code, { src: true })
.pipe($.plumber())
.pipe($.sourcemaps.init({ loadMaps: true }))
.pipe($.sourcemaps.write('./', {addComment: false}))
.pipe(gulp.dest(destinationFolder))
.pipe($.filter(['*', '!**/*.js.map']))
.pipe($.rename(exportFileName + '.min.js'))
.pipe($.sourcemaps.init({ loadMaps: true }))
.pipe($.uglify())
.pipe($.sourcemaps.write('./'))
.pipe($.header(banner))
.pipe(gulp.dest(destinationFolder))
.on('end', done);
}).catch(console.error);
}
function _mocha() {
return gulp.src(['test/setup/node.js', 'test/unit/**/*.js'], {read: false})
.pipe($.mocha({
reporter: 'dot',
globals: Object.keys(mochaGlobals.globals),
ignoreLeaks: false
}));
}
function _registerBabel() {
require('babel-register');
}
function test() {
_registerBabel();
return _mocha();
}
function coverage(done) {
_registerBabel();
gulp.src(['src/**/*.js'])
.pipe($.istanbul({ instrumenter: Instrumenter }))
.pipe($.istanbul.hookRequire())
.on('finish', () => {
return test()
.pipe($.istanbul.writeReports())
.on('end', done);
});
}
const watchFiles = ['src/**/*', 'test/**/*', 'package.json', '**/.eslintrc', '.jscsrc'];
// Run the headless unit tests as you make changes.
function watch() {
gulp.watch(watchFiles, ['test']);
}
function testBrowser() {
// Our testing bundle is made up of our unit tests, which
// should individually load up pieces of our application.
// We also include the browser setup file.
const testFiles = glob.sync('./test/unit/**/*.js');
const allFiles = ['./test/setup/browser.js'].concat(testFiles);
// Lets us differentiate between the first build and subsequent builds
var firstBuild = true;
// This empty stream might seem like a hack, but we need to specify all of our files through
// the `entry` option of webpack. Otherwise, it ignores whatever file(s) are placed in here.
return gulp.src('')
.pipe($.plumber())
.pipe(webpackStream({
watch: true,
entry: allFiles,
output: {
filename: '__spec-build.js'
},
module: {
loaders: [
// This is what allows us to author in future JavaScript
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' },
// This allows the test setup scripts to load `package.json`
{ test: /\.json$/, exclude: /node_modules/, loader: 'json-loader' }
]
},
plugins: [
// By default, webpack does `n=>n` compilation with entry files. This concatenates
// them into a single chunk.
new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 })
],
devtool: 'inline-source-map'
}, null, function() {
if (firstBuild) {
$.livereload.listen({port: 35729, host: 'localhost', start: true});
var watcher = gulp.watch(watchFiles, ['lint']);
} else {
$.livereload.reload('./tmp/__spec-build.js');
}
firstBuild = false;
}))
.pipe(gulp.dest('./tmp'));
}
// Remove the built files
gulp.task('clean', cleanDist);
// Remove our temporary files
gulp.task('clean-tmp', cleanTmp);
// Lint our source code
gulp.task('lint-src', lintSrc);
// Lint our test code
gulp.task('lint-test', lintTest);
// Lint this file
gulp.task('lint-gulpfile', lintGulpfile);
// Lint everything
gulp.task('lint', ['lint-src', 'lint-test', 'lint-gulpfile']);
// Build two versions of the library
gulp.task('build', ['lint', 'clean'], build);
// Lint and run our tests
gulp.task('test', ['lint'], test);
// Set up coverage and run tests
gulp.task('coverage', ['lint'], coverage);
// Set up a livereload environment for our spec runner `test/runner.html`
gulp.task('test-browser', ['lint', 'clean-tmp'], testBrowser);
// Run the headless unit tests as you make changes.
gulp.task('watch', watch);
// An alias of test
gulp.task('default', ['test']);

View File

@@ -0,0 +1,88 @@
{
"name": "backbone.radio",
"description": "Messaging patterns for Backbone applications.",
"homepage": "https://github.com/marionettejs/backbone.radio",
"version": "1.0.4",
"main": "build/backbone.radio.js",
"keywords": [
"backbone",
"marionette",
"decoupled",
"pubsub",
"publish",
"subscribe",
"messaging",
"architecture",
"spa"
],
"licenses": [
{
"type": "MIT",
"url": "https://github.com/marionettejs/backbone.radio/blob/master/LICENSE"
}
],
"scripts": {
"test": "gulp",
"test-browser": "gulp test-browser",
"build": "gulp build",
"coverage": "gulp coverage"
},
"author": {
"name": "Jmeas",
"email": "jellyes2@gmail.com",
"web": "http://jmeas.com"
},
"bugs": {
"url": "https://github.com/marionettejs/backbone.radio/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/marionettejs/backbone.radio.git"
},
"github": "https://github.com/marionettejs/backbone.radio",
"dependencies": {
"backbone": "1.0.0 - 1.3.x",
"underscore": "1.4.4 - 1.8.3"
},
"devDependencies": {
"babel-core": "^6.3.26",
"babel-eslint": "^4.1.6",
"babel-loader": "^6.2.0",
"babel-polyfill": "^6.3.14",
"babel-preset-es2015": "^6.3.13",
"babel-preset-es2015-rollup": "^1.1.1",
"babel-register": "^6.3.13",
"chai": "^3.4.1",
"del": "^2.2.0",
"glob": "^6.0.3",
"gulp": "^3.9.0",
"gulp-eslint": "^1.1.1",
"gulp-file": "^0.2.0",
"gulp-filter": "^3.0.0",
"gulp-header": "^1.7.1",
"gulp-istanbul": "^0.10.3",
"gulp-jscs": "^3.0.0",
"gulp-livereload": "^3.8.1",
"gulp-load-plugins": "^1.1.0",
"gulp-mocha": "^2.2.0",
"gulp-plumber": "^1.0.1",
"gulp-rename": "^1.2.2",
"gulp-sourcemaps": "^1.6.0",
"gulp-uglify": "^1.5.1",
"gulp-util": "^3.0.7",
"isparta": "^4.0.0",
"json-loader": "^0.5.3",
"mkdirp": "^0.5.1",
"mocha": "^2.3.4",
"rollup": "^0.25.4",
"rollup-plugin-babel": "^2.4.0",
"sinon": "^1.17.2",
"sinon-chai": "^2.8.0",
"webpack": "^1.12.9",
"webpack-stream": "^3.1.0"
},
"babelBoilerplateOptions": {
"entryFileName": "backbone.radio",
"mainVarName": "Backbone.Radio"
}
}

View File

@@ -0,0 +1,323 @@
import _ from 'underscore';
import Backbone from 'backbone';
var previousRadio = Backbone.Radio;
var Radio = Backbone.Radio = {};
Radio.VERSION = '<%= version %>';
// This allows you to run multiple instances of Radio on the same
// webapp. After loading the new version, call `noConflict()` to
// get a reference to it. At the same time the old version will be
// returned to Backbone.Radio.
Radio.noConflict = function() {
Backbone.Radio = previousRadio;
return this;
};
// Whether or not we're in DEBUG mode or not. DEBUG mode helps you
// get around the issues of lack of warnings when events are mis-typed.
Radio.DEBUG = false;
// Format debug text.
Radio._debugText = function(warning, eventName, channelName) {
return warning + (channelName ? ' on the ' + channelName + ' channel' : '') +
': "' + eventName + '"';
};
// This is the method that's called when an unregistered event was called.
// By default, it logs warning to the console. By overriding this you could
// make it throw an Error, for instance. This would make firing a nonexistent event
// have the same consequence as firing a nonexistent method on an Object.
Radio.debugLog = function(warning, eventName, channelName) {
if (Radio.DEBUG && console && console.warn) {
console.warn(Radio._debugText(warning, eventName, channelName));
}
};
var eventSplitter = /\s+/;
// An internal method used to handle Radio's method overloading for Requests.
// It's borrowed from Backbone.Events. It differs from Backbone's overload
// API (which is used in Backbone.Events) in that it doesn't support space-separated
// event names.
Radio._eventsApi = function(obj, action, name, rest) {
if (!name) {
return false;
}
var results = {};
// Handle event maps.
if (typeof name === 'object') {
for (var key in name) {
var result = obj[action].apply(obj, [key, name[key]].concat(rest));
eventSplitter.test(key) ? _.extend(results, result) : results[key] = result;
}
return results;
}
// Handle space separated event names.
if (eventSplitter.test(name)) {
var names = name.split(eventSplitter);
for (var i = 0, l = names.length; i < l; i++) {
results[names[i]] = obj[action].apply(obj, [names[i]].concat(rest));
}
return results;
}
return false;
};
// An optimized way to execute callbacks.
Radio._callHandler = function(callback, context, args) {
var a1 = args[0], a2 = args[1], a3 = args[2];
switch (args.length) {
case 0: return callback.call(context);
case 1: return callback.call(context, a1);
case 2: return callback.call(context, a1, a2);
case 3: return callback.call(context, a1, a2, a3);
default: return callback.apply(context, args);
}
};
// A helper used by `off` methods to the handler from the store
function removeHandler(store, name, callback, context) {
var event = store[name];
if (
(!callback || (callback === event.callback || callback === event.callback._callback)) &&
(!context || (context === event.context))
) {
delete store[name];
return true;
}
}
function removeHandlers(store, name, callback, context) {
store || (store = {});
var names = name ? [name] : _.keys(store);
var matched = false;
for (var i = 0, length = names.length; i < length; i++) {
name = names[i];
// If there's no event by this name, log it and continue
// with the loop
if (!store[name]) {
continue;
}
if (removeHandler(store, name, callback, context)) {
matched = true;
}
}
return matched;
}
/*
* tune-in
* -------
* Get console logs of a channel's activity
*
*/
var _logs = {};
// This is to produce an identical function in both tuneIn and tuneOut,
// so that Backbone.Events unregisters it.
function _partial(channelName) {
return _logs[channelName] || (_logs[channelName] = _.bind(Radio.log, Radio, channelName));
}
_.extend(Radio, {
// Log information about the channel and event
log: function(channelName, eventName) {
if (typeof console === 'undefined') { return; }
var args = _.toArray(arguments).slice(2);
console.log('[' + channelName + '] "' + eventName + '"', args);
},
// Logs all events on this channel to the console. It sets an
// internal value on the channel telling it we're listening,
// then sets a listener on the Backbone.Events
tuneIn: function(channelName) {
var channel = Radio.channel(channelName);
channel._tunedIn = true;
channel.on('all', _partial(channelName));
return this;
},
// Stop logging all of the activities on this channel to the console
tuneOut: function(channelName) {
var channel = Radio.channel(channelName);
channel._tunedIn = false;
channel.off('all', _partial(channelName));
delete _logs[channelName];
return this;
}
});
/*
* Backbone.Radio.Requests
* -----------------------
* A messaging system for requesting data.
*
*/
function makeCallback(callback) {
return _.isFunction(callback) ? callback : function() { return callback; };
}
Radio.Requests = {
// Make a request
request: function(name) {
var args = _.toArray(arguments).slice(1);
var results = Radio._eventsApi(this, 'request', name, args);
if (results) {
return results;
}
var channelName = this.channelName;
var requests = this._requests;
// Check if we should log the request, and if so, do it
if (channelName && this._tunedIn) {
Radio.log.apply(this, [channelName, name].concat(args));
}
// If the request isn't handled, log it in DEBUG mode and exit
if (requests && (requests[name] || requests['default'])) {
var handler = requests[name] || requests['default'];
args = requests[name] ? args : arguments;
return Radio._callHandler(handler.callback, handler.context, args);
} else {
Radio.debugLog('An unhandled request was fired', name, channelName);
}
},
// Set up a handler for a request
reply: function(name, callback, context) {
if (Radio._eventsApi(this, 'reply', name, [callback, context])) {
return this;
}
this._requests || (this._requests = {});
if (this._requests[name]) {
Radio.debugLog('A request was overwritten', name, this.channelName);
}
this._requests[name] = {
callback: makeCallback(callback),
context: context || this
};
return this;
},
// Set up a handler that can only be requested once
replyOnce: function(name, callback, context) {
if (Radio._eventsApi(this, 'replyOnce', name, [callback, context])) {
return this;
}
var self = this;
var once = _.once(function() {
self.stopReplying(name);
return makeCallback(callback).apply(this, arguments);
});
return this.reply(name, once, context);
},
// Remove handler(s)
stopReplying: function(name, callback, context) {
if (Radio._eventsApi(this, 'stopReplying', name)) {
return this;
}
// Remove everything if there are no arguments passed
if (!name && !callback && !context) {
delete this._requests;
} else if (!removeHandlers(this._requests, name, callback, context)) {
Radio.debugLog('Attempted to remove the unregistered request', name, this.channelName);
}
return this;
}
};
/*
* Backbone.Radio.channel
* ----------------------
* Get a reference to a channel by name.
*
*/
Radio._channels = {};
Radio.channel = function(channelName) {
if (!channelName) {
throw new Error('You must provide a name for the channel.');
}
if (Radio._channels[channelName]) {
return Radio._channels[channelName];
} else {
return (Radio._channels[channelName] = new Radio.Channel(channelName));
}
};
/*
* Backbone.Radio.Channel
* ----------------------
* A Channel is an object that extends from Backbone.Events,
* and Radio.Requests.
*
*/
Radio.Channel = function(channelName) {
this.channelName = channelName;
};
_.extend(Radio.Channel.prototype, Backbone.Events, Radio.Requests, {
// Remove all handlers from the messaging systems of this channel
reset: function() {
this.off();
this.stopListening();
this.stopReplying();
return this;
}
});
/*
* Top-level API
* -------------
* Supplies the 'top-level API' for working with Channels directly
* from Backbone.Radio.
*
*/
var channel, args, systems = [Backbone.Events, Radio.Requests];
_.each(systems, function(system) {
_.each(system, function(method, methodName) {
Radio[methodName] = function(channelName) {
args = _.toArray(arguments).slice(1);
channel = this.channel(channelName);
return channel[methodName].apply(channel, args);
};
});
});
Radio.reset = function(channelName) {
var channels = !channelName ? this._channels : [this._channels[channelName]];
_.each(channels, function(channel) { channel.reset();});
};
export default Radio;