зеркало из https://github.com/nextcloud/spreed.git
add Backbone.Marionette
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
This commit is contained in:
Родитель
8f9cb3db4b
Коммит
1fbda6ed4b
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"directory": "js/vendor"
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "spreed",
|
||||
"authors": [
|
||||
"Christoph Wurst <christoph@winzerhof-wurst.at>"
|
||||
],
|
||||
"description": "",
|
||||
"main": "",
|
||||
"license": "AGPLv3",
|
||||
"homepage": "",
|
||||
"private": true,
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"core/vendor",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"backbone": "1.2.3",
|
||||
"backbone.marionette": "^3.1.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
"name": "backbone.marionette",
|
||||
"description": "The Backbone Framework",
|
||||
"homepage": "http://marionettejs.org",
|
||||
"main": "./lib/backbone.marionette.js",
|
||||
"version": "3.1.0",
|
||||
"keywords": [
|
||||
"backbone",
|
||||
"framework",
|
||||
"client",
|
||||
"browser",
|
||||
"composite"
|
||||
],
|
||||
"author": {
|
||||
"name": "Derick Bailey",
|
||||
"email": "derickbailey@gmail.com"
|
||||
},
|
||||
"ignore": [
|
||||
"api",
|
||||
"docs",
|
||||
"gulp",
|
||||
"jsdoc",
|
||||
"src",
|
||||
"tasks",
|
||||
"test",
|
||||
".babelrc",
|
||||
".editorconfig",
|
||||
".eslintrc",
|
||||
".gitignore",
|
||||
".jscsrc",
|
||||
".npmignore",
|
||||
".travis.yml",
|
||||
"CONTRIBUTING.md",
|
||||
"gulpfile.babel.js",
|
||||
"SpecRunner.html",
|
||||
"upgradeGuide.md"
|
||||
],
|
||||
"dependencies": {
|
||||
"backbone.radio": "^2.0.0"
|
||||
},
|
||||
"_release": "3.1.0",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v3.1.0",
|
||||
"commit": "c1d41d73c60ad117b285fd7495b4c1801ca1873d"
|
||||
},
|
||||
"_source": "https://github.com/marionettejs/backbone.marionette.git",
|
||||
"_target": "^3.1.0",
|
||||
"_originalSource": "backbone.marionette",
|
||||
"_direct": true
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
### Description
|
||||
|
||||
1. The problem you are facing (in as much detail as is necessary to describe the problem to someone who doesn't know anything about the system you're building)
|
||||
2. A summary of the proposed solution
|
||||
3. A description of how this solution solves the problem, in more detail than item #2
|
||||
4. Any additional discussion on possible problems this might introduce, questions that you have related to the changes, etc.
|
||||
|
||||
### Expected behavior
|
||||
|
||||
Tell us what you think should happen.
|
||||
|
||||
### Actual behavior
|
||||
|
||||
If possible, please create a small demo that demonstrates the issue.
|
||||
You can fork https://jsfiddle.net/marionettejs/adhv48ky/ for quick demo setup.
|
||||
Please refrain from giving code examples in altJS languages like CoffeeScript, etc. Marionette is written in plain-old JavaScript and is generally easier for all members in the community to read.
|
||||
|
||||
### Environment
|
||||
|
||||
1. Marionette version:
|
||||
2. Backbone version:
|
||||
3. Additional build tools, etc:
|
|
@ -0,0 +1,6 @@
|
|||
### Proposed changes
|
||||
-
|
||||
-
|
||||
-
|
||||
|
||||
Link to the issue:
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"name": "backbone.marionette",
|
||||
"description": "The Backbone Framework",
|
||||
"homepage": "http://marionettejs.org",
|
||||
"main": "./lib/backbone.marionette.js",
|
||||
"version": "3.1.0",
|
||||
"keywords": [
|
||||
"backbone",
|
||||
"framework",
|
||||
"client",
|
||||
"browser",
|
||||
"composite"
|
||||
],
|
||||
"author": {
|
||||
"name": "Derick Bailey",
|
||||
"email": "derickbailey@gmail.com"
|
||||
},
|
||||
"ignore": [
|
||||
"api",
|
||||
"docs",
|
||||
"gulp",
|
||||
"jsdoc",
|
||||
"src",
|
||||
"tasks",
|
||||
"test",
|
||||
".babelrc",
|
||||
".editorconfig",
|
||||
".eslintrc",
|
||||
".gitignore",
|
||||
".jscsrc",
|
||||
".npmignore",
|
||||
".travis.yml",
|
||||
"CONTRIBUTING.md",
|
||||
"gulpfile.babel.js",
|
||||
"SpecRunner.html",
|
||||
"upgradeGuide.md"
|
||||
],
|
||||
"dependencies": {
|
||||
"backbone.radio": "^2.0.0"
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1 @@
|
|||
MarionetteJS is distributed under [MIT license](http://mutedsolutions.mit-license.org/).
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 3.5 KiB |
|
@ -0,0 +1,90 @@
|
|||
{
|
||||
"name": "backbone.marionette",
|
||||
"description": "The Backbone Framework",
|
||||
"version": "3.1.0",
|
||||
"homepage": "https://github.com/marionettejs/backbone.marionette",
|
||||
"main": "lib/backbone.marionette.js",
|
||||
"keywords": [
|
||||
"backbone",
|
||||
"plugin",
|
||||
"marionette",
|
||||
"composite",
|
||||
"architecture",
|
||||
"single",
|
||||
"page",
|
||||
"app",
|
||||
"client",
|
||||
"browser"
|
||||
],
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "gulp build",
|
||||
"coverage": "gulp coverage",
|
||||
"coveralls": "gulp coveralls",
|
||||
"test": "gulp",
|
||||
"test-browser": "gulp test-browser"
|
||||
},
|
||||
"author": {
|
||||
"name": "Derick Bailey",
|
||||
"email": "derickbailey@gmail.com",
|
||||
"url": "http://derickbailey.com/"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/marionettejs/backbone.marionette/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/marionettejs/backbone.marionette.git"
|
||||
},
|
||||
"github": "https://github.com/marionettejs/backbone.marionette",
|
||||
"dependencies": {
|
||||
"backbone.radio": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"backbone": "~1.3.3",
|
||||
"underscore": "~1.8.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "6.17.0",
|
||||
"babel-eslint": "6.0.4",
|
||||
"babel-plugin-transform-regenerator": "6.16.1",
|
||||
"babel-polyfill": "6.6.1",
|
||||
"babel-preset-es2015": "6.16.0",
|
||||
"babel-preset-es2015-rollup": "1.1.1",
|
||||
"babel-register": "6.4.3",
|
||||
"backbone": "1.2.1 - 1.3.x",
|
||||
"chai": "3.4.0",
|
||||
"chai-jq": "0.0.9",
|
||||
"eslint": "3.2.2",
|
||||
"gulp": "3.9.0",
|
||||
"gulp-coveralls": "0.1.4",
|
||||
"gulp-eslint": "3.0.1",
|
||||
"gulp-file": "0.3.0",
|
||||
"gulp-filter": "3.0.1",
|
||||
"gulp-istanbul": "1.0.0",
|
||||
"gulp-lintspaces": "0.4.1",
|
||||
"gulp-livereload": "3.8.1",
|
||||
"gulp-mocha": "3.0.0",
|
||||
"gulp-plumber": "1.0.1",
|
||||
"gulp-rename": "1.2.2",
|
||||
"gulp-sourcemaps": "1.6.0",
|
||||
"gulp-uglify": "2.0.0",
|
||||
"gulp-util": "3.0.7",
|
||||
"isparta": "4.0.0",
|
||||
"jquery": "^3.1.0",
|
||||
"jsdom": "9.4.1",
|
||||
"mocha": "3.0.0",
|
||||
"opn": "4.0.2",
|
||||
"rollup": "0.34.3",
|
||||
"rollup-plugin-babel": "2.6.1",
|
||||
"rollup-plugin-commonjs": "3.3.1",
|
||||
"rollup-plugin-json": "2.0.1",
|
||||
"rollup-plugin-multi-entry": "2.0.1",
|
||||
"rollup-plugin-node-globals": "1.0.6",
|
||||
"rollup-plugin-node-resolve": "2.0.0",
|
||||
"run-sequence": "1.1.5",
|
||||
"sinon": "1.17.2",
|
||||
"sinon-chai": "2.8.0",
|
||||
"underscore": "1.8 - 1.8.3"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
<h1 align="center">Marionette.js</h1>
|
||||
<p align="center">
|
||||
<img title="backbone marionette" src='marionette-logo.png' />
|
||||
</p>
|
||||
<p align="center">The Backbone Framework</p>
|
||||
<p align="center">
|
||||
<a title='Build Status' href="https://travis-ci.org/marionettejs/backbone.marionette">
|
||||
<img src='https://secure.travis-ci.org/marionettejs/backbone.marionette.svg?branch=master' />
|
||||
</a>
|
||||
<a href='https://coveralls.io/r/marionettejs/backbone.marionette'>
|
||||
<img src='https://img.shields.io/coveralls/marionettejs/backbone.marionette.svg' alt='Coverage Status' />
|
||||
</a>
|
||||
<a href='https://gitter.im/marionettejs/backbone.marionette?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge'>
|
||||
<img src='https://badges.gitter.im/Join%20Chat.svg' alt='Gitter Chat' />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## Marionette v3
|
||||
|
||||
Marionette 3 is now available! See our
|
||||
[upgrade notes](http://marionettejs.com/docs/v3.0.0) for the differences between
|
||||
v2 and v3. Please let us know if you encounter any issues so we can resolve
|
||||
them and
|
||||
[help us continue work on Marionette!](https://github.com/marionettejs/backbone.marionette/milestones/v3.x)
|
||||
|
||||
## About Marionette
|
||||
|
||||
Marionette is a composite application library for Backbone.js that
|
||||
aims to simplify the construction of large scale JavaScript applications.
|
||||
It is a collection of common design and implementation patterns found in
|
||||
applications.
|
||||
|
||||
## Documentation
|
||||
|
||||
All of the documentation for Marionette can be found at
|
||||
|
||||
##### [marionettejs.com/docs/current](http://marionettejs.com/docs/current)
|
||||
|
||||
### App Architecture On Backbone's Building Blocks
|
||||
|
||||
Backbone provides a great set of building blocks for our JavaScript
|
||||
applications. It gives us the core constructs that are needed to build
|
||||
small apps, organize jQuery DOM events, or create single page apps that
|
||||
support mobile devices and large scale enterprise needs. But Backbone is
|
||||
not a complete framework. It's a set of building blocks. It leaves
|
||||
much of the application design, architecture and scalability to the
|
||||
developer, including memory management, view management, and more.
|
||||
|
||||
Marionette brings an application architecture to Backbone, along with
|
||||
built in view management and memory management. It's designed to be a
|
||||
lightweight and flexible library of tools that sits on top of Backbone,
|
||||
providing the framework for building a scalable application.
|
||||
|
||||
Like Backbone itself, you're not required to use all of Marionette just
|
||||
because you want to use some of it. You can pick and choose which features
|
||||
you want to use. This allows you to work with other Backbone
|
||||
frameworks and plugins easily. It also means that you are not required
|
||||
to engage in an all-or-nothing migration to begin using Marionette.
|
||||
|
||||
### Chat with us
|
||||
|
||||
Find us [on gitter](https://gitter.im/marionettejs/backbone.marionette) or on
|
||||
IRC in the FreeNode.net [#marionette channel](http://freenode.net).
|
||||
|
||||
We're happy to discuss design patterns and learn how you're using Marionette.
|
||||
|
||||
|
||||
### Key Benefits
|
||||
|
||||
* Scalable: applications built in modules with event-driven architecture
|
||||
* Sensible defaults: Underscore templates are used for view rendering
|
||||
* Easily modifiable: works with the specific needs of your application
|
||||
* Reduce boilerplate: for all views, including specialized types
|
||||
* Create: application visuals at runtime with `Region` and `View` objects
|
||||
* Nested: `View`s and `CollectionView`s within visual regions
|
||||
* Built-in: memory management and zombie-killing for `View`s, `CollectionViews`a and `Region`s
|
||||
* Event-driven architecture: utilizing `Backbone.Radio`
|
||||
* Flexible: "as-needed" architecture allowing you to pick and choose what you need
|
||||
* And much, much more
|
||||
|
||||
## Source Code and Downloads
|
||||
|
||||
You can
|
||||
[download the latest builds directly](https://github.com/marionettejs/backbone.marionette/tree/v3.0.0/lib)
|
||||
or visit the [downloads section on the Marionette website](http://marionettejs.com#download)
|
||||
for more downloading options.
|
||||
|
||||
#### [MarionetteJS.com](http://marionettejs.com#download)
|
||||
|
||||
### NPM and Bower
|
||||
|
||||
Marionette is available via bower and npm:
|
||||
|
||||
```bash
|
||||
# NPM
|
||||
npm install backbone.marionette
|
||||
|
||||
# Bower
|
||||
bower install marionette
|
||||
```
|
||||
|
||||
## Release Notes And Upgrade Guide
|
||||
|
||||
**Changelog**: For change logs and release notes, see the
|
||||
[changelog](changelog.md) file.
|
||||
|
||||
**Upgrade Guide**: Be sure to read [the upgrade guide](upgradeGuide.md)
|
||||
for information on upgrading to the latest version of Marionette.
|
||||
|
||||
|
||||
### Annotated Source Code
|
||||
|
||||
The source code for Marionette is heavily documented.
|
||||
You can read the annotations for all the details of how Marionette works and advice on which methods to override.
|
||||
|
||||
##### [View the annotated source code](http://marionettejs.com/annotated-src/backbone.marionette)
|
||||
|
||||
## Compatibility and Requirements
|
||||
|
||||
MarionetteJS currently works with the following libraries:
|
||||
|
||||
* [jQuery](http://jquery.com) v1.8+
|
||||
* [Underscore](http://underscorejs.org) v1.8.3
|
||||
* [Backbone](http://backbonejs.org) v1.3.3
|
||||
* [Backbone.Radio](https://github.com/marionettejs/backbone.radio) v2.0.0+
|
||||
|
||||
Marionette has not been tested against any other versions of these
|
||||
libraries. You may or may not have success if you use a version other
|
||||
than what is listed here.
|
||||
|
||||
## How to Contribute
|
||||
|
||||
If you would like to contribute to Marionette's source code, please read
|
||||
the [guidelines for pull requests and contributions](CONTRIBUTING.md).
|
||||
Following these guidelines will help make your contributions easier to
|
||||
bring into the next release.
|
||||
|
||||
### [Github Issues](https://github.com/marionettejs/backbone.marionette/issues)
|
||||
|
||||
Report issues with Marionette, submit pull requests to fix problems, or to
|
||||
create summarized and documented feature requests (preferably with pull
|
||||
requests that implement the feature).
|
|
@ -0,0 +1,32 @@
|
|||
var Travis = require('travis-ci');
|
||||
var repo = 'marionettejs/marionettejs.com';
|
||||
var travis = new Travis({
|
||||
version: '2.0.0',
|
||||
headers: {
|
||||
'User-Agent': 'Travis/1.0'
|
||||
}
|
||||
});
|
||||
|
||||
travis.authenticate({
|
||||
github_token: process.env.GH_TOKEN
|
||||
}, function (err, res) {
|
||||
if (err) {
|
||||
return console.error(err);
|
||||
}
|
||||
|
||||
//get repo builds
|
||||
travis.repos(repo.split('/')[0], repo.split('/')[1]).builds.get(function (err, res) {
|
||||
if (err) {
|
||||
return console.error(err);
|
||||
}
|
||||
//rebuild latest build
|
||||
travis.requests.post({
|
||||
build_id: res.builds[0].id
|
||||
}, function (err, res) {
|
||||
if (err) {
|
||||
return console.error(err);
|
||||
}
|
||||
console.log(res.flash[0].notice);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"name": "backbone.radio",
|
||||
"version": "2.0.0",
|
||||
"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"
|
||||
],
|
||||
"_release": "2.0.0",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v2.0.0",
|
||||
"commit": "8d3c7deec61205daddbd49ce86dbac27afb1aaad"
|
||||
},
|
||||
"_source": "https://github.com/marionettejs/backbone.radio.git",
|
||||
"_target": "^2.0.0",
|
||||
"_originalSource": "backbone.radio"
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
### [2.0.0](https://github.com/marionettejs/backbone.radio/releases/tag/2.0.0)
|
||||
|
||||
- Updated Backbone and Underscore version ranges.
|
||||
- Moved Backbone and Underscore to peerDependencies.
|
||||
|
||||
### [2.0.0-pre.2](https://github.com/marionettejs/backbone.radio/releases/tag/2.0.0-pre.2)
|
||||
|
||||
- Updated Backbone and Underscore version ranges.
|
||||
|
||||
### [2.0.0-pre.1](https://github.com/marionettejs/backbone.radio/releases/tag/2.0.0-pre.1)
|
||||
|
||||
- Moved Backbone and Underscore to peerDependencies.
|
||||
|
||||
### [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
|
|
@ -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.
|
|
@ -0,0 +1,353 @@
|
|||
# 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
|
||||
```
|
||||
|
||||
You must also ensure that Backbone.Radio's dependencies on Underscore (or Lodash) and Backbone are installed.
|
||||
|
||||
## 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();
|
||||
```
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"name": "backbone.radio",
|
||||
"version": "2.0.0",
|
||||
"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"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,350 @@
|
|||
// Backbone.Radio v2.0.0
|
||||
|
||||
(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 _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;
|
||||
};
|
||||
|
||||
var previousRadio = Backbone.Radio;
|
||||
|
||||
var Radio = Backbone.Radio = {};
|
||||
|
||||
Radio.VERSION = '2.0.0';
|
||||
|
||||
// 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' : _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
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,3 @@
|
|||
// Backbone.Radio v2.0.0
|
||||
!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];if(!(t&&t!==o.callback&&t!==o.callback._callback||r&&r!==o.context))return delete e[n],!0}function r(n,r,o,i){n||(n={});for(var s=r?[r]:e.keys(n),u=!1,c=0,a=s.length;c<a;c++)r=s[c],n[r]&&t(n,r,o,i)&&(u=!0);return u}function o(n){return l[n]||(l[n]=e.bind(c.log,c,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="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},u=n.Radio,c=n.Radio={};c.VERSION="2.0.0",c.noConflict=function(){return n.Radio=u,this},c.DEBUG=!1,c._debugText=function(e,n,t){return e+(t?" on the "+t+" channel":"")+': "'+n+'"'},c.debugLog=function(e,n,t){c.DEBUG&&console&&console.warn&&console.warn(c._debugText(e,n,t))};var a=/\s+/;c._eventsApi=function(n,t,r,o){if(!r)return!1;var i={};if("object"===("undefined"==typeof r?"undefined":s(r))){for(var u in r){var c=n[t].apply(n,[u,r[u]].concat(o));a.test(u)?e.extend(i,c):i[u]=c}return i}if(a.test(r)){for(var l=r.split(a),f=0,h=l.length;f<h;f++)i[l[f]]=n[t].apply(n,[l[f]].concat(o));return i}return!1},c._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(c,{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=c.channel(e);return n._tunedIn=!0,n.on("all",o(e)),this},tuneOut:function(e){var n=c.channel(e);return n._tunedIn=!1,n.off("all",o(e)),delete l[e],this}}),c.Requests={request:function(n){var t=e.toArray(arguments).slice(1),r=c._eventsApi(this,"request",n,t);if(r)return r;var o=this.channelName,i=this._requests;if(o&&this._tunedIn&&c.log.apply(this,[o,n].concat(t)),i&&(i[n]||i["default"])){var s=i[n]||i["default"];return t=i[n]?t:arguments,c._callHandler(s.callback,s.context,t)}c.debugLog("An unhandled request was fired",n,o)},reply:function(e,n,t){return c._eventsApi(this,"reply",e,[n,t])?this:(this._requests||(this._requests={}),this._requests[e]&&c.debugLog("A request was overwritten",e,this.channelName),this._requests[e]={callback:i(n),context:t||this},this)},replyOnce:function(n,t,r){if(c._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 c._eventsApi(this,"stopReplying",e)?this:(e||n||t?r(this._requests,e,n,t)||c.debugLog("Attempted to remove the unregistered request",e,this.channelName):delete this._requests,this)}},c._channels={},c.channel=function(e){if(!e)throw new Error("You must provide a name for the channel.");return c._channels[e]?c._channels[e]:c._channels[e]=new c.Channel(e)},c.Channel=function(e){this.channelName=e},e.extend(c.Channel.prototype,n.Events,c.Requests,{reset:function(){return this.off(),this.stopListening(),this.stopReplying(),this}});var f,h,d=[n.Events,c.Requests];return e.each(d,function(n){e.each(n,function(n,t){c[t]=function(n){return h=e.toArray(arguments).slice(1),f=this.channel(n),f[t].apply(f,h)}})}),c.reset=function(n){var t=n?[this._channels[n]]:this._channels;e.each(t,function(e){e.reset()})},c});
|
||||
//# sourceMappingURL=backbone.radio.min.js.map
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -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($.header(banner))
|
||||
.pipe($.sourcemaps.write('./'))
|
||||
.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']);
|
|
@ -0,0 +1,91 @@
|
|||
{
|
||||
"name": "backbone.radio",
|
||||
"description": "Messaging patterns for Backbone applications.",
|
||||
"homepage": "https://github.com/marionettejs/backbone.radio",
|
||||
"version": "2.0.0",
|
||||
"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",
|
||||
"peerDependencies": {
|
||||
"backbone": "^1.3.3",
|
||||
"underscore": "^1.8.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "6.7.0",
|
||||
"babel-eslint": "6.0.4",
|
||||
"babel-loader": "6.2.0",
|
||||
"babel-polyfill": "6.6.1",
|
||||
"babel-preset-es2015": "6.3.13",
|
||||
"babel-preset-es2015-rollup": "1.1.1",
|
||||
"babel-register": "6.4.3",
|
||||
"backbone": ">=1.3.3 <1.4.0",
|
||||
"chai": "3.4.1",
|
||||
"del": "2.2.0",
|
||||
"eslint": "3.2.2",
|
||||
"glob": "6.0.3",
|
||||
"gulp": "3.9.0",
|
||||
"gulp-eslint": "3.0.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",
|
||||
"underscore": "1.8.3",
|
||||
"webpack": "1.12.9",
|
||||
"webpack-stream": "3.1.0"
|
||||
},
|
||||
"babelBoilerplateOptions": {
|
||||
"entryFileName": "backbone.radio",
|
||||
"mainVarName": "Backbone.Radio"
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"name": "backbone",
|
||||
"main": "backbone.js",
|
||||
"dependencies": {
|
||||
"underscore": ">=1.7.0"
|
||||
},
|
||||
"ignore": [
|
||||
"docs",
|
||||
"examples",
|
||||
"test",
|
||||
"*.yml",
|
||||
"*.html",
|
||||
"*.ico",
|
||||
"*.md",
|
||||
"CNAME",
|
||||
".*",
|
||||
"karma.*",
|
||||
"component.json",
|
||||
"package.json"
|
||||
],
|
||||
"homepage": "https://github.com/jashkenas/backbone",
|
||||
"version": "1.2.3",
|
||||
"_release": "1.2.3",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "1.2.3",
|
||||
"commit": "05fde9e201f7e2137796663081105cd6dad12a98"
|
||||
},
|
||||
"_source": "https://github.com/jashkenas/backbone.git",
|
||||
"_target": "1.2.3",
|
||||
"_originalSource": "backbone"
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 2010-2015 Jeremy Ashkenas, DocumentCloud
|
||||
|
||||
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.
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name" : "backbone",
|
||||
"main" : "backbone.js",
|
||||
"dependencies" : {
|
||||
"underscore" : ">=1.7.0"
|
||||
},
|
||||
"ignore" : ["docs", "examples", "test", "*.yml", "*.html", "*.ico", "*.md", "CNAME", ".*", "karma.*", "component.json", "package.json"]
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "underscore",
|
||||
"version": "1.8.3",
|
||||
"main": "underscore.js",
|
||||
"keywords": [
|
||||
"util",
|
||||
"functional",
|
||||
"server",
|
||||
"client",
|
||||
"browser"
|
||||
],
|
||||
"ignore": [
|
||||
"docs",
|
||||
"test",
|
||||
"*.yml",
|
||||
"CNAME",
|
||||
"index.html",
|
||||
"favicon.ico",
|
||||
"CONTRIBUTING.md",
|
||||
".*",
|
||||
"component.json",
|
||||
"package.json",
|
||||
"karma.*"
|
||||
],
|
||||
"homepage": "https://github.com/jashkenas/underscore",
|
||||
"_release": "1.8.3",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "1.8.3",
|
||||
"commit": "e4743ab712b8ab42ad4ccb48b155034d02394e4d"
|
||||
},
|
||||
"_source": "https://github.com/jashkenas/underscore.git",
|
||||
"_target": ">=1.8.3",
|
||||
"_originalSource": "underscore"
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
Copyright (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative
|
||||
Reporters & Editors
|
||||
|
||||
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.
|
|
@ -0,0 +1,22 @@
|
|||
__
|
||||
/\ \ __
|
||||
__ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ /\_\ ____
|
||||
/\ \/\ \ /' _ `\ /'_ \ /'__`\/\ __\/ ,__\ / ___\ / __`\/\ __\/'__`\ \/\ \ /',__\
|
||||
\ \ \_\ \/\ \/\ \/\ \ \ \/\ __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\ __/ __ \ \ \/\__, `\
|
||||
\ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/
|
||||
\/___/ \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ \/____/\/___/ \/_/ \/____/\/_//\ \_\ \/___/
|
||||
\ \____/
|
||||
\/___/
|
||||
|
||||
Underscore.js is a utility-belt library for JavaScript that provides
|
||||
support for the usual functional suspects (each, map, reduce, filter...)
|
||||
without extending any core JavaScript objects.
|
||||
|
||||
For Docs, License, Tests, and pre-packed downloads, see:
|
||||
http://underscorejs.org
|
||||
|
||||
Underscore is an open-sourced component of DocumentCloud:
|
||||
https://github.com/documentcloud
|
||||
|
||||
Many thanks to our contributors:
|
||||
https://github.com/jashkenas/underscore/contributors
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"name": "underscore",
|
||||
"version": "1.8.3",
|
||||
"main": "underscore.js",
|
||||
"keywords": ["util", "functional", "server", "client", "browser"],
|
||||
"ignore" : ["docs", "test", "*.yml", "CNAME", "index.html", "favicon.ico", "CONTRIBUTING.md", ".*", "component.json", "package.json", "karma.*"]
|
||||
}
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -6,6 +6,8 @@ style('spreed', 'style');
|
|||
script(
|
||||
'spreed',
|
||||
[
|
||||
'vendor/backbone.radio/build/backbone.radio.min',
|
||||
'vendor/backbone.marionette/lib/backbone.marionette.min',
|
||||
'simplewebrtc',
|
||||
'xhrconnection',
|
||||
'rooms',
|
||||
|
|
Загрузка…
Ссылка в новой задаче