From 00cfb95971017e3f458c43a1f27a70bd26a766b4 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 18 Sep 2012 23:42:52 -0700 Subject: [PATCH] Update vendors. Former-commit-id: fddaef2be532e30f197f8bdff70dc6ec9bfa3cfc --- vendor/backbone/backbone.js | 42 +++++---- vendor/backbone/test/collection.js | 21 ++++- vendor/backbone/test/router.js | 30 +++---- vendor/platform.js/platform.js | 4 +- vendor/underscore/test/collections.js | 16 ++++ vendor/underscore/test/utility.js | 5 ++ vendor/underscore/underscore-min.js | 50 +++++------ vendor/underscore/underscore.js | 123 ++++++++++++++------------ 8 files changed, 176 insertions(+), 115 deletions(-) diff --git a/vendor/backbone/backbone.js b/vendor/backbone/backbone.js index 75ab600b8..1fbc89429 100644 --- a/vendor/backbone/backbone.js +++ b/vendor/backbone/backbone.js @@ -735,13 +735,7 @@ throw new Error('Cannot sort a set without a comparator'); } - // If provided an attribute name, use it to sort the collection. - if (_.isString(this.comparator)) { - var attr = this.comparator; - this.comparator = function(model){ return model.get(attr); }; - } - - if (this.comparator.length === 1) { + if (_.isString(this.comparator) || this.comparator.length === 1) { this.models = this.sortBy(this.comparator, this); } else { this.models.sort(_.bind(this.comparator, this)); @@ -753,7 +747,7 @@ // Pluck an attribute from each model in the collection. pluck: function(attr) { - return _.map(this.models, function(model){ return model.get(attr); }); + return _.invoke(this.models, 'get', attr); }, // When you have more items than you want to add or remove individually, @@ -867,9 +861,9 @@ var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl', 'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select', 'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke', - 'max', 'min', 'sortBy', 'sortedIndex', 'toArray', 'size', 'first', 'head', - 'take', 'initial', 'rest', 'tail', 'last', 'without', 'indexOf', 'shuffle', - 'lastIndexOf', 'isEmpty', 'groupBy']; + 'max', 'min', 'sortedIndex', 'toArray', 'size', 'first', 'head', 'take', + 'initial', 'rest', 'tail', 'last', 'without', 'indexOf', 'shuffle', + 'lastIndexOf', 'isEmpty']; // Mix in each Underscore method as a proxy to `Collection#models`. _.each(methods, function(method) { @@ -880,6 +874,19 @@ }; }); + // Underscore methods that take a property name as an argument. + var attributeMethods = ['groupBy', 'countBy', 'sortBy']; + + // Use attributes instead of properties. + _.each(attributeMethods, function(method) { + Collection.prototype[method] = function(value, context) { + var iterator = _.isFunction(value) ? value : function(model) { + return model.get(value); + }; + return _[method](this.models, iterator, context); + }; + }); + // Backbone.Router // ------------------- @@ -964,11 +971,15 @@ // Handles cross-browser history management, based on URL fragments. If the // browser does not support `onhashchange`, falls back to polling. - var History = Backbone.History = function(options) { + var History = Backbone.History = function() { this.handlers = []; _.bindAll(this, 'checkUrl'); - this.location = options && options.location || root.location; - this.history = options && options.history || root.history; + + // #1653 - Ensure that `History` can be used outside of the browser. + if (typeof window !== 'undefined') { + this.location = window.location; + this.history = window.history; + } }; // Cached regex for cleaning leading hashes and slashes. @@ -1160,7 +1171,8 @@ var href = location.href.replace(/(javascript:|#).*$/, ''); location.replace(href + '#' + fragment); } else { - location.hash = fragment; + // #1649 - Some browsers require that `hash` contains a leading #. + location.hash = '#' + fragment; } } diff --git a/vendor/backbone/test/collection.js b/vendor/backbone/test/collection.js index 98fd53e5e..1c44b0d0d 100644 --- a/vendor/backbone/test/collection.js +++ b/vendor/backbone/test/collection.js @@ -665,7 +665,7 @@ $(document).ready(function() { collection.create({id: 1}); }); - test("#1447 - create with wait adds model.", function() { + test("#1447 - create with wait adds model.", 1, function() { var collection = new Backbone.Collection; var model = new Backbone.Model; model.sync = function(method, model, options){ options.success(); }; @@ -673,7 +673,7 @@ $(document).ready(function() { collection.create(model, {wait: true}); }); - test("#1448 - add sorts collection after merge.", function() { + test("#1448 - add sorts collection after merge.", 1, function() { var collection = new Backbone.Collection([ {id: 1, x: 1}, {id: 2, x: 2} @@ -682,4 +682,21 @@ $(document).ready(function() { collection.add({id: 1, x: 3}, {merge: true}); deepEqual(collection.pluck('id'), [2, 1]); }); + + test("#1655 - groupBy can be used with a string argument.", 3, function() { + var collection = new Backbone.Collection([{x: 1}, {x: 2}]); + var grouped = collection.groupBy('x'); + strictEqual(_.keys(grouped).length, 2); + strictEqual(grouped[1][0].get('x'), 1); + strictEqual(grouped[2][0].get('x'), 2); + }); + + test("#1655 - sortBy can be used with a string argument.", 1, function() { + var collection = new Backbone.Collection([{x: 3}, {x: 1}, {x: 2}]); + var values = _.map(collection.sortBy('x'), function(model) { + return model.get('x'); + }); + deepEqual(values, [1, 2, 3]); + }); + }); diff --git a/vendor/backbone/test/router.js b/vendor/backbone/test/router.js index 66d6c9d68..f7522210e 100644 --- a/vendor/backbone/test/router.js +++ b/vendor/backbone/test/router.js @@ -41,7 +41,7 @@ $(document).ready(function() { setup: function() { location = new Location('http://example.com'); - Backbone.history = new Backbone.History({location: location}); + Backbone.history = _.extend(new Backbone.History, {location: location}); router = new Router({testing: 101}); Backbone.history.interval = 9; Backbone.history.start({pushState: false}); @@ -233,12 +233,12 @@ $(document).ready(function() { location.replace('http://example.com/root/foo'); Backbone.history.stop(); - Backbone.history = new Backbone.History({location: location}); + Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history.start({root: '/root', hashChange: false, silent: true}); strictEqual(Backbone.history.getFragment(), 'foo'); Backbone.history.stop(); - Backbone.history = new Backbone.History({location: location}); + Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history.start({root: '/root/', hashChange: false, silent: true}); strictEqual(Backbone.history.getFragment(), 'foo'); }); @@ -272,7 +272,7 @@ $(document).ready(function() { test("#1185 - Use pathname when hashChange is not wanted.", 1, function() { Backbone.history.stop(); location.replace('http://example.com/path/name#hash'); - Backbone.history = new Backbone.History({location: location}); + Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history.start({hashChange: false}); var fragment = Backbone.history.getFragment(); strictEqual(fragment, location.pathname.replace(/^\//, '')); @@ -281,7 +281,7 @@ $(document).ready(function() { test("#1206 - Strip leading slash before location.assign.", 1, function() { Backbone.history.stop(); location.replace('http://example.com/root/'); - Backbone.history = new Backbone.History({location: location}); + Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history.start({hashChange: false, root: '/root/'}); location.assign = function(pathname) { strictEqual(pathname, '/root/fragment'); @@ -292,7 +292,7 @@ $(document).ready(function() { test("#1387 - Root fragment without trailing slash.", 1, function() { Backbone.history.stop(); location.replace('http://example.com/root'); - Backbone.history = new Backbone.History({location: location}); + Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history.start({hashChange: false, root: '/root/', silent: true}); strictEqual(Backbone.history.getFragment(), ''); }); @@ -300,7 +300,7 @@ $(document).ready(function() { test("#1366 - History does not prepend root to fragment.", 2, function() { Backbone.history.stop(); location.replace('http://example.com/root/'); - Backbone.history = new Backbone.History({ + Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: function(state, title, url) { @@ -320,7 +320,7 @@ $(document).ready(function() { test("Normalize root.", 1, function() { Backbone.history.stop(); location.replace('http://example.com/root'); - Backbone.history = new Backbone.History({ + Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: function(state, title, url) { @@ -339,7 +339,7 @@ $(document).ready(function() { test("Normalize root.", 1, function() { Backbone.history.stop(); location.replace('http://example.com/root#fragment'); - Backbone.history = new Backbone.History({ + Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: function(state, title, url) {}, @@ -357,7 +357,7 @@ $(document).ready(function() { test("Normalize root.", 1, function() { Backbone.history.stop(); location.replace('http://example.com/root'); - Backbone.history = new Backbone.History({location: location}); + Backbone.history = _.extend(new Backbone.History, {location: location}); Backbone.history.loadUrl = function() { ok(true); }; Backbone.history.start({ pushState: true, @@ -368,7 +368,7 @@ $(document).ready(function() { test("Normalize root - leading slash.", 1, function() { Backbone.history.stop(); location.replace('http://example.com/root'); - Backbone.history = new Backbone.History({ + Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: function(){}, @@ -382,7 +382,7 @@ $(document).ready(function() { test("Transition from hashChange to pushState.", 1, function() { Backbone.history.stop(); location.replace('http://example.com/root#x/y'); - Backbone.history = new Backbone.History({ + Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: function(){}, @@ -400,7 +400,7 @@ $(document).ready(function() { test("#1619: Router: Normalize empty root", 1, function() { Backbone.history.stop(); location.replace('http://example.com/'); - Backbone.history = new Backbone.History({ + Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: function(){}, @@ -414,7 +414,7 @@ $(document).ready(function() { test("#1619: Router: nagivate with empty root", 1, function() { Backbone.history.stop(); location.replace('http://example.com/'); - Backbone.history = new Backbone.History({ + Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: function(state, title, url) { @@ -436,7 +436,7 @@ $(document).ready(function() { location.replace = function(url) { strictEqual(url, '/root/?a=b#x/y'); }; - Backbone.history = new Backbone.History({ + Backbone.history = _.extend(new Backbone.History, { location: location, history: { pushState: null, diff --git a/vendor/platform.js/platform.js b/vendor/platform.js/platform.js index a8a5482b0..a63ceab25 100644 --- a/vendor/platform.js/platform.js +++ b/vendor/platform.js/platform.js @@ -830,10 +830,10 @@ }; } // add browser/OS architecture - if ((data = / (?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) { + if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) { if (os) { os.architecture = 64; - os.family = os.family.replace(data, ''); + os.family = os.family.replace(RegExp(' *' + data), ''); } if (name && (/WOW64/i.test(ua) || (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform)))) { diff --git a/vendor/underscore/test/collections.js b/vendor/underscore/test/collections.js index 64047d989..60ad7e9e6 100644 --- a/vendor/underscore/test/collections.js +++ b/vendor/underscore/test/collections.js @@ -206,6 +206,16 @@ $(document).ready(function() { equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'pulls names out of objects'); }); + test('where', function() { + var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; + var result = _.where(list, {a: 1}); + equal(result.length, 3); + equal(result[result.length - 1].b, 4); + result = _.where(list, {b: 2}); + equal(result.length, 2); + equal(result[0].a, 1); + }); + test('max', function() { equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max'); @@ -280,6 +290,9 @@ $(document).ready(function() { equal(grouped['3'].join(' '), 'one two six ten'); equal(grouped['4'].join(' '), 'four five nine'); equal(grouped['5'].join(' '), 'three seven eight'); + + var context = {}; + _.groupBy([{}], function(){ ok(this === context); }, context); }); test('countBy', function() { @@ -292,6 +305,9 @@ $(document).ready(function() { equal(grouped['3'], 4); equal(grouped['4'], 3); equal(grouped['5'], 3); + + var context = {}; + _.countBy([{}], function(){ ok(this === context); }, context); }); test('sortedIndex', function() { diff --git a/vendor/underscore/test/utility.js b/vendor/underscore/test/utility.js index d5fb9603a..c9be20ad7 100644 --- a/vendor/underscore/test/utility.js +++ b/vendor/underscore/test/utility.js @@ -241,4 +241,9 @@ $(document).ready(function() { deepEqual(settings, {}); }); + test('#779 - delimeters are applied to unescaped text.', 1, function() { + var template = _.template('<<\nx\n>>', null, {evaluate: /<<(.*?)>>/g}); + strictEqual(template(), '<<\nx\n>>'); + }); + }); diff --git a/vendor/underscore/underscore-min.js b/vendor/underscore/underscore-min.js index ed8e59ba1..a499cf046 100644 --- a/vendor/underscore/underscore-min.js +++ b/vendor/underscore/underscore-min.js @@ -5,29 +5,29 @@ // Oliver Steele's Functional, and John Resig's Micro-Templating. // For all details and documentation: // http://documentcloud.github.com/underscore -(function(){var s=this,M=s._,o={},k=Array.prototype,p=Object.prototype,t=k.push,f=k.slice,q=k.concat,l=p.toString,N=p.hasOwnProperty,z=k.forEach,A=k.map,B=k.reduce,C=k.reduceRight,D=k.filter,E=k.every,F=k.some,r=k.indexOf,G=k.lastIndexOf,p=Array.isArray,O=Object.keys,u=Function.prototype.bind,b=function(a){if(a instanceof b)return a;if(!(this instanceof b))return new b(a);this._wrapped=a};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=b),exports._= -b):s._=b;b.VERSION="1.3.3";var j=b.each=b.forEach=function(a,c,d){if(a!=null)if(z&&a.forEach===z)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,h=a.length;e2;a==null&&(a= -[]);if(B&&a.reduce===B){e&&(c=b.bind(c,e));return h?a.reduce(c,d):a.reduce(c)}j(a,function(a,b,f){if(h)d=c.call(e,d,a,b,f);else{d=a;h=true}});if(!h)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var h=arguments.length>2;a==null&&(a=[]);if(C&&a.reduceRight===C){e&&(c=b.bind(c,e));return h?a.reduceRight(c,d):a.reduceRight(c)}var g=b.toArray(a).reverse();e&&!h&&(c=b.bind(c,e));return h?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect= -function(a,c,b){var e;H(a,function(a,g,i){if(c.call(b,a,g,i)){e=a;return true}});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(D&&a.filter===D)return a.filter(c,b);j(a,function(a,g,i){c.call(b,a,g,i)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,i){c.call(b,a,g,i)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,d){c||(c=b.identity);var e=true;if(a==null)return e;if(E&&a.every===E)return a.every(c,d);j(a,function(a, -b,i){if(!(e=e&&c.call(d,a,b,i)))return o});return!!e};var H=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(F&&a.some===F)return a.some(c,d);j(a,function(a,b,i){if(e||(e=c.call(d,a,b,i)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;if(r&&a.indexOf===r)return a.indexOf(c)!=-1;return b=H(a,function(a){return a===c})};b.invoke=function(a,c){var d=f.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c:a[c]).apply(a, -d)})};b.pluck=function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0]&&a.length<65535)return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,i){b=c?c.call(d,a,b,i):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0]&&a.length<65535)return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a, -function(a,b,i){b=c?c.call(d,a,b,i):a;bd?1:e>1;d(a[g])=0})})};b.difference=function(a){var c=q.apply(k,f.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=f.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this, -arguments)}};b.keys=O||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.pairs=function(a){return b.map(a,function(a,b){return[b,a]})};b.invert=function(a){return b.reduce(a,function(a,b,e){a[b]=e;return a},{})};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(f.call(arguments,1),function(b){for(var d in b)a[d]= -b[d]});return a};b.pick=function(a){var b={},d=q.apply(k,f.call(arguments,1));j(d,function(d){d in a&&(b[d]=a[d])});return b};b.omit=function(a){var c={},d=q.apply(k,f.call(arguments,1)),e;for(e in a)b.include(d,e)||(c[e]=a[e]);return c};b.defaults=function(a){j(f.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};var v=function(a,c,d,e){if(a===c)return a!== -0||1/a==1/c;if(a==null||c==null)return a===c;if(a instanceof b)a=a._wrapped;if(c instanceof b)c=c._wrapped;var h=l.call(a);if(h!=l.call(c))return false;switch(h){case "[object String]":return a==""+c;case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var g= -d.length;g--;)if(d[g]==a)return e[g]==c;d.push(a);e.push(c);var g=0,i=true;if(h=="[object Array]"){g=a.length;if(i=g==c.length)for(;g--;)if(!(i=v(a[g],c[g],d,e)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var f in a)if(b.has(a,f)){g++;if(!(i=b.has(c,f)&&v(a[f],c[f],d,e)))break}if(i){for(f in c)if(b.has(c,f)&&!g--)break;i=!g}}d.pop();e.pop();return i};b.isEqual=function(a,b){return v(a,b,[],[])};b.isEmpty=function(a){if(a==null)return true;if(b.isArray(a)|| -b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};j("Arguments,Function,String,Number,Date,RegExp".split(","),function(a){b["is"+a]=function(b){return l.call(b)=="[object "+a+"]"}});b.isArguments(arguments)||(b.isArguments=function(a){return!(!a||!b.has(a,"callee"))});b.isFinite=function(a){return b.isNumber(a)&& -isFinite(a)};b.isNaN=function(a){return b.isNumber(a)&&a!=+a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return N.call(a,b)};b.noConflict=function(){s._=M;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e":">", -'"':""","'":"'","/":"/"}};m.unescape=b.invert(m.escape);var P={escape:RegExp("["+b.keys(m.escape).join("")+"]","g"),unescape:RegExp("("+b.keys(m.unescape).join("|")+")","g")};b.each(["escape","unescape"],function(a){b[a]=function(b){return b==null?"":(""+b).replace(P[a],function(b){return m[a][b]})}});b.result=function(a,c){if(a==null)return null;var d=a[c];return b.isFunction(d)?d.call(a):d};b.mixin=function(a){j(b.functions(a),function(c){var d=b[c]=a[c];b.prototype[c]=function(){var a= -[this._wrapped];t.apply(a,arguments);a=d.apply(b,a);return this._chain?b(a).chain():a}})};var Q=0;b.uniqueId=function(a){var b=Q++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var w=/.^/,n={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"},x;for(x in n)n[n[x]]=x;var R=/\\|'|\r|\n|\t|\u2028|\u2029/g,S=/\\(\\|'|r|n|t|u2028|u2029)/g,y=function(a){return a.replace(S,function(a,b){return n[b]})};b.template= -function(a,c,d){d=b.defaults({},d,b.templateSettings);a="__p+='"+a.replace(R,function(a){return"\\"+n[a]}).replace(d.escape||w,function(a,b){return"'+\n((__t=("+y(b)+"))==null?'':_.escape(__t))+\n'"}).replace(d.interpolate||w,function(a,b){return"'+\n((__t=("+y(b)+"))==null?'':__t)+\n'"}).replace(d.evaluate||w,function(a,b){return"';\n"+y(b)+"\n__p+='"})+"';\n";d.variable||(a="with(obj||{}){\n"+a+"}\n");a="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+ -a+"return __p;\n";try{var e=new Function(d.variable||"obj","_",a)}catch(f){f.source=a;throw f;}if(c)return e(c,b);c=function(a){return e.call(this,a,b)};c.source="function("+(d.variable||"obj")+"){\n"+a+"}";return c};b.chain=function(a){return b(a).chain()};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var c=k[a];b.prototype[a]=function(){var d=this._wrapped;c.apply(d,arguments);(a=="shift"||a=="splice")&&d.length===0&&delete d[0];return this._chain?b(d).chain(): +(function(){var r=this,J=r._,n={},k=Array.prototype,o=Object.prototype,s=k.push,g=k.slice,p=k.concat,l=o.toString,K=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,q=k.indexOf,D=k.lastIndexOf,o=Array.isArray,L=Object.keys,t=Function.prototype.bind,b=function(a){if(a instanceof b)return a;if(!(this instanceof b))return new b(a);this._wrapped=a};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=b),exports._= +b):r._=b;b.VERSION="1.3.3";var j=b.each=b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,h=a.length;e2;a==null&&(a= +[]);if(y&&a.reduce===y){e&&(c=b.bind(c,e));return h?a.reduce(c,d):a.reduce(c)}j(a,function(a,b,M){if(h)d=c.call(e,d,a,b,M);else{d=a;h=true}});if(!h)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var h=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z){e&&(c=b.bind(c,e));return h?a.reduceRight(c,d):a.reduceRight(c)}var f=b.toArray(a).reverse();e&&!h&&(c=b.bind(c,e));return h?b.reduce(f,c,d,e):b.reduce(f,c)};b.find=b.detect= +function(a,c,b){var e;E(a,function(a,f,i){if(c.call(b,a,f,i)){e=a;return true}});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,f,i){c.call(b,a,f,i)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,f,i){c.call(b,a,f,i)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,d){c||(c=b.identity);var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,d);j(a,function(a, +b,i){if(!(e=e&&c.call(d,a,b,i)))return n});return!!e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,i){if(e||(e=c.call(d,a,b,i)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;if(q&&a.indexOf===q)return a.indexOf(c)!=-1;return b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=g.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c:a[c]).apply(a, +d)})};b.pluck=function(a,c){return b.map(a,function(a){return a[c]})};b.where=function(a,c){return b.isEmpty(c)?[]:b.filter(a,function(a){for(var b in c)if(c[b]!==a[b])return false;return true})};b.max=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0]&&a.length<65535)return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,i){b=c?c.call(d,a,b,i):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a)&& +a[0]===+a[0]&&a.length<65535)return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,i){b=c?c.call(d,a,b,i):a;bd||b===void 0)return 1;if(b>1;d(a[f])=0})})};b.difference=function(a){var c=p.apply(k,g.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=g.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=L||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.pairs=function(a){return b.map(a,function(a,b){return[b,a]})};b.invert=function(a){return b.reduce(a,function(a,b,e){a[b]=e;return a},{})};b.functions=b.methods=function(a){var c= +[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(g.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.pick=function(a){var b={},d=p.apply(k,g.call(arguments,1));j(d,function(d){d in a&&(b[d]=a[d])});return b};b.omit=function(a){var c={},d=p.apply(k,g.call(arguments,1)),e;for(e in a)b.include(d,e)||(c[e]=a[e]);return c};b.defaults=function(a){j(g.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)? +a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};var u=function(a,c,d,e){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a instanceof b)a=a._wrapped;if(c instanceof b)c=c._wrapped;var h=l.call(a);if(h!=l.call(c))return false;switch(h){case "[object String]":return a==""+c;case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==c.source&&a.global==c.global&& +a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return e[f]==c;d.push(a);e.push(c);var f=0,i=true;if(h=="[object Array]"){f=a.length;if(i=f==c.length)for(;f--;)if(!(i=u(a[f],c[f],d,e)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var g in a)if(b.has(a,g)){f++;if(!(i=b.has(c,g)&&u(a[g],c[g],d,e)))break}if(i){for(g in c)if(b.has(c,g)&&!f--)break;i=!f}}d.pop(); +e.pop();return i};b.isEqual=function(a,b){return u(a,b,[],[])};b.isEmpty=function(a){if(a==null)return true;if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};j("Arguments,Function,String,Number,Date,RegExp".split(","),function(a){b["is"+a]=function(b){return l.call(b)=="[object "+a+"]"}}); +b.isArguments(arguments)||(b.isArguments=function(a){return!(!a||!b.has(a,"callee"))});b.isFinite=function(a){return b.isNumber(a)&&isFinite(a)};b.isNaN=function(a){return b.isNumber(a)&&a!=+a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return K.call(a,b)};b.noConflict=function(){r._=J;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e= +0;e":">",'"':""","'":"'","/":"/"}};m.unescape=b.invert(m.escape);var N={escape:RegExp("["+b.keys(m.escape).join("")+"]","g"),unescape:RegExp("("+b.keys(m.unescape).join("|")+")","g")};b.each(["escape","unescape"],function(a){b[a]=function(b){return b==null?"":(""+b).replace(N[a],function(b){return m[a][b]})}});b.result=function(a,c){if(a==null)return null; +var d=a[c];return b.isFunction(d)?d.call(a):d};b.mixin=function(a){j(b.functions(a),function(c){var d=b[c]=a[c];b.prototype[c]=function(){var a=[this._wrapped];s.apply(a,arguments);a=d.apply(b,a);return this._chain?b(a).chain():a}})};var O=0;b.uniqueId=function(a){var b=O++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var v=/(.)^/,P={"'":"'","\\":"\\","\r":"r","\n":"n","\t":"t","\u2028":"u2028","\u2029":"u2029"},Q=/\\|'|\r|\n|\t|\u2028|\u2029/g; +b.template=function(a,c,d){var d=b.defaults({},d,b.templateSettings),e=RegExp([(d.escape||v).source,(d.interpolate||v).source,(d.evaluate||v).source].join("|")+"|$","g"),h=0,f="__p+='";a.replace(e,function(b,c,d,e,g){f=f+a.slice(h,g).replace(Q,function(a){return"\\"+P[a]});f=f+(c?"'+\n((__t=("+c+"))==null?'':_.escape(__t))+\n'":d?"'+\n((__t=("+d+"))==null?'':__t)+\n'":e?"';\n"+e+"\n__p+='":"");h=g+b.length});f=f+"';\n";d.variable||(f="with(obj||{}){\n"+f+"}\n");f="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+ +f+"return __p;\n";try{var g=new Function(d.variable||"obj","_",f)}catch(j){j.source=f;throw j;}if(c)return g(c,b);c=function(a){return g.call(this,a,b)};c.source="function("+(d.variable||"obj")+"){\n"+f+"}";return c};b.chain=function(a){return b(a).chain()};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var c=k[a];b.prototype[a]=function(){var d=this._wrapped;c.apply(d,arguments);(a=="shift"||a=="splice")&&d.length===0&&delete d[0];return this._chain?b(d).chain(): d}});j(["concat","join","slice"],function(a){var c=k[a];b.prototype[a]=function(){var a=c.apply(this._wrapped,arguments);return this._chain?b(a).chain():a}});b.extend(b.prototype,{chain:function(){this._chain=true;return this},value:function(){return this._wrapped}})}).call(this); diff --git a/vendor/underscore/underscore.js b/vendor/underscore/underscore.js index 4889be4e0..ede5757fe 100644 --- a/vendor/underscore/underscore.js +++ b/vendor/underscore/underscore.js @@ -228,6 +228,18 @@ return _.map(obj, function(value){ return value[key]; }); }; + // Convenience version of a common use case of `filter`: selecting only objects + // with specific `key:value` pairs. + _.where = function(obj, attrs) { + if (_.isEmpty(attrs)) return []; + return _.filter(obj, function(value) { + for (var key in attrs) { + if (attrs[key] !== value[key]) return false; + } + return true; + }); + }; + // Return the maximum element or (element-based computation). // Can't optimize arrays of integers longer than 65,535 elements. // See: https://bugs.webkit.org/show_bug.cgi?id=80797 @@ -264,16 +276,21 @@ var index = 0; var shuffled = []; each(obj, function(value) { - rand = Math.floor(Math.random() * ++index); + rand = _.random(index++); shuffled[index - 1] = shuffled[rand]; shuffled[rand] = value; }); return shuffled; }; + // An internal function to generate lookup iterators. + var lookupIterator = function(value) { + return _.isFunction(value) ? value : function(obj){ return obj[value]; }; + }; + // Sort the object's values by a criterion produced by an iterator. - _.sortBy = function(obj, val, context) { - var iterator = lookupIterator(obj, val); + _.sortBy = function(obj, value, context) { + var iterator = lookupIterator(value); return _.pluck(_.map(obj, function(value, index, list) { return { value : value, @@ -281,26 +298,22 @@ criteria : iterator.call(context, value, index, list) }; }).sort(function(left, right) { - var a = left.criteria, b = right.criteria; - var ai = left.index, bi = right.index; - if (a === b) return ai < bi ? -1 : 1; - if (a === void 0) return 1; - if (b === void 0) return -1; - return a < b ? -1 : a > b ? 1 : ai < bi ? -1 : 1; + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index < right.index ? -1 : 1; }), 'value'); }; - // An internal function to generate lookup iterators. - var lookupIterator = function(obj, val) { - return _.isFunction(val) ? val : function(obj) { return obj[val]; }; - }; - // An internal function used for aggregate "group by" operations. - var group = function(obj, val, behavior) { + var group = function(obj, value, context, behavior) { var result = {}; - var iterator = lookupIterator(obj, val); + var iterator = lookupIterator(value); each(obj, function(value, index) { - var key = iterator(value, index); + var key = iterator.call(context, value, index); behavior(result, key, value); }); return result; @@ -308,8 +321,8 @@ // Groups the object's values by a criterion. Pass either a string attribute // to group by, or a function that returns the criterion. - _.groupBy = function(obj, val) { - return group(obj, val, function(result, key, value) { + _.groupBy = function(obj, value, context) { + return group(obj, value, context, function(result, key, value) { (result[key] || (result[key] = [])).push(value); }); }; @@ -317,8 +330,8 @@ // Counts instances of an object that group by a certain criterion. Pass // either a string attribute to count by, or a function that returns the // criterion. - _.countBy = function(obj, val) { - return group(obj, val, function(result, key, value) { + _.countBy = function(obj, value, context) { + return group(obj, value, context, function(result, key, value) { result[key] || (result[key] = 0); result[key]++; }); @@ -958,6 +971,10 @@ // Return a random integer between min and max (inclusive). _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } return min + (0 | Math.random() * (max - min + 1)); }; @@ -1029,31 +1046,21 @@ // When customizing `templateSettings`, if you don't want to define an // interpolation, evaluation or escaping regex, we need one that is // guaranteed not to match. - var noMatch = /.^/; + var noMatch = /(.)^/; // Certain characters need to be escaped so that they can be put into a // string literal. var escapes = { - '\\': '\\', - "'": "'", - r: '\r', - n: '\n', - t: '\t', - u2028: '\u2028', - u2029: '\u2029' + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' }; - for (var key in escapes) escapes[escapes[key]] = key; var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; - var unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g; - - // Within an interpolation, evaluation, or escaping, remove HTML escaping - // that had been previously added. - var unescape = function(code) { - return code.replace(unescaper, function(match, escape) { - return escapes[escape]; - }); - }; // JavaScript micro-templating, similar to John Resig's implementation. // Underscore templating handles arbitrary delimiters, preserves whitespace, @@ -1061,22 +1068,26 @@ _.template = function(text, data, settings) { settings = _.defaults({}, settings, _.templateSettings); - // Compile the template source, taking care to escape characters that - // cannot be included in a string literal and then unescape them in code - // blocks. - var source = "__p+='" + text - .replace(escaper, function(match) { - return '\\' + escapes[match]; - }) - .replace(settings.escape || noMatch, function(match, code) { - return "'+\n((__t=(" + unescape(code) + "))==null?'':_.escape(__t))+\n'"; - }) - .replace(settings.interpolate || noMatch, function(match, code) { - return "'+\n((__t=(" + unescape(code) + "))==null?'':__t)+\n'"; - }) - .replace(settings.evaluate || noMatch, function(match, code) { - return "';\n" + unescape(code) + "\n__p+='"; - }) + "';\n"; + // Combine delimiters into one regular expression via alternation. + var matcher = new RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset) + .replace(escaper, function(match) { return '\\' + escapes[match]; }); + source += + escape ? "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" : + interpolate ? "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" : + evaluate ? "';\n" + evaluate + "\n__p+='" : ''; + index = offset + match.length; + }); + source += "';\n"; // If a variable is not specified, place data values in local scope. if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; @@ -1156,4 +1167,4 @@ }); -}).call(this); \ No newline at end of file +}).call(this);