Initial commit with build step
commit
046d444802
@ -0,0 +1,2 @@
|
|||||||
|
scripts/*
|
||||||
|
node_modules/*
|
@ -0,0 +1,3 @@
|
|||||||
|
node_modules/
|
||||||
|
npm-debug.log
|
||||||
|
static/
|
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"preset": "crockford",
|
||||||
|
"validateIndentation": 2,
|
||||||
|
"disallowMultipleVarDecl": true,
|
||||||
|
"disallowDanglingUnderscores": null,
|
||||||
|
"requireMultipleVarDecl": null
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"bitwise": true,
|
||||||
|
"camelcase": true,
|
||||||
|
"curly": true,
|
||||||
|
"enforceall": true,
|
||||||
|
"eqeqeq": true,
|
||||||
|
"es3": true,
|
||||||
|
"forin": true,
|
||||||
|
"freeze": true,
|
||||||
|
"immed": true,
|
||||||
|
"latedef": true,
|
||||||
|
"newcap": true,
|
||||||
|
"noarg": true,
|
||||||
|
"nocomma": false,
|
||||||
|
"noempty": true,
|
||||||
|
"nonbsp": true,
|
||||||
|
"nonew": true,
|
||||||
|
"notypeof": true,
|
||||||
|
"quotmark": true,
|
||||||
|
"singleGroups": true,
|
||||||
|
"undef": true,
|
||||||
|
"unused": true,
|
||||||
|
|
||||||
|
"eqnull": true,
|
||||||
|
|
||||||
|
"maxcomplexity": 4,
|
||||||
|
"maxdepth": 4,
|
||||||
|
"maxerr": 50,
|
||||||
|
"maxlen": 80,
|
||||||
|
"maxparams": 4,
|
||||||
|
|
||||||
|
"indent": 2,
|
||||||
|
"globals": {
|
||||||
|
"define": true,
|
||||||
|
"describe": true,
|
||||||
|
"expect": true,
|
||||||
|
"it": true,
|
||||||
|
"jasmine": true,
|
||||||
|
"module": true,
|
||||||
|
"require": true,
|
||||||
|
"requirejs": true,
|
||||||
|
"xdescribe": true,
|
||||||
|
"xit": true
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
FROM ubuntu:14.04
|
||||||
|
MAINTAINER Buddy Sandidge <buddy.sandidge@gmail.com>
|
||||||
|
|
||||||
|
# UTF-8 locale
|
||||||
|
RUN locale-gen en_US.UTF-8
|
||||||
|
ENV LANG en_US.UTF-8
|
||||||
|
ENV LANGUAGE en_US:en
|
||||||
|
ENV LC_ALL en_US.UTF-8
|
||||||
|
|
||||||
|
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe multiverse" \
|
||||||
|
> /etc/apt/sources.list.d/multiverse.list
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get upgrade -y && \
|
||||||
|
yes | apt-get install -y \
|
||||||
|
build-essential \
|
||||||
|
curl \
|
||||||
|
libfontconfig \
|
||||||
|
python \
|
||||||
|
ruby1.9.1-dev \
|
||||||
|
# For PhantomJS 2.0
|
||||||
|
g++ flex bison gperf ruby perl libsqlite3-dev libfontconfig1-dev \
|
||||||
|
libicu-dev libfreetype6 libssl-dev \
|
||||||
|
libpng-dev libjpeg-dev unzip ttf-mscorefonts-installer && \
|
||||||
|
rm -r /var/lib/apt/lists
|
||||||
|
|
||||||
|
# PhantomJS 2.0
|
||||||
|
# The linux binary is not yet available for download
|
||||||
|
# We need to build from source
|
||||||
|
RUN curl --silent --location --output /opt/phantomjs-2.0.0-source.zip \
|
||||||
|
https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.0.0-source.zip && \
|
||||||
|
unzip -q /opt/phantomjs-2.0.0-source.zip -d /opt && \
|
||||||
|
cd /opt/phantomjs-2.0.0 && ./build.sh --confirm && \
|
||||||
|
mv /opt/phantomjs-2.0.0/bin/phantomjs /usr/local/bin/phantomjs-2.0.0 && \
|
||||||
|
rm -r /opt/phantomjs-2.0.0/ && \
|
||||||
|
rm /opt/phantomjs-2.0.0-source.zip
|
||||||
|
|
||||||
|
# PhantomJS 1.9.8
|
||||||
|
RUN curl --location --silent --output /opt/phantom-1.9.8.tar.bz2 \
|
||||||
|
https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.8-linux-x86_64.tar.bz2 && \
|
||||||
|
mkdir /opt/phantomjs && \
|
||||||
|
tar xf /opt/phantom-1.9.8.tar.bz2 --strip-components 1 --directory /opt/phantomjs && \
|
||||||
|
mv /opt/phantomjs/bin/phantomjs /usr/local/bin/phantomjs-1.9.8 && \
|
||||||
|
rm -rf /opt/phantom-1.9.8.tar.bz2 /opt/phantomjs
|
||||||
|
|
||||||
|
# Compass
|
||||||
|
RUN gem install compass --version 1.0.1
|
||||||
|
|
||||||
|
# Node
|
||||||
|
ENV NODE_VERSION 0.10.35
|
||||||
|
RUN mkdir -p /opt/node && \
|
||||||
|
curl --silent --output /opt/node.tar.gz \
|
||||||
|
https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.gz && \
|
||||||
|
tar xzf /opt/node.tar.gz --strip-components 1 --directory /opt/node && \
|
||||||
|
rm /opt/node.tar.gz
|
||||||
|
|
||||||
|
RUN cd /usr/local/bin/ && ln -s phantomjs-1.9.8 phantomjs
|
||||||
|
|
||||||
|
ENV PATH /opt/node/bin:/opt/phantom-talk/node_modules/.bin:$PATH
|
||||||
|
ENV PHANTOMJS_BIN /usr/local/bin/phantomjs
|
||||||
|
|
||||||
|
# Mount this in the docker container
|
||||||
|
VOLUME ["/opt/phantom-talk"]
|
||||||
|
WORKDIR /opt/phantom-talk
|
||||||
|
COPY package.json /opt/phantom-talk/package.json
|
||||||
|
RUN ["npm", "install"]
|
||||||
|
EXPOSE 9900
|
||||||
|
ENTRYPOINT ["npm"]
|
@ -0,0 +1,93 @@
|
|||||||
|
var _ = require('lodash');
|
||||||
|
var requireConfig = require('./assets/app/config');
|
||||||
|
|
||||||
|
function buildRequireConfig(options) {
|
||||||
|
'use strict';
|
||||||
|
if (options == null) {
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
var ret = {};
|
||||||
|
_.extend(ret, requireConfig('../..'), options, {
|
||||||
|
baseUrl: 'static/app',
|
||||||
|
name: 'main',
|
||||||
|
optimize: 'none',
|
||||||
|
out: './static/app.js'
|
||||||
|
});
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function (grunt) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-compass');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-requirejs');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||||
|
grunt.loadNpmTasks('grunt-jscs');
|
||||||
|
grunt.loadNpmTasks('grunt-karma');
|
||||||
|
|
||||||
|
grunt.initConfig({
|
||||||
|
requirejs: {
|
||||||
|
build: {
|
||||||
|
options: buildRequireConfig({
|
||||||
|
generateSourceMaps: true,
|
||||||
|
optimize: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
copy: {
|
||||||
|
app: {
|
||||||
|
src: '**/*.js',
|
||||||
|
dest: '<%= clean.app %>',
|
||||||
|
cwd: './assets/app',
|
||||||
|
expand: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
clean: {
|
||||||
|
app: './static/app'
|
||||||
|
},
|
||||||
|
|
||||||
|
compass: {
|
||||||
|
dist: {
|
||||||
|
options: {
|
||||||
|
sassDir: 'assets/style',
|
||||||
|
cssDir: 'static/style',
|
||||||
|
importPath: ['vendor/normalize-scss']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
karma: {unit: {configFile: 'config/test.js'}},
|
||||||
|
|
||||||
|
jshint: {
|
||||||
|
options: {jshintrc: './.jshintrc'},
|
||||||
|
grunt: {
|
||||||
|
files: {src: 'Gruntfile.js'}
|
||||||
|
},
|
||||||
|
test: {
|
||||||
|
files: {src: './test/**/*.js'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
jscs: {
|
||||||
|
src: ['Gruntfile.js', 'test/**/*.js'],
|
||||||
|
options: {config: '.jscsrc'}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
grunt.registerTask('test', ['jshint', 'jscs', 'karma']);
|
||||||
|
grunt.registerTask('dev', ['default']);
|
||||||
|
|
||||||
|
grunt.registerTask('default', [
|
||||||
|
'clean',
|
||||||
|
'compass',
|
||||||
|
'copy',
|
||||||
|
'requirejs',
|
||||||
|
'jshint'
|
||||||
|
]);
|
||||||
|
};
|
@ -0,0 +1,22 @@
|
|||||||
|
define(['marionette', 'jquery'], function AppDefine(Marionette, $) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Application = Marionette.Application;
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
Application.apply(this, arguments);
|
||||||
|
}
|
||||||
|
App.prototype = new Application();
|
||||||
|
|
||||||
|
App.prototype.onStart = function onStart(options) {
|
||||||
|
if (options == null) {
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
if (options.el == null) {
|
||||||
|
options.el = 'body';
|
||||||
|
}
|
||||||
|
$(options.el).text('started');
|
||||||
|
};
|
||||||
|
|
||||||
|
return App;
|
||||||
|
});
|
@ -0,0 +1,28 @@
|
|||||||
|
(function (root, factory) {
|
||||||
|
'use strict';
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
define('config', [], factory);
|
||||||
|
} else if (typeof exports === 'object') {
|
||||||
|
module.exports = factory();
|
||||||
|
} else {
|
||||||
|
root.RequireConfig = factory();
|
||||||
|
}
|
||||||
|
}(this, function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
return function (prefix) {
|
||||||
|
prefix = prefix || '';
|
||||||
|
|
||||||
|
return {
|
||||||
|
paths: {
|
||||||
|
backbone: prefix + '/vendor/backbone/backbone',
|
||||||
|
jquery: prefix + '/vendor/jquery/dist/jquery',
|
||||||
|
marionette: prefix + '/vendor/marionette/lib/backbone.marionette',
|
||||||
|
underscore: prefix + '/vendor/underscore/underscore'
|
||||||
|
},
|
||||||
|
shim: {
|
||||||
|
underscore: {exports: '_'}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
@ -0,0 +1,9 @@
|
|||||||
|
define('main', ['config', 'app'], function main(config, App) {
|
||||||
|
'use strict';
|
||||||
|
requirejs.config(config());
|
||||||
|
return function main(options) {
|
||||||
|
var app = new App();
|
||||||
|
app.start(options);
|
||||||
|
return app;
|
||||||
|
};
|
||||||
|
});
|
@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<title></title>
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="/static/style/main.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="deck"></div>
|
||||||
|
<script src="/vendor/requirejs/require.js"></script>
|
||||||
|
<script src="/static/app.js"></script>
|
||||||
|
<script>
|
||||||
|
(function (global) {
|
||||||
|
require(['main'], function _main(main) {
|
||||||
|
global.app = main({el: '#deck'});
|
||||||
|
});
|
||||||
|
}(this));
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,4 @@
|
|||||||
|
@import "_normalize";
|
||||||
|
body {
|
||||||
|
background-color: #bada55;
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
//# vi: ft=javascript
|
||||||
|
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
var handlebars = require('handlebars');
|
||||||
|
var express = require('express');
|
||||||
|
|
||||||
|
var app = express();
|
||||||
|
var staticHandler = express['static'].bind(express);
|
||||||
|
|
||||||
|
app.get('/', function index(req, res) {
|
||||||
|
var indexFile = __dirname + '/../assets/index.html';
|
||||||
|
|
||||||
|
function compileServe(err, text) {
|
||||||
|
if (err) {
|
||||||
|
res.writeHead(500, {'Content-Type': 'text/plain'}, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var tmpl = handlebars.compile(text);
|
||||||
|
res.send(tmpl());
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.readFile(indexFile, {encoding: 'utf8'}, compileServe);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.use('/vendor', staticHandler('vendor'));
|
||||||
|
app.use('/static', staticHandler('static'));
|
||||||
|
|
||||||
|
app.listen(9900);
|
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "phantom-talk",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"authors": [
|
||||||
|
"Buddy Sandidge <buddy.sandidge@gmail.com>"
|
||||||
|
],
|
||||||
|
"description": "PhantomJS Talk for JS.LA",
|
||||||
|
"main": "bin/deck.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"private": true,
|
||||||
|
"ignore": [
|
||||||
|
"**/.*",
|
||||||
|
"node_modules",
|
||||||
|
"bower_components",
|
||||||
|
"vendor",
|
||||||
|
"test",
|
||||||
|
"tests"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"marionette": "~2.3.1",
|
||||||
|
"normalize-scss": "~3.0.2",
|
||||||
|
"requirejs": "~2.1.15"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
// Karma configuration
|
||||||
|
|
||||||
|
module.exports = function(config) {
|
||||||
|
config.set({
|
||||||
|
// base path that will be used to resolve all patterns (eg. files, exclude)
|
||||||
|
basePath: '..',
|
||||||
|
|
||||||
|
// frameworks to use
|
||||||
|
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||||
|
frameworks: ['jasmine', 'requirejs'],
|
||||||
|
|
||||||
|
// list of files / patterns to load in the browser
|
||||||
|
files: [
|
||||||
|
{pattern: 'vendor/**/*.js', included: false},
|
||||||
|
{pattern: 'test/**/!(test-main).js', included: false},
|
||||||
|
{pattern: 'static/**/!(config).js', included: false},
|
||||||
|
{pattern: 'static/**/*.map', included: false},
|
||||||
|
{pattern: 'static/app/config.js', included: true},
|
||||||
|
{pattern: 'test/test-main.js', included: true}
|
||||||
|
],
|
||||||
|
|
||||||
|
// list of files to exclude
|
||||||
|
exclude: ['**/*.swp'],
|
||||||
|
|
||||||
|
// preprocess matching files before serving them to the browser
|
||||||
|
// available preprocessors:
|
||||||
|
// https://npmjs.org/browse/keyword/karma-preprocessor
|
||||||
|
preprocessors: {},
|
||||||
|
|
||||||
|
// test results reporter to use
|
||||||
|
// possible values: 'dots', 'progress'
|
||||||
|
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||||
|
reporters: ['progress'],
|
||||||
|
|
||||||
|
// web server port
|
||||||
|
port: 9900,
|
||||||
|
|
||||||
|
// enable / disable colors in the output (reporters and logs)
|
||||||
|
colors: true,
|
||||||
|
|
||||||
|
// level of logging
|
||||||
|
// possible values: config.LOG_DISABLE || config.LOG_ERROR
|
||||||
|
// || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||||
|
logLevel: config.LOG_INFO,
|
||||||
|
|
||||||
|
// enable / disable watching file and executing tests
|
||||||
|
// whenever any file changes
|
||||||
|
autoWatch: false,
|
||||||
|
|
||||||
|
// start these browsers
|
||||||
|
// available browser launchers:
|
||||||
|
// https://npmjs.org/browse/keyword/karma-launcher
|
||||||
|
browsers: ['PhantomJS'],
|
||||||
|
|
||||||
|
// Continuous Integration mode
|
||||||
|
// if true, Karma captures browsers, runs the tests and exits
|
||||||
|
singleRun: true
|
||||||
|
});
|
||||||
|
};
|
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"name": "phantom-talk",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Slide deck for PhantomJS talk",
|
||||||
|
"main": "lib/deck.js",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "grunt dev",
|
||||||
|
"deck": "./bin/deck",
|
||||||
|
"test": "grunt test"
|
||||||
|
},
|
||||||
|
"author": "Buddy Sandidge",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"bower": "^1.3.12",
|
||||||
|
"grunt": "^0.4.5",
|
||||||
|
"grunt-cli": "^0.1.13",
|
||||||
|
"grunt-contrib-clean": "^0.6.0",
|
||||||
|
"grunt-contrib-compass": "^1.0.1",
|
||||||
|
"grunt-contrib-copy": "^0.7.0",
|
||||||
|
"grunt-contrib-handlebars": "^0.9.2",
|
||||||
|
"grunt-contrib-jshint": "^0.11.0",
|
||||||
|
"grunt-contrib-requirejs": "^0.4.4",
|
||||||
|
"grunt-contrib-watch": "^0.6.1",
|
||||||
|
"grunt-jscs": "^1.2.0",
|
||||||
|
"grunt-karma": "^0.10.1",
|
||||||
|
"jasmine-core": "^2.2.0",
|
||||||
|
"karma": "^0.12.31",
|
||||||
|
"karma-jasmine": "^0.3.5",
|
||||||
|
"karma-phantomjs-launcher": "^0.1.4",
|
||||||
|
"karma-requirejs": "^0.2.2",
|
||||||
|
"lodash": "^3.1.0",
|
||||||
|
"requirejs": "^2.1.15"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"express": "^4.11.2",
|
||||||
|
"handlebars": "^2.0.0"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
dir=$(dirname $0)
|
||||||
|
source $dir/common
|
||||||
|
|
||||||
|
docker run \
|
||||||
|
--interactive \
|
||||||
|
--tty \
|
||||||
|
--volume $(abspath $dir/..):/opt/phantom-talk \
|
||||||
|
--publish=9876:9876 \
|
||||||
|
--entrypoint /bin/bash \
|
||||||
|
phantom-talk
|
@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
docker build --tag phantom-talk $(dirname $0)/..
|
@ -0,0 +1,3 @@
|
|||||||
|
function abspath {
|
||||||
|
python -c 'import sys, os; print(os.path.abspath(sys.argv[1]))' "$1"
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
dir=$(dirname $0)
|
||||||
|
source $dir/common
|
||||||
|
|
||||||
|
docker run \
|
||||||
|
--volume $(abspath $dir/..):/opt/phantom-talk \
|
||||||
|
--publish 9900:9900 \
|
||||||
|
phantom-talk \
|
||||||
|
run dev
|
@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
dir=$(dirname $0)
|
||||||
|
source $dir/common
|
||||||
|
|
||||||
|
docker run \
|
||||||
|
--volume $(abspath $dir/..):/opt/phantom-talk \
|
||||||
|
--publish 9900:9900 \
|
||||||
|
phantom-talk \
|
||||||
|
run deck
|
@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
dir=$(dirname $0)
|
||||||
|
source $dir/common
|
||||||
|
|
||||||
|
docker run \
|
||||||
|
--volume $(abspath $dir/..):/opt/phantom-talk \
|
||||||
|
--publish 9900:9900 \
|
||||||
|
phantom-talk \
|
||||||
|
test
|
@ -0,0 +1,15 @@
|
|||||||
|
define(['app/app'], function (App) {
|
||||||
|
describe('App', function () {
|
||||||
|
it('→ exits`', function () {
|
||||||
|
expect(new App()).not.toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('→ start()`', function () {
|
||||||
|
it('→ can be called', function () {
|
||||||
|
expect(function noError() {
|
||||||
|
(new App()).start();
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,21 @@
|
|||||||
|
(function (root) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var testDir = /base\/test/;
|
||||||
|
var isTestMain = /test-main.js$/;
|
||||||
|
|
||||||
|
var tests = Object.keys(root.__karma__.files).filter(function (file) {
|
||||||
|
return testDir.test(file) && !isTestMain.test(file);
|
||||||
|
});
|
||||||
|
|
||||||
|
require(['config'], function configRequire(mkConfig) {
|
||||||
|
var config = mkConfig('/base');
|
||||||
|
|
||||||
|
config.deps = tests;
|
||||||
|
config.baseUrl = '/base/static';
|
||||||
|
config.callback = root.__karma__.start;
|
||||||
|
|
||||||
|
require.config(config);
|
||||||
|
});
|
||||||
|
|
||||||
|
}(this));
|
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"name": "backbone.babysitter",
|
||||||
|
"version": "0.1.6",
|
||||||
|
"homepage": "https://github.com/marionettejs/backbone.babysitter",
|
||||||
|
"authors": [
|
||||||
|
"Derick Bailey <derickbailey@gmail.com>"
|
||||||
|
],
|
||||||
|
"description": "Manage child views in a Backbone.View",
|
||||||
|
"main": "lib/backbone.babysitter.js",
|
||||||
|
"keywords": [
|
||||||
|
"backbone",
|
||||||
|
"plugin",
|
||||||
|
"computed",
|
||||||
|
"field",
|
||||||
|
"model",
|
||||||
|
"client",
|
||||||
|
"browser"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"backbone": ">=0.9.9 <=1.1.2",
|
||||||
|
"underscore": ">=1.4.0 <=1.6.0"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"ignore": [
|
||||||
|
"**/.*",
|
||||||
|
"node_modules",
|
||||||
|
"bower_components",
|
||||||
|
"test",
|
||||||
|
"tests"
|
||||||
|
],
|
||||||
|
"_release": "0.1.6",
|
||||||
|
"_resolution": {
|
||||||
|
"type": "version",
|
||||||
|
"tag": "v0.1.6",
|
||||||
|
"commit": "13af3ea9675368ba34b3aff3ba8ff0ecb03461c4"
|
||||||
|
},
|
||||||
|
"_source": "git://github.com/marionettejs/backbone.babysitter.git",
|
||||||
|
"_target": "^0.1.0",
|
||||||
|
"_originalSource": "backbone.babysitter"
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
# Change log
|
||||||
|
|
||||||
|
### v0.1.6
|
||||||
|
|
||||||
|
* Expose `reduce` to babysitter collections. Thanks @romanbsd
|
||||||
|
|
||||||
|
### v0.1.5
|
||||||
|
|
||||||
|
* Minor updates to bower.json
|
||||||
|
|
||||||
|
### v0.1.4
|
||||||
|
|
||||||
|
* Update UMD Wrapper and build process
|
||||||
|
|
||||||
|
### v0.1.2
|
||||||
|
|
||||||
|
* Add .VERSION and n.oConflict
|
||||||
|
* General cleanups to tests and package.json
|
||||||
|
* Add travis build info
|
||||||
|
|
||||||
|
### v0.1.1
|
||||||
|
* Remove AMD builds and replace with a single UMD style wrapper.
|
||||||
|
|
||||||
|
### v0.1.0
|
||||||
|
* allow chaining of add and remove methods
|
||||||
|
* add component.json
|
||||||
|
|
||||||
|
#### General
|
||||||
|
* update grunt file
|
||||||
|
* readme fixed
|
||||||
|
* fix gruntfile url
|
||||||
|
|
||||||
|
### v0.0.6
|
||||||
|
|
||||||
|
* Removed `.findByCollection` method
|
||||||
|
* Added `.findByModelCid` method
|
||||||
|
|
||||||
|
### v0.0.5
|
||||||
|
|
||||||
|
* Updated build process to use GruntJS v0.4
|
||||||
|
|
||||||
|
### v0.0.4
|
||||||
|
|
||||||
|
* Added a fix for IE < 9, when applying a function to the views
|
||||||
|
* Added `.pluck` as a method, from Underscore.js
|
||||||
|
* Can specify an array of views to the container constructor
|
||||||
|
|
||||||
|
### v0.0.3
|
||||||
|
|
||||||
|
* Added iterators and other collection processing functions from Underscore.js
|
||||||
|
|
||||||
|
### v0.0.2
|
||||||
|
|
||||||
|
* Added `.length` attribute
|
||||||
|
* Added `.findByIndex` method
|
||||||
|
|
||||||
|
### v0.0.1
|
||||||
|
|
||||||
|
* Initial release
|
@ -0,0 +1,130 @@
|
|||||||
|
/*global module:false*/
|
||||||
|
module.exports = function(grunt) {
|
||||||
|
|
||||||
|
// Project configuration.
|
||||||
|
grunt.initConfig({
|
||||||
|
pkg: grunt.file.readJSON('package.json'),
|
||||||
|
meta: {
|
||||||
|
version: '<%= pkg.version %>',
|
||||||
|
banner:
|
||||||
|
'// Backbone.BabySitter\n' +
|
||||||
|
'// -------------------\n' +
|
||||||
|
'// v<%= pkg.version %>\n' +
|
||||||
|
'//\n' +
|
||||||
|
'// Copyright (c)<%= grunt.template.today("yyyy") %> Derick Bailey, Muted Solutions, LLC.\n' +
|
||||||
|
'// Distributed under MIT license\n' +
|
||||||
|
'//\n' +
|
||||||
|
'// http://github.com/marionettejs/backbone.babysitter\n' +
|
||||||
|
'\n'
|
||||||
|
},
|
||||||
|
|
||||||
|
lint: {
|
||||||
|
files: ['src/*.js']
|
||||||
|
},
|
||||||
|
|
||||||
|
preprocess: {
|
||||||
|
umd: {
|
||||||
|
src: 'src/build/backbone.babysitter.js',
|
||||||
|
dest: 'lib/backbone.babysitter.js'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
template: {
|
||||||
|
options: {
|
||||||
|
data: {
|
||||||
|
version: '<%= meta.version %>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
umd: {
|
||||||
|
src: '<%= preprocess.umd.dest %>',
|
||||||
|
dest: '<%= preprocess.umd.dest %>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
concat: {
|
||||||
|
options: {
|
||||||
|
banner: "<%= meta.banner %>"
|
||||||
|
},
|
||||||
|
umd: {
|
||||||
|
src: '<%= preprocess.umd.dest %>',
|
||||||
|
dest: '<%= preprocess.umd.dest %>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
uglify : {
|
||||||
|
options: {
|
||||||
|
banner: "<%= meta.banner %>"
|
||||||
|
},
|
||||||
|
umd : {
|
||||||
|
src : 'lib/backbone.babysitter.js',
|
||||||
|
dest : 'lib/backbone.babysitter.min.js',
|
||||||
|
options : {
|
||||||
|
sourceMap : 'lib/backbone.babysitter.map',
|
||||||
|
sourceMappingURL : 'backbone.babysitter.map',
|
||||||
|
sourceMapPrefix : 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
jasmine : {
|
||||||
|
options : {
|
||||||
|
helpers : 'spec/javascripts/helpers/*.js',
|
||||||
|
specs : 'spec/javascripts/**/*.spec.js',
|
||||||
|
vendor : [
|
||||||
|
'public/javascripts/jquery.js',
|
||||||
|
'public/javascripts/json2.js',
|
||||||
|
'public/javascripts/underscore.js',
|
||||||
|
'public/javascripts/backbone.js'
|
||||||
|
],
|
||||||
|
},
|
||||||
|
babysitter : {
|
||||||
|
src : ['src/*.js']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
jshint: {
|
||||||
|
options: {
|
||||||
|
jshintrc : '.jshintrc'
|
||||||
|
},
|
||||||
|
babysitter : [ 'src/*.js' ]
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
babysitter : {
|
||||||
|
files : ['src/*.js', 'spec/**/*.js'],
|
||||||
|
tasks : ['jshint', 'jasmine:babysitter']
|
||||||
|
},
|
||||||
|
server : {
|
||||||
|
files : ['src/*.js', 'spec/**/*.js'],
|
||||||
|
tasks : ['jasmine:babysitter:build']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
connect: {
|
||||||
|
server: {
|
||||||
|
options: {
|
||||||
|
port: 8888
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
grunt.loadNpmTasks('grunt-preprocess');
|
||||||
|
grunt.loadNpmTasks('grunt-template');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-jasmine');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-connect');
|
||||||
|
|
||||||
|
grunt.registerTask('test', ['jshint', 'jasmine:babysitter']);
|
||||||
|
|
||||||
|
grunt.registerTask('dev', ['test', 'watch:babysitter']);
|
||||||
|
|
||||||
|
grunt.registerTask('server', ['jasmine:babysitter:build', 'connect:server', 'watch:server']);
|
||||||
|
|
||||||
|
// Default task.
|
||||||
|
grunt.registerTask('default', ['jshint', 'jasmine:babysitter', 'preprocess', 'template', 'concat', 'uglify']);
|
||||||
|
|
||||||
|
};
|
@ -0,0 +1,5 @@
|
|||||||
|
# Backbone.BabySitter
|
||||||
|
|
||||||
|
Copyright (C)2013 Derick Bailey, Muted Solutions, LLC
|
||||||
|
|
||||||
|
Distributed Under [MIT License](http://mutedsolutions.mit-license.org/)
|
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"name": "backbone.babysitter",
|
||||||
|
"version": "0.1.6",
|
||||||
|
"homepage": "https://github.com/marionettejs/backbone.babysitter",
|
||||||
|
"authors": [
|
||||||
|
"Derick Bailey <derickbailey@gmail.com>"
|
||||||
|
],
|
||||||
|
"description": "Manage child views in a Backbone.View",
|
||||||
|
"main": "lib/backbone.babysitter.js",
|
||||||
|
"keywords": [
|
||||||
|
"backbone",
|
||||||
|
"plugin",
|
||||||
|
"computed",
|
||||||
|
"field",
|
||||||
|
"model",
|
||||||
|
"client",
|
||||||
|
"browser"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"backbone": ">=0.9.9 <=1.1.2",
|
||||||
|
"underscore": ">=1.4.0 <=1.6.0"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"ignore": [
|
||||||
|
"**/.*",
|
||||||
|
"node_modules",
|
||||||
|
"bower_components",
|
||||||
|
"test",
|
||||||
|
"tests"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"name": "backbone.babysitter",
|
||||||
|
"description": "Manage child views in a Backbone.View",
|
||||||
|
"version": "0.1.4",
|
||||||
|
"repo": "marionettejs/backbone.babysitter",
|
||||||
|
"main": "lib/backbone.babysitter.js",
|
||||||
|
"keywords": [
|
||||||
|
"backbone",
|
||||||
|
"plugin",
|
||||||
|
"computed",
|
||||||
|
"field",
|
||||||
|
"model",
|
||||||
|
"client",
|
||||||
|
"browser"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"licenses": [
|
||||||
|
{
|
||||||
|
"type": "MIT",
|
||||||
|
"url": "https://github.com/marionettejs/backbone.babysitter/blob/master/LICENSE.md"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"scripts": [
|
||||||
|
"lib/backbone.babysitter.js"
|
||||||
|
],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "Derick Bailey",
|
||||||
|
"email": "marionettejs@gmail.com",
|
||||||
|
"web": "http://derickbailey.lostechies.com"
|
||||||
|
},
|
||||||
|
|
||||||
|
"dependencies": {
|
||||||
|
"jashkenas/backbone": "*",
|
||||||
|
"jashkenas/underscore": "*"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,190 @@
|
|||||||
|
// Backbone.BabySitter
|
||||||
|
// -------------------
|
||||||
|
// v0.1.6
|
||||||
|
//
|
||||||
|
// Copyright (c)2015 Derick Bailey, Muted Solutions, LLC.
|
||||||
|
// Distributed under MIT license
|
||||||
|
//
|
||||||
|
// http://github.com/marionettejs/backbone.babysitter
|
||||||
|
|
||||||
|
(function(root, factory) {
|
||||||
|
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
define(['backbone', 'underscore'], function(Backbone, _) {
|
||||||
|
return factory(Backbone, _);
|
||||||
|
});
|
||||||
|
} else if (typeof exports !== 'undefined') {
|
||||||
|
var Backbone = require('backbone');
|
||||||
|
var _ = require('underscore');
|
||||||
|
module.exports = factory(Backbone, _);
|
||||||
|
} else {
|
||||||
|
factory(root.Backbone, root._);
|
||||||
|
}
|
||||||
|
|
||||||
|
}(this, function(Backbone, _) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var previousChildViewContainer = Backbone.ChildViewContainer;
|
||||||
|
|
||||||
|
// BabySitter.ChildViewContainer
|
||||||
|
// -----------------------------
|
||||||
|
//
|
||||||
|
// Provide a container to store, retrieve and
|
||||||
|
// shut down child views.
|
||||||
|
|
||||||
|
Backbone.ChildViewContainer = (function (Backbone, _) {
|
||||||
|
|
||||||
|
// Container Constructor
|
||||||
|
// ---------------------
|
||||||
|
|
||||||
|
var Container = function(views){
|
||||||
|
this._views = {};
|
||||||
|
this._indexByModel = {};
|
||||||
|
this._indexByCustom = {};
|
||||||
|
this._updateLength();
|
||||||
|
|
||||||
|
_.each(views, this.add, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Container Methods
|
||||||
|
// -----------------
|
||||||
|
|
||||||
|
_.extend(Container.prototype, {
|
||||||
|
|
||||||
|
// Add a view to this container. Stores the view
|
||||||
|
// by `cid` and makes it searchable by the model
|
||||||
|
// cid (and model itself). Optionally specify
|
||||||
|
// a custom key to store an retrieve the view.
|
||||||
|
add: function(view, customIndex){
|
||||||
|
var viewCid = view.cid;
|
||||||
|
|
||||||
|
// store the view
|
||||||
|
this._views[viewCid] = view;
|
||||||
|
|
||||||
|
// index it by model
|
||||||
|
if (view.model){
|
||||||
|
this._indexByModel[view.model.cid] = viewCid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// index by custom
|
||||||
|
if (customIndex){
|
||||||
|
this._indexByCustom[customIndex] = viewCid;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._updateLength();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Find a view by the model that was attached to
|
||||||
|
// it. Uses the model's `cid` to find it.
|
||||||
|
findByModel: function(model){
|
||||||
|
return this.findByModelCid(model.cid);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Find a view by the `cid` of the model that was attached to
|
||||||
|
// it. Uses the model's `cid` to find the view `cid` and
|
||||||
|
// retrieve the view using it.
|
||||||
|
findByModelCid: function(modelCid){
|
||||||
|
var viewCid = this._indexByModel[modelCid];
|
||||||
|
return this.findByCid(viewCid);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Find a view by a custom indexer.
|
||||||
|
findByCustom: function(index){
|
||||||
|
var viewCid = this._indexByCustom[index];
|
||||||
|
return this.findByCid(viewCid);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Find by index. This is not guaranteed to be a
|
||||||
|
// stable index.
|
||||||
|
findByIndex: function(index){
|
||||||
|
return _.values(this._views)[index];
|
||||||
|
},
|
||||||
|
|
||||||
|
// retrieve a view by its `cid` directly
|
||||||
|
findByCid: function(cid){
|
||||||
|
return this._views[cid];
|
||||||
|
},
|
||||||
|
|
||||||
|
// Remove a view
|
||||||
|
remove: function(view){
|
||||||
|
var viewCid = view.cid;
|
||||||
|
|
||||||
|
// delete model index
|
||||||
|
if (view.model){
|
||||||
|
delete this._indexByModel[view.model.cid];
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete custom index
|
||||||
|
_.any(this._indexByCustom, function(cid, key) {
|
||||||
|
if (cid === viewCid) {
|
||||||
|
delete this._indexByCustom[key];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
// remove the view from the container
|
||||||
|
delete this._views[viewCid];
|
||||||
|
|
||||||
|
// update the length
|
||||||
|
this._updateLength();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Call a method on every view in the container,
|
||||||
|
// passing parameters to the call method one at a
|
||||||
|
// time, like `function.call`.
|
||||||
|
call: function(method){
|
||||||
|
this.apply(method, _.tail(arguments));
|
||||||
|
},
|
||||||
|
|
||||||
|
// Apply a method on every view in the container,
|
||||||
|
// passing parameters to the call method one at a
|
||||||
|
// time, like `function.apply`.
|
||||||
|
apply: function(method, args){
|
||||||
|
_.each(this._views, function(view){
|
||||||
|
if (_.isFunction(view[method])){
|
||||||
|
view[method].apply(view, args || []);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Update the `.length` attribute on this container
|
||||||
|
_updateLength: function(){
|
||||||
|
this.length = _.size(this._views);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Borrowing this code from Backbone.Collection:
|
||||||
|
// http://backbonejs.org/docs/backbone.html#section-106
|
||||||
|
//
|
||||||
|
// Mix in methods from Underscore, for iteration, and other
|
||||||
|
// collection related features.
|
||||||
|
var methods = ['forEach', 'each', 'map', 'find', 'detect', 'filter',
|
||||||
|
'select', 'reject', 'every', 'all', 'some', 'any', 'include',
|
||||||
|
'contains', 'invoke', 'toArray', 'first', 'initial', 'rest',
|
||||||
|
'last', 'without', 'isEmpty', 'pluck', 'reduce'];
|
||||||
|
|
||||||
|
_.each(methods, function(method) {
|
||||||
|
Container.prototype[method] = function() {
|
||||||
|
var views = _.values(this._views);
|
||||||
|
var args = [views].concat(_.toArray(arguments));
|
||||||
|
return _[method].apply(_, args);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// return the public API
|
||||||
|
return Container;
|
||||||
|
})(Backbone, _);
|
||||||
|
|
||||||
|
|
||||||
|
Backbone.ChildViewContainer.VERSION = '0.1.6';
|
||||||
|
|
||||||
|
Backbone.ChildViewContainer.noConflict = function () {
|
||||||
|
Backbone.ChildViewContainer = previousChildViewContainer;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
return Backbone.ChildViewContainer;
|
||||||
|
|
||||||
|
}));
|
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["?"],"names":["root","factory","define","amd","Backbone","_","exports","require","module","this","previousChildViewContainer","ChildViewContainer","Container","views","_views","_indexByModel","_indexByCustom","_updateLength","each","add","extend","prototype","view","customIndex","viewCid","cid","model","findByModel","findByModelCid","modelCid","findByCid","findByCustom","index","findByIndex","values","remove","any","key","call","method","apply","tail","arguments","args","isFunction","length","size","methods","concat","toArray","VERSION","noConflict"],"mappings":"CASC,SAASA,EAAMC,GAEd,GAAsB,kBAAXC,SAAyBA,OAAOC,IACzCD,QAAQ,WAAY,cAAe,SAASE,EAAUC,GACpD,MAAOJ,GAAQG,EAAUC,SAEtB,IAAuB,mBAAZC,SAAyB,CACzC,GAAIF,GAAWG,QAAQ,YACnBF,EAAIE,QAAQ,aAChBC,QAAOF,QAAUL,EAAQG,EAAUC,OAEnCJ,GAAQD,EAAKI,SAAUJ,EAAKK,KAG9BI,KAAM,SAASL,EAAUC,GACzB,YAEA,IAAIK,GAA6BN,EAASO,kBAiK1C,OAzJAP,GAASO,mBAAqB,SAAWP,EAAUC,GAKjD,GAAIO,GAAY,SAASC,GACvBJ,KAAKK,UACLL,KAAKM,iBACLN,KAAKO,kBACLP,KAAKQ,gBAELZ,EAAEa,KAAKL,EAAOJ,KAAKU,IAAKV,MAM1BJ,GAAEe,OAAOR,EAAUS,WAMjBF,IAAK,SAASG,EAAMC,GAClB,GAAIC,GAAUF,EAAKG,GAgBnB,OAbAhB,MAAKK,OAAOU,GAAWF,EAGnBA,EAAKI,QACPjB,KAAKM,cAAcO,EAAKI,MAAMD,KAAOD,GAInCD,IACFd,KAAKO,eAAeO,GAAeC,GAGrCf,KAAKQ,gBACER,MAKTkB,YAAa,SAASD,GACpB,MAAOjB,MAAKmB,eAAeF,EAAMD,MAMnCG,eAAgB,SAASC,GACvB,GAAIL,GAAUf,KAAKM,cAAcc,EACjC,OAAOpB,MAAKqB,UAAUN,IAIxBO,aAAc,SAASC,GACrB,GAAIR,GAAUf,KAAKO,eAAegB,EAClC,OAAOvB,MAAKqB,UAAUN,IAKxBS,YAAa,SAASD,GACpB,MAAO3B,GAAE6B,OAAOzB,KAAKK,QAAQkB,IAI/BF,UAAW,SAASL,GAClB,MAAOhB,MAAKK,OAAOW,IAIrBU,OAAQ,SAASb,GACf,GAAIE,GAAUF,EAAKG,GAoBnB,OAjBIH,GAAKI,aACAjB,MAAKM,cAAcO,EAAKI,MAAMD,KAIvCpB,EAAE+B,IAAI3B,KAAKO,eAAgB,SAASS,EAAKY,GACvC,MAAIZ,KAAQD,SACHf,MAAKO,eAAeqB,IACpB,GAFT,QAIC5B,YAGIA,MAAKK,OAAOU,GAGnBf,KAAKQ,gBACER,MAMT6B,KAAM,SAASC,GACb9B,KAAK+B,MAAMD,EAAQlC,EAAEoC,KAAKC,aAM5BF,MAAO,SAASD,EAAQI,GACtBtC,EAAEa,KAAKT,KAAKK,OAAQ,SAASQ,GACvBjB,EAAEuC,WAAWtB,EAAKiB,KACpBjB,EAAKiB,GAAQC,MAAMlB,EAAMqB,UAM/B1B,cAAe,WACbR,KAAKoC,OAASxC,EAAEyC,KAAKrC,KAAKK,UAS9B,IAAIiC,IAAW,UAAW,OAAQ,MAAO,OAAQ,SAAU,SACzD,SAAU,SAAU,QAAS,MAAO,OAAQ,MAAO,UACnD,WAAY,SAAU,UAAW,QAAS,UAAW,OACrD,OAAQ,UAAW,UAAW,QAAS,SAWzC,OATA1C,GAAEa,KAAK6B,EAAS,SAASR,GACvB3B,EAAUS,UAAUkB,GAAU,WAC5B,GAAI1B,GAAQR,EAAE6B,OAAOzB,KAAKK,QACtB6B,GAAQ9B,GAAOmC,OAAO3C,EAAE4C,QAAQP,WACpC,OAAOrC,GAAEkC,GAAQC,MAAMnC,EAAGsC,MAKvB/B,GACNR,EAAUC,GAGbD,EAASO,mBAAmBuC,QAAU,QAEtC9C,EAASO,mBAAmBwC,WAAa,WAEvC,MADA/C,GAASO,mBAAqBD,EACvBD,MAGFL,EAASO","file":"lib/backbone.babysitter.min.js"}
|
@ -0,0 +1,11 @@
|
|||||||
|
// Backbone.BabySitter
|
||||||
|
// -------------------
|
||||||
|
// v0.1.6
|
||||||
|
//
|
||||||
|
// Copyright (c)2015 Derick Bailey, Muted Solutions, LLC.
|
||||||
|
// Distributed under MIT license
|
||||||
|
//
|
||||||
|
// http://github.com/marionettejs/backbone.babysitter
|
||||||
|
|
||||||
|
(function(i,e){if("function"==typeof define&&define.amd)define(["backbone","underscore"],function(i,t){return e(i,t)});else if("undefined"!=typeof exports){var t=require("backbone"),n=require("underscore");module.exports=e(t,n)}else e(i.Backbone,i._)})(this,function(i,e){"use strict";var t=i.ChildViewContainer;return i.ChildViewContainer=function(i,e){var t=function(i){this._views={},this._indexByModel={},this._indexByCustom={},this._updateLength(),e.each(i,this.add,this)};e.extend(t.prototype,{add:function(i,e){var t=i.cid;return this._views[t]=i,i.model&&(this._indexByModel[i.model.cid]=t),e&&(this._indexByCustom[e]=t),this._updateLength(),this},findByModel:function(i){return this.findByModelCid(i.cid)},findByModelCid:function(i){var e=this._indexByModel[i];return this.findByCid(e)},findByCustom:function(i){var e=this._indexByCustom[i];return this.findByCid(e)},findByIndex:function(i){return e.values(this._views)[i]},findByCid:function(i){return this._views[i]},remove:function(i){var t=i.cid;return i.model&&delete this._indexByModel[i.model.cid],e.any(this._indexByCustom,function(i,e){return i===t?(delete this._indexByCustom[e],!0):void 0},this),delete this._views[t],this._updateLength(),this},call:function(i){this.apply(i,e.tail(arguments))},apply:function(i,t){e.each(this._views,function(n){e.isFunction(n[i])&&n[i].apply(n,t||[])})},_updateLength:function(){this.length=e.size(this._views)}});var n=["forEach","each","map","find","detect","filter","select","reject","every","all","some","any","include","contains","invoke","toArray","first","initial","rest","last","without","isEmpty","pluck","reduce"];return e.each(n,function(i){t.prototype[i]=function(){var t=e.values(this._views),n=[t].concat(e.toArray(arguments));return e[i].apply(e,n)}}),t}(i,e),i.ChildViewContainer.VERSION="0.1.6",i.ChildViewContainer.noConflict=function(){return i.ChildViewContainer=t,this},i.ChildViewContainer});
|
||||||
|
//@ sourceMappingURL=backbone.babysitter.map
|
@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"name": "backbone.babysitter",
|
||||||
|
"description": "Manage child views in a Backbone.View",
|
||||||
|
"version": "0.1.6",
|
||||||
|
"homepage": "https://github.com/marionettejs/backbone.babysitter",
|
||||||
|
"main": "lib/backbone.babysitter.js",
|
||||||
|
"keywords": [
|
||||||
|
"backbone",
|
||||||
|
"plugin",
|
||||||
|
"computed",
|
||||||
|
"field",
|
||||||
|
"model",
|
||||||
|
"client",
|
||||||
|
"browser"
|
||||||
|
],
|
||||||
|
"licenses": [
|
||||||
|
{
|
||||||
|
"type": "MIT",
|
||||||
|
"url": "https://github.com/marionettejs/backbone.babysitter/blob/master/LICENSE.md"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"test": "grunt jasmine",
|
||||||
|
"start": "grunt jasmine-server",
|
||||||
|
"build": "grunt"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"name": "Derick Bailey",
|
||||||
|
"email": "marionettejs@gmail.com",
|
||||||
|
"web": "http://derickbailey.lostechies.com"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/marionettejs/backbone.babysitter/issues"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/marionettejs/backbone.babysitter.git"
|
||||||
|
},
|
||||||
|
"github": "https://github.com/marionettejs/backbone.babysitter",
|
||||||
|
"dependencies": {
|
||||||
|
"backbone": ">=0.9.9 <=1.1.2",
|
||||||
|
"underscore": ">=1.4.0 <=1.6.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"grunt": "0.4.4",
|
||||||
|
"grunt-cli": "0.1.13",
|
||||||
|
"grunt-contrib-concat": "0.1.2",
|
||||||
|
"grunt-contrib-connect": "0.1.2",
|
||||||
|
"grunt-contrib-jasmine": "0.6.4",
|
||||||
|
"grunt-contrib-jshint": "0.1.1",
|
||||||
|
"grunt-contrib-uglify": "0.1.1",
|
||||||
|
"grunt-contrib-watch": "0.2.0",
|
||||||
|
"grunt-preprocess": "4.0.0",
|
||||||
|
"grunt-template": "0.2.3"
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,487 @@
|
|||||||
|
/*
|
||||||
|
http://www.JSON.org/json2.js
|
||||||
|
2011-10-19
|
||||||
|
|
||||||
|
Public Domain.
|
||||||
|
|
||||||
|
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||||
|
|
||||||
|
See http://www.JSON.org/js.html
|
||||||
|
|
||||||
|
|
||||||
|
This code should be minified before deployment.
|
||||||
|
See http://javascript.crockford.com/jsmin.html
|
||||||
|
|
||||||
|
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
||||||
|
NOT CONTROL.
|
||||||
|
|
||||||
|
|
||||||
|
This file creates a global JSON object containing two methods: stringify
|
||||||
|
and parse.
|
||||||
|
|
||||||
|
JSON.stringify(value, replacer, space)
|
||||||
|
value any JavaScript value, usually an object or array.
|
||||||
|
|
||||||
|
replacer an optional parameter that determines how object
|
||||||
|
values are stringified for objects. It can be a
|
||||||
|
function or an array of strings.
|
||||||
|
|
||||||
|
space an optional parameter that specifies the indentation
|
||||||
|
of nested structures. If it is omitted, the text will
|
||||||
|
be packed without extra whitespace. If it is a number,
|
||||||
|
it will specify the number of spaces to indent at each
|
||||||
|
level. If it is a string (such as '\t' or ' '),
|
||||||
|
it contains the characters used to indent at each level.
|
||||||
|
|
||||||
|
This method produces a JSON text from a JavaScript value.
|
||||||
|
|
||||||
|
When an object value is found, if the object contains a toJSON
|
||||||
|
method, its toJSON method will be called and the result will be
|
||||||
|
stringified. A toJSON method does not serialize: it returns the
|
||||||
|
value represented by the name/value pair that should be serialized,
|
||||||
|
or undefined if nothing should be serialized. The toJSON method
|
||||||
|
will be passed the key associated with the value, and this will be
|
||||||
|
bound to the value
|
||||||
|
|
||||||
|
For example, this would serialize Dates as ISO strings.
|
||||||
|
|
||||||
|
Date.prototype.toJSON = function (key) {
|
||||||
|
function f(n) {
|
||||||
|
// Format integers to have at least two digits.
|
||||||
|
return n < 10 ? '0' + n : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.getUTCFullYear() + '-' +
|
||||||
|
f(this.getUTCMonth() + 1) + '-' +
|
||||||
|
f(this.getUTCDate()) + 'T' +
|
||||||
|
f(this.getUTCHours()) + ':' +
|
||||||
|
f(this.getUTCMinutes()) + ':' +
|
||||||
|
f(this.getUTCSeconds()) + 'Z';
|
||||||
|
};
|
||||||
|
|
||||||
|
You can provide an optional replacer method. It will be passed the
|
||||||
|
key and value of each member, with this bound to the containing
|
||||||
|
object. The value that is returned from your method will be
|
||||||
|
serialized. If your method returns undefined, then the member will
|
||||||
|
be excluded from the serialization.
|
||||||
|
|
||||||
|
If the replacer parameter is an array of strings, then it will be
|
||||||
|
used to select the members to be serialized. It filters the results
|
||||||
|
such that only members with keys listed in the replacer array are
|
||||||
|
stringified.
|
||||||
|
|
||||||
|
Values that do not have JSON representations, such as undefined or
|
||||||
|
functions, will not be serialized. Such values in objects will be
|
||||||
|
dropped; in arrays they will be replaced with null. You can use
|
||||||
|
a replacer function to replace those with JSON values.
|
||||||
|
JSON.stringify(undefined) returns undefined.
|
||||||
|
|
||||||
|
The optional space parameter produces a stringification of the
|
||||||
|
value that is filled with line breaks and indentation to make it
|
||||||
|
easier to read.
|
||||||
|
|
||||||
|
If the space parameter is a non-empty string, then that string will
|
||||||
|
be used for indentation. If the space parameter is a number, then
|
||||||
|
the indentation will be that many spaces.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
||||||
|
// text is '["e",{"pluribus":"unum"}]'
|
||||||
|
|
||||||
|
|
||||||
|
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
||||||
|
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
||||||
|
|
||||||
|
text = JSON.stringify([new Date()], function (key, value) {
|
||||||
|
return this[key] instanceof Date ?
|
||||||
|
'Date(' + this[key] + ')' : value;
|
||||||
|
});
|
||||||
|
// text is '["Date(---current time---)"]'
|
||||||
|
|
||||||
|
|
||||||
|
JSON.parse(text, reviver)
|
||||||
|
This method parses a JSON text to produce an object or array.
|
||||||
|
It can throw a SyntaxError exception.
|
||||||
|
|
||||||
|
The optional reviver parameter is a function that can filter and
|
||||||
|
transform the results. It receives each of the keys and values,
|
||||||
|
and its return value is used instead of the original value.
|
||||||
|
If it returns what it received, then the structure is not modified.
|
||||||
|
If it returns undefined then the member is deleted.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
// Parse the text. Values that look like ISO date strings will
|
||||||
|
// be converted to Date objects.
|
||||||
|
|
||||||
|
myData = JSON.parse(text, function (key, value) {
|
||||||
|
var a;
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
a =
|
||||||
|
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
||||||
|
if (a) {
|
||||||
|
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
||||||
|
+a[5], +a[6]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
|
||||||
|
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
||||||
|
var d;
|
||||||
|
if (typeof value === 'string' &&
|
||||||
|
value.slice(0, 5) === 'Date(' &&
|
||||||
|
value.slice(-1) === ')') {
|
||||||
|
d = new Date(value.slice(5, -1));
|
||||||
|
if (d) {
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
This is a reference implementation. You are free to copy, modify, or
|
||||||
|
redistribute.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*jslint evil: true, regexp: true */
|
||||||
|
|
||||||
|
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
||||||
|
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
||||||
|
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
||||||
|
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
||||||
|
test, toJSON, toString, valueOf
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Create a JSON object only if one does not already exist. We create the
|
||||||
|
// methods in a closure to avoid creating global variables.
|
||||||
|
|
||||||
|
var JSON;
|
||||||
|
if (!JSON) {
|
||||||
|
JSON = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function f(n) {
|
||||||
|
// Format integers to have at least two digits.
|
||||||
|
return n < 10 ? '0' + n : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof Date.prototype.toJSON !== 'function') {
|
||||||
|
|
||||||
|
Date.prototype.toJSON = function (key) {
|
||||||
|
|
||||||
|
return isFinite(this.valueOf())
|
||||||
|
? this.getUTCFullYear() + '-' +
|
||||||
|
f(this.getUTCMonth() + 1) + '-' +
|
||||||
|
f(this.getUTCDate()) + 'T' +
|
||||||
|
f(this.getUTCHours()) + ':' +
|
||||||
|
f(this.getUTCMinutes()) + ':' +
|
||||||
|
f(this.getUTCSeconds()) + 'Z'
|
||||||
|
: null;
|
||||||
|
};
|
||||||
|
|
||||||
|
String.prototype.toJSON =
|
||||||
|
Number.prototype.toJSON =
|
||||||
|
Boolean.prototype.toJSON = function (key) {
|
||||||
|
return this.valueOf();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||||
|
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||||
|
gap,
|
||||||
|
indent,
|
||||||
|
meta = { // table of character substitutions
|
||||||
|
'\b': '\\b',
|
||||||
|
'\t': '\\t',
|
||||||
|
'\n': '\\n',
|
||||||
|
'\f': '\\f',
|
||||||
|
'\r': '\\r',
|
||||||
|
'"' : '\\"',
|
||||||
|
'\\': '\\\\'
|
||||||
|
},
|
||||||
|
rep;
|
||||||
|
|
||||||
|
|
||||||
|
function quote(string) {
|
||||||
|
|
||||||
|
// If the string contains no control characters, no quote characters, and no
|
||||||
|
// backslash characters, then we can safely slap some quotes around it.
|
||||||
|
// Otherwise we must also replace the offending characters with safe escape
|
||||||
|
// sequences.
|
||||||
|
|
||||||
|
escapable.lastIndex = 0;
|
||||||
|
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
|
||||||
|
var c = meta[a];
|
||||||
|
return typeof c === 'string'
|
||||||
|
? c
|
||||||
|
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||||
|
}) + '"' : '"' + string + '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function str(key, holder) {
|
||||||
|
|
||||||
|
// Produce a string from holder[key].
|
||||||
|
|
||||||
|
var i, // The loop counter.
|
||||||
|
k, // The member key.
|
||||||
|
v, // The member value.
|
||||||
|
length,
|
||||||
|
mind = gap,
|
||||||
|
partial,
|
||||||
|
value = holder[key];
|
||||||
|
|
||||||
|
// If the value has a toJSON method, call it to obtain a replacement value.
|
||||||
|
|
||||||
|
if (value && typeof value === 'object' &&
|
||||||
|
typeof value.toJSON === 'function') {
|
||||||
|
value = value.toJSON(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we were called with a replacer function, then call the replacer to
|
||||||
|
// obtain a replacement value.
|
||||||
|
|
||||||
|
if (typeof rep === 'function') {
|
||||||
|
value = rep.call(holder, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// What happens next depends on the value's type.
|
||||||
|
|
||||||
|
switch (typeof value) {
|
||||||
|
case 'string':
|
||||||
|
return quote(value);
|
||||||
|
|
||||||
|
case 'number':
|
||||||
|
|
||||||
|
// JSON numbers must be finite. Encode non-finite numbers as null.
|
||||||
|
|
||||||
|
return isFinite(value) ? String(value) : 'null';
|
||||||
|
|
||||||
|
case 'boolean':
|
||||||
|
case 'null':
|
||||||
|
|
||||||
|
// If the value is a boolean or null, convert it to a string. Note:
|
||||||
|
// typeof null does not produce 'null'. The case is included here in
|
||||||
|
// the remote chance that this gets fixed someday.
|
||||||
|
|
||||||
|
return String(value);
|
||||||
|
|
||||||
|
// If the type is 'object', we might be dealing with an object or an array or
|
||||||
|
// null.
|
||||||
|
|
||||||
|
case 'object':
|
||||||
|
|
||||||
|
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
||||||
|
// so watch out for that case.
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
return 'null';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make an array to hold the partial results of stringifying this object value.
|
||||||
|
|
||||||
|
gap += indent;
|
||||||
|
partial = [];
|
||||||
|
|
||||||
|
// Is the value an array?
|
||||||
|
|
||||||
|
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
||||||
|
|
||||||
|
// The value is an array. Stringify every element. Use null as a placeholder
|
||||||
|
// for non-JSON values.
|
||||||
|
|
||||||
|
length = value.length;
|
||||||
|
for (i = 0; i < length; i += 1) {
|
||||||
|
partial[i] = str(i, value) || 'null';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join all of the elements together, separated with commas, and wrap them in
|
||||||
|
// brackets.
|
||||||
|
|
||||||
|
v = partial.length === 0
|
||||||
|
? '[]'
|
||||||
|
: gap
|
||||||
|
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
|
||||||
|
: '[' + partial.join(',') + ']';
|
||||||
|
gap = mind;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the replacer is an array, use it to select the members to be stringified.
|
||||||
|
|
||||||
|
if (rep && typeof rep === 'object') {
|
||||||
|
length = rep.length;
|
||||||
|
for (i = 0; i < length; i += 1) {
|
||||||
|
if (typeof rep[i] === 'string') {
|
||||||
|
k = rep[i];
|
||||||
|
v = str(k, value);
|
||||||
|
if (v) {
|
||||||
|
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Otherwise, iterate through all of the keys in the object.
|
||||||
|
|
||||||
|
for (k in value) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
||||||
|
v = str(k, value);
|
||||||
|
if (v) {
|
||||||
|
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join all of the member texts together, separated with commas,
|
||||||
|
// and wrap them in braces.
|
||||||
|
|
||||||
|
v = partial.length === 0
|
||||||
|
? '{}'
|
||||||
|
: gap
|
||||||
|
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
|
||||||
|
: '{' + partial.join(',') + '}';
|
||||||
|
gap = mind;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the JSON object does not yet have a stringify method, give it one.
|
||||||
|
|
||||||
|
if (typeof JSON.stringify !== 'function') {
|
||||||
|
JSON.stringify = function (value, replacer, space) {
|
||||||
|
|
||||||
|
// The stringify method takes a value and an optional replacer, and an optional
|
||||||
|
// space parameter, and returns a JSON text. The replacer can be a function
|
||||||
|
// that can replace values, or an array of strings that will select the keys.
|
||||||
|
// A default replacer method can be provided. Use of the space parameter can
|
||||||
|
// produce text that is more easily readable.
|
||||||
|
|
||||||
|
var i;
|
||||||
|
gap = '';
|
||||||
|
indent = '';
|
||||||
|
|
||||||
|
// If the space parameter is a number, make an indent string containing that
|
||||||
|
// many spaces.
|
||||||
|
|
||||||
|
if (typeof space === 'number') {
|
||||||
|
for (i = 0; i < space; i += 1) {
|
||||||
|
indent += ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the space parameter is a string, it will be used as the indent string.
|
||||||
|
|
||||||
|
} else if (typeof space === 'string') {
|
||||||
|
indent = space;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is a replacer, it must be a function or an array.
|
||||||
|
// Otherwise, throw an error.
|
||||||
|
|
||||||
|
rep = replacer;
|
||||||
|
if (replacer && typeof replacer !== 'function' &&
|
||||||
|
(typeof replacer !== 'object' ||
|
||||||
|
typeof replacer.length !== 'number')) {
|
||||||
|
throw new Error('JSON.stringify');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a fake root object containing our value under the key of ''.
|
||||||
|
// Return the result of stringifying the value.
|
||||||
|
|
||||||
|
return str('', {'': value});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// If the JSON object does not yet have a parse method, give it one.
|
||||||
|
|
||||||
|
if (typeof JSON.parse !== 'function') {
|
||||||
|
JSON.parse = function (text, reviver) {
|
||||||
|
|
||||||
|
// The parse method takes a text and an optional reviver function, and returns
|
||||||
|
// a JavaScript value if the text is a valid JSON text.
|
||||||
|
|
||||||
|
var j;
|
||||||
|
|
||||||
|
function walk(holder, key) {
|
||||||
|
|
||||||
|
// The walk method is used to recursively walk the resulting structure so
|
||||||
|
// that modifications can be made.
|
||||||
|
|
||||||
|
var k, v, value = holder[key];
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
for (k in value) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
||||||
|
v = walk(value, k);
|
||||||
|
if (v !== undefined) {
|
||||||
|
value[k] = v;
|
||||||
|
} else {
|
||||||
|
delete value[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reviver.call(holder, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Parsing happens in four stages. In the first stage, we replace certain
|
||||||
|
// Unicode characters with escape sequences. JavaScript handles many characters
|
||||||
|
// incorrectly, either silently deleting them, or treating them as line endings.
|
||||||
|
|
||||||
|
text = String(text);
|
||||||
|
cx.lastIndex = 0;
|
||||||
|
if (cx.test(text)) {
|
||||||
|
text = text.replace(cx, function (a) {
|
||||||
|
return '\\u' +
|
||||||
|
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the second stage, we run the text against regular expressions that look
|
||||||
|
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
||||||
|
// because they can cause invocation, and '=' because it can cause mutation.
|
||||||
|
// But just to be safe, we want to reject all unexpected forms.
|
||||||
|
|
||||||
|
// We split the second stage into 4 regexp operations in order to work around
|
||||||
|
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
||||||
|
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
||||||
|
// replace all simple value tokens with ']' characters. Third, we delete all
|
||||||
|
// open brackets that follow a colon or comma or that begin the text. Finally,
|
||||||
|
// we look to see that the remaining characters are only whitespace or ']' or
|
||||||
|
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
||||||
|
|
||||||
|
if (/^[\],:{}\s]*$/
|
||||||
|
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
|
||||||
|
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
|
||||||
|
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
||||||
|
|
||||||
|
// In the third stage we use the eval function to compile the text into a
|
||||||
|
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
||||||
|
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
||||||
|
// in parens to eliminate the ambiguity.
|
||||||
|
|
||||||
|
j = eval('(' + text + ')');
|
||||||
|
|
||||||
|
// In the optional fourth stage, we recursively walk the new structure, passing
|
||||||
|
// each name/value pair to a reviver function for possible transformation.
|
||||||
|
|
||||||
|
return typeof reviver === 'function'
|
||||||
|
? walk({'': j}, '')
|
||||||
|
: j;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
||||||
|
|
||||||
|
throw new SyntaxError('JSON.parse');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}());
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,236 @@
|
|||||||
|
# Backbone.BabySitter
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/marionettejs/backbone.babysitter.svg?branch=master)](https://travis-ci.org/marionettejs/backbone.babysitter)
|
||||||
|
|
||||||
|
Manage child views in a Backbone.View.
|
||||||
|
|
||||||
|
## About Backbone.BabySitter
|
||||||
|
|
||||||
|
Backbone provides a lot of functionality in its views, but does not directly
|
||||||
|
provide a way to manage child views or nested views. This is not terribly
|
||||||
|
difficult to do on your own, but it gets tedious to write the same code
|
||||||
|
over and over again.
|
||||||
|
|
||||||
|
Backbone.BabySitter provides a simple way to manage an unknown number of
|
||||||
|
child views within a Backbone.View, or other object that needs to track a
|
||||||
|
list of views.
|
||||||
|
|
||||||
|
## Downloads And Source
|
||||||
|
|
||||||
|
Grab the source from the `src` folder above. Grab the most recent builds
|
||||||
|
from the links below.
|
||||||
|
|
||||||
|
* Development: [backbone.babysitter.js](https://raw.github.com/marionettejs/backbone.babysitter/master/lib/backbone.babysitter.js)
|
||||||
|
|
||||||
|
* Production: [backbone.babysitter.min.js](https://raw.github.com/marionettejs/backbone.babysitter/master/lib/backbone.babysitter.min.js)
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Backbone.BabySitter exposes one constructor function: `Backbone.ChildViewContainer`.
|
||||||
|
This constructor function contains all of the necessary code for managing a list of
|
||||||
|
views.
|
||||||
|
|
||||||
|
### Storing Views
|
||||||
|
|
||||||
|
Views can be added to a container by calling the `add` method:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var container = new Backbone.ChildViewContainer();
|
||||||
|
|
||||||
|
container.add(someView);
|
||||||
|
container.add(anotherView);
|
||||||
|
```
|
||||||
|
|
||||||
|
Views will be stored once and indexed in several ways:
|
||||||
|
|
||||||
|
* by `view.cid`
|
||||||
|
* by `view.model.cid` if the view has a model
|
||||||
|
* by a custom index key
|
||||||
|
|
||||||
|
When adding a view, you can optionally specify a custom index key
|
||||||
|
by which you can later retrieve the view.
|
||||||
|
|
||||||
|
```js
|
||||||
|
container.add(aView, "an indexer");
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the custom indexer should be unique within the container. If you
|
||||||
|
add two different views with the same custom indexer, the last one in will
|
||||||
|
be the only one stored by that index key.
|
||||||
|
|
||||||
|
### Constructing With Views
|
||||||
|
|
||||||
|
An initial list of views can be added to the container through the
|
||||||
|
constructor function call. This list must be an array of view instances:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var views = [someView, anotherView];
|
||||||
|
var container = new Backbone.ChildViewContainer(views);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Retrieving Views
|
||||||
|
|
||||||
|
You can retrieve a view by any of the index:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var container = new Backbone.ChildViewContainer();
|
||||||
|
|
||||||
|
container.add(someView);
|
||||||
|
container.add(anotherView);
|
||||||
|
container.add(collectionView);
|
||||||
|
container.add(aView, "an indexer");
|
||||||
|
|
||||||
|
// find by view cid
|
||||||
|
var s = container.findByCid(someView.cid);
|
||||||
|
|
||||||
|
// find by model
|
||||||
|
var av = container.findByModel(anotherView.model);
|
||||||
|
|
||||||
|
// find by model cid
|
||||||
|
var av2 = container.findByModelCid(anotherView.model.cid);
|
||||||
|
|
||||||
|
// find by custom key
|
||||||
|
var custv = container.findByCustom("an indexer");
|
||||||
|
|
||||||
|
// find by numeric index (unstable)
|
||||||
|
var custv = container.findByIndex(0);
|
||||||
|
```
|
||||||
|
|
||||||
|
If the `findBy*` method cannot find the view, it will return undefined.
|
||||||
|
|
||||||
|
### Removing A View
|
||||||
|
|
||||||
|
You can remove a view directly and it will be removed from all available
|
||||||
|
indexes.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var container = new Backbone.ChildViewContainer();
|
||||||
|
|
||||||
|
container.add(view);
|
||||||
|
|
||||||
|
// some time later
|
||||||
|
container.remove(view);
|
||||||
|
```
|
||||||
|
|
||||||
|
To remove a view by an index, find it by that index and then remove
|
||||||
|
the resulting view.
|
||||||
|
|
||||||
|
### Executing Methods On All Views
|
||||||
|
|
||||||
|
You can execute any arbitrary method with any arbitrary parameters on all of
|
||||||
|
the views within the container. There are two ways to do this: `container.call`
|
||||||
|
and `container.apply`. These methods work similarly to `function.call` and
|
||||||
|
`function.apply` in how parameters are passed through. However, they do not
|
||||||
|
allow the context to be specified. The view on which a method is being called
|
||||||
|
will always be the context of the call.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var View = Backbone.View.extend({
|
||||||
|
doStuff: function(a, b){
|
||||||
|
},
|
||||||
|
|
||||||
|
moreStuff: function(a, b){
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var v1 = new View();
|
||||||
|
var v2 = new View();
|
||||||
|
|
||||||
|
var container = new Backbone.ChildViewContainer();
|
||||||
|
container.add(v1);
|
||||||
|
container.add(v2);
|
||||||
|
|
||||||
|
// call the doStuff function
|
||||||
|
container.call("doStuff", 1, 2);
|
||||||
|
|
||||||
|
// apply the doStuff function
|
||||||
|
container.apply("doStuff", [1, 2]);
|
||||||
|
```
|
||||||
|
|
||||||
|
If any given view within the container does not have the method specified, it
|
||||||
|
will not be called on that view. No errors will be thrown in this situation.
|
||||||
|
|
||||||
|
### Get The Number Of Stored Views
|
||||||
|
|
||||||
|
To get the number of stored views, call the `container.length`
|
||||||
|
attribute. This attribute is updated any time a view is added or
|
||||||
|
removed.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var container = new Backbone.ChildViewContainer();
|
||||||
|
|
||||||
|
container.add(view);
|
||||||
|
container.add(v2);
|
||||||
|
container.add(v3);
|
||||||
|
|
||||||
|
console.log(container.length); //=> 3
|
||||||
|
|
||||||
|
container.remove(v2);
|
||||||
|
|
||||||
|
console.log(container.length); //=> 2
|
||||||
|
```
|
||||||
|
|
||||||
|
### Iterators And Collection Functions
|
||||||
|
|
||||||
|
The container object borrows several functions from Underscore.js, to
|
||||||
|
provide iterators and other collection functions, including:
|
||||||
|
|
||||||
|
* forEach
|
||||||
|
* each
|
||||||
|
* map
|
||||||
|
* reduce
|
||||||
|
* find
|
||||||
|
* detect
|
||||||
|
* filter
|
||||||
|
* select
|
||||||
|
* reject
|
||||||
|
* every
|
||||||
|
* all
|
||||||
|
* some
|
||||||
|
* any
|
||||||
|
* include
|
||||||
|
* contains
|
||||||
|
* invoke
|
||||||
|
* toArray
|
||||||
|
* first
|
||||||
|
* initial
|
||||||
|
* rest
|
||||||
|
* last
|
||||||
|
* without
|
||||||
|
* isEmpty
|
||||||
|
* pluck
|
||||||
|
|
||||||
|
These methods can be called directly on the container, to iterate and
|
||||||
|
process the views held by the container.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var container = new Backbone.ChildViewContainer();
|
||||||
|
|
||||||
|
container.add(v1);
|
||||||
|
container.add(v2);
|
||||||
|
container.add(v3);
|
||||||
|
|
||||||
|
// iterate over all of the views
|
||||||
|
container.each(function(view){
|
||||||
|
|
||||||
|
// process each view individually, here
|
||||||
|
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
For more information about these methods, see the [Underscore.js documentation](http://underscorejs.org).
|
||||||
|
|
||||||
|
## ChangeLog
|
||||||
|
|
||||||
|
For a complete change log, see the [CHANGELOG.md](https://github.com/marionettejs/backbone.babysitter/blob/master/CHANGELOG.md)
|
||||||
|
file.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT - see [LICENSE.md](https://github.com/marionettejs/backbone.babysitter/blob/master/LICENSE.md)
|
||||||
|
|
||||||
|
## Dev
|
||||||
|
|
||||||
|
* `npm install`
|
||||||
|
* `npm install -g grunt-cli`
|
||||||
|
* `grunt`
|
@ -0,0 +1,248 @@
|
|||||||
|
describe("childview container", function(){
|
||||||
|
|
||||||
|
describe("when providing an array of views to the constructor", function(){
|
||||||
|
var container;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
var views = [
|
||||||
|
new Backbone.View(),
|
||||||
|
new Backbone.View(),
|
||||||
|
new Backbone.View()
|
||||||
|
]
|
||||||
|
container = new Backbone.ChildViewContainer(views);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should add all of the views", function(){
|
||||||
|
expect(container.length).toBe(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when adding a view that does not have a model to the container", function(){
|
||||||
|
var container, view, foundView, indexView;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
view = new Backbone.View();
|
||||||
|
|
||||||
|
container = new Backbone.ChildViewContainer();
|
||||||
|
|
||||||
|
container.add(view);
|
||||||
|
|
||||||
|
foundView = container.findByCid(view.cid);
|
||||||
|
indexView = container.findByIndex(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should make the view retrievable by the view's cid", function(){
|
||||||
|
expect(foundView).toBe(view);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should make the view retrievable by numeric index", function(){
|
||||||
|
expect(indexView).toBe(view);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should update the size of the chidren", function(){
|
||||||
|
expect(container.length).toBe(1);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when adding a view that has a model, to the container", function(){
|
||||||
|
var container, view, foundView, model;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
model = new Backbone.Model();
|
||||||
|
view = new Backbone.View({
|
||||||
|
model: model
|
||||||
|
});
|
||||||
|
|
||||||
|
container = new Backbone.ChildViewContainer();
|
||||||
|
|
||||||
|
container.add(view);
|
||||||
|
|
||||||
|
foundView = container.findByModel(model);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should make the view retrievable by the model", function(){
|
||||||
|
expect(foundView).toBe(view);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when adding a view with a custom index value", function(){
|
||||||
|
var container, view, foundView;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
view = new Backbone.View();
|
||||||
|
|
||||||
|
container = new Backbone.ChildViewContainer();
|
||||||
|
|
||||||
|
container.add(view, "custom indexer");
|
||||||
|
|
||||||
|
foundView = container.findByCustom("custom indexer");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should make the view retrievable by the custom indexer", function(){
|
||||||
|
expect(foundView).toBe(view);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when removing a view", function(){
|
||||||
|
var container, view, model, col, cust;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
model = new Backbone.Model();
|
||||||
|
cust = "custome indexer";
|
||||||
|
|
||||||
|
view = new Backbone.View({
|
||||||
|
model: model
|
||||||
|
});
|
||||||
|
|
||||||
|
container = new Backbone.ChildViewContainer();
|
||||||
|
container.add(view, cust);
|
||||||
|
|
||||||
|
container.remove(view);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should update the size of the chidren", function(){
|
||||||
|
expect(container.length).toBe(0);
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should remove the index by model", function(){
|
||||||
|
var v = container.findByModel(model);
|
||||||
|
expect(v).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should remove the index by custom", function(){
|
||||||
|
var v = container.findByCustom(cust);
|
||||||
|
expect(v).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should remove the view from the container", function(){
|
||||||
|
var v = container.findByCid(view.cid);
|
||||||
|
expect(v).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("adding or removing a view", function(){
|
||||||
|
var container, view, model;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
model = new Backbone.Model();
|
||||||
|
|
||||||
|
view = new Backbone.View({
|
||||||
|
model: model
|
||||||
|
});
|
||||||
|
|
||||||
|
container = new Backbone.ChildViewContainer();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return itself when adding, for chaining methods", function(){
|
||||||
|
expect(container.add(view)).toBe(container);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return itself when removing, for chaining methods", function(){
|
||||||
|
expect(container.remove(view)).toBe(container);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when a container has 2 views in it", function(){
|
||||||
|
|
||||||
|
describe("and applying a method with parameters", function(){
|
||||||
|
var container, v1, v2;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
v1 = new Backbone.View();
|
||||||
|
v1.someFunc = jasmine.createSpy("some func");
|
||||||
|
|
||||||
|
v2 = new Backbone.View();
|
||||||
|
v2.someFunc = jasmine.createSpy("some func");
|
||||||
|
|
||||||
|
container = new Backbone.ChildViewContainer();
|
||||||
|
container.add(v1);
|
||||||
|
container.add(v2);
|
||||||
|
|
||||||
|
container.apply("someFunc", ["1", "2"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call that method on the first view", function(){
|
||||||
|
expect(v1.someFunc).toHaveBeenCalledWith("1", "2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call that method on the second view", function(){
|
||||||
|
expect(v2.someFunc).toHaveBeenCalledWith("1", "2");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("and calling a method with parameters", function(){
|
||||||
|
var container, v1, v2;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
v1 = new Backbone.View();
|
||||||
|
v1.someFunc = jasmine.createSpy("some func");
|
||||||
|
|
||||||
|
v2 = new Backbone.View();
|
||||||
|
v2.someFunc = jasmine.createSpy("some func");
|
||||||
|
|
||||||
|
container = new Backbone.ChildViewContainer();
|
||||||
|
container.add(v1);
|
||||||
|
container.add(v2);
|
||||||
|
|
||||||
|
container.call("someFunc", "1", "2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call that method on the first view", function(){
|
||||||
|
expect(v1.someFunc).toHaveBeenCalledWith("1", "2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call that method on the second view", function(){
|
||||||
|
expect(v2.someFunc).toHaveBeenCalledWith("1", "2");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("and calling a method that doesn't exist on one of the views", function(){
|
||||||
|
var container, v1, v2;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
v1 = new Backbone.View();
|
||||||
|
|
||||||
|
v2 = new Backbone.View();
|
||||||
|
v2.someFunc = jasmine.createSpy("some func");
|
||||||
|
|
||||||
|
container = new Backbone.ChildViewContainer();
|
||||||
|
container.add(v1);
|
||||||
|
container.add(v2);
|
||||||
|
|
||||||
|
container.call("someFunc", "1", "2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call that method on the second view", function(){
|
||||||
|
expect(v2.someFunc).toHaveBeenCalledWith("1", "2");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("iterators and collection functions", function(){
|
||||||
|
var container, view, views;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
views = [];
|
||||||
|
view = new Backbone.View();
|
||||||
|
|
||||||
|
container = new Backbone.ChildViewContainer();
|
||||||
|
container.add(view);
|
||||||
|
|
||||||
|
container.each(function(v, k){
|
||||||
|
views.push(v);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should provide a .each iterator", function(){
|
||||||
|
expect(_.isFunction(container.each)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should iterate the views with the .each function", function(){
|
||||||
|
expect(views[0]).toBe(view);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,8 @@
|
|||||||
|
beforeEach(function() {
|
||||||
|
jasmine.addMatchers({
|
||||||
|
toHaveOwnProperty: function(expectedProperty) {
|
||||||
|
var obj = this.actual;
|
||||||
|
return obj.hasOwnProperty(expectedProperty);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,31 @@
|
|||||||
|
(function(root, factory) {
|
||||||
|
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
define(['backbone', 'underscore'], function(Backbone, _) {
|
||||||
|
return factory(Backbone, _);
|
||||||
|
});
|
||||||
|
} else if (typeof exports !== 'undefined') {
|
||||||
|
var Backbone = require('backbone');
|
||||||
|
var _ = require('underscore');
|
||||||
|
module.exports = factory(Backbone, _);
|
||||||
|
} else {
|
||||||
|
factory(root.Backbone, root._);
|
||||||
|
}
|
||||||
|
|
||||||
|
}(this, function(Backbone, _) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var previousChildViewContainer = Backbone.ChildViewContainer;
|
||||||
|
|
||||||
|
// @include ../childviewcontainer.js
|
||||||
|
|
||||||
|
Backbone.ChildViewContainer.VERSION = '<%= version %>';
|
||||||
|
|
||||||
|
Backbone.ChildViewContainer.noConflict = function () {
|
||||||
|
Backbone.ChildViewContainer = previousChildViewContainer;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
return Backbone.ChildViewContainer;
|
||||||
|
|
||||||
|
}));
|
@ -0,0 +1,150 @@
|
|||||||
|
// BabySitter.ChildViewContainer
|
||||||
|
// -----------------------------
|
||||||
|
//
|
||||||
|
// Provide a container to store, retrieve and
|
||||||
|
// shut down child views.
|
||||||
|
|
||||||
|
Backbone.ChildViewContainer = (function (Backbone, _) {
|
||||||
|
|
||||||
|
// Container Constructor
|
||||||
|
// ---------------------
|
||||||
|
|
||||||
|
var Container = function(views){
|
||||||
|
this._views = {};
|
||||||
|
this._indexByModel = {};
|
||||||
|
this._indexByCustom = {};
|
||||||
|
this._updateLength();
|
||||||
|
|
||||||
|
_.each(views, this.add, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Container Methods
|
||||||
|
// -----------------
|
||||||
|
|
||||||
|
_.extend(Container.prototype, {
|
||||||
|
|
||||||
|
// Add a view to this container. Stores the view
|
||||||
|
// by `cid` and makes it searchable by the model
|
||||||
|
// cid (and model itself). Optionally specify
|
||||||
|
// a custom key to store an retrieve the view.
|
||||||
|
add: function(view, customIndex){
|
||||||
|
var viewCid = view.cid;
|
||||||
|
|
||||||
|
// store the view
|
||||||
|
this._views[viewCid] = view;
|
||||||
|
|
||||||
|
// index it by model
|
||||||
|
if (view.model){
|
||||||
|
this._indexByModel[view.model.cid] = viewCid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// index by custom
|
||||||
|
if (customIndex){
|
||||||
|
this._indexByCustom[customIndex] = viewCid;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._updateLength();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Find a view by the model that was attached to
|
||||||
|
// it. Uses the model's `cid` to find it.
|
||||||
|
findByModel: function(model){
|
||||||
|
return this.findByModelCid(model.cid);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Find a view by the `cid` of the model that was attached to
|
||||||
|
// it. Uses the model's `cid` to find the view `cid` and
|
||||||
|
// retrieve the view using it.
|
||||||
|
findByModelCid: function(modelCid){
|
||||||
|
var viewCid = this._indexByModel[modelCid];
|
||||||
|
return this.findByCid(viewCid);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Find a view by a custom indexer.
|
||||||
|
findByCustom: function(index){
|
||||||
|
var viewCid = this._indexByCustom[index];
|
||||||
|
return this.findByCid(viewCid);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Find by index. This is not guaranteed to be a
|
||||||
|
// stable index.
|
||||||
|
findByIndex: function(index){
|
||||||
|
return _.values(this._views)[index];
|
||||||
|
},
|
||||||
|
|
||||||
|
// retrieve a view by its `cid` directly
|
||||||
|
findByCid: function(cid){
|
||||||
|
return this._views[cid];
|
||||||
|
},
|
||||||
|
|
||||||
|
// Remove a view
|
||||||
|
remove: function(view){
|
||||||
|
var viewCid = view.cid;
|
||||||
|
|
||||||
|
// delete model index
|
||||||
|
if (view.model){
|
||||||
|
delete this._indexByModel[view.model.cid];
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete custom index
|
||||||
|
_.any(this._indexByCustom, function(cid, key) {
|
||||||
|
if (cid === viewCid) {
|
||||||
|
delete this._indexByCustom[key];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
// remove the view from the container
|
||||||
|
delete this._views[viewCid];
|
||||||
|
|
||||||
|
// update the length
|
||||||
|
this._updateLength();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Call a method on every view in the container,
|
||||||
|
// passing parameters to the call method one at a
|
||||||
|
// time, like `function.call`.
|
||||||
|
call: function(method){
|
||||||
|
this.apply(method, _.tail(arguments));
|
||||||
|
},
|
||||||
|
|
||||||
|
// Apply a method on every view in the container,
|
||||||
|
// passing parameters to the call method one at a
|
||||||
|
// time, like `function.apply`.
|
||||||
|
apply: function(method, args){
|
||||||
|
_.each(this._views, function(view){
|
||||||
|
if (_.isFunction(view[method])){
|
||||||
|
view[method].apply(view, args || []);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Update the `.length` attribute on this container
|
||||||
|
_updateLength: function(){
|
||||||
|
this.length = _.size(this._views);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Borrowing this code from Backbone.Collection:
|
||||||
|
// http://backbonejs.org/docs/backbone.html#section-106
|
||||||
|
//
|
||||||
|
// Mix in methods from Underscore, for iteration, and other
|
||||||
|
// collection related features.
|
||||||
|
var methods = ['forEach', 'each', 'map', 'find', 'detect', 'filter',
|
||||||
|
'select', 'reject', 'every', 'all', 'some', 'any', 'include',
|
||||||
|
'contains', 'invoke', 'toArray', 'first', 'initial', 'rest',
|
||||||
|
'last', 'without', 'isEmpty', 'pluck', 'reduce'];
|
||||||
|
|
||||||
|
_.each(methods, function(method) {
|
||||||
|
Container.prototype[method] = function() {
|
||||||
|
var views = _.values(this._views);
|
||||||
|
var args = [views].concat(_.toArray(arguments));
|
||||||
|
return _[method].apply(_, args);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// return the public API
|
||||||
|
return Container;
|
||||||
|
})(Backbone, _);
|
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"name": "backbone.wreqr",
|
||||||
|
"version": "1.3.2",
|
||||||
|
"homepage": "https://github.com/marionettejs/backbone.wreqr",
|
||||||
|
"authors": [
|
||||||
|
"Derick Bailey"
|
||||||
|
],
|
||||||
|
"description": "A Simple Service Bus For Backbone and Backbone.Marionette",
|
||||||
|
"main": "lib/backbone.wreqr.js",
|
||||||
|
"keywords": [
|
||||||
|
"backbone",
|
||||||
|
"plugin",
|
||||||
|
"computed",
|
||||||
|
"field",
|
||||||
|
"model"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"backbone": ">=0.9.9 <=1.1.2",
|
||||||
|
"underscore": ">=1.3.3 <=1.7.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"grunt": "0.4.0",
|
||||||
|
"grunt-contrib-jasmine": "0.4.1",
|
||||||
|
"grunt-contrib-uglify": "0.1.2",
|
||||||
|
"grunt-contrib-concat": "0.1.3",
|
||||||
|
"grunt-contrib-jshint": "0.2.0",
|
||||||
|
"grunt-contrib-watch": "0.3.1",
|
||||||
|
"grunt-contrib-connect": "0.2.0",
|
||||||
|
"grunt-template-jasmine-istanbul": "0.2.0",
|
||||||
|
"grunt-preprocess": "2.0.0",
|
||||||
|
"grunt-plato": "0.1.5"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"ignore": [
|
||||||
|
"**/.*",
|
||||||
|
"node_modules",
|
||||||
|
"bower_components",
|
||||||
|
"test",
|
||||||
|
"tests"
|
||||||
|
],
|
||||||
|
"_release": "1.3.2",
|
||||||
|
"_resolution": {
|
||||||
|
"type": "version",
|
||||||
|
"tag": "v1.3.2",
|
||||||
|
"commit": "ce146daac2a5a44d0874f353061253199007bd62"
|
||||||
|
},
|
||||||
|
"_source": "git://github.com/marionettejs/backbone.wreqr.git",
|
||||||
|
"_target": "^1.0.0",
|
||||||
|
"_originalSource": "backbone.wreqr"
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
# Change log
|
||||||
|
|
||||||
|
### v1.3.2
|
||||||
|
* Increase underscore range
|
||||||
|
* Minor underscore refactors
|
||||||
|
|
||||||
|
### v1.3.1
|
||||||
|
* Fix UMD setup and build process
|
||||||
|
|
||||||
|
### v1.3.0
|
||||||
|
* Add Wreqr.noConflict()
|
||||||
|
* Add Wreqr.VERSION
|
||||||
|
* Fixed a bug where reqres would not return a value using the 'top-level' Channel API.
|
||||||
|
|
||||||
|
### v1.2.1
|
||||||
|
* Remove AMD builds and add a single UMD style build.
|
||||||
|
|
||||||
|
### v1.2.0
|
||||||
|
* Adds Radio, allowing you to create explicit namespaces called Channels. A Channel is made up of
|
||||||
|
an instance of each of the three messaging systems.
|
||||||
|
|
||||||
|
### v1.1.0
|
||||||
|
* Removes the Error on unhandled commands/requests
|
||||||
|
|
||||||
|
### v1.0.1
|
||||||
|
* update dependencies
|
||||||
|
|
||||||
|
### v1.0.0
|
||||||
|
* major version release
|
||||||
|
* minor fixes
|
||||||
|
|
||||||
|
### v0.2.0
|
||||||
|
|
||||||
|
* Handlers (Commands/RequestResponse)
|
||||||
|
* **BREAKING:** renamed `addHandler` to `setHandler` to clarify the point of single handlers per named item
|
||||||
|
* Allow an `initialize` function when extending from the base type
|
||||||
|
* Added a `setHandlers` function that takes an object literal as the parameter, to configure multiple handlers in a single call
|
||||||
|
|
||||||
|
* Commands
|
||||||
|
* Introduced Wreqr.CommandStorage to store commands for later execution
|
||||||
|
* When a command has no handler, it will be stored for later execution
|
||||||
|
* When a handler for a stored command is added, the stored command will be
|
||||||
|
executed
|
||||||
|
|
||||||
|
* Updated build process to use Grunt v0.4
|
||||||
|
|
||||||
|
### v0.1.1
|
||||||
|
|
||||||
|
* Fixed "option strict" to be "use strict" ... #facepalm :P
|
||||||
|
* Added jam package config
|
||||||
|
|
||||||
|
### v0.1.0
|
||||||
|
|
||||||
|
* Fix calls to `.apply` to account for IE < 9 throwing an error when `arguments` is null or undefined
|
||||||
|
|
||||||
|
### v0.0.1
|
||||||
|
|
||||||
|
* Commands
|
||||||
|
* Can specify multiple arguments for `execute` method
|
||||||
|
|
||||||
|
* RequestResponse
|
||||||
|
* Can speicfy multiple arguments for `request` method
|
||||||
|
|
||||||
|
### v0.0.0
|
||||||
|
|
||||||
|
* Initial release
|
@ -0,0 +1,138 @@
|
|||||||
|
/*global module:false*/
|
||||||
|
module.exports = function(grunt) {
|
||||||
|
|
||||||
|
// Project configuration.
|
||||||
|
grunt.initConfig({
|
||||||
|
pkg: grunt.file.readJSON('package.json'),
|
||||||
|
meta: {
|
||||||
|
version: '<%= pkg.version %>',
|
||||||
|
banner:
|
||||||
|
'// Backbone.Wreqr (Backbone.Marionette)\n' +
|
||||||
|
'// ----------------------------------\n' +
|
||||||
|
'// v<%= pkg.version %>\n' +
|
||||||
|
'//\n' +
|
||||||
|
'// Copyright (c)<%= grunt.template.today("yyyy") %> Derick Bailey, Muted Solutions, LLC.\n' +
|
||||||
|
'// Distributed under MIT license\n' +
|
||||||
|
'//\n' +
|
||||||
|
'// http://github.com/marionettejs/backbone.wreqr\n' +
|
||||||
|
'\n\n'
|
||||||
|
},
|
||||||
|
|
||||||
|
lint: {
|
||||||
|
files: ['src/wreqr*.js']
|
||||||
|
},
|
||||||
|
|
||||||
|
preprocess: {
|
||||||
|
umd: {
|
||||||
|
src: 'src/build/backbone.wreqr.js',
|
||||||
|
dest: 'lib/backbone.wreqr.js'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
template: {
|
||||||
|
options: {
|
||||||
|
data: {
|
||||||
|
version: '<%= meta.version %>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
umd: {
|
||||||
|
src: '<%= preprocess.umd.dest %>',
|
||||||
|
dest: '<%= preprocess.umd.dest %>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
concat: {
|
||||||
|
options: {
|
||||||
|
banner: "<%= meta.banner %>"
|
||||||
|
},
|
||||||
|
umd: {
|
||||||
|
src: '<%= preprocess.umd.dest %>',
|
||||||
|
dest: '<%= preprocess.umd.dest %>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
uglify : {
|
||||||
|
options: {
|
||||||
|
banner: "<%= meta.banner %>"
|
||||||
|
},
|
||||||
|
umd : {
|
||||||
|
src : 'lib/backbone.wreqr.js',
|
||||||
|
dest : 'lib/backbone.wreqr.min.js',
|
||||||
|
options : {
|
||||||
|
sourceMap : 'lib/backbone.wreqr.map',
|
||||||
|
sourceMappingURL : 'backbone.wreqr.map',
|
||||||
|
sourceMapPrefix : 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
jasmine : {
|
||||||
|
options : {
|
||||||
|
helpers : 'spec/javascripts/helpers/*.js',
|
||||||
|
specs : 'spec/javascripts/**/*.spec.js',
|
||||||
|
vendor : [
|
||||||
|
'public/javascripts/json2.js',
|
||||||
|
'public/javascripts/jquery.js',
|
||||||
|
'node_modules/underscore/underscore.js',
|
||||||
|
'node_modules/backbone/backbone.js',
|
||||||
|
'node_modules/sinon/pkg/sinon.js',
|
||||||
|
'node_modules/jasmine-sinon/lib/jasmine-sinon.js',
|
||||||
|
],
|
||||||
|
keepRunner: true,
|
||||||
|
},
|
||||||
|
wreqr: {
|
||||||
|
src : [
|
||||||
|
'src/build/backbone.wreqr.js',
|
||||||
|
'spec/javascripts/support/wreqrHelper.js',
|
||||||
|
'src/wreqr.handlers.js',
|
||||||
|
'src/wreqr.*.js'
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
jshint: {
|
||||||
|
options: {
|
||||||
|
jshintrc : '.jshintrc'
|
||||||
|
},
|
||||||
|
wreqr : [ 'src/*.js' ]
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
wreqr : {
|
||||||
|
files : ['src/*.js', 'spec/**/*.js'],
|
||||||
|
tasks : ['jshint', 'jasmine:wreqr']
|
||||||
|
},
|
||||||
|
server : {
|
||||||
|
files : ['src/*.js', 'spec/**/*.js'],
|
||||||
|
tasks : ['jasmine:wreqr:build']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
connect: {
|
||||||
|
server: {
|
||||||
|
options: {
|
||||||
|
port: 8888
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
grunt.loadNpmTasks('grunt-preprocess');
|
||||||
|
grunt.loadNpmTasks('grunt-template');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-jasmine');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-connect');
|
||||||
|
|
||||||
|
grunt.registerTask('test', ['jshint', 'jasmine:wreqr']);
|
||||||
|
|
||||||
|
grunt.registerTask('dev', ['test', 'watch:wreqr']);
|
||||||
|
|
||||||
|
grunt.registerTask('server', ['jasmine:wreqr:build', 'connect:server', 'watch:server']);
|
||||||
|
|
||||||
|
// Default task.
|
||||||
|
grunt.registerTask('default', ['jshint', 'jasmine:wreqr', 'preprocess', 'template', 'concat', 'uglify']);
|
||||||
|
|
||||||
|
};
|
@ -0,0 +1,5 @@
|
|||||||
|
# Backbone.Wreqr
|
||||||
|
|
||||||
|
Copyright (C)2012 Derick Bailey, Muted Solutions, LLC
|
||||||
|
|
||||||
|
Distributed Under MIT License
|
@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"name": "backbone.wreqr",
|
||||||
|
"version": "1.3.2",
|
||||||
|
"homepage": "https://github.com/marionettejs/backbone.wreqr",
|
||||||
|
"authors": [
|
||||||
|
"Derick Bailey"
|
||||||
|
],
|
||||||
|
"description": "A Simple Service Bus For Backbone and Backbone.Marionette",
|
||||||
|
"main": "lib/backbone.wreqr.js",
|
||||||
|
"keywords": [
|
||||||
|
"backbone",
|
||||||
|
"plugin",
|
||||||
|
"computed",
|
||||||
|
"field",
|
||||||
|
"model"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"backbone": ">=0.9.9 <=1.1.2",
|
||||||
|
"underscore": ">=1.3.3 <=1.7.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"grunt": "0.4.0",
|
||||||
|
"grunt-contrib-jasmine": "0.4.1",
|
||||||
|
"grunt-contrib-uglify": "0.1.2",
|
||||||
|
"grunt-contrib-concat": "0.1.3",
|
||||||
|
"grunt-contrib-jshint": "0.2.0",
|
||||||
|
"grunt-contrib-watch": "0.3.1",
|
||||||
|
"grunt-contrib-connect": "0.2.0",
|
||||||
|
"grunt-template-jasmine-istanbul": "0.2.0",
|
||||||
|
"grunt-preprocess": "2.0.0",
|
||||||
|
"grunt-plato": "0.1.5"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"ignore": [
|
||||||
|
"**/.*",
|
||||||
|
"node_modules",
|
||||||
|
"bower_components",
|
||||||
|
"test",
|
||||||
|
"tests"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "backbone.wreqr",
|
||||||
|
"description": "A Simple Service Bus For Backbone and Backbone.Marionette",
|
||||||
|
"version": "1.3.1",
|
||||||
|
"repo": "marionettejs/backbone.wreqr",
|
||||||
|
"keywords": [
|
||||||
|
"backbone",
|
||||||
|
"plugin",
|
||||||
|
"computed",
|
||||||
|
"field",
|
||||||
|
"model",
|
||||||
|
"client",
|
||||||
|
"browser"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"licenses": [
|
||||||
|
{
|
||||||
|
"type": "MIT",
|
||||||
|
"url": "https://github.com/marionettejs/backbone.wreqr/blob/master/LICENSE.md"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "Derick Bailey",
|
||||||
|
"email": "marionettejs@gmail.com",
|
||||||
|
"web": "http://derickbailey.lostechies.com"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"jashkenas/backbone": "*",
|
||||||
|
"jashkenas/underscore": "*"
|
||||||
|
},
|
||||||
|
"main": "lib/backbone.wreqr.js",
|
||||||
|
"scripts": [
|
||||||
|
"lib/backbone.wreqr.js"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,435 @@
|
|||||||
|
// Backbone.Wreqr (Backbone.Marionette)
|
||||||
|
// ----------------------------------
|
||||||
|
// v1.3.2
|
||||||
|
//
|
||||||
|
// Copyright (c)2014 Derick Bailey, Muted Solutions, LLC.
|
||||||
|
// Distributed under MIT license
|
||||||
|
//
|
||||||
|
// http://github.com/marionettejs/backbone.wreqr
|
||||||
|
|
||||||
|
|
||||||
|
(function(root, factory) {
|
||||||
|
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
define(['backbone', 'underscore'], function(Backbone, _) {
|
||||||
|
return factory(Backbone, _);
|
||||||
|
});
|
||||||
|
} else if (typeof exports !== 'undefined') {
|
||||||
|
var Backbone = require('backbone');
|
||||||
|
var _ = require('underscore');
|
||||||
|
module.exports = factory(Backbone, _);
|
||||||
|
} else {
|
||||||
|
factory(root.Backbone, root._);
|
||||||
|
}
|
||||||
|
|
||||||
|
}(this, function(Backbone, _) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var previousWreqr = Backbone.Wreqr;
|
||||||
|
|
||||||
|
var Wreqr = Backbone.Wreqr = {};
|
||||||
|
|
||||||
|
Backbone.Wreqr.VERSION = '1.3.2';
|
||||||
|
|
||||||
|
Backbone.Wreqr.noConflict = function () {
|
||||||
|
Backbone.Wreqr = previousWreqr;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handlers
|
||||||
|
// --------
|
||||||
|
// A registry of functions to call, given a name
|
||||||
|
|
||||||
|
Wreqr.Handlers = (function(Backbone, _){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
// -----------
|
||||||
|
|
||||||
|
var Handlers = function(options){
|
||||||
|
this.options = options;
|
||||||
|
this._wreqrHandlers = {};
|
||||||
|
|
||||||
|
if (_.isFunction(this.initialize)){
|
||||||
|
this.initialize(options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Handlers.extend = Backbone.Model.extend;
|
||||||
|
|
||||||
|
// Instance Members
|
||||||
|
// ----------------
|
||||||
|
|
||||||
|
_.extend(Handlers.prototype, Backbone.Events, {
|
||||||
|
|
||||||
|
// Add multiple handlers using an object literal configuration
|
||||||
|
setHandlers: function(handlers){
|
||||||
|
_.each(handlers, function(handler, name){
|
||||||
|
var context = null;
|
||||||
|
|
||||||
|
if (_.isObject(handler) && !_.isFunction(handler)){
|
||||||
|
context = handler.context;
|
||||||
|
handler = handler.callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setHandler(name, handler, context);
|
||||||
|
}, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Add a handler for the given name, with an
|
||||||
|
// optional context to run the handler within
|
||||||
|
setHandler: function(name, handler, context){
|
||||||
|
var config = {
|
||||||
|
callback: handler,
|
||||||
|
context: context
|
||||||
|
};
|
||||||
|
|
||||||
|
this._wreqrHandlers[name] = config;
|
||||||
|
|
||||||
|
this.trigger("handler:add", name, handler, context);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Determine whether or not a handler is registered
|
||||||
|
hasHandler: function(name){
|
||||||
|
return !! this._wreqrHandlers[name];
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get the currently registered handler for
|
||||||
|
// the specified name. Throws an exception if
|
||||||
|
// no handler is found.
|
||||||
|
getHandler: function(name){
|
||||||
|
var config = this._wreqrHandlers[name];
|
||||||
|
|
||||||
|
if (!config){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return function(){
|
||||||
|
return config.callback.apply(config.context, arguments);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
// Remove a handler for the specified name
|
||||||
|
removeHandler: function(name){
|
||||||
|
delete this._wreqrHandlers[name];
|
||||||
|
},
|
||||||
|
|
||||||
|
// Remove all handlers from this registry
|
||||||
|
removeAllHandlers: function(){
|
||||||
|
this._wreqrHandlers = {};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Handlers;
|
||||||
|
})(Backbone, _);
|
||||||
|
|
||||||
|
// Wreqr.CommandStorage
|
||||||
|
// --------------------
|
||||||
|
//
|
||||||
|
// Store and retrieve commands for execution.
|
||||||
|
Wreqr.CommandStorage = (function(){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Constructor function
|
||||||
|
var CommandStorage = function(options){
|
||||||
|
this.options = options;
|
||||||
|
this._commands = {};
|
||||||
|
|
||||||
|
if (_.isFunction(this.initialize)){
|
||||||
|
this.initialize(options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Instance methods
|
||||||
|
_.extend(CommandStorage.prototype, Backbone.Events, {
|
||||||
|
|
||||||
|
// Get an object literal by command name, that contains
|
||||||
|
// the `commandName` and the `instances` of all commands
|
||||||
|
// represented as an array of arguments to process
|
||||||
|
getCommands: function(commandName){
|
||||||
|
var commands = this._commands[commandName];
|
||||||
|
|
||||||
|
// we don't have it, so add it
|
||||||
|
if (!commands){
|
||||||
|
|
||||||
|
// build the configuration
|
||||||
|
commands = {
|
||||||
|
command: commandName,
|
||||||
|
instances: []
|
||||||
|
};
|
||||||
|
|
||||||
|
// store it
|
||||||
|
this._commands[commandName] = commands;
|
||||||
|
}
|
||||||
|
|
||||||
|
return commands;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Add a command by name, to the storage and store the
|
||||||
|
// args for the command
|
||||||
|
addCommand: function(commandName, args){
|
||||||
|
var command = this.getCommands(commandName);
|
||||||
|
command.instances.push(args);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Clear all commands for the given `commandName`
|
||||||
|
clearCommands: function(commandName){
|
||||||
|
var command = this.getCommands(commandName);
|
||||||
|
command.instances = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return CommandStorage;
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Wreqr.Commands
|
||||||
|
// --------------
|
||||||
|
//
|
||||||
|
// A simple command pattern implementation. Register a command
|
||||||
|
// handler and execute it.
|
||||||
|
Wreqr.Commands = (function(Wreqr, _){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
return Wreqr.Handlers.extend({
|
||||||
|
// default storage type
|
||||||
|
storageType: Wreqr.CommandStorage,
|
||||||
|
|
||||||
|
constructor: function(options){
|
||||||
|
this.options = options || {};
|
||||||
|
|
||||||
|
this._initializeStorage(this.options);
|
||||||
|
this.on("handler:add", this._executeCommands, this);
|
||||||
|
|
||||||
|
Wreqr.Handlers.prototype.constructor.apply(this, arguments);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Execute a named command with the supplied args
|
||||||
|
execute: function(name){
|
||||||
|
name = arguments[0];
|
||||||
|
var args = _.rest(arguments);
|
||||||
|
|
||||||
|
if (this.hasHandler(name)){
|
||||||
|
this.getHandler(name).apply(this, args);
|
||||||
|
} else {
|
||||||
|
this.storage.addCommand(name, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
// Internal method to handle bulk execution of stored commands
|
||||||
|
_executeCommands: function(name, handler, context){
|
||||||
|
var command = this.storage.getCommands(name);
|
||||||
|
|
||||||
|
// loop through and execute all the stored command instances
|
||||||
|
_.each(command.instances, function(args){
|
||||||
|
handler.apply(context, args);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.storage.clearCommands(name);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Internal method to initialize storage either from the type's
|
||||||
|
// `storageType` or the instance `options.storageType`.
|
||||||
|
_initializeStorage: function(options){
|
||||||
|
var storage;
|
||||||
|
|
||||||
|
var StorageType = options.storageType || this.storageType;
|
||||||
|
if (_.isFunction(StorageType)){
|
||||||
|
storage = new StorageType();
|
||||||
|
} else {
|
||||||
|
storage = StorageType;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.storage = storage;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
})(Wreqr, _);
|
||||||
|
|
||||||
|
// Wreqr.RequestResponse
|
||||||
|
// ---------------------
|
||||||
|
//
|
||||||
|
// A simple request/response implementation. Register a
|
||||||
|
// request handler, and return a response from it
|
||||||
|
Wreqr.RequestResponse = (function(Wreqr, _){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
return Wreqr.Handlers.extend({
|
||||||
|
request: function(name){
|
||||||
|
if (this.hasHandler(name)) {
|
||||||
|
return this.getHandler(name).apply(this, _.rest(arguments));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
})(Wreqr, _);
|
||||||
|
|
||||||
|
// Event Aggregator
|
||||||
|
// ----------------
|
||||||
|
// A pub-sub object that can be used to decouple various parts
|
||||||
|
// of an application through event-driven architecture.
|
||||||
|
|
||||||
|
Wreqr.EventAggregator = (function(Backbone, _){
|
||||||
|
"use strict";
|
||||||
|
var EA = function(){};
|
||||||
|
|
||||||
|
// Copy the `extend` function used by Backbone's classes
|
||||||
|
EA.extend = Backbone.Model.extend;
|
||||||
|
|
||||||
|
// Copy the basic Backbone.Events on to the event aggregator
|
||||||
|
_.extend(EA.prototype, Backbone.Events);
|
||||||
|
|
||||||
|
return EA;
|
||||||
|
})(Backbone, _);
|
||||||
|
|
||||||
|
// Wreqr.Channel
|
||||||
|
// --------------
|
||||||
|
//
|
||||||
|
// An object that wraps the three messaging systems:
|
||||||
|
// EventAggregator, RequestResponse, Commands
|
||||||
|
Wreqr.Channel = (function(Wreqr){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Channel = function(channelName) {
|
||||||
|
this.vent = new Backbone.Wreqr.EventAggregator();
|
||||||
|
this.reqres = new Backbone.Wreqr.RequestResponse();
|
||||||
|
this.commands = new Backbone.Wreqr.Commands();
|
||||||
|
this.channelName = channelName;
|
||||||
|
};
|
||||||
|
|
||||||
|
_.extend(Channel.prototype, {
|
||||||
|
|
||||||
|
// Remove all handlers from the messaging systems of this channel
|
||||||
|
reset: function() {
|
||||||
|
this.vent.off();
|
||||||
|
this.vent.stopListening();
|
||||||
|
this.reqres.removeAllHandlers();
|
||||||
|
this.commands.removeAllHandlers();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Connect a hash of events; one for each messaging system
|
||||||
|
connectEvents: function(hash, context) {
|
||||||
|
this._connect('vent', hash, context);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
connectCommands: function(hash, context) {
|
||||||
|
this._connect('commands', hash, context);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
connectRequests: function(hash, context) {
|
||||||
|
this._connect('reqres', hash, context);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Attach the handlers to a given message system `type`
|
||||||
|
_connect: function(type, hash, context) {
|
||||||
|
if (!hash) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context = context || this;
|
||||||
|
var method = (type === 'vent') ? 'on' : 'setHandler';
|
||||||
|
|
||||||
|
_.each(hash, function(fn, eventName) {
|
||||||
|
this[type][method](eventName, _.bind(fn, context));
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return Channel;
|
||||||
|
})(Wreqr);
|
||||||
|
|
||||||
|
// Wreqr.Radio
|
||||||
|
// --------------
|
||||||
|
//
|
||||||
|
// An object that lets you communicate with many channels.
|
||||||
|
Wreqr.radio = (function(Wreqr, _){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Radio = function() {
|
||||||
|
this._channels = {};
|
||||||
|
this.vent = {};
|
||||||
|
this.commands = {};
|
||||||
|
this.reqres = {};
|
||||||
|
this._proxyMethods();
|
||||||
|
};
|
||||||
|
|
||||||
|
_.extend(Radio.prototype, {
|
||||||
|
|
||||||
|
channel: function(channelName) {
|
||||||
|
if (!channelName) {
|
||||||
|
throw new Error('Channel must receive a name');
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._getChannel( channelName );
|
||||||
|
},
|
||||||
|
|
||||||
|
_getChannel: function(channelName) {
|
||||||
|
var channel = this._channels[channelName];
|
||||||
|
|
||||||
|
if(!channel) {
|
||||||
|
channel = new Wreqr.Channel(channelName);
|
||||||
|
this._channels[channelName] = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return channel;
|
||||||
|
},
|
||||||
|
|
||||||
|
_proxyMethods: function() {
|
||||||
|
_.each(['vent', 'commands', 'reqres'], function(system) {
|
||||||
|
_.each( messageSystems[system], function(method) {
|
||||||
|
this[system][method] = proxyMethod(this, system, method);
|
||||||
|
}, this);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var messageSystems = {
|
||||||
|
vent: [
|
||||||
|
'on',
|
||||||
|
'off',
|
||||||
|
'trigger',
|
||||||
|
'once',
|
||||||
|
'stopListening',
|
||||||
|
'listenTo',
|
||||||
|
'listenToOnce'
|
||||||
|
],
|
||||||
|
|
||||||
|
commands: [
|
||||||
|
'execute',
|
||||||
|
'setHandler',
|
||||||
|
'setHandlers',
|
||||||
|
'removeHandler',
|
||||||
|
'removeAllHandlers'
|
||||||
|
],
|
||||||
|
|
||||||
|
reqres: [
|
||||||
|
'request',
|
||||||
|
'setHandler',
|
||||||
|
'setHandlers',
|
||||||
|
'removeHandler',
|
||||||
|
'removeAllHandlers'
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
var proxyMethod = function(radio, system, method) {
|
||||||
|
return function(channelName) {
|
||||||
|
var messageSystem = radio._getChannel(channelName)[system];
|
||||||
|
|
||||||
|
return messageSystem[method].apply(messageSystem, _.rest(arguments));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Radio();
|
||||||
|
|
||||||
|
})(Wreqr, _);
|
||||||
|
|
||||||
|
|
||||||
|
return Backbone.Wreqr;
|
||||||
|
|
||||||
|
}));
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,12 @@
|
|||||||
|
// Backbone.Wreqr (Backbone.Marionette)
|
||||||
|
// ----------------------------------
|
||||||
|
// v1.3.2
|
||||||
|
//
|
||||||
|
// Copyright (c)2014 Derick Bailey, Muted Solutions, LLC.
|
||||||
|
// Distributed under MIT license
|
||||||
|
//
|
||||||
|
// http://github.com/marionettejs/backbone.wreqr
|
||||||
|
|
||||||
|
|
||||||
|
(function(n,e){if("function"==typeof define&&define.amd)define(["backbone","underscore"],function(n,t){return e(n,t)});else if("undefined"!=typeof exports){var t=require("backbone"),r=require("underscore");module.exports=e(t,r)}else e(n.Backbone,n._)})(this,function(n,e){"use strict";var t=n.Wreqr,r=n.Wreqr={};return n.Wreqr.VERSION="1.3.2",n.Wreqr.noConflict=function(){return n.Wreqr=t,this},r.Handlers=function(n,e){var t=function(n){this.options=n,this._wreqrHandlers={},e.isFunction(this.initialize)&&this.initialize(n)};return t.extend=n.Model.extend,e.extend(t.prototype,n.Events,{setHandlers:function(n){e.each(n,function(n,t){var r=null;e.isObject(n)&&!e.isFunction(n)&&(r=n.context,n=n.callback),this.setHandler(t,n,r)},this)},setHandler:function(n,e,t){var r={callback:e,context:t};this._wreqrHandlers[n]=r,this.trigger("handler:add",n,e,t)},hasHandler:function(n){return!!this._wreqrHandlers[n]},getHandler:function(n){var e=this._wreqrHandlers[n];if(e)return function(){return e.callback.apply(e.context,arguments)}},removeHandler:function(n){delete this._wreqrHandlers[n]},removeAllHandlers:function(){this._wreqrHandlers={}}}),t}(n,e),r.CommandStorage=function(){var t=function(n){this.options=n,this._commands={},e.isFunction(this.initialize)&&this.initialize(n)};return e.extend(t.prototype,n.Events,{getCommands:function(n){var e=this._commands[n];return e||(e={command:n,instances:[]},this._commands[n]=e),e},addCommand:function(n,e){var t=this.getCommands(n);t.instances.push(e)},clearCommands:function(n){var e=this.getCommands(n);e.instances=[]}}),t}(),r.Commands=function(n,e){return n.Handlers.extend({storageType:n.CommandStorage,constructor:function(e){this.options=e||{},this._initializeStorage(this.options),this.on("handler:add",this._executeCommands,this),n.Handlers.prototype.constructor.apply(this,arguments)},execute:function(n){n=arguments[0];var t=e.rest(arguments);this.hasHandler(n)?this.getHandler(n).apply(this,t):this.storage.addCommand(n,t)},_executeCommands:function(n,t,r){var s=this.storage.getCommands(n);e.each(s.instances,function(n){t.apply(r,n)}),this.storage.clearCommands(n)},_initializeStorage:function(n){var t,r=n.storageType||this.storageType;t=e.isFunction(r)?new r:r,this.storage=t}})}(r,e),r.RequestResponse=function(n,e){return n.Handlers.extend({request:function(n){return this.hasHandler(n)?this.getHandler(n).apply(this,e.rest(arguments)):void 0}})}(r,e),r.EventAggregator=function(n,e){var t=function(){};return t.extend=n.Model.extend,e.extend(t.prototype,n.Events),t}(n,e),r.Channel=function(){var t=function(e){this.vent=new n.Wreqr.EventAggregator,this.reqres=new n.Wreqr.RequestResponse,this.commands=new n.Wreqr.Commands,this.channelName=e};return e.extend(t.prototype,{reset:function(){return this.vent.off(),this.vent.stopListening(),this.reqres.removeAllHandlers(),this.commands.removeAllHandlers(),this},connectEvents:function(n,e){return this._connect("vent",n,e),this},connectCommands:function(n,e){return this._connect("commands",n,e),this},connectRequests:function(n,e){return this._connect("reqres",n,e),this},_connect:function(n,t,r){if(t){r=r||this;var s="vent"===n?"on":"setHandler";e.each(t,function(t,i){this[n][s](i,e.bind(t,r))},this)}}}),t}(r),r.radio=function(n,e){var t=function(){this._channels={},this.vent={},this.commands={},this.reqres={},this._proxyMethods()};e.extend(t.prototype,{channel:function(n){if(!n)throw Error("Channel must receive a name");return this._getChannel(n)},_getChannel:function(e){var t=this._channels[e];return t||(t=new n.Channel(e),this._channels[e]=t),t},_proxyMethods:function(){e.each(["vent","commands","reqres"],function(n){e.each(r[n],function(e){this[n][e]=s(this,n,e)},this)},this)}});var r={vent:["on","off","trigger","once","stopListening","listenTo","listenToOnce"],commands:["execute","setHandler","setHandlers","removeHandler","removeAllHandlers"],reqres:["request","setHandler","setHandlers","removeHandler","removeAllHandlers"]},s=function(n,t,r){return function(s){var i=n._getChannel(s)[t];return i[r].apply(i,e.rest(arguments))}};return new t}(r,e),n.Wreqr});
|
||||||
|
//@ sourceMappingURL=backbone.wreqr.map
|
@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"name": "backbone.wreqr",
|
||||||
|
"description": "A Simple Service Bus For Backbone and Backbone.Marionette",
|
||||||
|
"version": "1.3.2",
|
||||||
|
"homepage": "https://github.com/marionettejs/backbone.wreqr",
|
||||||
|
"main": "lib/backbone.wreqr.js",
|
||||||
|
"keywords": [
|
||||||
|
"backbone",
|
||||||
|
"plugin",
|
||||||
|
"client",
|
||||||
|
"browser",
|
||||||
|
"message",
|
||||||
|
"messages",
|
||||||
|
"messaging",
|
||||||
|
"decoupled",
|
||||||
|
"architecture"
|
||||||
|
],
|
||||||
|
"licenses": [
|
||||||
|
{
|
||||||
|
"type": "MIT",
|
||||||
|
"url": "https://github.com/marionettejs/backbone.wreqr/blob/master/LICENSE.md"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"test": "grunt jasmine",
|
||||||
|
"start": "grunt jasmine-server"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"name": "Derick Bailey",
|
||||||
|
"email": "marionettejs@gmail.com",
|
||||||
|
"web": "http://derickbailey.lostechies.com"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"web": "https://github.com/marionettejs/backbone.wreqr/issues"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/marionettejs/backbone.wreqr.git"
|
||||||
|
},
|
||||||
|
"github": "https://github.com/marionettejs/backbone.wreqr",
|
||||||
|
"dependencies": {
|
||||||
|
"backbone": ">=0.9.9 <=1.1.2",
|
||||||
|
"underscore": ">=1.3.3 <=1.7.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"grunt": "0.4.0",
|
||||||
|
"grunt-contrib-jasmine": "0.4.1",
|
||||||
|
"grunt-contrib-uglify": "0.1.2",
|
||||||
|
"grunt-contrib-concat": "0.1.3",
|
||||||
|
"grunt-contrib-jshint": "0.2.0",
|
||||||
|
"grunt-contrib-watch": "0.3.1",
|
||||||
|
"grunt-contrib-connect": "0.2.0",
|
||||||
|
"grunt-preprocess": "4.0.0",
|
||||||
|
"sinon": "1.9.0",
|
||||||
|
"jasmine-sinon": "0.3.1",
|
||||||
|
"grunt-template": "^0.2.3"
|
||||||
|
},
|
||||||
|
"jam": {
|
||||||
|
"dependencies": {
|
||||||
|
"backbone": ">=0.9.9",
|
||||||
|
"underscore": ">=1.3.1"
|
||||||
|
},
|
||||||
|
"main": "lib/amd/backbone.wreqr.js",
|
||||||
|
"include": [
|
||||||
|
"lib/amd/backbone.wreqr.js",
|
||||||
|
"readme.md"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"maintainers": [
|
||||||
|
{
|
||||||
|
"name": "Stefan Zerkalica",
|
||||||
|
"email": "zerkalica@gmail.com",
|
||||||
|
"web": "https://github.com/zerkalica"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Richard Mitchell",
|
||||||
|
"email": "richard.j.mitchell@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Joe Gornick",
|
||||||
|
"web": "http://joegornick.com",
|
||||||
|
"twitter": "https://twitter.com/jgornick"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -0,0 +1,487 @@
|
|||||||
|
/*
|
||||||
|
http://www.JSON.org/json2.js
|
||||||
|
2011-10-19
|
||||||
|
|
||||||
|
Public Domain.
|
||||||
|
|
||||||
|
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||||
|
|
||||||
|
See http://www.JSON.org/js.html
|
||||||
|
|
||||||
|
|
||||||
|
This code should be minified before deployment.
|
||||||
|
See http://javascript.crockford.com/jsmin.html
|
||||||
|
|
||||||
|
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
||||||
|
NOT CONTROL.
|
||||||
|
|
||||||
|
|
||||||
|
This file creates a global JSON object containing two methods: stringify
|
||||||
|
and parse.
|
||||||
|
|
||||||
|
JSON.stringify(value, replacer, space)
|
||||||
|
value any JavaScript value, usually an object or array.
|
||||||
|
|
||||||
|
replacer an optional parameter that determines how object
|
||||||
|
values are stringified for objects. It can be a
|
||||||
|
function or an array of strings.
|
||||||
|
|
||||||
|
space an optional parameter that specifies the indentation
|
||||||
|
of nested structures. If it is omitted, the text will
|
||||||
|
be packed without extra whitespace. If it is a number,
|
||||||
|
it will specify the number of spaces to indent at each
|
||||||
|
level. If it is a string (such as '\t' or ' '),
|
||||||
|
it contains the characters used to indent at each level.
|
||||||
|
|
||||||
|
This method produces a JSON text from a JavaScript value.
|
||||||
|
|
||||||
|
When an object value is found, if the object contains a toJSON
|
||||||
|
method, its toJSON method will be called and the result will be
|
||||||
|
stringified. A toJSON method does not serialize: it returns the
|
||||||
|
value represented by the name/value pair that should be serialized,
|
||||||
|
or undefined if nothing should be serialized. The toJSON method
|
||||||
|
will be passed the key associated with the value, and this will be
|
||||||
|
bound to the value
|
||||||
|
|
||||||
|
For example, this would serialize Dates as ISO strings.
|
||||||
|
|
||||||
|
Date.prototype.toJSON = function (key) {
|
||||||
|
function f(n) {
|
||||||
|
// Format integers to have at least two digits.
|
||||||
|
return n < 10 ? '0' + n : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.getUTCFullYear() + '-' +
|
||||||
|
f(this.getUTCMonth() + 1) + '-' +
|
||||||
|
f(this.getUTCDate()) + 'T' +
|
||||||
|
f(this.getUTCHours()) + ':' +
|
||||||
|
f(this.getUTCMinutes()) + ':' +
|
||||||
|
f(this.getUTCSeconds()) + 'Z';
|
||||||
|
};
|
||||||
|
|
||||||
|
You can provide an optional replacer method. It will be passed the
|
||||||
|
key and value of each member, with this bound to the containing
|
||||||
|
object. The value that is returned from your method will be
|
||||||
|
serialized. If your method returns undefined, then the member will
|
||||||
|
be excluded from the serialization.
|
||||||
|
|
||||||
|
If the replacer parameter is an array of strings, then it will be
|
||||||
|
used to select the members to be serialized. It filters the results
|
||||||
|
such that only members with keys listed in the replacer array are
|
||||||
|
stringified.
|
||||||
|
|
||||||
|
Values that do not have JSON representations, such as undefined or
|
||||||
|
functions, will not be serialized. Such values in objects will be
|
||||||
|
dropped; in arrays they will be replaced with null. You can use
|
||||||
|
a replacer function to replace those with JSON values.
|
||||||
|
JSON.stringify(undefined) returns undefined.
|
||||||
|
|
||||||
|
The optional space parameter produces a stringification of the
|
||||||
|
value that is filled with line breaks and indentation to make it
|
||||||
|
easier to read.
|
||||||
|
|
||||||
|
If the space parameter is a non-empty string, then that string will
|
||||||
|
be used for indentation. If the space parameter is a number, then
|
||||||
|
the indentation will be that many spaces.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
||||||
|
// text is '["e",{"pluribus":"unum"}]'
|
||||||
|
|
||||||
|
|
||||||
|
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
||||||
|
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
||||||
|
|
||||||
|
text = JSON.stringify([new Date()], function (key, value) {
|
||||||
|
return this[key] instanceof Date ?
|
||||||
|
'Date(' + this[key] + ')' : value;
|
||||||
|
});
|
||||||
|
// text is '["Date(---current time---)"]'
|
||||||
|
|
||||||
|
|
||||||
|
JSON.parse(text, reviver)
|
||||||
|
This method parses a JSON text to produce an object or array.
|
||||||
|
It can throw a SyntaxError exception.
|
||||||
|
|
||||||
|
The optional reviver parameter is a function that can filter and
|
||||||
|
transform the results. It receives each of the keys and values,
|
||||||
|
and its return value is used instead of the original value.
|
||||||
|
If it returns what it received, then the structure is not modified.
|
||||||
|
If it returns undefined then the member is deleted.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
// Parse the text. Values that look like ISO date strings will
|
||||||
|
// be converted to Date objects.
|
||||||
|
|
||||||
|
myData = JSON.parse(text, function (key, value) {
|
||||||
|
var a;
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
a =
|
||||||
|
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
||||||
|
if (a) {
|
||||||
|
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
||||||
|
+a[5], +a[6]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
|
||||||
|
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
||||||
|
var d;
|
||||||
|
if (typeof value === 'string' &&
|
||||||
|
value.slice(0, 5) === 'Date(' &&
|
||||||
|
value.slice(-1) === ')') {
|
||||||
|
d = new Date(value.slice(5, -1));
|
||||||
|
if (d) {
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
This is a reference implementation. You are free to copy, modify, or
|
||||||
|
redistribute.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*jslint evil: true, regexp: true */
|
||||||
|
|
||||||
|
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
||||||
|
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
||||||
|
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
||||||
|
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
||||||
|
test, toJSON, toString, valueOf
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Create a JSON object only if one does not already exist. We create the
|
||||||
|
// methods in a closure to avoid creating global variables.
|
||||||
|
|
||||||
|
var JSON;
|
||||||
|
if (!JSON) {
|
||||||
|
JSON = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function f(n) {
|
||||||
|
// Format integers to have at least two digits.
|
||||||
|
return n < 10 ? '0' + n : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof Date.prototype.toJSON !== 'function') {
|
||||||
|
|
||||||
|
Date.prototype.toJSON = function (key) {
|
||||||
|
|
||||||
|
return isFinite(this.valueOf())
|
||||||
|
? this.getUTCFullYear() + '-' +
|
||||||
|
f(this.getUTCMonth() + 1) + '-' +
|
||||||
|
f(this.getUTCDate()) + 'T' +
|
||||||
|
f(this.getUTCHours()) + ':' +
|
||||||
|
f(this.getUTCMinutes()) + ':' +
|
||||||
|
f(this.getUTCSeconds()) + 'Z'
|
||||||
|
: null;
|
||||||
|
};
|
||||||
|
|
||||||
|
String.prototype.toJSON =
|
||||||
|
Number.prototype.toJSON =
|
||||||
|
Boolean.prototype.toJSON = function (key) {
|
||||||
|
return this.valueOf();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||||
|
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||||
|
gap,
|
||||||
|
indent,
|
||||||
|
meta = { // table of character substitutions
|
||||||
|
'\b': '\\b',
|
||||||
|
'\t': '\\t',
|
||||||
|
'\n': '\\n',
|
||||||
|
'\f': '\\f',
|
||||||
|
'\r': '\\r',
|
||||||
|
'"' : '\\"',
|
||||||
|
'\\': '\\\\'
|
||||||
|
},
|
||||||
|
rep;
|
||||||
|
|
||||||
|
|
||||||
|
function quote(string) {
|
||||||
|
|
||||||
|
// If the string contains no control characters, no quote characters, and no
|
||||||
|
// backslash characters, then we can safely slap some quotes around it.
|
||||||
|
// Otherwise we must also replace the offending characters with safe escape
|
||||||
|
// sequences.
|
||||||
|
|
||||||
|
escapable.lastIndex = 0;
|
||||||
|
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
|
||||||
|
var c = meta[a];
|
||||||
|
return typeof c === 'string'
|
||||||
|
? c
|
||||||
|
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||||
|
}) + '"' : '"' + string + '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function str(key, holder) {
|
||||||
|
|
||||||
|
// Produce a string from holder[key].
|
||||||
|
|
||||||
|
var i, // The loop counter.
|
||||||
|
k, // The member key.
|
||||||
|
v, // The member value.
|
||||||
|
length,
|
||||||
|
mind = gap,
|
||||||
|
partial,
|
||||||
|
value = holder[key];
|
||||||
|
|
||||||
|
// If the value has a toJSON method, call it to obtain a replacement value.
|
||||||
|
|
||||||
|
if (value && typeof value === 'object' &&
|
||||||
|
typeof value.toJSON === 'function') {
|
||||||
|
value = value.toJSON(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we were called with a replacer function, then call the replacer to
|
||||||
|
// obtain a replacement value.
|
||||||
|
|
||||||
|
if (typeof rep === 'function') {
|
||||||
|
value = rep.call(holder, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// What happens next depends on the value's type.
|
||||||
|
|
||||||
|
switch (typeof value) {
|
||||||
|
case 'string':
|
||||||
|
return quote(value);
|
||||||
|
|
||||||
|
case 'number':
|
||||||
|
|
||||||
|
// JSON numbers must be finite. Encode non-finite numbers as null.
|
||||||
|
|
||||||
|
return isFinite(value) ? String(value) : 'null';
|
||||||
|
|
||||||
|
case 'boolean':
|
||||||
|
case 'null':
|
||||||
|
|
||||||
|
// If the value is a boolean or null, convert it to a string. Note:
|
||||||
|
// typeof null does not produce 'null'. The case is included here in
|
||||||
|
// the remote chance that this gets fixed someday.
|
||||||
|
|
||||||
|
return String(value);
|
||||||
|
|
||||||
|
// If the type is 'object', we might be dealing with an object or an array or
|
||||||
|
// null.
|
||||||
|
|
||||||
|
case 'object':
|
||||||
|
|
||||||
|
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
||||||
|
// so watch out for that case.
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
return 'null';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make an array to hold the partial results of stringifying this object value.
|
||||||
|
|
||||||
|
gap += indent;
|
||||||
|
partial = [];
|
||||||
|
|
||||||
|
// Is the value an array?
|
||||||
|
|
||||||
|
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
||||||
|
|
||||||
|
// The value is an array. Stringify every element. Use null as a placeholder
|
||||||
|
// for non-JSON values.
|
||||||
|
|
||||||
|
length = value.length;
|
||||||
|
for (i = 0; i < length; i += 1) {
|
||||||
|
partial[i] = str(i, value) || 'null';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join all of the elements together, separated with commas, and wrap them in
|
||||||
|
// brackets.
|
||||||
|
|
||||||
|
v = partial.length === 0
|
||||||
|
? '[]'
|
||||||
|
: gap
|
||||||
|
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
|
||||||
|
: '[' + partial.join(',') + ']';
|
||||||
|
gap = mind;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the replacer is an array, use it to select the members to be stringified.
|
||||||
|
|
||||||
|
if (rep && typeof rep === 'object') {
|
||||||
|
length = rep.length;
|
||||||
|
for (i = 0; i < length; i += 1) {
|
||||||
|
if (typeof rep[i] === 'string') {
|
||||||
|
k = rep[i];
|
||||||
|
v = str(k, value);
|
||||||
|
if (v) {
|
||||||
|
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Otherwise, iterate through all of the keys in the object.
|
||||||
|
|
||||||
|
for (k in value) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
||||||
|
v = str(k, value);
|
||||||
|
if (v) {
|
||||||
|
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join all of the member texts together, separated with commas,
|
||||||
|
// and wrap them in braces.
|
||||||
|
|
||||||
|
v = partial.length === 0
|
||||||
|
? '{}'
|
||||||
|
: gap
|
||||||
|
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
|
||||||
|
: '{' + partial.join(',') + '}';
|
||||||
|
gap = mind;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the JSON object does not yet have a stringify method, give it one.
|
||||||
|
|
||||||
|
if (typeof JSON.stringify !== 'function') {
|
||||||
|
JSON.stringify = function (value, replacer, space) {
|
||||||
|
|
||||||
|
// The stringify method takes a value and an optional replacer, and an optional
|
||||||
|
// space parameter, and returns a JSON text. The replacer can be a function
|
||||||
|
// that can replace values, or an array of strings that will select the keys.
|
||||||
|
// A default replacer method can be provided. Use of the space parameter can
|
||||||
|
// produce text that is more easily readable.
|
||||||
|
|
||||||
|
var i;
|
||||||
|
gap = '';
|
||||||
|
indent = '';
|
||||||
|
|
||||||
|
// If the space parameter is a number, make an indent string containing that
|
||||||
|
// many spaces.
|
||||||
|
|
||||||
|
if (typeof space === 'number') {
|
||||||
|
for (i = 0; i < space; i += 1) {
|
||||||
|
indent += ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the space parameter is a string, it will be used as the indent string.
|
||||||
|
|
||||||
|
} else if (typeof space === 'string') {
|
||||||
|
indent = space;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is a replacer, it must be a function or an array.
|
||||||
|
// Otherwise, throw an error.
|
||||||
|
|
||||||
|
rep = replacer;
|
||||||
|
if (replacer && typeof replacer !== 'function' &&
|
||||||
|
(typeof replacer !== 'object' ||
|
||||||
|
typeof replacer.length !== 'number')) {
|
||||||
|
throw new Error('JSON.stringify');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a fake root object containing our value under the key of ''.
|
||||||
|
// Return the result of stringifying the value.
|
||||||
|
|
||||||
|
return str('', {'': value});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// If the JSON object does not yet have a parse method, give it one.
|
||||||
|
|
||||||
|
if (typeof JSON.parse !== 'function') {
|
||||||
|
JSON.parse = function (text, reviver) {
|
||||||
|
|
||||||
|
// The parse method takes a text and an optional reviver function, and returns
|
||||||
|
// a JavaScript value if the text is a valid JSON text.
|
||||||
|
|
||||||
|
var j;
|
||||||
|
|
||||||
|
function walk(holder, key) {
|
||||||
|
|
||||||
|
// The walk method is used to recursively walk the resulting structure so
|
||||||
|
// that modifications can be made.
|
||||||
|
|
||||||
|
var k, v, value = holder[key];
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
for (k in value) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
||||||
|
v = walk(value, k);
|
||||||
|
if (v !== undefined) {
|
||||||
|
value[k] = v;
|
||||||
|
} else {
|
||||||
|
delete value[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reviver.call(holder, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Parsing happens in four stages. In the first stage, we replace certain
|
||||||
|
// Unicode characters with escape sequences. JavaScript handles many characters
|
||||||
|
// incorrectly, either silently deleting them, or treating them as line endings.
|
||||||
|
|
||||||
|
text = String(text);
|
||||||
|
cx.lastIndex = 0;
|
||||||
|
if (cx.test(text)) {
|
||||||
|
text = text.replace(cx, function (a) {
|
||||||
|
return '\\u' +
|
||||||
|
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the second stage, we run the text against regular expressions that look
|
||||||
|
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
||||||
|
// because they can cause invocation, and '=' because it can cause mutation.
|
||||||
|
// But just to be safe, we want to reject all unexpected forms.
|
||||||
|
|
||||||
|
// We split the second stage into 4 regexp operations in order to work around
|
||||||
|
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
||||||
|
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
||||||
|
// replace all simple value tokens with ']' characters. Third, we delete all
|
||||||
|
// open brackets that follow a colon or comma or that begin the text. Finally,
|
||||||
|
// we look to see that the remaining characters are only whitespace or ']' or
|
||||||
|
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
||||||
|
|
||||||
|
if (/^[\],:{}\s]*$/
|
||||||
|
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
|
||||||
|
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
|
||||||
|
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
||||||
|
|
||||||
|
// In the third stage we use the eval function to compile the text into a
|
||||||
|
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
||||||
|
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
||||||
|
// in parens to eliminate the ambiguity.
|
||||||
|
|
||||||
|
j = eval('(' + text + ')');
|
||||||
|
|
||||||
|
// In the optional fourth stage, we recursively walk the new structure, passing
|
||||||
|
// each name/value pair to a reviver function for possible transformation.
|
||||||
|
|
||||||
|
return typeof reviver === 'function'
|
||||||
|
? walk({'': j}, '')
|
||||||
|
: j;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
||||||
|
|
||||||
|
throw new SyntaxError('JSON.parse');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}());
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,186 @@
|
|||||||
|
<h1 align="center">Backbone.Wreqr</h1>
|
||||||
|
<p align="center">
|
||||||
|
<a title='Build Status' href="https://travis-ci.org/marionettejs/backbone.wreqr">
|
||||||
|
<img src='https://travis-ci.org/marionettejs/backbone.wreqr.svg' />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
A simple infrastructure based on [messaging patterns](http://www.eaipatterns.com/)
|
||||||
|
and service bus implementations for decoupling [Backbone](http://backbonejs.org)
|
||||||
|
and [Backbone.Marionette](http://marionettejs.com) applications.
|
||||||
|
|
||||||
|
**Notice:** In the next major release of Marionette, v3, Wreqr will be swapped for an updated library,
|
||||||
|
[Radio](https://github.com/jmeas/backbone.radio). If you've already begun using Wreqr, don't worry. This change
|
||||||
|
isn't for quite some time: a few months, at the earliest. Also, we will support easily swapping the two libraries,
|
||||||
|
so you won't run into any problems if you decide to continue using Wreqr.
|
||||||
|
|
||||||
|
For an introduction to Radio, check out
|
||||||
|
[our blog post](http://marionettejs.github.io/2014/07/11/introducing-backbone-radio/index.html). As of Marionette v2.1, you can easily
|
||||||
|
swap in Radio for Wreqr with [this shim](https://gist.github.com/jmeas/7992474cdb1c5672d88b). We think you'll really like the changes!
|
||||||
|
|
||||||
|
## Downloads And Source
|
||||||
|
|
||||||
|
Grab the source from the `src` folder above. Grab the most recent builds
|
||||||
|
from the links below.
|
||||||
|
|
||||||
|
### Standard Builds
|
||||||
|
|
||||||
|
* Development: [backbone.wreqr.js](https://raw.github.com/marionettejs/backbone.wreqr/master/lib/backbone.wreqr.js)
|
||||||
|
|
||||||
|
* Production: [backbone.wreqr.min.js](https://raw.github.com/marionettejs/backbone.wreqr/master/lib/backbone.wreqr.min.js)
|
||||||
|
|
||||||
|
## Basic Use
|
||||||
|
|
||||||
|
### Event Aggregator
|
||||||
|
|
||||||
|
An event aggregator implementation. It extends from `Backbone.Events` to
|
||||||
|
provide the core event handling code in an object that can itself be
|
||||||
|
extended and instantiated as needed.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var vent = new Backbone.Wreqr.EventAggregator();
|
||||||
|
|
||||||
|
vent.on("foo", function(){
|
||||||
|
console.log("foo event");
|
||||||
|
});
|
||||||
|
|
||||||
|
vent.trigger("foo");
|
||||||
|
```
|
||||||
|
|
||||||
|
### Commands And Request / Response
|
||||||
|
|
||||||
|
Wreqr can be used by instantiating a `Backbone.Wreqr.Commands`
|
||||||
|
or `Backbone.Wreqr.RequestResponse` object. These objects provide a
|
||||||
|
`setHandler` method to add a handler for a named request or command.
|
||||||
|
Commands can then be executed with the `execute` method, and
|
||||||
|
request/response can be done through the `request` method.
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
```js
|
||||||
|
var commands = new Backbone.Wreqr.Commands();
|
||||||
|
|
||||||
|
commands.setHandler("foo", function(){
|
||||||
|
console.log("the foo command was executed");
|
||||||
|
});
|
||||||
|
|
||||||
|
commands.execute("foo");
|
||||||
|
```
|
||||||
|
|
||||||
|
### Request/Response
|
||||||
|
|
||||||
|
```js
|
||||||
|
var reqres = new Backbone.Wreqr.RequestResponse();
|
||||||
|
|
||||||
|
reqres.setHandler("foo", function(){
|
||||||
|
return "foo requested. this is the response";
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = reqres.request("foo");
|
||||||
|
console.log(result);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Radio
|
||||||
|
|
||||||
|
Radio is a convenient way for emitting events through channels. Radio can be used to either retrieve a channel, or talk through a channel with either command, reqres, or vent.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// channels
|
||||||
|
var globalChannel = Backbone.Wreqr.radio.channel('global');
|
||||||
|
var userChannel = Backbone.Wreqr.radio.channel('user');
|
||||||
|
|
||||||
|
// Wreqr events
|
||||||
|
Backbone.Wreqr.radio.commands.execute( 'global', 'shutdown' );
|
||||||
|
Backbone.Wreqr.radio.reqres.request( 'global', 'current-user' );
|
||||||
|
Backbone.Wreqr.radio.vent.trigger( 'global', 'game-over');
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Channel
|
||||||
|
Channel is an object that wraps EventAggregator, Commands, and Reqres. Channels provide a convenient way for the objects in your system to talk to one another without the global channel becoming too noisy.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// global channel
|
||||||
|
var globalChannel = Backbone.Wreqr.radio.channel('global');
|
||||||
|
globalChannel.commands.execute('shutdown' );
|
||||||
|
globalChannel.reqres.request('current-user' );
|
||||||
|
globalChannel.vent.trigger('game-over');
|
||||||
|
|
||||||
|
// user channel
|
||||||
|
var userChannel = Backbone.Wreqr.radio.channel('user');
|
||||||
|
userChannel.commands.execute('punnish');
|
||||||
|
userChannel.reqres.request('user-avatar');
|
||||||
|
userChannel.vent.trigger('win', {
|
||||||
|
level: 2,
|
||||||
|
stars: 3
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding Multiple Handlers
|
||||||
|
|
||||||
|
Multiple handlers can be set on the Commands and RequestResponse
|
||||||
|
objects in a single call, using the `setHandlers` method and supplying
|
||||||
|
a `{"name": configuration}` hash where the `configuration` is an
|
||||||
|
object literal or a function.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var reqres = new Backbone.Wreqr.RequestResponse();
|
||||||
|
|
||||||
|
reqres.setHandlers({
|
||||||
|
"foo": function(){ /* ... */ },
|
||||||
|
"bar": {
|
||||||
|
callback: function(){ /* ... */ },
|
||||||
|
context: someObject
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = reqres.request("foo");
|
||||||
|
```
|
||||||
|
|
||||||
|
The "foo" handler is assigned directly to a function, while the
|
||||||
|
"bar" handler is assigned to a function with a specific context
|
||||||
|
to execute the function within.
|
||||||
|
|
||||||
|
This works for all `Handlers`, `Commands` and `RequestResponse`
|
||||||
|
objects.
|
||||||
|
|
||||||
|
### Removing Handlers
|
||||||
|
|
||||||
|
Removing handlers for commands or requests is done the
|
||||||
|
same way, with the `removeHandler` or `removeAllHandlers`
|
||||||
|
functions.
|
||||||
|
|
||||||
|
```js
|
||||||
|
reqres.removeHandler("foo");
|
||||||
|
|
||||||
|
commands.removeAllHandlers();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Extending Wreqr Objects
|
||||||
|
|
||||||
|
The EventAggregator, Commands and RequestResponse objects can all be
|
||||||
|
extended using Backbone's standard `extend` method.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var MyEventAgg = Backbone.Wreqr.EventAggregator.extend({
|
||||||
|
foo: function(){...}
|
||||||
|
});
|
||||||
|
|
||||||
|
var MyCommands = Backbone.Wreqr.Commands.extend({
|
||||||
|
foo: function(){...}
|
||||||
|
});
|
||||||
|
|
||||||
|
var MyReqRes = Backbone.Wreqr.RequestResponse.extend({
|
||||||
|
foo: function(){...}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT - see [LICENSE.md](https://raw.github.com/marionettejs/backbone.wreqr/master/LICENSE.md)
|
||||||
|
|
||||||
|
## Dev
|
||||||
|
* `npm install`
|
||||||
|
* `npm install -g grunt-cli`
|
||||||
|
* `grunt`
|
||||||
|
|
@ -0,0 +1,41 @@
|
|||||||
|
describe('Executing `connectCommands` with a hash as the first argument', function() {
|
||||||
|
|
||||||
|
var
|
||||||
|
ch,
|
||||||
|
label1 = 'one',
|
||||||
|
label2 = 'two',
|
||||||
|
cbOne,
|
||||||
|
cbTwo,
|
||||||
|
p,
|
||||||
|
ret,
|
||||||
|
commandsHash;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
cbOne = function() {};
|
||||||
|
cbTwo = function() {};
|
||||||
|
ch = Wreqr.radio.channel('foo');
|
||||||
|
|
||||||
|
commandsHash = {};
|
||||||
|
commandsHash[label2] = cbOne;
|
||||||
|
commandsHash[label1] = cbTwo;
|
||||||
|
|
||||||
|
ret = ch.connectCommands( commandsHash );
|
||||||
|
|
||||||
|
p = ch.commands._wreqrHandlers || {};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
ch.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should attach the listeners to the Channel', function() {
|
||||||
|
expect(_.keys(p)).toEqual( [label2, label1] );
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should return the Channel', function() {
|
||||||
|
expect( ret ).toBe( ch );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,41 @@
|
|||||||
|
describe('Executing `connectEvents` with a hash as the first argument', function() {
|
||||||
|
|
||||||
|
var
|
||||||
|
ch,
|
||||||
|
label1 = 'one',
|
||||||
|
label2 = 'two',
|
||||||
|
cbOne,
|
||||||
|
cbTwo,
|
||||||
|
p,
|
||||||
|
ret,
|
||||||
|
eventsHash;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
cbOne = function() {};
|
||||||
|
cbTwo = function() {};
|
||||||
|
ch = Wreqr.radio.channel('test');
|
||||||
|
|
||||||
|
eventsHash = {};
|
||||||
|
eventsHash[label2] = cbOne;
|
||||||
|
eventsHash[label1] = cbTwo;
|
||||||
|
|
||||||
|
ret = ch.connectEvents( eventsHash );
|
||||||
|
|
||||||
|
p = ch.vent._events || {};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
ch.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should attach the listeners to the Channel', function() {
|
||||||
|
expect(_.keys(p)).toEqual( [label2, label1] );
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should return the Channel', function() {
|
||||||
|
expect( ret ).toBe( ch );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,41 @@
|
|||||||
|
describe('Executing `connectRequests` with a hash as the first argument', function() {
|
||||||
|
|
||||||
|
var
|
||||||
|
ch,
|
||||||
|
label1 = 'one',
|
||||||
|
label2 = 'two',
|
||||||
|
cbOne,
|
||||||
|
cbTwo,
|
||||||
|
p,
|
||||||
|
ret,
|
||||||
|
requestsHash;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
cbOne = function() {};
|
||||||
|
cbTwo = function() {};
|
||||||
|
ch = Wreqr.radio.channel('test');
|
||||||
|
|
||||||
|
requestsHash = {};
|
||||||
|
requestsHash[label2] = cbOne;
|
||||||
|
requestsHash[label1] = cbTwo;
|
||||||
|
|
||||||
|
ret = ch.connectRequests( requestsHash );
|
||||||
|
|
||||||
|
p = ch.reqres._wreqrHandlers || {};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
ch.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should attach the listeners to the Channel', function() {
|
||||||
|
expect(_.keys(p)).toEqual( [label2, label1] );
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should return the Channel', function() {
|
||||||
|
expect( ret ).toBe( ch );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,23 @@
|
|||||||
|
describe('Creating a Channel', function() {
|
||||||
|
|
||||||
|
var
|
||||||
|
ch,
|
||||||
|
chName,
|
||||||
|
name = 'test',
|
||||||
|
v, c, r;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
ch = new Wreqr.Channel( name );
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should set the name', function() {
|
||||||
|
expect( ch.channelName ).toEqual( name );
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should instantiate a new instance of each messaging system', function() {
|
||||||
|
expect( ch.vent instanceof Backbone.Wreqr.EventAggregator ).toBeTruthy();
|
||||||
|
expect( ch.commands instanceof Backbone.Wreqr.Commands ).toBeTruthy();
|
||||||
|
expect( ch.reqres instanceof Backbone.Wreqr.RequestResponse ).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,44 @@
|
|||||||
|
describe('Running `resetChannel`', function() {
|
||||||
|
|
||||||
|
var
|
||||||
|
ch,
|
||||||
|
v1Stub, v2Stub, cStub, rStub,
|
||||||
|
v, c, r,
|
||||||
|
ret;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
ch = new Wreqr.Channel( 'test' );
|
||||||
|
v = ch.vent;
|
||||||
|
c = ch.commands;
|
||||||
|
r = ch.reqres;
|
||||||
|
v1Stub = sinon.spy( v, "off");
|
||||||
|
v2Stub = sinon.spy( v, "stopListening");
|
||||||
|
cStub = sinon.spy( c, "removeAllHandlers");
|
||||||
|
rStub = sinon.spy( r, "removeAllHandlers");
|
||||||
|
|
||||||
|
ret = ch.reset();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
|
||||||
|
v1Stub.restore();
|
||||||
|
v2Stub.restore();
|
||||||
|
cStub.restore();
|
||||||
|
rStub.restore();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should call the reset functions for each messaging system', function() {
|
||||||
|
expect( v1Stub ).toHaveBeenCalledOnce();
|
||||||
|
expect( v2Stub ).toHaveBeenCalledOnce();
|
||||||
|
expect( cStub ).toHaveBeenCalledOnce();
|
||||||
|
expect( rStub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should return the Channel', function() {
|
||||||
|
expect( ret ).toBe( ch );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,93 @@
|
|||||||
|
describe("command storage - custom storage", function(){
|
||||||
|
|
||||||
|
describe("when providing a custom storage type as a constructor function to a Commands type", function(){
|
||||||
|
var commands, StorageType;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
StorageType = function(){};
|
||||||
|
_.extend(StorageType, {
|
||||||
|
addCommand: jasmine.createSpy("add command"),
|
||||||
|
getCommands: jasmine.createSpy("get commands"),
|
||||||
|
clearCommands: jasmine.createSpy("clear commands")
|
||||||
|
});
|
||||||
|
|
||||||
|
var Commands = Wreqr.Commands.extend({
|
||||||
|
storageType: StorageType
|
||||||
|
});
|
||||||
|
|
||||||
|
commands = new Commands();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should instantiate and use that storage type", function(){
|
||||||
|
expect(commands.storage instanceof StorageType).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when providing a custom storage type as an object literal to a Commands type", function(){
|
||||||
|
var commands, StorageType;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
StorageType = {
|
||||||
|
addCommand: jasmine.createSpy("add command"),
|
||||||
|
getCommands: jasmine.createSpy("get commands"),
|
||||||
|
clearCommands: jasmine.createSpy("clear commands")
|
||||||
|
};
|
||||||
|
|
||||||
|
var Commands = Wreqr.Commands.extend({
|
||||||
|
storageType: StorageType
|
||||||
|
});
|
||||||
|
|
||||||
|
commands = new Commands();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should instantiate and use that storage type", function(){
|
||||||
|
expect(commands.storage).toBe(StorageType);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when providing a custom storage type as a constructor function to a Commands instance", function(){
|
||||||
|
var commands, StorageType;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
StorageType = function(){};
|
||||||
|
_.extend(StorageType, {
|
||||||
|
addCommand: jasmine.createSpy("add command"),
|
||||||
|
getCommands: jasmine.createSpy("get commands"),
|
||||||
|
clearCommands: jasmine.createSpy("clear commands")
|
||||||
|
});
|
||||||
|
|
||||||
|
commands = new Wreqr.Commands({
|
||||||
|
storageType: StorageType
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should instantiate and use that storage type", function(){
|
||||||
|
expect(commands.storage instanceof StorageType).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when providing a custom storage type as an object literal to a Commands instance", function(){
|
||||||
|
var commands, StorageType;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
StorageType = {
|
||||||
|
addCommand: jasmine.createSpy("add command"),
|
||||||
|
getCommands: jasmine.createSpy("get commands"),
|
||||||
|
clearCommands: jasmine.createSpy("clear commands")
|
||||||
|
};
|
||||||
|
|
||||||
|
commands = new Wreqr.Commands({
|
||||||
|
storageType: StorageType
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should instantiate and use that storage type", function(){
|
||||||
|
expect(commands.storage).toBe(StorageType);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,41 @@
|
|||||||
|
describe("commands - storage", function(){
|
||||||
|
|
||||||
|
describe("when a command execution occurs and there are no handlers", function(){
|
||||||
|
var commands, cmd;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
commands = new Wreqr.Commands();
|
||||||
|
commands.execute("foo");
|
||||||
|
|
||||||
|
cmd = commands.storage.getCommands("foo");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should store the command for later execution", function(){
|
||||||
|
expect(cmd.command).toBe("foo");
|
||||||
|
expect(cmd.instances.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("given no handler for a command, and that command has been called, when adding the handler", function(){
|
||||||
|
var commands, cmd, handler;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
handler = jasmine.createSpy("foo handler");
|
||||||
|
|
||||||
|
commands = new Wreqr.Commands();
|
||||||
|
commands.execute("foo", 1, 2);
|
||||||
|
|
||||||
|
commands.setHandler("foo", handler);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should execute the command with that handler with any supplied args", function(){
|
||||||
|
expect(handler).toHaveBeenCalledWith(1, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should clear the existing stored command instances for that command name", function(){
|
||||||
|
expect(commands.storage.getCommands("foo").instances.length).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,59 @@
|
|||||||
|
describe("commands", function(){
|
||||||
|
|
||||||
|
describe("when executing a command", function(){
|
||||||
|
var commands, result;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
commands = new Wreqr.Commands();
|
||||||
|
|
||||||
|
commands.setHandler("do:it", function(){
|
||||||
|
return "some value";
|
||||||
|
});
|
||||||
|
|
||||||
|
result = commands.execute("do:it");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not return any value", function(){
|
||||||
|
expect(result).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when executing a command with a parameter", function(){
|
||||||
|
var commands, result, param;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
commands = new Wreqr.Commands();
|
||||||
|
|
||||||
|
commands.setHandler("do:it", function(p){
|
||||||
|
param = p;
|
||||||
|
});
|
||||||
|
|
||||||
|
result = commands.execute("do:it", "foo");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should pass the param along", function(){
|
||||||
|
expect(param).toBe("foo");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when executing with multiple parameters", function(){
|
||||||
|
var commands, result, param1, param2;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
commands = new Wreqr.Commands();
|
||||||
|
|
||||||
|
commands.setHandler("do:it", function(p, p2){
|
||||||
|
param1 = p;
|
||||||
|
param2= p2;
|
||||||
|
});
|
||||||
|
|
||||||
|
commands.execute("do:it", "foo", "bar");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should pass the param along", function(){
|
||||||
|
expect(param1).toBe("foo");
|
||||||
|
expect(param2).toBe("bar");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,43 @@
|
|||||||
|
describe("event aggregator", function(){
|
||||||
|
|
||||||
|
describe("when triggering an event", function(){
|
||||||
|
var vent, handlerCalled;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
var vent = new Wreqr.EventAggregator();
|
||||||
|
|
||||||
|
vent.on("foo", function(){
|
||||||
|
handlerCalled = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
vent.trigger("foo");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should fire handlers", function(){
|
||||||
|
expect(handlerCalled).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when unbinding from an event and then triggering it", function(){
|
||||||
|
var vent, handlerCalled;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
var vent = new Wreqr.EventAggregator();
|
||||||
|
|
||||||
|
var callback = function(){
|
||||||
|
handlerCalled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
binding = vent.on("foo", callback);
|
||||||
|
|
||||||
|
vent.off("foo", callback);
|
||||||
|
|
||||||
|
vent.trigger("foo");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not fire any handlers", function(){
|
||||||
|
expect(handlerCalled).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,55 @@
|
|||||||
|
describe("handler - set from hash", function(){
|
||||||
|
|
||||||
|
describe("when adding multiple handlers via an object literal / hash", function(){
|
||||||
|
var handlers, hndlrs;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
hndlrs = {
|
||||||
|
"foo": jasmine.createSpy("foo handler"),
|
||||||
|
"bar": jasmine.createSpy("bar handler")
|
||||||
|
};
|
||||||
|
|
||||||
|
handlers = new Wreqr.Handlers();
|
||||||
|
handlers.setHandlers(hndlrs);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should add all named handlers", function(){
|
||||||
|
expect(handlers.hasHandler("foo")).toBe(true);
|
||||||
|
expect(handlers.hasHandler("bar")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should execute the handler", function(){
|
||||||
|
handlers.getHandler("foo")();
|
||||||
|
handlers.getHandler("bar")();
|
||||||
|
|
||||||
|
expect(hndlrs.foo).toHaveBeenCalled();
|
||||||
|
expect(hndlrs.bar).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when the object literal values are objects with a callback and context attribute", function(){
|
||||||
|
var handlers, hndlrs, ctx;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
ctx = {};
|
||||||
|
|
||||||
|
hndlrs = {
|
||||||
|
"foo": {
|
||||||
|
callback: jasmine.createSpy("foo handler"),
|
||||||
|
context: ctx
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handlers = new Wreqr.Handlers();
|
||||||
|
handlers.setHandlers(hndlrs);
|
||||||
|
|
||||||
|
handlers.getHandler("foo")();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should execute the handler callback with the specified context", function(){
|
||||||
|
expect(hndlrs.foo.callback).toHaveBeenCalled();
|
||||||
|
expect(hndlrs.foo.callback.mostRecentCall.object).toBe(ctx);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,105 @@
|
|||||||
|
describe("handlers", function(){
|
||||||
|
|
||||||
|
describe("when adding a handler", function(){
|
||||||
|
var handlers, handler, setHandleredHandler, ctx;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
handlers = new Wreqr.Handlers();
|
||||||
|
spyOn(handlers, "trigger");
|
||||||
|
|
||||||
|
ctx = {};
|
||||||
|
setHandleredHandler = jasmine.createSpy("a setHandlered handler");
|
||||||
|
|
||||||
|
handlers.setHandler("foo", setHandleredHandler, ctx);
|
||||||
|
|
||||||
|
handler = handlers.getHandler("foo");
|
||||||
|
handler();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should trigger a handler:add event", function(){
|
||||||
|
expect(handlers.trigger).toHaveBeenCalledWith("handler:add", "foo", setHandleredHandler, ctx);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when requesting a handler by name", function(){
|
||||||
|
|
||||||
|
describe("and a handler has been setHandlered with that name", function(){
|
||||||
|
var handler, setHandleredHandler, ctx;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
var handlers = new Wreqr.Handlers();
|
||||||
|
|
||||||
|
ctx = {};
|
||||||
|
setHandleredHandler = jasmine.createSpy("a setHandlered handler");
|
||||||
|
handlers.setHandler("handler", setHandleredHandler, ctx);
|
||||||
|
|
||||||
|
handler = handlers.getHandler("handler");
|
||||||
|
handler();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return the setHandlered handler callback", function(){
|
||||||
|
expect(setHandleredHandler).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return the setHandlered handler context", function(){
|
||||||
|
expect(setHandleredHandler.mostRecentCall.object).toBe(ctx);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("and a handler has not been setHandlered with that name", function(){
|
||||||
|
var handlers, handle;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
handlers = new Wreqr.Handlers();
|
||||||
|
handle = handlers.getHandler();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should thrown an error saying a handler was not found", function(){
|
||||||
|
expect(handle).toBeUndefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when removing a named handler", function(){
|
||||||
|
var handlers, setHandleredHandler, ctx, handle;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
handlers = new Wreqr.Handlers();
|
||||||
|
|
||||||
|
ctx = {};
|
||||||
|
setHandleredHandler = jasmine.createSpy("a setHandlered handler");
|
||||||
|
handlers.setHandler("handler", setHandleredHandler, ctx);
|
||||||
|
handlers.removeHandler("handler");
|
||||||
|
handle = handlers.getHandler("handler");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should no longer return the requested hander", function(){
|
||||||
|
expect(handle).toBeUndefined;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when removing all handlers", function(){
|
||||||
|
var handlers, setHandleredHandler, ctx, handle1, handle2;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
handlers = new Wreqr.Handlers();
|
||||||
|
|
||||||
|
ctx = {};
|
||||||
|
setHandleredHandler = jasmine.createSpy("a setHandlered handler");
|
||||||
|
handlers.setHandler("handler1", setHandleredHandler, ctx);
|
||||||
|
handlers.setHandler("handler2", setHandleredHandler, ctx);
|
||||||
|
handlers.removeAllHandlers();
|
||||||
|
handle1 = handlers.getHandler("handler1");
|
||||||
|
handle2 = handlers.getHandler("handler2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should no longer return the requested handler", function(){
|
||||||
|
expect(handle1).toBeUndefined;
|
||||||
|
expect(handle2).toBeUndefined;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,8 @@
|
|||||||
|
beforeEach(function() {
|
||||||
|
this.addMatchers({
|
||||||
|
toHaveOwnProperty: function(expectedProperty) {
|
||||||
|
var obj = this.actual;
|
||||||
|
return obj.hasOwnProperty(expectedProperty);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,42 @@
|
|||||||
|
describe('radio.channel', function () {
|
||||||
|
|
||||||
|
var channel, channelName;
|
||||||
|
|
||||||
|
describe('with no arguments', function() {
|
||||||
|
|
||||||
|
it( 'should throw an exception', function() {
|
||||||
|
expect( function() { Wreqr.radio.channel()} ).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('for a nonexistent channel', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
channel = Wreqr.radio.channel('lala');
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should return an instance of the default channel', function() {
|
||||||
|
expect( channel.channelName ).toEqual( 'lala' );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('twice with the same name', function() {
|
||||||
|
|
||||||
|
var chOne, chTwo;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chOne = Wreqr.radio.channel( 'lala' );
|
||||||
|
chTwo = Wreqr.radio.channel( 'lala' );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should return the same channel', function() {
|
||||||
|
expect( chOne ).toBe( chTwo );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,156 @@
|
|||||||
|
describe('radio.commands', function() {
|
||||||
|
|
||||||
|
describe('.execute', function() {
|
||||||
|
|
||||||
|
var ch, chName, commandName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
commandName = 'some:command';
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.commands, 'execute' );
|
||||||
|
Wreqr.radio.commands.execute( chName, commandName );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
stub.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel\'s commands execute function', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass the correct arguments to commands.execute', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledWith( commandName );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.setHandler', function() {
|
||||||
|
|
||||||
|
var ch, chName, fn, commandName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
fn = function() {};
|
||||||
|
commandName = 'some:command';
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.commands, 'setHandler' );
|
||||||
|
Wreqr.radio.commands.setHandler( chName, commandName, fn );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
stub.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel\'s commands object', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce;
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass the correct arguments to commands.setHandler', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledWith( commandName, fn );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.setHandlers', function() {
|
||||||
|
|
||||||
|
var ch, chName, obj, commandName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
obj = {
|
||||||
|
some1: function() {},
|
||||||
|
some2: function() {}
|
||||||
|
};
|
||||||
|
commandName = 'some:command';
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.commands, 'setHandlers' );
|
||||||
|
Wreqr.radio.commands.setHandlers( chName, commandName, obj );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel\'s commands object', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass the correct arguments to commands.setHandlers', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledWith( commandName, obj );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.removeHandlers', function() {
|
||||||
|
|
||||||
|
var ch, chName, commandName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
commandName = 'some:command';
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.commands, 'removeHandler' );
|
||||||
|
Wreqr.radio.commands.removeHandler( chName, commandName );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
stub.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel\'s commands object', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass the correct arguments to commands.removeHandler', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledWith( commandName );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.removeAllHandlers', function() {
|
||||||
|
|
||||||
|
var ch, chName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.commands, 'removeAllHandlers' );
|
||||||
|
Wreqr.radio.commands.removeAllHandlers( chName );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel\'s commands object', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,182 @@
|
|||||||
|
describe('radio.reqres', function() {
|
||||||
|
|
||||||
|
describe('.request`', function() {
|
||||||
|
|
||||||
|
var ch, chName, reqName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
reqName = 'some:request';
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.reqres, 'request' );
|
||||||
|
Wreqr.radio.reqres.request( chName, reqName );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
stub.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel\'s reqres request function', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass the correct arguments to reqres.request', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledWith( reqName );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.setHandler` ', function() {
|
||||||
|
|
||||||
|
var ch, chName, fn, commandName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
fn = function() {};
|
||||||
|
commandName = 'some:command';
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.reqres, 'setHandler' );
|
||||||
|
Wreqr.radio.reqres.setHandler( chName, commandName, fn );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel\'s reqres object', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass the correct arguments to reqres.setHandler', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledWith( commandName, fn );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.setHandlers', function() {
|
||||||
|
|
||||||
|
var ch, chName, obj, commandName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
obj = {
|
||||||
|
some1: function() {},
|
||||||
|
some2: function() {}
|
||||||
|
};
|
||||||
|
commandName = 'some:command';
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.reqres, 'setHandlers' );
|
||||||
|
Wreqr.radio.reqres.setHandlers( chName, commandName, obj );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel\'s reqres object', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass the correct arguments to reqres.setHandlers', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledWith( commandName, obj );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.removeHandler', function() {
|
||||||
|
|
||||||
|
var ch, chName, commandName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
commandName = 'some:command';
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.reqres, 'removeHandler' );
|
||||||
|
Wreqr.radio.reqres.removeHandler( chName, commandName );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel\'s reqres object', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass the correct arguments to reqres.removeHandler', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledWith( commandName );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.removeAllHandlers', function() {
|
||||||
|
|
||||||
|
var ch, chName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.reqres, 'removeAllHandlers' );
|
||||||
|
Wreqr.radio.reqres.removeAllHandlers( chName );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel\'s reqres object', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('passing data between the handler and the request', function() {
|
||||||
|
|
||||||
|
var ch, chName, fn, returnObject;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
chName = 'test';
|
||||||
|
reqName = 'some:request';
|
||||||
|
fn = function(p1, p2){
|
||||||
|
return p1 + p2;
|
||||||
|
};
|
||||||
|
|
||||||
|
Wreqr.radio.reqres.setHandler( chName, reqName, fn );
|
||||||
|
returnObject = Wreqr.radio.reqres.request( chName, reqName , 1, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass parameters to handler from request', function() {
|
||||||
|
expect( returnObject ).toEqual(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
@ -0,0 +1,283 @@
|
|||||||
|
describe('radio.vent', function() {
|
||||||
|
|
||||||
|
describe('.off', function() {
|
||||||
|
|
||||||
|
var ch, chName, obj, fn, eventName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
fn = function() {};
|
||||||
|
eventName = 'some:event';
|
||||||
|
obj = { test: true, testTwo: false };
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.vent, 'on' );
|
||||||
|
Wreqr.radio.vent.on( chName, eventName, fn, obj );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the corresponding Channel vent method', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass the correct arguments to vent.on', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledWith( eventName, fn, obj );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.off with no additional arguments', function() {
|
||||||
|
|
||||||
|
var ch, chName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.vent, 'off' );
|
||||||
|
Wreqr.radio.vent.off( chName );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel vent `off` method', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Passing additional arguments to the `off` function', function() {
|
||||||
|
|
||||||
|
var ch, chName, obj, fn, eventName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
fn = function() {};
|
||||||
|
eventName = 'some:event';
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.vent, 'off' );
|
||||||
|
Wreqr.radio.vent.off( chName, eventName, fn );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass them along to vent.off', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledWith( eventName, fn );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.once', function() {
|
||||||
|
|
||||||
|
var ch, chName, obj, fn, eventName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
fn = function() {};
|
||||||
|
eventName = 'some:event';
|
||||||
|
obj = { test: true, testTwo: false };
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.vent, 'once' );
|
||||||
|
Wreqr.radio.vent.once( chName, eventName, fn, obj );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
stub.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel vent `once`', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass the correct arguments to vent.once', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledWith( eventName, fn, obj );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.trigger', function() {
|
||||||
|
|
||||||
|
var ch, chName, obj, fn, eventName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
fn = function() {};
|
||||||
|
eventName = 'some:event';
|
||||||
|
obj = { test: true, testTwo: false };
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.vent, 'trigger' );
|
||||||
|
Wreqr.radio.vent.trigger( chName, eventName, fn, obj, true, '2' );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel vent `trigger`', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass the correct arguments to vent.trigger', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledWith( eventName, fn, obj, true, '2' );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.stopListening with no extra arguments', function() {
|
||||||
|
|
||||||
|
var ch, chName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.vent, 'stopListening' );
|
||||||
|
Wreqr.radio.vent.stopListening( chName );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel vent `stopListening`', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.stopListening with additional arguments', function() {
|
||||||
|
|
||||||
|
var ch, chName, obj, fn, eventName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
fn = function() {};
|
||||||
|
eventName = 'some:event';
|
||||||
|
obj = { test: true, testTwo: false };
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.vent, 'stopListening' );
|
||||||
|
Wreqr.radio.vent.stopListening( chName, eventName, fn, obj );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass the correct arguments to vent.trigger', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledWith( eventName, fn, obj );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.listenTo', function() {
|
||||||
|
|
||||||
|
var ch, chName, obj, fn, eventName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
fn = function() {};
|
||||||
|
eventName = 'some:event';
|
||||||
|
obj = { test: true, testTwo: false };
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.vent, 'listenTo' );
|
||||||
|
Wreqr.radio.vent.listenTo( chName, eventName, fn, obj, true, '2' );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel vent `trigger`', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass the correct arguments to vent.trigger', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledWith( eventName, fn, obj, true, '2' );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.listenToOnce', function() {
|
||||||
|
|
||||||
|
var ch, chName, obj, fn, eventName, stub;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
|
||||||
|
chName = 'test';
|
||||||
|
fn = function() {};
|
||||||
|
eventName = 'some:event';
|
||||||
|
obj = { test: true, testTwo: false };
|
||||||
|
|
||||||
|
ch = Wreqr.radio.channel( chName );
|
||||||
|
|
||||||
|
stub = sinon.stub( ch.vent, 'listenToOnce' );
|
||||||
|
Wreqr.radio.vent.listenToOnce( chName, eventName, fn, obj, true, '2' );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should forward the call to the Channel vent `listenToOnce`', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'should pass the correct arguments to vent.listenToOnce', function() {
|
||||||
|
expect( stub ).toHaveBeenCalledWith( eventName, fn, obj, true, '2' );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
})
|
@ -0,0 +1,60 @@
|
|||||||
|
describe("request/response", function(){
|
||||||
|
|
||||||
|
describe("when requesting a response", function(){
|
||||||
|
var reqres, result;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
reqres = new Wreqr.RequestResponse();
|
||||||
|
|
||||||
|
reqres.setHandler("do:it", function(){
|
||||||
|
return "some value";
|
||||||
|
});
|
||||||
|
|
||||||
|
result = reqres.request("do:it");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return a value", function(){
|
||||||
|
expect(result).toBe("some value");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when requesting a response, with a parameter", function(){
|
||||||
|
var reqres, result, param;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
reqres = new Wreqr.RequestResponse();
|
||||||
|
|
||||||
|
reqres.setHandler("do:it", function(p){
|
||||||
|
param = p;
|
||||||
|
});
|
||||||
|
|
||||||
|
result = reqres.request("do:it", "foo");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should pass the param along", function(){
|
||||||
|
expect(param).toBe("foo");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when requesting a response, with multiple parameters", function(){
|
||||||
|
var reqres, result, param1, param2;
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
reqres = new Wreqr.RequestResponse();
|
||||||
|
|
||||||
|
reqres.setHandler("do:it", function(p, p2){
|
||||||
|
param1 = p;
|
||||||
|
param2= p2;
|
||||||
|
});
|
||||||
|
|
||||||
|
result = reqres.request("do:it", "foo", "bar");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should pass the param along", function(){
|
||||||
|
expect(param1).toBe("foo");
|
||||||
|
expect(param2).toBe("bar");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,3 @@
|
|||||||
|
(function(global){
|
||||||
|
global.Wreqr = Backbone.Wreqr;
|
||||||
|
})(this);
|
@ -0,0 +1,39 @@
|
|||||||
|
(function(root, factory) {
|
||||||
|
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
define(['backbone', 'underscore'], function(Backbone, _) {
|
||||||
|
return factory(Backbone, _);
|
||||||
|
});
|
||||||
|
} else if (typeof exports !== 'undefined') {
|
||||||
|
var Backbone = require('backbone');
|
||||||
|
var _ = require('underscore');
|
||||||
|
module.exports = factory(Backbone, _);
|
||||||
|
} else {
|
||||||
|
factory(root.Backbone, root._);
|
||||||
|
}
|
||||||
|
|
||||||
|
}(this, function(Backbone, _) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var previousWreqr = Backbone.Wreqr;
|
||||||
|
|
||||||
|
var Wreqr = Backbone.Wreqr = {};
|
||||||
|
|
||||||
|
Backbone.Wreqr.VERSION = '<%= version %>';
|
||||||
|
|
||||||
|
Backbone.Wreqr.noConflict = function () {
|
||||||
|
Backbone.Wreqr = previousWreqr;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// @include ../wreqr.handlers.js
|
||||||
|
// @include ../wreqr.commandStorage.js
|
||||||
|
// @include ../wreqr.commands.js
|
||||||
|
// @include ../wreqr.requestresponse.js
|
||||||
|
// @include ../wreqr.eventaggregator.js
|
||||||
|
// @include ../wreqr.channel.js
|
||||||
|
// @include ../wreqr.radio.js
|
||||||
|
|
||||||
|
return Backbone.Wreqr;
|
||||||
|
|
||||||
|
}));
|
@ -0,0 +1,60 @@
|
|||||||
|
// Wreqr.Channel
|
||||||
|
// --------------
|
||||||
|
//
|
||||||
|
// An object that wraps the three messaging systems:
|
||||||
|
// EventAggregator, RequestResponse, Commands
|
||||||
|
Wreqr.Channel = (function(Wreqr){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Channel = function(channelName) {
|
||||||
|
this.vent = new Backbone.Wreqr.EventAggregator();
|
||||||
|
this.reqres = new Backbone.Wreqr.RequestResponse();
|
||||||
|
this.commands = new Backbone.Wreqr.Commands();
|
||||||
|
this.channelName = channelName;
|
||||||
|
};
|
||||||
|
|
||||||
|
_.extend(Channel.prototype, {
|
||||||
|
|
||||||
|
// Remove all handlers from the messaging systems of this channel
|
||||||
|
reset: function() {
|
||||||
|
this.vent.off();
|
||||||
|
this.vent.stopListening();
|
||||||
|
this.reqres.removeAllHandlers();
|
||||||
|
this.commands.removeAllHandlers();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Connect a hash of events; one for each messaging system
|
||||||
|
connectEvents: function(hash, context) {
|
||||||
|
this._connect('vent', hash, context);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
connectCommands: function(hash, context) {
|
||||||
|
this._connect('commands', hash, context);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
connectRequests: function(hash, context) {
|
||||||
|
this._connect('reqres', hash, context);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Attach the handlers to a given message system `type`
|
||||||
|
_connect: function(type, hash, context) {
|
||||||
|
if (!hash) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context = context || this;
|
||||||
|
var method = (type === 'vent') ? 'on' : 'setHandler';
|
||||||
|
|
||||||
|
_.each(hash, function(fn, eventName) {
|
||||||
|
this[type][method](eventName, _.bind(fn, context));
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return Channel;
|
||||||
|
})(Wreqr);
|
@ -0,0 +1,58 @@
|
|||||||
|
// Wreqr.CommandStorage
|
||||||
|
// --------------------
|
||||||
|
//
|
||||||
|
// Store and retrieve commands for execution.
|
||||||
|
Wreqr.CommandStorage = (function(){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Constructor function
|
||||||
|
var CommandStorage = function(options){
|
||||||
|
this.options = options;
|
||||||
|
this._commands = {};
|
||||||
|
|
||||||
|
if (_.isFunction(this.initialize)){
|
||||||
|
this.initialize(options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Instance methods
|
||||||
|
_.extend(CommandStorage.prototype, Backbone.Events, {
|
||||||
|
|
||||||
|
// Get an object literal by command name, that contains
|
||||||
|
// the `commandName` and the `instances` of all commands
|
||||||
|
// represented as an array of arguments to process
|
||||||
|
getCommands: function(commandName){
|
||||||
|
var commands = this._commands[commandName];
|
||||||
|
|
||||||
|
// we don't have it, so add it
|
||||||
|
if (!commands){
|
||||||
|
|
||||||
|
// build the configuration
|
||||||
|
commands = {
|
||||||
|
command: commandName,
|
||||||
|
instances: []
|
||||||
|
};
|
||||||
|
|
||||||
|
// store it
|
||||||
|
this._commands[commandName] = commands;
|
||||||
|
}
|
||||||
|
|
||||||
|
return commands;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Add a command by name, to the storage and store the
|
||||||
|
// args for the command
|
||||||
|
addCommand: function(commandName, args){
|
||||||
|
var command = this.getCommands(commandName);
|
||||||
|
command.instances.push(args);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Clear all commands for the given `commandName`
|
||||||
|
clearCommands: function(commandName){
|
||||||
|
var command = this.getCommands(commandName);
|
||||||
|
command.instances = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return CommandStorage;
|
||||||
|
})();
|
@ -0,0 +1,63 @@
|
|||||||
|
// Wreqr.Commands
|
||||||
|
// --------------
|
||||||
|
//
|
||||||
|
// A simple command pattern implementation. Register a command
|
||||||
|
// handler and execute it.
|
||||||
|
Wreqr.Commands = (function(Wreqr, _){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
return Wreqr.Handlers.extend({
|
||||||
|
// default storage type
|
||||||
|
storageType: Wreqr.CommandStorage,
|
||||||
|
|
||||||
|
constructor: function(options){
|
||||||
|
this.options = options || {};
|
||||||
|
|
||||||
|
this._initializeStorage(this.options);
|
||||||
|
this.on("handler:add", this._executeCommands, this);
|
||||||
|
|
||||||
|
Wreqr.Handlers.prototype.constructor.apply(this, arguments);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Execute a named command with the supplied args
|
||||||
|
execute: function(name){
|
||||||
|
name = arguments[0];
|
||||||
|
var args = _.rest(arguments);
|
||||||
|
|
||||||
|
if (this.hasHandler(name)){
|
||||||
|
this.getHandler(name).apply(this, args);
|
||||||
|
} else {
|
||||||
|
this.storage.addCommand(name, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
// Internal method to handle bulk execution of stored commands
|
||||||
|
_executeCommands: function(name, handler, context){
|
||||||
|
var command = this.storage.getCommands(name);
|
||||||
|
|
||||||
|
// loop through and execute all the stored command instances
|
||||||
|
_.each(command.instances, function(args){
|
||||||
|
handler.apply(context, args);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.storage.clearCommands(name);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Internal method to initialize storage either from the type's
|
||||||
|
// `storageType` or the instance `options.storageType`.
|
||||||
|
_initializeStorage: function(options){
|
||||||
|
var storage;
|
||||||
|
|
||||||
|
var StorageType = options.storageType || this.storageType;
|
||||||
|
if (_.isFunction(StorageType)){
|
||||||
|
storage = new StorageType();
|
||||||
|
} else {
|
||||||
|
storage = StorageType;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.storage = storage;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
})(Wreqr, _);
|
@ -0,0 +1,17 @@
|
|||||||
|
// Event Aggregator
|
||||||
|
// ----------------
|
||||||
|
// A pub-sub object that can be used to decouple various parts
|
||||||
|
// of an application through event-driven architecture.
|
||||||
|
|
||||||
|
Wreqr.EventAggregator = (function(Backbone, _){
|
||||||
|
"use strict";
|
||||||
|
var EA = function(){};
|
||||||
|
|
||||||
|
// Copy the `extend` function used by Backbone's classes
|
||||||
|
EA.extend = Backbone.Model.extend;
|
||||||
|
|
||||||
|
// Copy the basic Backbone.Events on to the event aggregator
|
||||||
|
_.extend(EA.prototype, Backbone.Events);
|
||||||
|
|
||||||
|
return EA;
|
||||||
|
})(Backbone, _);
|
@ -0,0 +1,86 @@
|
|||||||
|
// Handlers
|
||||||
|
// --------
|
||||||
|
// A registry of functions to call, given a name
|
||||||
|
|
||||||
|
Wreqr.Handlers = (function(Backbone, _){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
// -----------
|
||||||
|
|
||||||
|
var Handlers = function(options){
|
||||||
|
this.options = options;
|
||||||
|
this._wreqrHandlers = {};
|
||||||
|
|
||||||
|
if (_.isFunction(this.initialize)){
|
||||||
|
this.initialize(options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Handlers.extend = Backbone.Model.extend;
|
||||||
|
|
||||||
|
// Instance Members
|
||||||
|
// ----------------
|
||||||
|
|
||||||
|
_.extend(Handlers.prototype, Backbone.Events, {
|
||||||
|
|
||||||
|
// Add multiple handlers using an object literal configuration
|
||||||
|
setHandlers: function(handlers){
|
||||||
|
_.each(handlers, function(handler, name){
|
||||||
|
var context = null;
|
||||||
|
|
||||||
|
if (_.isObject(handler) && !_.isFunction(handler)){
|
||||||
|
context = handler.context;
|
||||||
|
handler = handler.callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setHandler(name, handler, context);
|
||||||
|
}, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Add a handler for the given name, with an
|
||||||
|
// optional context to run the handler within
|
||||||
|
setHandler: function(name, handler, context){
|
||||||
|
var config = {
|
||||||
|
callback: handler,
|
||||||
|
context: context
|
||||||
|
};
|
||||||
|
|
||||||
|
this._wreqrHandlers[name] = config;
|
||||||
|
|
||||||
|
this.trigger("handler:add", name, handler, context);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Determine whether or not a handler is registered
|
||||||
|
hasHandler: function(name){
|
||||||
|
return !! this._wreqrHandlers[name];
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get the currently registered handler for
|
||||||
|
// the specified name. Throws an exception if
|
||||||
|
// no handler is found.
|
||||||
|
getHandler: function(name){
|
||||||
|
var config = this._wreqrHandlers[name];
|
||||||
|
|
||||||
|
if (!config){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return function(){
|
||||||
|
return config.callback.apply(config.context, arguments);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
// Remove a handler for the specified name
|
||||||
|
removeHandler: function(name){
|
||||||
|
delete this._wreqrHandlers[name];
|
||||||
|
},
|
||||||
|
|
||||||
|
// Remove all handlers from this registry
|
||||||
|
removeAllHandlers: function(){
|
||||||
|
this._wreqrHandlers = {};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Handlers;
|
||||||
|
})(Backbone, _);
|
@ -0,0 +1,85 @@
|
|||||||
|
// Wreqr.Radio
|
||||||
|
// --------------
|
||||||
|
//
|
||||||
|
// An object that lets you communicate with many channels.
|
||||||
|
Wreqr.radio = (function(Wreqr, _){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Radio = function() {
|
||||||
|
this._channels = {};
|
||||||
|
this.vent = {};
|
||||||
|
this.commands = {};
|
||||||
|
this.reqres = {};
|
||||||
|
this._proxyMethods();
|
||||||
|
};
|
||||||
|
|
||||||
|
_.extend(Radio.prototype, {
|
||||||
|
|
||||||
|
channel: function(channelName) {
|
||||||
|
if (!channelName) {
|
||||||
|
throw new Error('Channel must receive a name');
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._getChannel( channelName );
|
||||||
|
},
|
||||||
|
|
||||||
|
_getChannel: function(channelName) {
|
||||||
|
var channel = this._channels[channelName];
|
||||||
|
|
||||||
|
if(!channel) {
|
||||||
|
channel = new Wreqr.Channel(channelName);
|
||||||
|
this._channels[channelName] = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return channel;
|
||||||
|
},
|
||||||
|
|
||||||
|
_proxyMethods: function() {
|
||||||
|
_.each(['vent', 'commands', 'reqres'], function(system) {
|
||||||
|
_.each( messageSystems[system], function(method) {
|
||||||
|
this[system][method] = proxyMethod(this, system, method);
|
||||||
|
}, this);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var messageSystems = {
|
||||||
|
vent: [
|
||||||
|
'on',
|
||||||
|
'off',
|
||||||
|
'trigger',
|
||||||
|
'once',
|
||||||
|
'stopListening',
|
||||||
|
'listenTo',
|
||||||
|
'listenToOnce'
|
||||||
|
],
|
||||||
|
|
||||||
|
commands: [
|
||||||
|
'execute',
|
||||||
|
'setHandler',
|
||||||
|
'setHandlers',
|
||||||
|
'removeHandler',
|
||||||
|
'removeAllHandlers'
|
||||||
|
],
|
||||||
|
|
||||||
|
reqres: [
|
||||||
|
'request',
|
||||||
|
'setHandler',
|
||||||
|
'setHandlers',
|
||||||
|
'removeHandler',
|
||||||
|
'removeAllHandlers'
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
var proxyMethod = function(radio, system, method) {
|
||||||
|
return function(channelName) {
|
||||||
|
var messageSystem = radio._getChannel(channelName)[system];
|
||||||
|
|
||||||
|
return messageSystem[method].apply(messageSystem, _.rest(arguments));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Radio();
|
||||||
|
|
||||||
|
})(Wreqr, _);
|
@ -0,0 +1,17 @@
|
|||||||
|
// Wreqr.RequestResponse
|
||||||
|
// ---------------------
|
||||||
|
//
|
||||||
|
// A simple request/response implementation. Register a
|
||||||
|
// request handler, and return a response from it
|
||||||
|
Wreqr.RequestResponse = (function(Wreqr, _){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
return Wreqr.Handlers.extend({
|
||||||
|
request: function(name){
|
||||||
|
if (this.hasHandler(name)) {
|
||||||
|
return this.getHandler(name).apply(this, _.rest(arguments));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
})(Wreqr, _);
|
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "backbone",
|
||||||
|
"version": "1.1.2",
|
||||||
|
"main": "backbone.js",
|
||||||
|
"dependencies": {
|
||||||
|
"underscore": ">=1.5.0"
|
||||||
|
},
|
||||||
|
"ignore": [
|
||||||
|
"backbone-min.js",
|
||||||
|
"docs",
|
||||||
|
"examples",
|
||||||
|
"test",
|
||||||
|
"*.yml",
|
||||||
|
"*.map",
|
||||||
|
".html",
|
||||||
|
"*.ico"
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/jashkenas/backbone",
|
||||||
|
"_release": "1.1.2",
|
||||||
|
"_resolution": {
|
||||||
|
"type": "version",
|
||||||
|
"tag": "1.1.2",
|
||||||
|
"commit": "53f77901a4ea9c7cf75d3db93ddddf491998d90f"
|
||||||
|
},
|
||||||
|
"_source": "git://github.com/jashkenas/backbone.git",
|
||||||
|
"_target": "1.0.0 - 1.1.2",
|
||||||
|
"_originalSource": "backbone"
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
raw
|
||||||
|
*.sw?
|
||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
bower_components
|
@ -0,0 +1,7 @@
|
|||||||
|
test/
|
||||||
|
Rakefile
|
||||||
|
docs/
|
||||||
|
raw/
|
||||||
|
examples/
|
||||||
|
index.html
|
||||||
|
.jshintrc
|
@ -0,0 +1,2 @@
|
|||||||
|
backbonejs.org
|
||||||
|
|
@ -0,0 +1,22 @@
|
|||||||
|
## How to Open a Backbone.js Ticket
|
||||||
|
|
||||||
|
* Do not use tickets to ask for help with (debugging) your application. Ask on
|
||||||
|
the [mailing list](https://groups.google.com/forum/#!forum/backbonejs),
|
||||||
|
in the IRC channel (`#documentcloud` on Freenode), or if you understand your
|
||||||
|
specific problem, on [StackOverflow](http://stackoverflow.com/questions/tagged/backbone.js).
|
||||||
|
|
||||||
|
* Before you open a ticket or send a pull request,
|
||||||
|
[search](https://github.com/jashkenas/backbone/issues) for previous
|
||||||
|
discussions about the same feature or issue. Add to the earlier ticket if you
|
||||||
|
find one.
|
||||||
|
|
||||||
|
* Before sending a pull request for a feature or bug fix, be sure to have
|
||||||
|
[tests](http://backbonejs.org/test/).
|
||||||
|
|
||||||
|
* Use the same coding style as the rest of the
|
||||||
|
[codebase](https://github.com/jashkenas/backbone/blob/master/backbone.js).
|
||||||
|
|
||||||
|
* In your pull request, do not add documentation or rebuild the minified
|
||||||
|
`backbone-min.js` file. We'll do that before cutting a new release.
|
||||||
|
|
||||||
|
* All pull requests should be made to the `master` branch.
|
@ -0,0 +1,22 @@
|
|||||||
|
Copyright (c) 2010-2014 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,29 @@
|
|||||||
|
____ __ __
|
||||||
|
/\ _`\ /\ \ /\ \ __
|
||||||
|
\ \ \ \ \ __ ___\ \ \/'\\ \ \____ ___ ___ __ /\_\ ____
|
||||||
|
\ \ _ <' /'__`\ /'___\ \ , < \ \ '__`\ / __`\ /' _ `\ /'__`\ \/\ \ /',__\
|
||||||
|
\ \ \ \ \/\ \ \.\_/\ \__/\ \ \\`\\ \ \ \ \/\ \ \ \/\ \/\ \/\ __/ __ \ \ \/\__, `\
|
||||||
|
\ \____/\ \__/.\_\ \____\\ \_\ \_\ \_,__/\ \____/\ \_\ \_\ \____\/\_\_\ \ \/\____/
|
||||||
|
\/___/ \/__/\/_/\/____/ \/_/\/_/\/___/ \/___/ \/_/\/_/\/____/\/_/\ \_\ \/___/
|
||||||
|
\ \____/
|
||||||
|
\/___/
|
||||||
|
(_'_______________________________________________________________________________'_)
|
||||||
|
(_.———————————————————————————————————————————————————————————————————————————————._)
|
||||||
|
|
||||||
|
|
||||||
|
Backbone supplies structure to JavaScript-heavy applications by providing models key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing application over a RESTful JSON interface.
|
||||||
|
|
||||||
|
For Docs, License, Tests, pre-packed downloads, and everything else, really, see:
|
||||||
|
http://backbonejs.org
|
||||||
|
|
||||||
|
To suggest a feature, report a bug, or general discussion:
|
||||||
|
http://github.com/jashkenas/backbone/issues
|
||||||
|
|
||||||
|
Backbone is an open-sourced component of DocumentCloud:
|
||||||
|
https://github.com/documentcloud
|
||||||
|
|
||||||
|
Many thanks to our contributors:
|
||||||
|
http://github.com/jashkenas/backbone/contributors
|
||||||
|
|
||||||
|
Special thanks to Robert Kieffer for the original philosophy behind Backbone.
|
||||||
|
http://github.com/broofa
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name" : "backbone",
|
||||||
|
"version" : "1.1.2",
|
||||||
|
"main" : "backbone.js",
|
||||||
|
"dependencies" : {
|
||||||
|
"underscore" : ">=1.5.0"
|
||||||
|
},
|
||||||
|
"ignore" : ["backbone-min.js", "docs", "examples", "test", "*.yml", "*.map", ".html", "*.ico"]
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name" : "backbone",
|
||||||
|
"version" : "1.1.2",
|
||||||
|
"description" : "Give your JS App some Backbone with Models, Views, Collections, and Events.",
|
||||||
|
"keywords" : ["model", "view", "controller", "router", "server", "client", "browser"],
|
||||||
|
"repo" : "jashkenas/backbone",
|
||||||
|
"dependencies" : {
|
||||||
|
"jashkenas/underscore" : "*"
|
||||||
|
},
|
||||||
|
"main" : "backbone.js",
|
||||||
|
"scripts" : ["backbone.js"],
|
||||||
|
"license" : "MIT"
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@
|
|||||||
|
module.exports = require('./backbone');
|
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name" : "backbone",
|
||||||
|
"description" : "Give your JS App some Backbone with Models, Views, Collections, and Events.",
|
||||||
|
"url" : "http://backbonejs.org",
|
||||||
|
"keywords" : ["model", "view", "controller", "router", "server", "client", "browser"],
|
||||||
|
"author" : "Jeremy Ashkenas <jeremy@documentcloud.org>",
|
||||||
|
"dependencies" : {
|
||||||
|
"underscore" : ">=1.5.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"phantomjs": "1.9.0-1",
|
||||||
|
"docco": "0.6.1",
|
||||||
|
"coffee-script": "1.6.1"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "phantomjs test/vendor/runner.js test/index.html?noglobals=true && coffee test/model.coffee",
|
||||||
|
"build": "uglifyjs backbone.js --mangle --source-map backbone-min.map -o backbone-min.js",
|
||||||
|
"doc": "docco backbone.js && docco examples/todos/todos.js examples/backbone.localstorage.js",
|
||||||
|
"lint": "jsl -nofilelisting -nologo -conf docs/jsl.conf -process backbone.js"
|
||||||
|
},
|
||||||
|
"main" : "backbone.js",
|
||||||
|
"version" : "1.1.2",
|
||||||
|
"license" : "MIT",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/jashkenas/backbone.git"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"name": "jquery",
|
||||||
|
"version": "2.1.3",
|
||||||
|
"main": "dist/jquery.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"ignore": [
|
||||||
|
"**/.*",
|
||||||
|
"build",
|
||||||
|
"speed",
|
||||||
|
"test",
|
||||||
|
"*.md",
|
||||||
|
"AUTHORS.txt",
|
||||||
|
"Gruntfile.js",
|
||||||
|
"package.json"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"sizzle": "2.1.1-jquery.2.1.2",
|
||||||
|
"requirejs": "2.1.10",
|
||||||
|
"qunit": "1.14.0",
|
||||||
|
"sinon": "1.8.1"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"jquery",
|
||||||
|
"javascript",
|
||||||
|
"library"
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/jquery/jquery",
|
||||||
|
"_release": "2.1.3",
|
||||||
|
"_resolution": {
|
||||||
|
"type": "version",
|
||||||
|
"tag": "2.1.3",
|
||||||
|
"commit": "8f2a9d9272d6ed7f32d3a484740ab342c02541e0"
|
||||||
|
},
|
||||||
|
"_source": "git://github.com/jquery/jquery.git",
|
||||||
|
"_target": "^1.8.0 || ^2.0.0",
|
||||||
|
"_originalSource": "jquery"
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
Copyright 2014 jQuery Foundation and other contributors
|
||||||
|
http://jquery.com/
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "jquery",
|
||||||
|
"version": "2.1.3",
|
||||||
|
"main": "dist/jquery.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"ignore": [
|
||||||
|
"**/.*",
|
||||||
|
"build",
|
||||||
|
"speed",
|
||||||
|
"test",
|
||||||
|
"*.md",
|
||||||
|
"AUTHORS.txt",
|
||||||
|
"Gruntfile.js",
|
||||||
|
"package.json"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"sizzle": "2.1.1-jquery.2.1.2",
|
||||||
|
"requirejs": "2.1.10",
|
||||||
|
"qunit": "1.14.0",
|
||||||
|
"sinon": "1.8.1"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"jquery",
|
||||||
|
"javascript",
|
||||||
|
"library"
|
||||||
|
]
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue