(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o'; }; return LoaderView; })(Marionette.View); module.exports = LoaderView; },{"backbone.marionette":22}],4:[function(require,module,exports){ var App, Application; Application = require('./application.coffee'); App = new Application; App.start(); },{"./application.coffee":1}],5:[function(require,module,exports){ var Backbone, MapCollection, Radio, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; Backbone = require('backbone'); Radio = require('backbone.radio'); MapCollection = (function(superClass) { extend(MapCollection, superClass); function MapCollection(opts) { MapCollection.__super__.constructor.call(this, opts); } MapCollection.prototype.sync = function(method, model, options) { var SG, projectCode; SG = Radio.channel('app').request('getShotgun'); projectCode = options.projectCode; return SG.getMaps(projectCode).then(function(data) { return options.success(data, true, void 0); })["catch"](function(err) { return options.error(err); }); }; return MapCollection; })(Backbone.Collection); module.exports = MapCollection; },{"backbone":24,"backbone.radio":23}],6:[function(require,module,exports){ var MapCollectionView, MapView, MapsCollection, Marionette, Radio, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; Marionette = require('backbone.marionette'); Radio = require('backbone.radio'); MapView = require('./map.view.coffee'); MapsCollection = require('./map.collection.coffee'); MapCollectionView = (function(superClass) { extend(MapCollectionView, superClass); MapCollectionView.prototype.className = 'ui relaxed divided selection tiny list'; MapCollectionView.prototype.childView = MapView; MapCollectionView.prototype.collectionEvents = { 'sync': 'render' }; MapCollectionView.prototype.collection = new MapsCollection; function MapCollectionView(opts) { MapCollectionView.__super__.constructor.call(this, opts); } return MapCollectionView; })(Marionette.CollectionView); module.exports = MapCollectionView; },{"./map.collection.coffee":5,"./map.view.coffee":7,"backbone.marionette":22,"backbone.radio":23}],7:[function(require,module,exports){ var MapView, Marionette, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; Marionette = require('backbone.marionette'); MapView = (function(superClass) { extend(MapView, superClass); function MapView() { MapView.__super__.constructor.call(this); } MapView.prototype.className = 'item'; MapView.prototype.template = require('../views/mapView.hbs'); return MapView; })(Marionette.View); module.exports = MapView; },{"../views/mapView.hbs":14,"backbone.marionette":22}],8:[function(require,module,exports){ var Backbone, Marionette, TreeNode, TreeView, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; Marionette = require('backbone.marionette'); Backbone = require('backbone'); TreeNode = (function(superClass) { extend(TreeNode, superClass); function TreeNode() { return TreeNode.__super__.constructor.apply(this, arguments); } TreeNode.prototype.tagName = 'li'; TreeNode.prototype.template = require('../views/treeNode.hbs'); TreeNode.prototype.regions = { tree: { el: 'ul', replaceElement: true } }; TreeNode.prototype.onRender = function() { var nodes, treeView; nodes = this.model.get('sg_assets_2'); if (nodes != null ? nodes.length : void 0) { treeView = new TreeView({ collection: new Backbone.Collection(nodes) }); return this.showChildView('tree', treeView); } }; return TreeNode; })(Marionette.View); TreeView = (function(superClass) { extend(TreeView, superClass); function TreeView() { return TreeView.__super__.constructor.apply(this, arguments); } TreeView.prototype.tagName = 'ul'; TreeView.prototype.childView = TreeNode; TreeView.prototype.onAttach = function() {}; return TreeView; })(Marionette.CollectionView); module.exports = TreeView; },{"../views/treeNode.hbs":17,"backbone":24,"backbone.marionette":22}],9:[function(require,module,exports){ var MapsCollectionView, Marionette, ProjectView, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; Marionette = require('backbone.marionette'); MapsCollectionView = require('../map/map.collection.view.coffee'); ProjectView = (function(superClass) { extend(ProjectView, superClass); function ProjectView() { return ProjectView.__super__.constructor.apply(this, arguments); } ProjectView.prototype.tagName = 'option'; ProjectView.prototype.className = 'item'; ProjectView.prototype.template = require('../views/projectView.hbs'); ProjectView.prototype.regions = { maps: { el: '.maps-list', replaceElement: true } }; ProjectView.prototype.onAttach = function() {}; return ProjectView; })(Marionette.View); module.exports = ProjectView; },{"../map/map.collection.view.coffee":6,"../views/projectView.hbs":15,"backbone.marionette":22}],10:[function(require,module,exports){ var Backbone, Model, ProjectsCollection, Radio, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; Backbone = require('backbone'); Model = require('./projects.model.coffee'); Radio = require('backbone.radio'); ProjectsCollection = (function(superClass) { extend(ProjectsCollection, superClass); function ProjectsCollection() { ProjectsCollection.__super__.constructor.call(this); } ProjectsCollection.prototype.model = Model; ProjectsCollection.prototype.sync = function(method, model, options) { var SG; SG = Radio.channel('app').request('getShotgun'); return SG.getProjects().then(function(data) { return options.success(data, true, void 0); })["catch"](function(err) { return options.error(err); }); }; return ProjectsCollection; })(Backbone.Collection); module.exports = ProjectsCollection; },{"./projects.model.coffee":12,"backbone":24,"backbone.radio":23}],11:[function(require,module,exports){ var Marionette, ProjectSelectionView, ProjectView, Radio, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; Marionette = require('backbone.marionette'); Radio = require('backbone.radio'); ProjectView = require('./project.view.coffee'); ProjectSelectionView = (function(superClass) { extend(ProjectSelectionView, superClass); ProjectSelectionView.prototype.tagName = 'select'; ProjectSelectionView.prototype.className = 'ui fluid loading search selection dropdown'; ProjectSelectionView.prototype.childView = ProjectView; function ProjectSelectionView() { ProjectSelectionView.__super__.constructor.call(this); this.collection = Radio.channel('app').request('getProjectsCollection'); this.collection.fetch({ success: (function(_this) { return function() { return $(_this.$el).parent().removeClass('loading'); }; })(this) }); this.collection; } ProjectSelectionView.prototype.onDropdownChange = function(value, text, choice) { return Radio.channel('app').trigger('project:selected', value); }; ProjectSelectionView.prototype.onAttach = function() { return $(this.$el).dropdown({ sortSelect: true, fullTextSearch: true, forceSelection: false, selectOnKeydown: false, showOnFocus: false, message: { noResults: 'No projects to display' }, onChange: this.onDropdownChange.bind(this) }); }; return ProjectSelectionView; })(Marionette.CollectionView); module.exports = ProjectSelectionView; },{"./project.view.coffee":9,"backbone.marionette":22,"backbone.radio":23}],12:[function(require,module,exports){ var Backbone, MapsCollection, ProjectModel, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; Backbone = require('backbone-associations'); MapsCollection = require('../map/map.collection.coffee'); ProjectModel = (function(superClass) { extend(ProjectModel, superClass); function ProjectModel(opts) { ProjectModel.__super__.constructor.call(this, opts); } return ProjectModel; })(Backbone.Model); module.exports = ProjectModel; },{"../map/map.collection.coffee":5,"backbone-associations":21}],13:[function(require,module,exports){ var Shotgun, _, httpproxyagent, xmlrpc; xmlrpc = require('xmlrpc'); httpproxyagent = require('https-proxy-agent'); _ = require('underscore'); Shotgun = (function() { Shotgun.prototype.ENTITIES = { asset: "Asset", batch: "CustomEntity03", jd_opus: "CustomEntity02", jd_tv: "CustomEntity05", map: "CustomEntity28", task: "Task", version: "Version", search_tags: "CustomEntity09" }; Shotgun.prototype.FIELDS = { assets_jd_opus: "sg_map_.CustomEntity28.custom_entity02_sg_maps_custom_entity02s", asset_latest_version: "sg_latest_asset", asset_maps: "sg_map_", asset_type: "sg_asset_type", batch_end_date: "sg_end_date", batch_number: "sg_batch_number", batch_start_date: "sg_start_date", date_created: "created_at", date_updated: "updated_at", description: "description", jd_tv_jd_opus: "sg_jdopus", map_assets: "sg_assets_2", map_batch: "sg_batch00", map_game_mode: "sg_game_mode", map_jdm_attributes: "sg_tags_jdm", map_jd_opus: "custom_entity02_sg_maps_custom_entity02s", map_list: "sg_maps", map_production_studio: "sg_production_studio", map_status: "sg_map_status", map_type: "sg_map_type", name: "code", nas_folder: "sg_nas_folder", task: "sg_task", task_template: "task_template", thumbnail: "image", version_link: "entity", version_uploaded_movie: "sg_uploaded_movie", version_status: "sg_status_list", search_labels: "sg_search_labels", search_tag_loc_id: "sg_loc_id", search_labels_maps: "custom_entity28_sg_search_labels_custom_entity28s" }; function Shotgun() { var proxyagent; proxyagent = new httpproxyagent('http://pun-net-bcproxy.ubisoft.org:3128'); this.client = xmlrpc.createSecureClient({ url: 'http://justdance.shotgunstudio.com/api3', agent: proxyagent }); } Shotgun.prototype.getAuthObject = function() { return { script_name: 'shotgate', script_key: 'ce5ad5fb39b240cedc4d2eabafbb6869077fe1dcb562045698e9654b6c1f2752' }; }; Shotgun.prototype.getDefaultFilter = function() { return [ { values: [ { type: 'Project', id: 67 } ], path: 'project', relation: 'is' } ]; }; Shotgun.prototype.getDefaultParamsObject = function() { return { return_paging_info: true, return_fields: ['id', 'content', 'code', 'sg_nas_folder'], return_only: 'active', api_return_image_urls: true, paging: { current_page: 1, entities_per_page: 500 }, filters: [], type: '' }; }; Shotgun.prototype.generateFilterObject = function(filters) { var defaults; defaults = { conditions: [], logical_operator: 'and' }; defaults.conditions = _.union(filters, this.getDefaultFilter()); return defaults; }; Shotgun.prototype.composeQuery = function(entity, filters, return_fields) { var auth, params, result; if (filters == null) { filters = []; } if (return_fields == null) { return_fields = []; } result = []; params = this.getDefaultParamsObject(); params.filters = this.generateFilterObject(filters); auth = this.getAuthObject(); params.type = entity; params.return_fields = _.union(params.return_fields, return_fields); result.push(auth, params); return result; }; Shotgun.prototype.getProjects = function() { return new Promise((function(_this) { return function(resolve, reject) { var params; params = _this.composeQuery(_this.ENTITIES.jd_opus, [], [_this.FIELDS.name, _this.FIELDS.map_assets]); return _this.client.methodCall('read', params, function(err, value, body) { if (err != null) { return reject(err); } else { return resolve(value.results.entities); } }); }; })(this)); }; Shotgun.prototype.getMaps = function(projectCode) { return new Promise((function(_this) { return function(resolve, reject) { var params; params = _this.composeQuery(_this.ENTITIES.map, [ { values: [projectCode], path: _this.FIELDS.map_jd_opus, relation: 'name_is' } ], [_this.FIELDS.map_assets]); return _this.client.methodCall('read', params, function(err, value, body) { if (err != null) { return reject(err); } else { return resolve(value.results.entities); } }); }; })(this)); }; return Shotgun; })(); module.exports = Shotgun; },{"https-proxy-agent":48,"underscore":52,"xmlrpc":82}],14:[function(require,module,exports){ // hbsfy compiled Handlebars template var HandlebarsCompiler = require('hbsfy/runtime'); module.exports = HandlebarsCompiler.template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { var helper; return "
\n
\n " + container.escapeExpression(((helper = (helper = helpers.code || (depth0 != null ? depth0.code : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : {},{"name":"code","hash":{},"data":data}) : helper))) + "\n
\n
\n"; },"useData":true}); },{"hbsfy/runtime":47}],15:[function(require,module,exports){ // hbsfy compiled Handlebars template var HandlebarsCompiler = require('hbsfy/runtime'); module.exports = HandlebarsCompiler.template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { var helper; return container.escapeExpression(((helper = (helper = helpers.code || (depth0 != null ? depth0.code : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : {},{"name":"code","hash":{},"data":data}) : helper))) + "\n"; },"useData":true}); },{"hbsfy/runtime":47}],16:[function(require,module,exports){ // hbsfy compiled Handlebars template var HandlebarsCompiler = require('hbsfy/runtime'); module.exports = HandlebarsCompiler.template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { return "
\r\n
\r\n Just Dance Tools\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n\r\n
\r\n"; },"useData":true}); },{"hbsfy/runtime":47}],17:[function(require,module,exports){ // hbsfy compiled Handlebars template var HandlebarsCompiler = require('hbsfy/runtime'); module.exports = HandlebarsCompiler.template({"1":function(container,depth0,helpers,partials,data) { var helper; return " " + container.escapeExpression(((helper = (helper = helpers.code || (depth0 != null ? depth0.code : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : {},{"name":"code","hash":{},"data":data}) : helper))) + "\r\n"; },"3":function(container,depth0,helpers,partials,data) { var stack1; return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.name : depth0),{"name":"if","hash":{},"fn":container.program(4, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : ""); },"4":function(container,depth0,helpers,partials,data) { var helper; return " " + container.escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : {},{"name":"name","hash":{},"data":data}) : helper))) + "\r\n"; },"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { var stack1; return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.code : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0),"inverse":container.program(3, data, 0),"data":data})) != null ? stack1 : "") + "\r\n\r\n"; },"useData":true}); },{"hbsfy/runtime":47}],18:[function(require,module,exports){ /** * Module dependencies. */ require('./patch-core'); var extend = require('extend'); var inherits = require('util').inherits; var EventEmitter = require('events').EventEmitter; /** * Module exports. */ module.exports = Agent; /** * Base `http.Agent` implementation. * No pooling/keep-alive is implemented by default. * * @param {Function} callback * @api public */ function Agent (callback) { if (!(this instanceof Agent)) return new Agent(callback); if ('function' != typeof callback) throw new Error('Must pass a "callback function"'); EventEmitter.call(this); this.callback = callback; } inherits(Agent, EventEmitter); /** * Called by node-core's "_http_client.js" module when creating * a new HTTP request with this Agent instance. * * @api public */ Agent.prototype.addRequest = function (req, host, port, localAddress) { var opts; if ('object' == typeof host) { // >= v0.11.x API opts = extend({}, req._options, host); } else { // <= v0.10.x API opts = extend({}, req._options, { host: host, port: port }); if (null != localAddress) { opts.localAddress = localAddress; } } if (opts.host && opts.path) { // if both a `host` and `path` are specified then it's most likely the // result of a `url.parse()` call... we need to remove the `path` portion so // that `net.connect()` doesn't attempt to open that as a unix socket file. delete opts.path; } // set default `port` if none was explicitly specified if (null == opts.port) { opts.port = opts.secureEndpoint ? 443 : 80; } delete opts.agent; delete opts.hostname; delete opts._defaultAgent; delete opts.defaultPort; delete opts.createConnection; // hint to use "Connection: close" // XXX: non-documented `http` module API :( req._last = true; req.shouldKeepAlive = false; // clean up a bit of memory since we're no longer using this req._options = null; // create the `net.Socket` instance var sync = true; this.callback(req, opts, function (err, socket) { function emitErr () { req.emit('error', err); // For Safety. Some additional errors might fire later on // and we need to make sure we don't double-fire the error event. req._hadError = true; } if (err) { if (sync) { // need to defer the "error" event, when sync, because by now the `req` // instance hasn't event been passed back to the user yet... process.nextTick(emitErr); } else { emitErr(); } } else { req.onSocket(socket); } }); sync = false; }; },{"./patch-core":20,"events":undefined,"extend":27,"util":undefined}],19:[function(require,module,exports){ exports = module.exports = SemVer; // The debug function is excluded entirely from the minified version. /* nomin */ var debug; /* nomin */ if (typeof process === 'object' && /* nomin */ process.env && /* nomin */ process.env.NODE_DEBUG && /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG)) /* nomin */ debug = function() { /* nomin */ var args = Array.prototype.slice.call(arguments, 0); /* nomin */ args.unshift('SEMVER'); /* nomin */ console.log.apply(console, args); /* nomin */ }; /* nomin */ else /* nomin */ debug = function() {}; // Note: this is the semver.org version of the spec that it implements // Not necessarily the package version of this code. exports.SEMVER_SPEC_VERSION = '2.0.0'; var MAX_LENGTH = 256; var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; // The actual regexps go on exports.re var re = exports.re = []; var src = exports.src = []; var R = 0; // The following Regular Expressions can be used for tokenizing, // validating, and parsing SemVer version strings. // ## Numeric Identifier // A single `0`, or a non-zero digit followed by zero or more digits. var NUMERICIDENTIFIER = R++; src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; var NUMERICIDENTIFIERLOOSE = R++; src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; // ## Non-numeric Identifier // Zero or more digits, followed by a letter or hyphen, and then zero or // more letters, digits, or hyphens. var NONNUMERICIDENTIFIER = R++; src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; // ## Main Version // Three dot-separated numeric identifiers. var MAINVERSION = R++; src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + '(' + src[NUMERICIDENTIFIER] + ')\\.' + '(' + src[NUMERICIDENTIFIER] + ')'; var MAINVERSIONLOOSE = R++; src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + '(' + src[NUMERICIDENTIFIERLOOSE] + ')'; // ## Pre-release Version Identifier // A numeric identifier, or a non-numeric identifier. var PRERELEASEIDENTIFIER = R++; src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + '|' + src[NONNUMERICIDENTIFIER] + ')'; var PRERELEASEIDENTIFIERLOOSE = R++; src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + '|' + src[NONNUMERICIDENTIFIER] + ')'; // ## Pre-release Version // Hyphen, followed by one or more dot-separated pre-release version // identifiers. var PRERELEASE = R++; src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'; var PRERELEASELOOSE = R++; src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'; // ## Build Metadata Identifier // Any combination of digits, letters, or hyphens. var BUILDIDENTIFIER = R++; src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; // ## Build Metadata // Plus sign, followed by one or more period-separated build metadata // identifiers. var BUILD = R++; src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'; // ## Full Version String // A main version, followed optionally by a pre-release version and // build metadata. // Note that the only major, minor, patch, and pre-release sections of // the version string are capturing groups. The build metadata is not a // capturing group, because it should not ever be used in version // comparison. var FULL = R++; var FULLPLAIN = 'v?' + src[MAINVERSION] + src[PRERELEASE] + '?' + src[BUILD] + '?'; src[FULL] = '^' + FULLPLAIN + '$'; // like full, but allows v1.2.3 and =1.2.3, which people do sometimes. // also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty // common in the npm registry. var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + src[PRERELEASELOOSE] + '?' + src[BUILD] + '?'; var LOOSE = R++; src[LOOSE] = '^' + LOOSEPLAIN + '$'; var GTLT = R++; src[GTLT] = '((?:<|>)?=?)'; // Something like "2.*" or "1.2.x". // Note that "x.x" is a valid xRange identifer, meaning "any version" // Only the first item is strictly required. var XRANGEIDENTIFIERLOOSE = R++; src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'; var XRANGEIDENTIFIER = R++; src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'; var XRANGEPLAIN = R++; src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + '(?:' + src[PRERELEASE] + ')?' + src[BUILD] + '?' + ')?)?'; var XRANGEPLAINLOOSE = R++; src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + '(?:' + src[PRERELEASELOOSE] + ')?' + src[BUILD] + '?' + ')?)?'; var XRANGE = R++; src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'; var XRANGELOOSE = R++; src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'; // Tilde ranges. // Meaning is "reasonably at or greater than" var LONETILDE = R++; src[LONETILDE] = '(?:~>?)'; var TILDETRIM = R++; src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'; re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g'); var tildeTrimReplace = '$1~'; var TILDE = R++; src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'; var TILDELOOSE = R++; src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'; // Caret ranges. // Meaning is "at least and backwards compatible with" var LONECARET = R++; src[LONECARET] = '(?:\\^)'; var CARETTRIM = R++; src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'; re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g'); var caretTrimReplace = '$1^'; var CARET = R++; src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'; var CARETLOOSE = R++; src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'; // A simple gt/lt/eq thing, or just "" to indicate "any version" var COMPARATORLOOSE = R++; src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'; var COMPARATOR = R++; src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'; // An expression to strip any whitespace between the gtlt and the thing // it modifies, so that `> 1.2.3` ==> `>1.2.3` var COMPARATORTRIM = R++; src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'; // this one has to use the /g flag re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g'); var comparatorTrimReplace = '$1$2$3'; // Something like `1.2.3 - 1.2.4` // Note that these all use the loose form, because they'll be // checked against either the strict or loose comparator form // later. var HYPHENRANGE = R++; src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + '\\s+-\\s+' + '(' + src[XRANGEPLAIN] + ')' + '\\s*$'; var HYPHENRANGELOOSE = R++; src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + '\\s+-\\s+' + '(' + src[XRANGEPLAINLOOSE] + ')' + '\\s*$'; // Star ranges basically just allow anything at all. var STAR = R++; src[STAR] = '(<|>)?=?\\s*\\*'; // Compile to actual regexp objects. // All are flag-free, unless they were created above with a flag. for (var i = 0; i < R; i++) { debug(i, src[i]); if (!re[i]) re[i] = new RegExp(src[i]); } exports.parse = parse; function parse(version, loose) { if (version instanceof SemVer) return version; if (typeof version !== 'string') return null; if (version.length > MAX_LENGTH) return null; var r = loose ? re[LOOSE] : re[FULL]; if (!r.test(version)) return null; try { return new SemVer(version, loose); } catch (er) { return null; } } exports.valid = valid; function valid(version, loose) { var v = parse(version, loose); return v ? v.version : null; } exports.clean = clean; function clean(version, loose) { var s = parse(version.trim().replace(/^[=v]+/, ''), loose); return s ? s.version : null; } exports.SemVer = SemVer; function SemVer(version, loose) { if (version instanceof SemVer) { if (version.loose === loose) return version; else version = version.version; } else if (typeof version !== 'string') { throw new TypeError('Invalid Version: ' + version); } if (version.length > MAX_LENGTH) throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') if (!(this instanceof SemVer)) return new SemVer(version, loose); debug('SemVer', version, loose); this.loose = loose; var m = version.trim().match(loose ? re[LOOSE] : re[FULL]); if (!m) throw new TypeError('Invalid Version: ' + version); this.raw = version; // these are actually numbers this.major = +m[1]; this.minor = +m[2]; this.patch = +m[3]; if (this.major > MAX_SAFE_INTEGER || this.major < 0) throw new TypeError('Invalid major version') if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) throw new TypeError('Invalid minor version') if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) throw new TypeError('Invalid patch version') // numberify any prerelease numeric ids if (!m[4]) this.prerelease = []; else this.prerelease = m[4].split('.').map(function(id) { if (/^[0-9]+$/.test(id)) { var num = +id if (num >= 0 && num < MAX_SAFE_INTEGER) return num } return id; }); this.build = m[5] ? m[5].split('.') : []; this.format(); } SemVer.prototype.format = function() { this.version = this.major + '.' + this.minor + '.' + this.patch; if (this.prerelease.length) this.version += '-' + this.prerelease.join('.'); return this.version; }; SemVer.prototype.inspect = function() { return ''; }; SemVer.prototype.toString = function() { return this.version; }; SemVer.prototype.compare = function(other) { debug('SemVer.compare', this.version, this.loose, other); if (!(other instanceof SemVer)) other = new SemVer(other, this.loose); return this.compareMain(other) || this.comparePre(other); }; SemVer.prototype.compareMain = function(other) { if (!(other instanceof SemVer)) other = new SemVer(other, this.loose); return compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch); }; SemVer.prototype.comparePre = function(other) { if (!(other instanceof SemVer)) other = new SemVer(other, this.loose); // NOT having a prerelease is > having one if (this.prerelease.length && !other.prerelease.length) return -1; else if (!this.prerelease.length && other.prerelease.length) return 1; else if (!this.prerelease.length && !other.prerelease.length) return 0; var i = 0; do { var a = this.prerelease[i]; var b = other.prerelease[i]; debug('prerelease compare', i, a, b); if (a === undefined && b === undefined) return 0; else if (b === undefined) return 1; else if (a === undefined) return -1; else if (a === b) continue; else return compareIdentifiers(a, b); } while (++i); }; // preminor will bump the version up to the next minor release, and immediately // down to pre-release. premajor and prepatch work the same way. SemVer.prototype.inc = function(release, identifier) { switch (release) { case 'premajor': this.prerelease.length = 0; this.patch = 0; this.minor = 0; this.major++; this.inc('pre', identifier); break; case 'preminor': this.prerelease.length = 0; this.patch = 0; this.minor++; this.inc('pre', identifier); break; case 'prepatch': // If this is already a prerelease, it will bump to the next version // drop any prereleases that might already exist, since they are not // relevant at this point. this.prerelease.length = 0; this.inc('patch', identifier); this.inc('pre', identifier); break; // If the input is a non-prerelease version, this acts the same as // prepatch. case 'prerelease': if (this.prerelease.length === 0) this.inc('patch', identifier); this.inc('pre', identifier); break; case 'major': // If this is a pre-major version, bump up to the same major version. // Otherwise increment major. // 1.0.0-5 bumps to 1.0.0 // 1.1.0 bumps to 2.0.0 if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) this.major++; this.minor = 0; this.patch = 0; this.prerelease = []; break; case 'minor': // If this is a pre-minor version, bump up to the same minor version. // Otherwise increment minor. // 1.2.0-5 bumps to 1.2.0 // 1.2.1 bumps to 1.3.0 if (this.patch !== 0 || this.prerelease.length === 0) this.minor++; this.patch = 0; this.prerelease = []; break; case 'patch': // If this is not a pre-release version, it will increment the patch. // If it is a pre-release it will bump up to the same patch version. // 1.2.0-5 patches to 1.2.0 // 1.2.0 patches to 1.2.1 if (this.prerelease.length === 0) this.patch++; this.prerelease = []; break; // This probably shouldn't be used publicly. // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. case 'pre': if (this.prerelease.length === 0) this.prerelease = [0]; else { var i = this.prerelease.length; while (--i >= 0) { if (typeof this.prerelease[i] === 'number') { this.prerelease[i]++; i = -2; } } if (i === -1) // didn't increment anything this.prerelease.push(0); } if (identifier) { // 1.2.0-beta.1 bumps to 1.2.0-beta.2, // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 if (this.prerelease[0] === identifier) { if (isNaN(this.prerelease[1])) this.prerelease = [identifier, 0]; } else this.prerelease = [identifier, 0]; } break; default: throw new Error('invalid increment argument: ' + release); } this.format(); this.raw = this.version; return this; }; exports.inc = inc; function inc(version, release, loose, identifier) { if (typeof(loose) === 'string') { identifier = loose; loose = undefined; } try { return new SemVer(version, loose).inc(release, identifier).version; } catch (er) { return null; } } exports.diff = diff; function diff(version1, version2) { if (eq(version1, version2)) { return null; } else { var v1 = parse(version1); var v2 = parse(version2); if (v1.prerelease.length || v2.prerelease.length) { for (var key in v1) { if (key === 'major' || key === 'minor' || key === 'patch') { if (v1[key] !== v2[key]) { return 'pre'+key; } } } return 'prerelease'; } for (var key in v1) { if (key === 'major' || key === 'minor' || key === 'patch') { if (v1[key] !== v2[key]) { return key; } } } } } exports.compareIdentifiers = compareIdentifiers; var numeric = /^[0-9]+$/; function compareIdentifiers(a, b) { var anum = numeric.test(a); var bnum = numeric.test(b); if (anum && bnum) { a = +a; b = +b; } return (anum && !bnum) ? -1 : (bnum && !anum) ? 1 : a < b ? -1 : a > b ? 1 : 0; } exports.rcompareIdentifiers = rcompareIdentifiers; function rcompareIdentifiers(a, b) { return compareIdentifiers(b, a); } exports.major = major; function major(a, loose) { return new SemVer(a, loose).major; } exports.minor = minor; function minor(a, loose) { return new SemVer(a, loose).minor; } exports.patch = patch; function patch(a, loose) { return new SemVer(a, loose).patch; } exports.compare = compare; function compare(a, b, loose) { return new SemVer(a, loose).compare(b); } exports.compareLoose = compareLoose; function compareLoose(a, b) { return compare(a, b, true); } exports.rcompare = rcompare; function rcompare(a, b, loose) { return compare(b, a, loose); } exports.sort = sort; function sort(list, loose) { return list.sort(function(a, b) { return exports.compare(a, b, loose); }); } exports.rsort = rsort; function rsort(list, loose) { return list.sort(function(a, b) { return exports.rcompare(a, b, loose); }); } exports.gt = gt; function gt(a, b, loose) { return compare(a, b, loose) > 0; } exports.lt = lt; function lt(a, b, loose) { return compare(a, b, loose) < 0; } exports.eq = eq; function eq(a, b, loose) { return compare(a, b, loose) === 0; } exports.neq = neq; function neq(a, b, loose) { return compare(a, b, loose) !== 0; } exports.gte = gte; function gte(a, b, loose) { return compare(a, b, loose) >= 0; } exports.lte = lte; function lte(a, b, loose) { return compare(a, b, loose) <= 0; } exports.cmp = cmp; function cmp(a, op, b, loose) { var ret; switch (op) { case '===': if (typeof a === 'object') a = a.version; if (typeof b === 'object') b = b.version; ret = a === b; break; case '!==': if (typeof a === 'object') a = a.version; if (typeof b === 'object') b = b.version; ret = a !== b; break; case '': case '=': case '==': ret = eq(a, b, loose); break; case '!=': ret = neq(a, b, loose); break; case '>': ret = gt(a, b, loose); break; case '>=': ret = gte(a, b, loose); break; case '<': ret = lt(a, b, loose); break; case '<=': ret = lte(a, b, loose); break; default: throw new TypeError('Invalid operator: ' + op); } return ret; } exports.Comparator = Comparator; function Comparator(comp, loose) { if (comp instanceof Comparator) { if (comp.loose === loose) return comp; else comp = comp.value; } if (!(this instanceof Comparator)) return new Comparator(comp, loose); debug('comparator', comp, loose); this.loose = loose; this.parse(comp); if (this.semver === ANY) this.value = ''; else this.value = this.operator + this.semver.version; debug('comp', this); } var ANY = {}; Comparator.prototype.parse = function(comp) { var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; var m = comp.match(r); if (!m) throw new TypeError('Invalid comparator: ' + comp); this.operator = m[1]; if (this.operator === '=') this.operator = ''; // if it literally is just '>' or '' then allow anything. if (!m[2]) this.semver = ANY; else this.semver = new SemVer(m[2], this.loose); }; Comparator.prototype.inspect = function() { return ''; }; Comparator.prototype.toString = function() { return this.value; }; Comparator.prototype.test = function(version) { debug('Comparator.test', version, this.loose); if (this.semver === ANY) return true; if (typeof version === 'string') version = new SemVer(version, this.loose); return cmp(version, this.operator, this.semver, this.loose); }; exports.Range = Range; function Range(range, loose) { if ((range instanceof Range) && range.loose === loose) return range; if (!(this instanceof Range)) return new Range(range, loose); this.loose = loose; // First, split based on boolean or || this.raw = range; this.set = range.split(/\s*\|\|\s*/).map(function(range) { return this.parseRange(range.trim()); }, this).filter(function(c) { // throw out any that are not relevant for whatever reason return c.length; }); if (!this.set.length) { throw new TypeError('Invalid SemVer Range: ' + range); } this.format(); } Range.prototype.inspect = function() { return ''; }; Range.prototype.format = function() { this.range = this.set.map(function(comps) { return comps.join(' ').trim(); }).join('||').trim(); return this.range; }; Range.prototype.toString = function() { return this.range; }; Range.prototype.parseRange = function(range) { var loose = this.loose; range = range.trim(); debug('range', range, loose); // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]; range = range.replace(hr, hyphenReplace); debug('hyphen replace', range); // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace); debug('comparator trim', range, re[COMPARATORTRIM]); // `~ 1.2.3` => `~1.2.3` range = range.replace(re[TILDETRIM], tildeTrimReplace); // `^ 1.2.3` => `^1.2.3` range = range.replace(re[CARETTRIM], caretTrimReplace); // normalize spaces range = range.split(/\s+/).join(' '); // At this point, the range is completely trimmed and // ready to be split into comparators. var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; var set = range.split(' ').map(function(comp) { return parseComparator(comp, loose); }).join(' ').split(/\s+/); if (this.loose) { // in loose mode, throw out any that are not valid comparators set = set.filter(function(comp) { return !!comp.match(compRe); }); } set = set.map(function(comp) { return new Comparator(comp, loose); }); return set; }; // Mostly just for testing and legacy API reasons exports.toComparators = toComparators; function toComparators(range, loose) { return new Range(range, loose).set.map(function(comp) { return comp.map(function(c) { return c.value; }).join(' ').trim().split(' '); }); } // comprised of xranges, tildes, stars, and gtlt's at this point. // already replaced the hyphen ranges // turn into a set of JUST comparators. function parseComparator(comp, loose) { debug('comp', comp); comp = replaceCarets(comp, loose); debug('caret', comp); comp = replaceTildes(comp, loose); debug('tildes', comp); comp = replaceXRanges(comp, loose); debug('xrange', comp); comp = replaceStars(comp, loose); debug('stars', comp); return comp; } function isX(id) { return !id || id.toLowerCase() === 'x' || id === '*'; } // ~, ~> --> * (any, kinda silly) // ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 // ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 // ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 // ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 // ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 function replaceTildes(comp, loose) { return comp.trim().split(/\s+/).map(function(comp) { return replaceTilde(comp, loose); }).join(' '); } function replaceTilde(comp, loose) { var r = loose ? re[TILDELOOSE] : re[TILDE]; return comp.replace(r, function(_, M, m, p, pr) { debug('tilde', comp, _, M, m, p, pr); var ret; if (isX(M)) ret = ''; else if (isX(m)) ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; else if (isX(p)) // ~1.2 == >=1.2.0- <1.3.0- ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; else if (pr) { debug('replaceTilde pr', pr); if (pr.charAt(0) !== '-') pr = '-' + pr; ret = '>=' + M + '.' + m + '.' + p + pr + ' <' + M + '.' + (+m + 1) + '.0'; } else // ~1.2.3 == >=1.2.3 <1.3.0 ret = '>=' + M + '.' + m + '.' + p + ' <' + M + '.' + (+m + 1) + '.0'; debug('tilde return', ret); return ret; }); } // ^ --> * (any, kinda silly) // ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 // ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 // ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 // ^1.2.3 --> >=1.2.3 <2.0.0 // ^1.2.0 --> >=1.2.0 <2.0.0 function replaceCarets(comp, loose) { return comp.trim().split(/\s+/).map(function(comp) { return replaceCaret(comp, loose); }).join(' '); } function replaceCaret(comp, loose) { debug('caret', comp, loose); var r = loose ? re[CARETLOOSE] : re[CARET]; return comp.replace(r, function(_, M, m, p, pr) { debug('caret', comp, _, M, m, p, pr); var ret; if (isX(M)) ret = ''; else if (isX(m)) ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; else if (isX(p)) { if (M === '0') ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; else ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0'; } else if (pr) { debug('replaceCaret pr', pr); if (pr.charAt(0) !== '-') pr = '-' + pr; if (M === '0') { if (m === '0') ret = '>=' + M + '.' + m + '.' + p + pr + ' <' + M + '.' + m + '.' + (+p + 1); else ret = '>=' + M + '.' + m + '.' + p + pr + ' <' + M + '.' + (+m + 1) + '.0'; } else ret = '>=' + M + '.' + m + '.' + p + pr + ' <' + (+M + 1) + '.0.0'; } else { debug('no pr'); if (M === '0') { if (m === '0') ret = '>=' + M + '.' + m + '.' + p + ' <' + M + '.' + m + '.' + (+p + 1); else ret = '>=' + M + '.' + m + '.' + p + ' <' + M + '.' + (+m + 1) + '.0'; } else ret = '>=' + M + '.' + m + '.' + p + ' <' + (+M + 1) + '.0.0'; } debug('caret return', ret); return ret; }); } function replaceXRanges(comp, loose) { debug('replaceXRanges', comp, loose); return comp.split(/\s+/).map(function(comp) { return replaceXRange(comp, loose); }).join(' '); } function replaceXRange(comp, loose) { comp = comp.trim(); var r = loose ? re[XRANGELOOSE] : re[XRANGE]; return comp.replace(r, function(ret, gtlt, M, m, p, pr) { debug('xRange', comp, ret, gtlt, M, m, p, pr); var xM = isX(M); var xm = xM || isX(m); var xp = xm || isX(p); var anyX = xp; if (gtlt === '=' && anyX) gtlt = ''; if (xM) { if (gtlt === '>' || gtlt === '<') { // nothing is allowed ret = '<0.0.0'; } else { // nothing is forbidden ret = '*'; } } else if (gtlt && anyX) { // replace X with 0 if (xm) m = 0; if (xp) p = 0; if (gtlt === '>') { // >1 => >=2.0.0 // >1.2 => >=1.3.0 // >1.2.3 => >= 1.2.4 gtlt = '>='; if (xm) { M = +M + 1; m = 0; p = 0; } else if (xp) { m = +m + 1; p = 0; } } else if (gtlt === '<=') { // <=0.7.x is actually <0.8.0, since any 0.7.x should // pass. Similarly, <=7.x is actually <8.0.0, etc. gtlt = '<' if (xm) M = +M + 1 else m = +m + 1 } ret = gtlt + M + '.' + m + '.' + p; } else if (xm) { ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; } else if (xp) { ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; } debug('xRange return', ret); return ret; }); } // Because * is AND-ed with everything else in the comparator, // and '' means "any version", just remove the *s entirely. function replaceStars(comp, loose) { debug('replaceStars', comp, loose); // Looseness is ignored here. star is always as loose as it gets! return comp.trim().replace(re[STAR], ''); } // This function is passed to string.replace(re[HYPHENRANGE]) // M, m, patch, prerelease, build // 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 // 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do // 1.2 - 3.4 => >=1.2.0 <3.5.0 function hyphenReplace($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr, tb) { if (isX(fM)) from = ''; else if (isX(fm)) from = '>=' + fM + '.0.0'; else if (isX(fp)) from = '>=' + fM + '.' + fm + '.0'; else from = '>=' + from; if (isX(tM)) to = ''; else if (isX(tm)) to = '<' + (+tM + 1) + '.0.0'; else if (isX(tp)) to = '<' + tM + '.' + (+tm + 1) + '.0'; else if (tpr) to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr; else to = '<=' + to; return (from + ' ' + to).trim(); } // if ANY of the sets match ALL of its comparators, then pass Range.prototype.test = function(version) { if (!version) return false; if (typeof version === 'string') version = new SemVer(version, this.loose); for (var i = 0; i < this.set.length; i++) { if (testSet(this.set[i], version)) return true; } return false; }; function testSet(set, version) { for (var i = 0; i < set.length; i++) { if (!set[i].test(version)) return false; } if (version.prerelease.length) { // Find the set of versions that are allowed to have prereleases // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 // That should allow `1.2.3-pr.2` to pass. // However, `1.2.4-alpha.notready` should NOT be allowed, // even though it's within the range set by the comparators. for (var i = 0; i < set.length; i++) { debug(set[i].semver); if (set[i].semver === ANY) continue; if (set[i].semver.prerelease.length > 0) { var allowed = set[i].semver; if (allowed.major === version.major && allowed.minor === version.minor && allowed.patch === version.patch) return true; } } // Version has a -pre, but it's not one of the ones we like. return false; } return true; } exports.satisfies = satisfies; function satisfies(version, range, loose) { try { range = new Range(range, loose); } catch (er) { return false; } return range.test(version); } exports.maxSatisfying = maxSatisfying; function maxSatisfying(versions, range, loose) { return versions.filter(function(version) { return satisfies(version, range, loose); }).sort(function(a, b) { return rcompare(a, b, loose); })[0] || null; } exports.validRange = validRange; function validRange(range, loose) { try { // Return '*' instead of '' so that truthiness works. // This will throw if it's invalid anyway return new Range(range, loose).range || '*'; } catch (er) { return null; } } // Determine if version is less than all the versions possible in the range exports.ltr = ltr; function ltr(version, range, loose) { return outside(version, range, '<', loose); } // Determine if version is greater than all the versions possible in the range. exports.gtr = gtr; function gtr(version, range, loose) { return outside(version, range, '>', loose); } exports.outside = outside; function outside(version, range, hilo, loose) { version = new SemVer(version, loose); range = new Range(range, loose); var gtfn, ltefn, ltfn, comp, ecomp; switch (hilo) { case '>': gtfn = gt; ltefn = lte; ltfn = lt; comp = '>'; ecomp = '>='; break; case '<': gtfn = lt; ltefn = gte; ltfn = gt; comp = '<'; ecomp = '<='; break; default: throw new TypeError('Must provide a hilo val of "<" or ">"'); } // If it satisifes the range it is not outside if (satisfies(version, range, loose)) { return false; } // From now on, variable terms are as if we're in "gtr" mode. // but note that everything is flipped for the "ltr" function. for (var i = 0; i < range.set.length; ++i) { var comparators = range.set[i]; var high = null; var low = null; comparators.forEach(function(comparator) { if (comparator.semver === ANY) { comparator = new Comparator('>=0.0.0') } high = high || comparator; low = low || comparator; if (gtfn(comparator.semver, high.semver, loose)) { high = comparator; } else if (ltfn(comparator.semver, low.semver, loose)) { low = comparator; } }); // If the edge version comparator has a operator then our version // isn't outside it if (high.operator === comp || high.operator === ecomp) { return false; } // If the lowest version comparator has an operator and our version // is less than it then it isn't higher than the range if ((!low.operator || low.operator === comp) && ltefn(version, low.semver)) { return false; } else if (low.operator === ecomp && ltfn(version, low.semver)) { return false; } } return true; } },{}],20:[function(require,module,exports){ var url = require('url'); var http = require('http'); var https = require('https'); var semver = require('semver'); var inherits = require('util').inherits; // we only need to patch the `http.request()` and // `http.ClientRequest` on older versions of Node.js if (semver.lt(process.version, '0.11.8')) { // subclass the native ClientRequest to include the // passed in `options` object. http.ClientRequest = (function (_ClientRequest) { function ClientRequest (options, cb) { this._options = options; _ClientRequest.call(this, options, cb); } inherits(ClientRequest, _ClientRequest); return ClientRequest; })(http.ClientRequest); // need to re-define the `request()` method, since on node v0.8/v0.10 // the closure-local ClientRequest is used, rather than the monkey // patched version we have created here. http.request = (function (request) { return function (options, cb) { if (typeof options === 'string') { options = url.parse(options); } if (options.protocol && options.protocol !== 'http:') { throw new Error('Protocol:' + options.protocol + ' not supported.'); } return new http.ClientRequest(options, cb); }; })(http.request); } // this currently needs to be applied to all Node.js versions // (v0.8.x, v0.10.x, v0.12.x), in order to determine if the `req` // is an HTTP or HTTPS request. There is currently no PR attempting // to move this property upstream. https.request = (function (request) { return function (options, cb) { if (typeof options === 'string') { options = url.parse(options); } if (null == options.port) options.port = 443; options.secureEndpoint = true; return request.call(https, options, cb); }; })(https.request); },{"http":undefined,"https":undefined,"semver":19,"url":undefined,"util":undefined}],21:[function(require,module,exports){ // // Backbone-associations.js 0.6.2 // // (c) 2014 Dhruva Ray, Jaynti Kanani, Persistent Systems Ltd. // Backbone-associations may be freely distributed under the MIT license. // For all details and documentation: // https://github.com/dhruvaray/backbone-associations/ // (function(root, factory) { // Set up Backbone-associations appropriately for the environment. Start with AMD. if (typeof define === 'function' && define.amd) { define(['underscore', 'backbone'], function(_, Backbone) { // Export global even in AMD case in case this script is loaded with // others that may still expect a global Backbone. return factory(root, Backbone, _); }); // Next for Node.js or CommonJS. } else if (typeof exports !== 'undefined') { var _ = require('underscore'), Backbone = require('backbone'); factory(root, Backbone, _); if (typeof module !== 'undefined' && module.exports) { module.exports = Backbone; } exports = Backbone; // Finally, as a browser global. } else { factory(root, root.Backbone, root._); } }(this, function(root, Backbone, _) { "use strict"; // Initial Setup // -------------- // The top-level namespace. All public Backbone classes and modules will be attached to this. // Exported for the browser and CommonJS. var BackboneModel, BackboneCollection, ModelProto, BackboneEvent, CollectionProto, AssociatedModel, pathChecker, delimiters, pathSeparator, sourceModel, sourceKey, endPoints = {}; // Create local reference `Model` prototype. BackboneModel = Backbone.Model; BackboneCollection = Backbone.Collection; ModelProto = BackboneModel.prototype; CollectionProto = BackboneCollection.prototype; BackboneEvent = Backbone.Events; Backbone.Associations = { VERSION: "0.6.2" }; // Alternative scopes other than root Backbone.Associations.scopes = []; // Define `getter` and `setter` for `separator` var getSeparator = function() { return pathSeparator; }; // Define `setSeperator` var setSeparator = function(value) { if (!_.isString(value) || _.size(value) < 1) { value = "."; } // set private properties pathSeparator = value; pathChecker = new RegExp("[\\" + pathSeparator + "\\[\\]]+", "g"); delimiters = new RegExp("[^\\" + pathSeparator + "\\[\\]]+", "g"); }; try { // Define `SEPERATOR` property to Backbone.Associations Object.defineProperty(Backbone.Associations, 'SEPARATOR', { enumerable: true, get: getSeparator, set: setSeparator }); } catch (e) {} // Backbone.AssociatedModel // -------------- //Add `Many` and `One` relations to Backbone Object. Backbone.Associations.Many = Backbone.Many = "Many"; Backbone.Associations.One = Backbone.One = "One"; Backbone.Associations.Self = Backbone.Self = "Self"; // Set default separator Backbone.Associations.SEPARATOR = "."; Backbone.Associations.getSeparator = getSeparator; Backbone.Associations.setSeparator = setSeparator; Backbone.Associations.EVENTS_BUBBLE = true; Backbone.Associations.EVENTS_WILDCARD = true; Backbone.Associations.EVENTS_NC = false; setSeparator(); // Define `AssociatedModel` (Extends Backbone.Model). AssociatedModel = Backbone.AssociatedModel = Backbone.Associations.AssociatedModel = BackboneModel.extend({ // Define relations with Associated Model. relations:undefined, // Define `Model` property which can keep track of already fired `events`, // and prevent redundant event to be triggered in case of cyclic model graphs. _proxyCalls:undefined, // Override constructor to set parents constructor: function (attributes, options) { // Set parent's opportunistically. options && options.__parents__ && (this.parents = [options.__parents__]); BackboneModel.apply(this, arguments); }, on: function (name, callback, context) { var result = BackboneEvent.on.apply(this, arguments); // No optimization possible if nested-events is wanted by the application if (Backbone.Associations.EVENTS_NC) return result; // Regular expression used to split event strings. var eventSplitter = /\s+/; // Handle atomic event names only if (_.isString(name) && name && (!eventSplitter.test(name)) && callback) { var endPoint = getPathEndPoint(name); if (endPoint) { //Increment end point counter. Represents # of nodes which listen to this end point endPoints[endPoint] = (typeof endPoints[endPoint] === 'undefined') ? 1 : (endPoints[endPoint] + 1); } } return result; }, off: function (name, callback, context) { // No optimization possible if nested-events is wanted by the application if (Backbone.Associations.EVENTS_NC) return BackboneEvent.off.apply(this, arguments); var eventSplitter = /\s+/, events = this._events, listeners = {}, names = events ? _.keys(events) : [], all = (!name && !callback && !context), atomic_event = (_.isString(name) && (!eventSplitter.test(name))); if (all || atomic_event) { for (var i = 0, l = names.length; i < l; i++) { // Store the # of callbacks listening to the event name prior to the `off` call listeners[names[i]] = events[names[i]] ? events[names[i]].length : 0; } } // Call Backbone off implementation var result = BackboneEvent.off.apply(this, arguments); if (all || atomic_event) { for (i = 0, l = names.length; i < l; i++) { var endPoint = getPathEndPoint(names[i]); if (endPoint) { if (events[names[i]]) { // Some listeners wiped out for this name for this object endPoints[endPoint] -= (listeners[names[i]] - events[names[i]].length); } else { // All listeners wiped out for this name for this object endPoints[endPoint] -= listeners[names[i]]; } } } } return result; }, // Get the value of an attribute. get:function (attr) { var cache = this.__attributes__, val = ModelProto.get.call(this, attr), obj = cache ? (isValuePresent(val) ? val : cache[attr]) : val; return isValuePresent(obj) ? obj : this._getAttr.apply(this, arguments); }, // Set a hash of model attributes on the Backbone Model. set:function (key, value, options) { var attributes, result; // Duplicate backbone's behavior to allow separate key/value parameters, // instead of a single 'attributes' object. if (_.isObject(key) || key == null) { attributes = key; options = value; } else { attributes = {}; attributes[key] = value; } result = this._set(attributes, options); // Trigger events which have been blocked until the entire object graph is updated. this._processPendingEvents(); return result; }, // Works with an attribute hash and options + fully qualified paths _set:function (attributes, options) { var attr, modelMap, modelId, obj, result = this; if (!attributes) return this; // temp cache of attributes this.__attributes__ = attributes; for (attr in attributes) { //Create a map for each unique object whose attributes we want to set modelMap || (modelMap = {}); if (attr.match(pathChecker)) { var pathTokens = getPathArray(attr), initials = _.initial(pathTokens), last = pathTokens[pathTokens.length - 1], parentModel = this.get(initials); if (parentModel instanceof BackboneModel) { obj = modelMap[parentModel.cid] || (modelMap[parentModel.cid] = {'model': parentModel, 'data': {}}); obj.data[last] = attributes[attr]; } } else { obj = modelMap[this.cid] || (modelMap[this.cid] = {'model':this, 'data':{}}); obj.data[attr] = attributes[attr]; } } if (modelMap) { for (modelId in modelMap) { obj = modelMap[modelId]; this._setAttr.call(obj.model, obj.data, options) || (result = false); } } else { result = this._setAttr.call(this, attributes, options); } delete this.__attributes__; return result; }, // Set a hash of model attributes on the object, // fire Backbone `event` with options. // It maintains relations between models during the set operation. // It also bubbles up child events to the parent. _setAttr:function (attributes, options) { var attr; // Extract attributes and options. options || (options = {}); if (options.unset) for (attr in attributes) attributes[attr] = void 0; this.parents = this.parents || []; if (this.relations) { // Iterate over `this.relations` and `set` model and collection values // if `relations` are available. _.each(this.relations, function (relation) { var relationKey = relation.key, activationContext = relation.scope || root, relatedModel = this._transformRelatedModel(relation, attributes), collectionType = this._transformCollectionType(relation, relatedModel, attributes), map = _.isString(relation.map) ? map2Scope(relation.map, activationContext) : relation.map, currVal = this.attributes[relationKey], idKey = currVal && currVal.idAttribute, val, relationOptions, data, relationValue, newCtx = false; // Merge in `options` specific to this relation. relationOptions = relation.options ? _.extend({}, relation.options, options) : options; if (attributes[relationKey]) { // Get value of attribute with relation key in `val`. val = _.result(attributes, relationKey); // Map `val` if a transformation function is provided. val = map ? map.call(this, val, collectionType ? collectionType : relatedModel) : val; if (!isValuePresent(val)) { data = val; } else { // If `relation.type` is `Backbone.Many`, // Create `Backbone.Collection` with passed data and perform Backbone `set`. if (relation.type === Backbone.Many) { if (currVal) { // Setting this flag will prevent events from firing immediately. That way clients // will not get events until the entire object graph is updated. currVal._deferEvents = true; // Use Backbone.Collection's `reset` or smart `set` method currVal[relationOptions.reset ? 'reset' : 'set']( val instanceof BackboneCollection ? val.models : val, relationOptions); data = currVal; } else { newCtx = true; if (val instanceof BackboneCollection) { data = val; } else { data = this._createCollection( collectionType || BackboneCollection, relation.collectionOptions || (relatedModel ? {model: relatedModel} : {}) ); data[relationOptions.reset ? 'reset' : 'set'](val, relationOptions); } } } else if (relation.type === Backbone.One) { var hasOwnProperty = (val instanceof BackboneModel) ? val.attributes.hasOwnProperty(idKey) : val.hasOwnProperty(idKey); var newIdKey = (val instanceof BackboneModel) ? val.attributes[idKey] : val[idKey]; //Is the passed in data for the same key? if (currVal && hasOwnProperty && currVal.attributes[idKey] === newIdKey) { // Setting this flag will prevent events from firing immediately. That way clients // will not get events until the entire object graph is updated. currVal._deferEvents = true; // Perform the traditional `set` operation currVal._set(val instanceof BackboneModel ? val.attributes : val, relationOptions); data = currVal; } else { newCtx = true; if (val instanceof BackboneModel) { data = val; } else { relationOptions.__parents__ = this; data = new relatedModel(val, relationOptions); delete relationOptions.__parents__; } } } else { throw new Error('type attribute must be specified and ' + 'have the values Backbone.One or Backbone.Many'); } } attributes[relationKey] = data; relationValue = data; // Add proxy events to respective parents. // Only add callback if not defined or new Ctx has been identified. if (newCtx || (relationValue && !relationValue._proxyCallback)) { if(!relationValue._proxyCallback) { relationValue._proxyCallback = function () { return Backbone.Associations.EVENTS_BUBBLE && this._bubbleEvent.call(this, relationKey, relationValue, arguments); }; } relationValue.on("all", relationValue._proxyCallback, this); } } //Distinguish between the value of undefined versus a set no-op if (attributes.hasOwnProperty(relationKey)) this._setupParents(attributes[relationKey], this.attributes[relationKey]); }, this); } // Return results for `BackboneModel.set`. return ModelProto.set.call(this, attributes, options); }, // Bubble-up event to `parent` Model _bubbleEvent:function (relationKey, relationValue, eventArguments) { var args = eventArguments, opt = args[0].split(":"), eventType = opt[0], catch_all = args[0] == "nested-change", isChangeEvent = eventType === "change", eventObject = args[1], indexEventObject = -1, _proxyCalls = relationValue._proxyCalls, cargs, eventPath = opt[1], eSrc = !eventPath || (eventPath.indexOf(pathSeparator) == -1), basecolEventPath; // Short circuit the listen in to the nested-graph event if (catch_all) return; // Record the source of the event if (eSrc) sourceKey = (getPathEndPoint(args[0]) || relationKey); // Short circuit the event bubbling as there are no listeners for this end point if (!Backbone.Associations.EVENTS_NC && !endPoints[sourceKey]) return; // Short circuit the listen in to the wild-card event if (Backbone.Associations.EVENTS_WILDCARD) { if (/\[\*\]/g.test(eventPath)) return this; } if (relationValue instanceof BackboneCollection && (isChangeEvent || eventPath)) { // O(n) search :( indexEventObject = relationValue.indexOf(sourceModel || eventObject); } if (this instanceof BackboneModel) { // A quicker way to identify the model which caused an update inside the collection (while bubbling up) sourceModel = this; } // Manipulate `eventPath`. eventPath = relationKey + ((indexEventObject !== -1 && (isChangeEvent || eventPath)) ? "[" + indexEventObject + "]" : "") + (eventPath ? pathSeparator + eventPath : ""); // Short circuit collection * events if (Backbone.Associations.EVENTS_WILDCARD) { basecolEventPath = eventPath.replace(/\[\d+\]/g, '[*]'); } cargs = []; cargs.push.apply(cargs, args); cargs[0] = eventType + ":" + eventPath; // Create a collection modified event with wild-card if (Backbone.Associations.EVENTS_WILDCARD && eventPath !== basecolEventPath) { cargs[0] = cargs[0] + " " + eventType + ":" + basecolEventPath; } // If event has been already triggered as result of same source `eventPath`, // no need to re-trigger event to prevent cycle. _proxyCalls = relationValue._proxyCalls = (_proxyCalls || {}); if (this._isEventAvailable.call(this, _proxyCalls, eventPath)) return this; // Add `eventPath` in `_proxyCalls` to keep track of already triggered `event`. _proxyCalls[eventPath] = true; // Set up previous attributes correctly. if (isChangeEvent) { this._previousAttributes[relationKey] = relationValue._previousAttributes; this.changed[relationKey] = relationValue; } // Bubble up event to parent `model` with new changed arguments. this.trigger.apply(this, cargs); //Only fire for change. Not change:attribute if (Backbone.Associations.EVENTS_NC && isChangeEvent && this.get(eventPath) != args[2]) { var ncargs = ["nested-change", eventPath, args[1]]; args[2] && ncargs.push(args[2]); //args[2] will be options if present this.trigger.apply(this, ncargs); } // Remove `eventPath` from `_proxyCalls`, // if `eventPath` and `_proxyCalls` are available, // which allow event to be triggered on for next operation of `set`. if (_proxyCalls && eventPath) delete _proxyCalls[eventPath]; sourceModel = undefined; return this; }, // Has event been fired from this source. Used to prevent event recursion in cyclic graphs _isEventAvailable:function (_proxyCalls, path) { return _.find(_proxyCalls, function (value, eventKey) { return path.indexOf(eventKey, path.length - eventKey.length) !== -1; }); }, //Maintain reverse pointers - a.k.a parents _setupParents: function (updated, original) { // Set new parent for updated if (updated) { updated.parents = updated.parents || []; (_.indexOf(updated.parents, this) == -1) && updated.parents.push(this); } // Remove `this` from the earlier set value's parents (if the new value is different). if (original && original.parents.length > 0 && original != updated) { original.parents = _.difference(original.parents, [this]); // Don't bubble to this parent anymore original._proxyCallback && original.off("all", original._proxyCallback, this); } }, // Returns new `collection` (or derivatives) of type `options.model`. _createCollection: function (type, options) { options = _.defaults(options, {model: type.model}); var c = new type([], _.isFunction(options) ? options.call(this) : options); c.parents = [this]; return c; }, // Process all pending events after the entire object graph has been updated _processPendingEvents:function () { if (!this._processedEvents) { this._processedEvents = true; this._deferEvents = false; // Trigger all pending events _.each(this._pendingEvents, function (e) { e.c.trigger.apply(e.c, e.a); }); this._pendingEvents = []; // Traverse down the object graph and call process pending events on sub-trees _.each(this.relations, function (relation) { var val = this.attributes[relation.key]; val && val._processPendingEvents && val._processPendingEvents(); }, this); delete this._processedEvents; } }, // Process the raw `relatedModel` value set in a relation _transformRelatedModel: function (relation, attributes) { var relatedModel = relation.relatedModel; var activationContext = relation.scope || root; // Call function if relatedModel is implemented as a function if (relatedModel && !(relatedModel.prototype instanceof BackboneModel)) relatedModel = _.isFunction(relatedModel) ? relatedModel.call(this, relation, attributes) : relatedModel; // Get class if relation and map is stored as a string. if (relatedModel && _.isString(relatedModel)) { relatedModel = (relatedModel === Backbone.Self) ? this.constructor : map2Scope(relatedModel, activationContext); } // Error checking if (relation.type === Backbone.One) { if (!relatedModel) throw new Error('specify a relatedModel for Backbone.One type'); if (!(relatedModel.prototype instanceof Backbone.Model)) throw new Error('specify an AssociatedModel or Backbone.Model for Backbone.One type'); } return relatedModel; }, // Process the raw `collectionType` value set in a relation _transformCollectionType: function (relation, relatedModel, attributes) { var collectionType = relation.collectionType; var activationContext = relation.scope || root; if (collectionType && _.isFunction(collectionType) && (collectionType.prototype instanceof BackboneModel)) throw new Error('type is of Backbone.Model. Specify derivatives of Backbone.Collection'); // Call function if collectionType is implemented as a function if (collectionType && !(collectionType.prototype instanceof BackboneCollection)) collectionType = _.isFunction(collectionType) ? collectionType.call(this, relation, attributes) : collectionType; collectionType && _.isString(collectionType) && (collectionType = map2Scope(collectionType, activationContext)); // `collectionType` of defined `relation` should be instance of `Backbone.Collection`. if (collectionType && !collectionType.prototype instanceof BackboneCollection) { throw new Error('collectionType must inherit from Backbone.Collection'); } // Error checking if (relation.type === Backbone.Many) { if ((!relatedModel) && (!collectionType)) throw new Error('specify either a relatedModel or collectionType'); } return collectionType; }, // Override trigger to defer events in the object graph. trigger:function (name) { // Defer event processing if (this._deferEvents) { this._pendingEvents = this._pendingEvents || []; // Maintain a queue of pending events to trigger after the entire object graph is updated. this._pendingEvents.push({c:this, a:arguments}); } else { ModelProto.trigger.apply(this, arguments); } }, // The JSON representation of the model. toJSON:function (options) { var json = {}, aJson; json[this.idAttribute] = this.id; if (!this.visited) { this.visited = true; // Get json representation from `BackboneModel.toJSON`. json = ModelProto.toJSON.apply(this, arguments); // Pick up only the keys you want to serialize if (options && options.serialize_keys) { json = _.pick(json, options.serialize_keys); } // If `this.relations` is defined, iterate through each `relation` // and added it's json representation to parents' json representation. if (this.relations) { _.each(this.relations, function (relation) { var key = relation.key, remoteKey = relation.remoteKey, attr = this.attributes[key], serialize = !relation.isTransient, serialize_keys = relation.serialize || [], _options = _.clone(options); // Remove default Backbone serialization for associations. delete json[key]; //Assign to remoteKey if specified. Otherwise use the default key. //Only for non-transient relationships if (serialize) { // Pass the keys to serialize as options to the toJSON method. if (serialize_keys.length) { _options ? (_options.serialize_keys = serialize_keys) : (_options = {serialize_keys: serialize_keys}) } aJson = attr && attr.toJSON ? attr.toJSON(_options) : attr; json[remoteKey || key] = _.isArray(aJson) ? _.compact(aJson) : aJson; } }, this); } delete this.visited; } return json; }, // Create a new model with identical attributes to this one. clone: function (options) { return new this.constructor(this.toJSON(options)); }, // Call this if you want to set an `AssociatedModel` to a falsy value like undefined/null directly. // Not calling this will leak memory and have wrong parents. // See test case "parent relations" cleanup:function (options) { options = options || {}; _.each(this.relations, function (relation) { var val = this.attributes[relation.key]; if(val) { val._proxyCallback && val.off("all", val._proxyCallback, this); val.parents = _.difference(val.parents, [this]); } }, this); (!options.listen) && this.off(); }, // Override destroy to perform house-keeping on `parents` collection destroy: function(options) { options = options ? _.clone(options) : {}; options = _.defaults(options, {remove_references: true, listen: true}); var model = this; if(options.remove_references && options.wait) { // Proxy success implementation var success = options.success; // Substitute with an implementation which will remove references to `model` options.success = function (resp) { if (success) success(model, resp, options); model.cleanup(options); } } // Call the base implementation var xhr = ModelProto.destroy.apply(this, [options]); if(options.remove_references && !options.wait) { model.cleanup(options); } return xhr; }, // Navigate the path to the leaf object in the path to query for the attribute value _getAttr:function (path) { var result = this, cache = this.__attributes__, //Tokenize the path attrs = getPathArray(path), key, i; if (_.size(attrs) < 1) return; for (i = 0; i < attrs.length; i++) { key = attrs[i]; if (!result) break; //Navigate the path to get to the result result = result instanceof BackboneCollection ? (isNaN(key) ? undefined : result.at(key)) : (cache ? (isValuePresent(result.attributes[key]) ? result.attributes[key] : cache[key]) : result.attributes[key] ); } return result; } }); // Tokenize the fully qualified event path var getPathArray = function (path) { if (path === '') return ['']; return _.isString(path) ? (path.match(delimiters)) : path || []; }; // Get the end point of the path. var getPathEndPoint = function (path) { if (!path) return path; // event_type: var tokens = path.split(":"); if (tokens.length > 1) { path = tokens[tokens.length - 1]; tokens = path.split(pathSeparator); return tokens.length > 1 ? tokens[tokens.length - 1].split('[')[0] : tokens[0].split('[')[0]; } else { //path of 0 depth return ""; } }; var map2Scope = function (path, context) { var target, scopes = [context]; // Check global scopes after passed-in context scopes.push.apply(scopes, Backbone.Associations.scopes); for (var ctx, i = 0, l = scopes.length; i < l; ++i) { if (ctx = scopes[i]) { target = _.reduce(path.split(pathSeparator), function (memo, elem) { return memo[elem]; }, ctx); if (target) break; } } return target; }; // Infer the relation from the collection's parents and find the appropriate map for the passed in `models` var map2models = function (parents, target, models) { var relation, surrogate; //Iterate over collection's parents _.find(parents, function (parent) { //Iterate over relations relation = _.find(parent.relations, function (rel) { return parent.get(rel.key) === target; }, this); if (relation) { surrogate = parent;//surrogate for transformation return true;//break; } }, this); //If we found a relation and it has a mapping function if (relation && relation.map) { return relation.map.call(surrogate, models, target); } return models; }; // Utility method to check for null or undefined value var isValuePresent = function (value) { return (!_.isUndefined(value)) && (!_.isNull(value)); }; var proxies = {}; // Proxy Backbone collection methods _.each(['set', 'remove', 'reset'], function (method) { proxies[method] = BackboneCollection.prototype[method]; CollectionProto[method] = function (models, options) { //Short-circuit if this collection doesn't hold `AssociatedModels` if (this.model.prototype instanceof AssociatedModel && this.parents) { //Find a map function if available and perform a transformation arguments[0] = map2models(this.parents, this, models); } return proxies[method].apply(this, arguments); } }); // Override trigger to defer events in the object graph. proxies['trigger'] = CollectionProto['trigger']; CollectionProto['trigger'] = function (name) { if (this._deferEvents) { this._pendingEvents = this._pendingEvents || []; // Maintain a queue of pending events to trigger after the entire object graph is updated. this._pendingEvents.push({c:this, a:arguments}); } else { proxies['trigger'].apply(this, arguments); } }; // Attach process pending event functionality on collections as well. Re-use from `AssociatedModel` CollectionProto._processPendingEvents = AssociatedModel.prototype._processPendingEvents; CollectionProto.on = AssociatedModel.prototype.on; CollectionProto.off = AssociatedModel.prototype.off; return Backbone; })); },{"backbone":24,"underscore":52}],22:[function(require,module,exports){ // MarionetteJS (Backbone.Marionette) // ---------------------------------- // v3.0.0 // // Copyright (c)2016 Derick Bailey, Muted Solutions, LLC. // Distributed under MIT license // // http://marionettejs.com (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('backbone'), require('underscore'), require('backbone.radio')) : typeof define === 'function' && define.amd ? define(['backbone', 'underscore', 'backbone.radio'], factory) : (global.Marionette = global['Mn'] = factory(global.Backbone,global._,global.Backbone.Radio)); }(this, function (Backbone,_,Radio) { 'use strict'; Backbone = 'default' in Backbone ? Backbone['default'] : Backbone; _ = 'default' in _ ? _['default'] : _; Radio = 'default' in Radio ? Radio['default'] : Radio; var version = "3.0.0"; //Internal utility for creating context style global utils var proxy = function proxy(method) { return function (context) { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } return method.apply(context, args); }; }; // Borrow the Backbone `extend` method so we can use it as needed var extend = Backbone.Model.extend; var deprecate = function deprecate(message, test) { if (_.isObject(message)) { message = message.prev + ' is going to be removed in the future. ' + 'Please use ' + message.next + ' instead.' + (message.url ? ' See: ' + message.url : ''); } if (!Marionette.DEV_MODE) { return; } if ((test === undefined || !test) && !deprecate._cache[message]) { deprecate._warn('Deprecation warning: ' + message); deprecate._cache[message] = true; } }; deprecate._console = typeof console !== 'undefined' ? console : {}; deprecate._warn = function () { var warn = deprecate._console.warn || deprecate._console.log || _.noop; return warn.apply(deprecate._console, arguments); }; deprecate._cache = {}; // Determine if `el` is a child of the document var isNodeAttached = function isNodeAttached(el) { return Backbone.$.contains(document.documentElement, el); }; // Merge `keys` from `options` onto `this` var mergeOptions = function mergeOptions(options, keys) { if (!options) { return; } _.extend(this, _.pick(options, keys)); }; // Marionette.getOption // -------------------- // Retrieve an object, function or other value from the // object or its `options`, with `options` taking precedence. var getOption = function getOption(optionName) { if (!optionName) { return; } if (this.options && this.options[optionName] !== undefined) { return this.options[optionName]; } else { return this[optionName]; } }; // Marionette.normalizeMethods // ---------------------- // Pass in a mapping of events => functions or function names // and return a mapping of events => functions var normalizeMethods = function normalizeMethods(hash) { var _this = this; return _.reduce(hash, function (normalizedHash, method, name) { if (!_.isFunction(method)) { method = _this[method]; } if (method) { normalizedHash[name] = method; } return normalizedHash; }, {}); }; // split the event name on the ":" var splitter = /(^|:)(\w)/gi; // take the event section ("section1:section2:section3") // and turn it in to uppercase name onSection1Section2Section3 function getEventName(match, prefix, eventName) { return eventName.toUpperCase(); } // Trigger an event and/or a corresponding method name. Examples: // // `this.triggerMethod("foo")` will trigger the "foo" event and // call the "onFoo" method. // // `this.triggerMethod("foo:bar")` will trigger the "foo:bar" event and // call the "onFooBar" method. function triggerMethod(event) { // get the method name from the event name var methodName = 'on' + event.replace(splitter, getEventName); var method = getOption.call(this, methodName); var result = void 0; // call the onMethodName if it exists for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } if (_.isFunction(method)) { // pass all args, except the event name result = method.apply(this, args); } // trigger the event this.trigger.apply(this, [event].concat(args)); return result; } // triggerMethodOn invokes triggerMethod on a specific context // // e.g. `Marionette.triggerMethodOn(view, 'show')` // will trigger a "show" event or invoke onShow the view. function triggerMethodOn(context) { var fnc = _.isFunction(context.triggerMethod) ? context.triggerMethod : triggerMethod; for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { args[_key2 - 1] = arguments[_key2]; } return fnc.apply(context, args); } // Trigger method on children unless a pure Backbone.View function triggerMethodChildren(view, event, shouldTrigger) { if (!view._getImmediateChildren) { return; } _.each(view._getImmediateChildren(), function (child) { if (!shouldTrigger(child)) { return; } triggerMethodOn(child, event, child); }); } function shouldTriggerAttach(view) { return !view._isAttached; } function shouldAttach(view) { if (!shouldTriggerAttach(view)) { return false; } view._isAttached = true; return true; } function shouldTriggerDetach(view) { return view._isAttached; } function shouldDetach(view) { if (!shouldTriggerDetach(view)) { return false; } view._isAttached = false; return true; } // Monitor a view's state, propagating attach/detach events to children and firing dom:refresh // whenever a rendered view is attached or an attached view is rendered. function monitorViewEvents(view) { if (view._areViewEventsMonitored) { return; } view._areViewEventsMonitored = true; function handleBeforeAttach() { triggerMethodChildren(view, 'before:attach', shouldTriggerAttach); } function handleAttach() { triggerMethodChildren(view, 'attach', shouldAttach); triggerDOMRefresh(); } function handleBeforeDetach() { triggerMethodChildren(view, 'before:detach', shouldTriggerDetach); } function handleDetach() { triggerMethodChildren(view, 'detach', shouldDetach); } function handleRender() { triggerDOMRefresh(); } function triggerDOMRefresh() { if (view._isAttached && view._isRendered) { triggerMethodOn(view, 'dom:refresh', view); } } view.on({ 'before:attach': handleBeforeAttach, 'attach': handleAttach, 'before:detach': handleBeforeDetach, 'detach': handleDetach, 'render': handleRender }); } var errorProps = ['description', 'fileName', 'lineNumber', 'name', 'message', 'number']; var MarionetteError = extend.call(Error, { urlRoot: 'http://marionettejs.com/docs/v' + version + '/', constructor: function constructor(message, options) { if (_.isObject(message)) { options = message; message = options.message; } else if (!options) { options = {}; } var error = Error.call(this, message); _.extend(this, _.pick(error, errorProps), _.pick(options, errorProps)); this.captureStackTrace(); if (options.url) { this.url = this.urlRoot + options.url; } }, captureStackTrace: function captureStackTrace() { if (Error.captureStackTrace) { Error.captureStackTrace(this, MarionetteError); } }, toString: function toString() { return this.name + ': ' + this.message + (this.url ? ' See: ' + this.url : ''); } }); MarionetteError.extend = extend; // Bind/unbind the event to handlers specified as a string of // handler names on the target object function bindFromStrings(target, entity, evt, methods, actionName) { var methodNames = methods.split(/\s+/); _.each(methodNames, function (methodName) { var method = target[methodName]; if (!method) { throw new MarionetteError('Method "' + methodName + '" was configured as an event handler, but does not exist.'); } target[actionName](entity, evt, method); }); } // generic looping function function iterateEvents(target, entity, bindings, actionName) { if (!entity || !bindings) { return; } // type-check bindings if (!_.isObject(bindings)) { throw new MarionetteError({ message: 'Bindings must be an object.', url: 'marionette.functions.html#marionettebindevents' }); } // iterate the bindings and bind/unbind them _.each(bindings, function (method, evt) { // allow for a list of method names as a string if (_.isString(method)) { bindFromStrings(target, entity, evt, method, actionName); return; } target[actionName](entity, evt, method); }); } function bindEvents(entity, bindings) { iterateEvents(this, entity, bindings, 'listenTo'); return this; } function unbindEvents(entity, bindings) { iterateEvents(this, entity, bindings, 'stopListening'); return this; } function iterateReplies(target, channel, bindings, actionName) { if (!channel || !bindings) { return; } // type-check bindings if (!_.isObject(bindings)) { throw new MarionetteError({ message: 'Bindings must be an object.', url: 'marionette.functions.html#marionettebindrequests' }); } var normalizedRadioRequests = normalizeMethods.call(target, bindings); channel[actionName](normalizedRadioRequests, target); } function bindRequests(channel, bindings) { iterateReplies(this, channel, bindings, 'reply'); return this; } function unbindRequests(channel, bindings) { iterateReplies(this, channel, bindings, 'stopReplying'); return this; } // Internal utility for setting options consistently across Mn var setOptions = function setOptions() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } this.options = _.extend.apply(_, [{}, _.result(this, 'options')].concat(args)); }; var CommonMixin = { // Imports the "normalizeMethods" to transform hashes of // events=>function references/names to a hash of events=>function references normalizeMethods: normalizeMethods, _setOptions: setOptions, // A handy way to merge passed-in options onto the instance mergeOptions: mergeOptions, // Enable getting options from this or this.options by name. getOption: getOption, // Enable binding view's events from another entity. bindEvents: bindEvents, // Enable unbinding view's events from another entity. unbindEvents: unbindEvents }; // MixinOptions // - channelName // - radioEvents // - radioRequests var RadioMixin = { _initRadio: function _initRadio() { var channelName = _.result(this, 'channelName'); if (!channelName) { return; } /* istanbul ignore next */ if (!Radio) { throw new MarionetteError({ name: 'BackboneRadioMissing', message: 'The dependency "backbone.radio" is missing.' }); } var channel = this._channel = Radio.channel(channelName); var radioEvents = _.result(this, 'radioEvents'); this.bindEvents(channel, radioEvents); var radioRequests = _.result(this, 'radioRequests'); this.bindRequests(channel, radioRequests); this.on('destroy', this._destroyRadio); }, _destroyRadio: function _destroyRadio() { this._channel.stopReplying(null, null, this); }, getChannel: function getChannel() { return this._channel; }, // Proxy `bindEvents` bindEvents: bindEvents, // Proxy `unbindEvents` unbindEvents: unbindEvents, // Proxy `bindRequests` bindRequests: bindRequests, // Proxy `unbindRequests` unbindRequests: unbindRequests }; var ClassOptions = ['channelName', 'radioEvents', 'radioRequests']; // A Base Class that other Classes should descend from. // Object borrows many conventions and utilities from Backbone. var MarionetteObject = function MarionetteObject(options) { this._setOptions(options); this.mergeOptions(options, ClassOptions); this.cid = _.uniqueId(this.cidPrefix); this._initRadio(); this.initialize.apply(this, arguments); }; MarionetteObject.extend = extend; // Object Methods // -------------- // Ensure it can trigger events with Backbone.Events _.extend(MarionetteObject.prototype, Backbone.Events, CommonMixin, RadioMixin, { cidPrefix: 'mno', // for parity with Marionette.AbstractView lifecyle _isDestroyed: false, isDestroyed: function isDestroyed() { return this._isDestroyed; }, //this is a noop method intended to be overridden by classes that extend from this base initialize: function initialize() {}, destroy: function destroy() { if (this._isDestroyed) { return this; } for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } this.triggerMethod.apply(this, ['before:destroy', this].concat(args)); this._isDestroyed = true; this.triggerMethod.apply(this, ['destroy', this].concat(args)); this.stopListening(); return this; }, triggerMethod: triggerMethod }); // Manage templates stored in `