Initial commit with build step

master
Buddy Sandidge 10 years ago
commit 046d444802

@ -0,0 +1,3 @@
{
"directory": "vendor"
}

@ -0,0 +1,2 @@
scripts/*
node_modules/*

3
.gitignore vendored

@ -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 '&nbsp;'),
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 '&nbsp;'),
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…
Cancel
Save