Update JS libs.

This commit is contained in:
Lars Jung 2014-05-21 23:42:11 +02:00
parent d59379a0f1
commit e13c268e9d
9 changed files with 4238 additions and 5770 deletions

View file

@ -6,12 +6,18 @@
* replaces PHP backtick operator with `exec` * replaces PHP backtick operator with `exec`
* adds PHP variant to calc folder sizes * adds PHP variant to calc folder sizes
* updates jQuery to 2.1.1
* updates json2.js to 2014-02-04
* updates markdown-js to 0.5.0
* updates Modernizr to 2.8.2
* updates Moment.js to 2.6.0
* updates Underscore.js to 1.6.0
* language updates (`bg`, `ko`, `pt`, `sv`) * language updates (`bg`, `ko`, `pt`, `sv`)
## v0.24.1 - *2014-04-09* ## v0.24.1 - *2014-04-09*
* security fixes! (issues #268, #269) * security fixes! (issues [#268], [#269])
* language updates (`fi`, `fr`, `hi`, `it`, `zh-tw`) * language updates (`fi`, `fr`, `hi`, `it`, `zh-tw`)
* fixes WinOS command detection * fixes WinOS command detection

View file

@ -1,6 +1,6 @@
/* /*
json2.js json2.js
2013-05-26 2014-02-04
Public Domain. Public Domain.
@ -192,19 +192,11 @@ if (typeof JSON !== 'object') {
}; };
} }
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, var cx,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, escapable,
gap, gap,
indent, indent,
meta = { // table of character substitutions meta,
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
rep; rep;
@ -356,6 +348,16 @@ if (typeof JSON !== 'object') {
// If the JSON object does not yet have a stringify method, give it one. // If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') { if (typeof JSON.stringify !== 'function') {
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
};
JSON.stringify = function (value, replacer, space) { JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional // The stringify method takes a value and an optional replacer, and an optional
@ -403,6 +405,7 @@ if (typeof JSON !== 'object') {
// If the JSON object does not yet have a parse method, give it one. // If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== 'function') { if (typeof JSON.parse !== 'function') {
cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
JSON.parse = function (text, reviver) { JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns // The parse method takes a text and an optional reviver function, and returns

View file

@ -825,10 +825,12 @@ Markdown.dialects.Gruber.inline = {
"]": function () {}, "]": function () {},
"}": function () {}, "}": function () {},
__escape__ : /^\\[\\`\*_{}\[\]()#\+.!\-]/,
"\\": function escaped( text ) { "\\": function escaped( text ) {
// [ length of input processed, node/children to add... ] // [ length of input processed, node/children to add... ]
// Only esacape: \ ` * _ { } [ ] ( ) # * + - . ! // Only esacape: \ ` * _ { } [ ] ( ) # * + - . !
if ( text.match( /^\\[\\`\*_{}\[\]()#\+.!\-]/ ) ) if ( this.dialect.inline.__escape__.exec( text ) )
return [ 2, text.charAt( 1 ) ]; return [ 2, text.charAt( 1 ) ];
else else
// Not an esacpe // Not an esacpe
@ -1287,7 +1289,7 @@ Markdown.dialects.Maruku.block.definition_list = function definition_list( block
// one or more terms followed by one or more definitions, in a single block // one or more terms followed by one or more definitions, in a single block
var tight = /^((?:[^\s:].*\n)+):\s+([\s\S]+)$/, var tight = /^((?:[^\s:].*\n)+):\s+([\s\S]+)$/,
list = [ "dl" ], list = [ "dl" ],
i; i, m;
// see if we're dealing with a tight or loose block // see if we're dealing with a tight or loose block
if ( ( m = block.match( tight ) ) ) { if ( ( m = block.match( tight ) ) ) {
@ -1321,6 +1323,72 @@ Markdown.dialects.Maruku.block.definition_list = function definition_list( block
return [ list ]; return [ list ];
}; };
// splits on unescaped instances of @ch. If @ch is not a character the result
// can be unpredictable
Markdown.dialects.Maruku.block.table = function table (block, next) {
var _split_on_unescaped = function(s, ch) {
ch = ch || '\\s';
if (ch.match(/^[\\|\[\]{}?*.+^$]$/)) { ch = '\\' + ch; }
var res = [ ],
r = new RegExp('^((?:\\\\.|[^\\\\' + ch + '])*)' + ch + '(.*)'),
m;
while(m = s.match(r)) {
res.push(m[1]);
s = m[2];
}
res.push(s);
return res;
}
var leading_pipe = /^ {0,3}\|(.+)\n {0,3}\|\s*([\-:]+[\-| :]*)\n((?:\s*\|.*(?:\n|$))*)(?=\n|$)/,
// find at least an unescaped pipe in each line
no_leading_pipe = /^ {0,3}(\S(?:\\.|[^\\|])*\|.*)\n {0,3}([\-:]+\s*\|[\-| :]*)\n((?:(?:\\.|[^\\|])*\|.*(?:\n|$))*)(?=\n|$)/,
i, m;
if (m = block.match(leading_pipe)) {
// remove leading pipes in contents
// (header and horizontal rule already have the leading pipe left out)
m[3] = m[3].replace(/^\s*\|/gm, '');
} else if (! ( m = block.match(no_leading_pipe))) {
return undefined;
}
var table = [ "table", [ "thead", [ "tr" ] ], [ "tbody" ] ];
// remove trailing pipes, then split on pipes
// (no escaped pipes are allowed in horizontal rule)
m[2] = m[2].replace(/\|\s*$/, '').split('|');
// process alignment
var html_attrs = [ ];
forEach (m[2], function (s) {
if (s.match(/^\s*-+:\s*$/)) html_attrs.push({align: "right"});
else if (s.match(/^\s*:-+\s*$/)) html_attrs.push({align: "left"});
else if (s.match(/^\s*:-+:\s*$/)) html_attrs.push({align: "center"});
else html_attrs.push({});
});
// now for the header, avoid escaped pipes
m[1] = _split_on_unescaped(m[1].replace(/\|\s*$/, ''), '|');
for (i = 0; i < m[1].length; i++) {
table[1][1].push(['th', html_attrs[i] || {}].concat(
this.processInline(m[1][i].trim())));
}
// now for body contents
forEach (m[3].replace(/\|\s*$/mg, '').split('\n'), function (row) {
var html_row = ['tr'];
row = _split_on_unescaped(row, '|');
for (i = 0; i < row.length; i++) {
html_row.push(['td', html_attrs[i] || {}].concat(this.processInline(row[i].trim())));
}
table[2].push(html_row);
}, this);
return [table];
}
Markdown.dialects.Maruku.inline[ "{:" ] = function inline_meta( text, matches, out ) { Markdown.dialects.Maruku.inline[ "{:" ] = function inline_meta( text, matches, out ) {
if ( !out.length ) { if ( !out.length ) {
return [ 2, "{:" ]; return [ 2, "{:" ];
@ -1358,6 +1426,8 @@ Markdown.dialects.Maruku.inline[ "{:" ] = function inline_meta( text, matches, o
return [ m[ 0 ].length, "" ]; return [ m[ 0 ].length, "" ];
}; };
Markdown.dialects.Maruku.inline.__escape__ = /^\\[\\`\*_{}\[\]()#\+.!\-|:]/;
Markdown.buildBlockOrder ( Markdown.dialects.Maruku.block ); Markdown.buildBlockOrder ( Markdown.dialects.Maruku.block );
Markdown.buildInlinePatterns( Markdown.dialects.Maruku.inline ); Markdown.buildInlinePatterns( Markdown.dialects.Maruku.inline );
@ -1603,7 +1673,8 @@ function convert_tree_to_html( tree, references, options ) {
if ( attrs ) { if ( attrs ) {
// if there are keys, skip over it // if there are keys, skip over it
for ( var key in jsonml[ 1 ] ) { for ( var key in jsonml[ 1 ] ) {
i = 2; i = 2;
break;
} }
// if there aren't, remove it // if there aren't, remove it
if ( i === 1 ) { if ( i === 1 ) {

View file

@ -1,418 +0,0 @@
/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
* Build: http://modernizr.com/download/#-opacity-rgba-canvas-history-audio-video-localstorage-shiv-cssclasses-prefixes
*/
;
window.Modernizr = (function( window, document, undefined ) {
var version = '2.6.2',
Modernizr = {},
enableClasses = true,
docElement = document.documentElement,
mod = 'modernizr',
modElem = document.createElement(mod),
mStyle = modElem.style,
inputElem ,
toString = {}.toString,
prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),
tests = {},
inputs = {},
attrs = {},
classes = [],
slice = classes.slice,
featureName,
_hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {
hasOwnProp = function (object, property) {
return _hasOwnProperty.call(object, property);
};
}
else {
hasOwnProp = function (object, property) {
return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
};
}
if (!Function.prototype.bind) {
Function.prototype.bind = function bind(that) {
var target = this;
if (typeof target != "function") {
throw new TypeError();
}
var args = slice.call(arguments, 1),
bound = function () {
if (this instanceof bound) {
var F = function(){};
F.prototype = target.prototype;
var self = new F();
var result = target.apply(
self,
args.concat(slice.call(arguments))
);
if (Object(result) === result) {
return result;
}
return self;
} else {
return target.apply(
that,
args.concat(slice.call(arguments))
);
}
};
return bound;
};
}
function setCss( str ) {
mStyle.cssText = str;
}
function setCssAll( str1, str2 ) {
return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
}
function is( obj, type ) {
return typeof obj === type;
}
function contains( str, substr ) {
return !!~('' + str).indexOf(substr);
}
function testDOMProps( props, obj, elem ) {
for ( var i in props ) {
var item = obj[props[i]];
if ( item !== undefined) {
if (elem === false) return props[i];
if (is(item, 'function')){
return item.bind(elem || obj);
}
return item;
}
}
return false;
} tests['canvas'] = function() {
var elem = document.createElement('canvas');
return !!(elem.getContext && elem.getContext('2d'));
};
tests['history'] = function() {
return !!(window.history && history.pushState);
}; tests['rgba'] = function() {
setCss('background-color:rgba(150,255,150,.5)');
return contains(mStyle.backgroundColor, 'rgba');
}; tests['opacity'] = function() {
setCssAll('opacity:.55');
return (/^0.55$/).test(mStyle.opacity);
};
tests['video'] = function() {
var elem = document.createElement('video'),
bool = false;
try {
if ( bool = !!elem.canPlayType ) {
bool = new Boolean(bool);
bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,'');
bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,'');
bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,'');
}
} catch(e) { }
return bool;
};
tests['audio'] = function() {
var elem = document.createElement('audio'),
bool = false;
try {
if ( bool = !!elem.canPlayType ) {
bool = new Boolean(bool);
bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,'');
bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,'');
bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,'');
bool.m4a = ( elem.canPlayType('audio/x-m4a;') ||
elem.canPlayType('audio/aac;')) .replace(/^no$/,'');
}
} catch(e) { }
return bool;
};
tests['localstorage'] = function() {
try {
localStorage.setItem(mod, mod);
localStorage.removeItem(mod);
return true;
} catch(e) {
return false;
}
};
for ( var feature in tests ) {
if ( hasOwnProp(tests, feature) ) {
featureName = feature.toLowerCase();
Modernizr[featureName] = tests[feature]();
classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
}
}
Modernizr.addTest = function ( feature, test ) {
if ( typeof feature == 'object' ) {
for ( var key in feature ) {
if ( hasOwnProp( feature, key ) ) {
Modernizr.addTest( key, feature[ key ] );
}
}
} else {
feature = feature.toLowerCase();
if ( Modernizr[feature] !== undefined ) {
return Modernizr;
}
test = typeof test == 'function' ? test() : test;
if (typeof enableClasses !== "undefined" && enableClasses) {
docElement.className += ' ' + (test ? '' : 'no-') + feature;
}
Modernizr[feature] = test;
}
return Modernizr;
};
setCss('');
modElem = inputElem = null;
;(function(window, document) {
var options = window.html5 || {};
var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
var supportsHtml5Styles;
var expando = '_html5shiv';
var expanID = 0;
var expandoData = {};
var supportsUnknownElements;
(function() {
try {
var a = document.createElement('a');
a.innerHTML = '<xyz></xyz>';
supportsHtml5Styles = ('hidden' in a);
supportsUnknownElements = a.childNodes.length == 1 || (function() {
(document.createElement)('a');
var frag = document.createDocumentFragment();
return (
typeof frag.cloneNode == 'undefined' ||
typeof frag.createDocumentFragment == 'undefined' ||
typeof frag.createElement == 'undefined'
);
}());
} catch(e) {
supportsHtml5Styles = true;
supportsUnknownElements = true;
}
}()); function addStyleSheet(ownerDocument, cssText) {
var p = ownerDocument.createElement('p'),
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
p.innerHTML = 'x<style>' + cssText + '</style>';
return parent.insertBefore(p.lastChild, parent.firstChild);
}
function getElements() {
var elements = html5.elements;
return typeof elements == 'string' ? elements.split(' ') : elements;
}
function getExpandoData(ownerDocument) {
var data = expandoData[ownerDocument[expando]];
if (!data) {
data = {};
expanID++;
ownerDocument[expando] = expanID;
expandoData[expanID] = data;
}
return data;
}
function createElement(nodeName, ownerDocument, data){
if (!ownerDocument) {
ownerDocument = document;
}
if(supportsUnknownElements){
return ownerDocument.createElement(nodeName);
}
if (!data) {
data = getExpandoData(ownerDocument);
}
var node;
if (data.cache[nodeName]) {
node = data.cache[nodeName].cloneNode();
} else if (saveClones.test(nodeName)) {
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
} else {
node = data.createElem(nodeName);
}
return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node;
}
function createDocumentFragment(ownerDocument, data){
if (!ownerDocument) {
ownerDocument = document;
}
if(supportsUnknownElements){
return ownerDocument.createDocumentFragment();
}
data = data || getExpandoData(ownerDocument);
var clone = data.frag.cloneNode(),
i = 0,
elems = getElements(),
l = elems.length;
for(;i<l;i++){
clone.createElement(elems[i]);
}
return clone;
}
function shivMethods(ownerDocument, data) {
if (!data.cache) {
data.cache = {};
data.createElem = ownerDocument.createElement;
data.createFrag = ownerDocument.createDocumentFragment;
data.frag = data.createFrag();
}
ownerDocument.createElement = function(nodeName) {
if (!html5.shivMethods) {
return data.createElem(nodeName);
}
return createElement(nodeName, ownerDocument, data);
};
ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
'var n=f.cloneNode(),c=n.createElement;' +
'h.shivMethods&&(' +
getElements().join().replace(/\w+/g, function(nodeName) {
data.createElem(nodeName);
data.frag.createElement(nodeName);
return 'c("' + nodeName + '")';
}) +
');return n}'
)(html5, data.frag);
} function shivDocument(ownerDocument) {
if (!ownerDocument) {
ownerDocument = document;
}
var data = getExpandoData(ownerDocument);
if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
data.hasCSS = !!addStyleSheet(ownerDocument,
'article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}' +
'mark{background:#FF0;color:#000}'
);
}
if (!supportsUnknownElements) {
shivMethods(ownerDocument, data);
}
return ownerDocument;
} var html5 = {
'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video',
'shivCSS': (options.shivCSS !== false),
'supportsUnknownElements': supportsUnknownElements,
'shivMethods': (options.shivMethods !== false),
'type': 'default',
'shivDocument': shivDocument,
createElement: createElement,
createDocumentFragment: createDocumentFragment
}; window.html5 = html5;
shivDocument(document);
}(this, document));
Modernizr._version = version;
Modernizr._prefixes = prefixes;
docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') +
(enableClasses ? ' js ' + classes.join(' ') : '');
return Modernizr;
})(this, this.document);
;

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
// Underscore.js 1.5.1 // Underscore.js 1.6.0
// http://underscorejs.org // http://underscorejs.org
// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors // (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license. // Underscore may be freely distributed under the MIT license.
(function() { (function() {
@ -8,7 +8,7 @@
// Baseline setup // Baseline setup
// -------------- // --------------
// Establish the root object, `window` in the browser, or `global` on the server. // Establish the root object, `window` in the browser, or `exports` on the server.
var root = this; var root = this;
// Save the previous value of the `_` variable. // Save the previous value of the `_` variable.
@ -65,7 +65,7 @@
} }
// Current version. // Current version.
_.VERSION = '1.5.1'; _.VERSION = '1.6.0';
// Collection Functions // Collection Functions
// -------------------- // --------------------
@ -74,20 +74,20 @@
// Handles objects with the built-in `forEach`, arrays, and raw objects. // Handles objects with the built-in `forEach`, arrays, and raw objects.
// Delegates to **ECMAScript 5**'s native `forEach` if available. // Delegates to **ECMAScript 5**'s native `forEach` if available.
var each = _.each = _.forEach = function(obj, iterator, context) { var each = _.each = _.forEach = function(obj, iterator, context) {
if (obj == null) return; if (obj == null) return obj;
if (nativeForEach && obj.forEach === nativeForEach) { if (nativeForEach && obj.forEach === nativeForEach) {
obj.forEach(iterator, context); obj.forEach(iterator, context);
} else if (obj.length === +obj.length) { } else if (obj.length === +obj.length) {
for (var i = 0, l = obj.length; i < l; i++) { for (var i = 0, length = obj.length; i < length; i++) {
if (iterator.call(context, obj[i], i, obj) === breaker) return; if (iterator.call(context, obj[i], i, obj) === breaker) return;
} }
} else { } else {
for (var key in obj) { var keys = _.keys(obj);
if (_.has(obj, key)) { for (var i = 0, length = keys.length; i < length; i++) {
if (iterator.call(context, obj[key], key, obj) === breaker) return; if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
}
} }
} }
return obj;
}; };
// Return the results of applying the iterator to each element. // Return the results of applying the iterator to each element.
@ -153,10 +153,10 @@
}; };
// Return the first value which passes a truth test. Aliased as `detect`. // Return the first value which passes a truth test. Aliased as `detect`.
_.find = _.detect = function(obj, iterator, context) { _.find = _.detect = function(obj, predicate, context) {
var result; var result;
any(obj, function(value, index, list) { any(obj, function(value, index, list) {
if (iterator.call(context, value, index, list)) { if (predicate.call(context, value, index, list)) {
result = value; result = value;
return true; return true;
} }
@ -167,33 +167,33 @@
// Return all the elements that pass a truth test. // Return all the elements that pass a truth test.
// Delegates to **ECMAScript 5**'s native `filter` if available. // Delegates to **ECMAScript 5**'s native `filter` if available.
// Aliased as `select`. // Aliased as `select`.
_.filter = _.select = function(obj, iterator, context) { _.filter = _.select = function(obj, predicate, context) {
var results = []; var results = [];
if (obj == null) return results; if (obj == null) return results;
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context);
each(obj, function(value, index, list) { each(obj, function(value, index, list) {
if (iterator.call(context, value, index, list)) results.push(value); if (predicate.call(context, value, index, list)) results.push(value);
}); });
return results; return results;
}; };
// Return all the elements for which a truth test fails. // Return all the elements for which a truth test fails.
_.reject = function(obj, iterator, context) { _.reject = function(obj, predicate, context) {
return _.filter(obj, function(value, index, list) { return _.filter(obj, function(value, index, list) {
return !iterator.call(context, value, index, list); return !predicate.call(context, value, index, list);
}, context); }, context);
}; };
// Determine whether all of the elements match a truth test. // Determine whether all of the elements match a truth test.
// Delegates to **ECMAScript 5**'s native `every` if available. // Delegates to **ECMAScript 5**'s native `every` if available.
// Aliased as `all`. // Aliased as `all`.
_.every = _.all = function(obj, iterator, context) { _.every = _.all = function(obj, predicate, context) {
iterator || (iterator = _.identity); predicate || (predicate = _.identity);
var result = true; var result = true;
if (obj == null) return result; if (obj == null) return result;
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context);
each(obj, function(value, index, list) { each(obj, function(value, index, list) {
if (!(result = result && iterator.call(context, value, index, list))) return breaker; if (!(result = result && predicate.call(context, value, index, list))) return breaker;
}); });
return !!result; return !!result;
}; };
@ -201,13 +201,13 @@
// Determine if at least one element in the object matches a truth test. // Determine if at least one element in the object matches a truth test.
// Delegates to **ECMAScript 5**'s native `some` if available. // Delegates to **ECMAScript 5**'s native `some` if available.
// Aliased as `any`. // Aliased as `any`.
var any = _.some = _.any = function(obj, iterator, context) { var any = _.some = _.any = function(obj, predicate, context) {
iterator || (iterator = _.identity); predicate || (predicate = _.identity);
var result = false; var result = false;
if (obj == null) return result; if (obj == null) return result;
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context);
each(obj, function(value, index, list) { each(obj, function(value, index, list) {
if (result || (result = iterator.call(context, value, index, list))) return breaker; if (result || (result = predicate.call(context, value, index, list))) return breaker;
}); });
return !!result; return !!result;
}; };
@ -233,25 +233,19 @@
// Convenience version of a common use case of `map`: fetching a property. // Convenience version of a common use case of `map`: fetching a property.
_.pluck = function(obj, key) { _.pluck = function(obj, key) {
return _.map(obj, function(value){ return value[key]; }); return _.map(obj, _.property(key));
}; };
// Convenience version of a common use case of `filter`: selecting only objects // Convenience version of a common use case of `filter`: selecting only objects
// containing specific `key:value` pairs. // containing specific `key:value` pairs.
_.where = function(obj, attrs, first) { _.where = function(obj, attrs) {
if (_.isEmpty(attrs)) return first ? void 0 : []; return _.filter(obj, _.matches(attrs));
return _[first ? 'find' : 'filter'](obj, function(value) {
for (var key in attrs) {
if (attrs[key] !== value[key]) return false;
}
return true;
});
}; };
// Convenience version of a common use case of `find`: getting the first object // Convenience version of a common use case of `find`: getting the first object
// containing specific `key:value` pairs. // containing specific `key:value` pairs.
_.findWhere = function(obj, attrs) { _.findWhere = function(obj, attrs) {
return _.where(obj, attrs, true); return _.find(obj, _.matches(attrs));
}; };
// Return the maximum element or (element-based computation). // Return the maximum element or (element-based computation).
@ -261,13 +255,15 @@
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
return Math.max.apply(Math, obj); return Math.max.apply(Math, obj);
} }
if (!iterator && _.isEmpty(obj)) return -Infinity; var result = -Infinity, lastComputed = -Infinity;
var result = {computed : -Infinity, value: -Infinity};
each(obj, function(value, index, list) { each(obj, function(value, index, list) {
var computed = iterator ? iterator.call(context, value, index, list) : value; var computed = iterator ? iterator.call(context, value, index, list) : value;
computed > result.computed && (result = {value : value, computed : computed}); if (computed > lastComputed) {
result = value;
lastComputed = computed;
}
}); });
return result.value; return result;
}; };
// Return the minimum element (or element-based computation). // Return the minimum element (or element-based computation).
@ -275,16 +271,19 @@
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
return Math.min.apply(Math, obj); return Math.min.apply(Math, obj);
} }
if (!iterator && _.isEmpty(obj)) return Infinity; var result = Infinity, lastComputed = Infinity;
var result = {computed : Infinity, value: Infinity};
each(obj, function(value, index, list) { each(obj, function(value, index, list) {
var computed = iterator ? iterator.call(context, value, index, list) : value; var computed = iterator ? iterator.call(context, value, index, list) : value;
computed < result.computed && (result = {value : value, computed : computed}); if (computed < lastComputed) {
result = value;
lastComputed = computed;
}
}); });
return result.value; return result;
}; };
// Shuffle an array. // Shuffle an array, using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/FisherYates_shuffle).
_.shuffle = function(obj) { _.shuffle = function(obj) {
var rand; var rand;
var index = 0; var index = 0;
@ -297,19 +296,32 @@
return shuffled; return shuffled;
}; };
// Sample **n** random values from a collection.
// If **n** is not specified, returns a single random element.
// The internal `guard` argument allows it to work with `map`.
_.sample = function(obj, n, guard) {
if (n == null || guard) {
if (obj.length !== +obj.length) obj = _.values(obj);
return obj[_.random(obj.length - 1)];
}
return _.shuffle(obj).slice(0, Math.max(0, n));
};
// An internal function to generate lookup iterators. // An internal function to generate lookup iterators.
var lookupIterator = function(value) { var lookupIterator = function(value) {
return _.isFunction(value) ? value : function(obj){ return obj[value]; }; if (value == null) return _.identity;
if (_.isFunction(value)) return value;
return _.property(value);
}; };
// Sort the object's values by a criterion produced by an iterator. // Sort the object's values by a criterion produced by an iterator.
_.sortBy = function(obj, value, context) { _.sortBy = function(obj, iterator, context) {
var iterator = lookupIterator(value); iterator = lookupIterator(iterator);
return _.pluck(_.map(obj, function(value, index, list) { return _.pluck(_.map(obj, function(value, index, list) {
return { return {
value : value, value: value,
index : index, index: index,
criteria : iterator.call(context, value, index, list) criteria: iterator.call(context, value, index, list)
}; };
}).sort(function(left, right) { }).sort(function(left, right) {
var a = left.criteria; var a = left.criteria;
@ -318,43 +330,46 @@
if (a > b || a === void 0) return 1; if (a > b || a === void 0) return 1;
if (a < b || b === void 0) return -1; if (a < b || b === void 0) return -1;
} }
return left.index < right.index ? -1 : 1; return left.index - right.index;
}), 'value'); }), 'value');
}; };
// An internal function used for aggregate "group by" operations. // An internal function used for aggregate "group by" operations.
var group = function(obj, value, context, behavior) { var group = function(behavior) {
var result = {}; return function(obj, iterator, context) {
var iterator = lookupIterator(value == null ? _.identity : value); var result = {};
each(obj, function(value, index) { iterator = lookupIterator(iterator);
var key = iterator.call(context, value, index, obj); each(obj, function(value, index) {
behavior(result, key, value); var key = iterator.call(context, value, index, obj);
}); behavior(result, key, value);
return result; });
return result;
};
}; };
// Groups the object's values by a criterion. Pass either a string attribute // Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion. // to group by, or a function that returns the criterion.
_.groupBy = function(obj, value, context) { _.groupBy = group(function(result, key, value) {
return group(obj, value, context, function(result, key, value) { _.has(result, key) ? result[key].push(value) : result[key] = [value];
(_.has(result, key) ? result[key] : (result[key] = [])).push(value); });
});
}; // Indexes the object's values by a criterion, similar to `groupBy`, but for
// when you know that your index values will be unique.
_.indexBy = group(function(result, key, value) {
result[key] = value;
});
// Counts instances of an object that group by a certain criterion. Pass // 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 // either a string attribute to count by, or a function that returns the
// criterion. // criterion.
_.countBy = function(obj, value, context) { _.countBy = group(function(result, key) {
return group(obj, value, context, function(result, key) { _.has(result, key) ? result[key]++ : result[key] = 1;
if (!_.has(result, key)) result[key] = 0; });
result[key]++;
});
};
// Use a comparator function to figure out the smallest index at which // Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search. // an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iterator, context) { _.sortedIndex = function(array, obj, iterator, context) {
iterator = iterator == null ? _.identity : lookupIterator(iterator); iterator = lookupIterator(iterator);
var value = iterator.call(context, obj); var value = iterator.call(context, obj);
var low = 0, high = array.length; var low = 0, high = array.length;
while (low < high) { while (low < high) {
@ -386,7 +401,9 @@
// allows it to work with `_.map`. // allows it to work with `_.map`.
_.first = _.head = _.take = function(array, n, guard) { _.first = _.head = _.take = function(array, n, guard) {
if (array == null) return void 0; if (array == null) return void 0;
return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; if ((n == null) || guard) return array[0];
if (n < 0) return [];
return slice.call(array, 0, n);
}; };
// Returns everything but the last entry of the array. Especially useful on // Returns everything but the last entry of the array. Especially useful on
@ -401,11 +418,8 @@
// values in the array. The **guard** check allows it to work with `_.map`. // values in the array. The **guard** check allows it to work with `_.map`.
_.last = function(array, n, guard) { _.last = function(array, n, guard) {
if (array == null) return void 0; if (array == null) return void 0;
if ((n != null) && !guard) { if ((n == null) || guard) return array[array.length - 1];
return slice.call(array, Math.max(array.length - n, 0)); return slice.call(array, Math.max(array.length - n, 0));
} else {
return array[array.length - 1];
}
}; };
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`. // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
@ -436,7 +450,7 @@
return output; return output;
}; };
// Return a completely flattened version of an array. // Flatten out an array, either recursively (by default), or just one level.
_.flatten = function(array, shallow) { _.flatten = function(array, shallow) {
return flatten(array, shallow, []); return flatten(array, shallow, []);
}; };
@ -446,6 +460,16 @@
return _.difference(array, slice.call(arguments, 1)); return _.difference(array, slice.call(arguments, 1));
}; };
// Split an array into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_.partition = function(array, predicate) {
var pass = [], fail = [];
each(array, function(elem) {
(predicate(elem) ? pass : fail).push(elem);
});
return [pass, fail];
};
// Produce a duplicate-free version of the array. If the array has already // Produce a duplicate-free version of the array. If the array has already
// been sorted, you have the option of using a faster algorithm. // been sorted, you have the option of using a faster algorithm.
// Aliased as `unique`. // Aliased as `unique`.
@ -479,7 +503,7 @@
var rest = slice.call(arguments, 1); var rest = slice.call(arguments, 1);
return _.filter(_.uniq(array), function(item) { return _.filter(_.uniq(array), function(item) {
return _.every(rest, function(other) { return _.every(rest, function(other) {
return _.indexOf(other, item) >= 0; return _.contains(other, item);
}); });
}); });
}; };
@ -494,7 +518,7 @@
// Zip together multiple lists into a single array -- elements that share // Zip together multiple lists into a single array -- elements that share
// an index go together. // an index go together.
_.zip = function() { _.zip = function() {
var length = _.max(_.pluck(arguments, "length").concat(0)); var length = _.max(_.pluck(arguments, 'length').concat(0));
var results = new Array(length); var results = new Array(length);
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
results[i] = _.pluck(arguments, '' + i); results[i] = _.pluck(arguments, '' + i);
@ -508,7 +532,7 @@
_.object = function(list, values) { _.object = function(list, values) {
if (list == null) return {}; if (list == null) return {};
var result = {}; var result = {};
for (var i = 0, l = list.length; i < l; i++) { for (var i = 0, length = list.length; i < length; i++) {
if (values) { if (values) {
result[list[i]] = values[i]; result[list[i]] = values[i];
} else { } else {
@ -526,17 +550,17 @@
// for **isSorted** to use binary search. // for **isSorted** to use binary search.
_.indexOf = function(array, item, isSorted) { _.indexOf = function(array, item, isSorted) {
if (array == null) return -1; if (array == null) return -1;
var i = 0, l = array.length; var i = 0, length = array.length;
if (isSorted) { if (isSorted) {
if (typeof isSorted == 'number') { if (typeof isSorted == 'number') {
i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted); i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted);
} else { } else {
i = _.sortedIndex(array, item); i = _.sortedIndex(array, item);
return array[i] === item ? i : -1; return array[i] === item ? i : -1;
} }
} }
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
for (; i < l; i++) if (array[i] === item) return i; for (; i < length; i++) if (array[i] === item) return i;
return -1; return -1;
}; };
@ -562,11 +586,11 @@
} }
step = arguments[2] || 1; step = arguments[2] || 1;
var len = Math.max(Math.ceil((stop - start) / step), 0); var length = Math.max(Math.ceil((stop - start) / step), 0);
var idx = 0; var idx = 0;
var range = new Array(len); var range = new Array(length);
while(idx < len) { while(idx < length) {
range[idx++] = start; range[idx++] = start;
start += step; start += step;
} }
@ -600,19 +624,27 @@
}; };
// Partially apply a function by creating a version that has had some of its // Partially apply a function by creating a version that has had some of its
// arguments pre-filled, without changing its dynamic `this` context. // arguments pre-filled, without changing its dynamic `this` context. _ acts
// as a placeholder, allowing any combination of arguments to be pre-filled.
_.partial = function(func) { _.partial = function(func) {
var args = slice.call(arguments, 1); var boundArgs = slice.call(arguments, 1);
return function() { return function() {
return func.apply(this, args.concat(slice.call(arguments))); var position = 0;
var args = boundArgs.slice();
for (var i = 0, length = args.length; i < length; i++) {
if (args[i] === _) args[i] = arguments[position++];
}
while (position < arguments.length) args.push(arguments[position++]);
return func.apply(this, args);
}; };
}; };
// Bind all of an object's methods to that object. Useful for ensuring that // Bind a number of an object's methods to that object. Remaining arguments
// all callbacks defined on an object belong to it. // are the method names to be bound. Useful for ensuring that all callbacks
// defined on an object belong to it.
_.bindAll = function(obj) { _.bindAll = function(obj) {
var funcs = slice.call(arguments, 1); var funcs = slice.call(arguments, 1);
if (funcs.length === 0) throw new Error("bindAll must be passed function names"); if (funcs.length === 0) throw new Error('bindAll must be passed function names');
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
return obj; return obj;
}; };
@ -651,12 +683,13 @@
var previous = 0; var previous = 0;
options || (options = {}); options || (options = {});
var later = function() { var later = function() {
previous = options.leading === false ? 0 : new Date; previous = options.leading === false ? 0 : _.now();
timeout = null; timeout = null;
result = func.apply(context, args); result = func.apply(context, args);
context = args = null;
}; };
return function() { return function() {
var now = new Date; var now = _.now();
if (!previous && options.leading === false) previous = now; if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous); var remaining = wait - (now - previous);
context = this; context = this;
@ -666,6 +699,7 @@
timeout = null; timeout = null;
previous = now; previous = now;
result = func.apply(context, args); result = func.apply(context, args);
context = args = null;
} else if (!timeout && options.trailing !== false) { } else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining); timeout = setTimeout(later, remaining);
} }
@ -678,18 +712,34 @@
// N milliseconds. If `immediate` is passed, trigger the function on the // N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing. // leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) { _.debounce = function(func, wait, immediate) {
var result; var timeout, args, context, timestamp, result;
var timeout = null;
return function() { var later = function() {
var context = this, args = arguments; var last = _.now() - timestamp;
var later = function() { if (last < wait) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null; timeout = null;
if (!immediate) result = func.apply(context, args); if (!immediate) {
}; result = func.apply(context, args);
context = args = null;
}
}
};
return function() {
context = this;
args = arguments;
timestamp = _.now();
var callNow = immediate && !timeout; var callNow = immediate && !timeout;
clearTimeout(timeout); if (!timeout) {
timeout = setTimeout(later, wait); timeout = setTimeout(later, wait);
if (callNow) result = func.apply(context, args); }
if (callNow) {
result = func.apply(context, args);
context = args = null;
}
return result; return result;
}; };
}; };
@ -711,11 +761,7 @@
// allowing you to adjust arguments, run code before and after, and // allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function. // conditionally execute the original function.
_.wrap = function(func, wrapper) { _.wrap = function(func, wrapper) {
return function() { return _.partial(wrapper, func);
var args = [func];
push.apply(args, arguments);
return wrapper.apply(this, args);
};
}; };
// Returns a function that is the composition of a list of functions, each // Returns a function that is the composition of a list of functions, each
@ -745,8 +791,9 @@
// Retrieve the names of an object's properties. // Retrieve the names of an object's properties.
// Delegates to **ECMAScript 5**'s native `Object.keys` // Delegates to **ECMAScript 5**'s native `Object.keys`
_.keys = nativeKeys || function(obj) { _.keys = function(obj) {
if (obj !== Object(obj)) throw new TypeError('Invalid object'); if (!_.isObject(obj)) return [];
if (nativeKeys) return nativeKeys(obj);
var keys = []; var keys = [];
for (var key in obj) if (_.has(obj, key)) keys.push(key); for (var key in obj) if (_.has(obj, key)) keys.push(key);
return keys; return keys;
@ -754,22 +801,33 @@
// Retrieve the values of an object's properties. // Retrieve the values of an object's properties.
_.values = function(obj) { _.values = function(obj) {
var values = []; var keys = _.keys(obj);
for (var key in obj) if (_.has(obj, key)) values.push(obj[key]); var length = keys.length;
var values = new Array(length);
for (var i = 0; i < length; i++) {
values[i] = obj[keys[i]];
}
return values; return values;
}; };
// Convert an object into a list of `[key, value]` pairs. // Convert an object into a list of `[key, value]` pairs.
_.pairs = function(obj) { _.pairs = function(obj) {
var pairs = []; var keys = _.keys(obj);
for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]); var length = keys.length;
var pairs = new Array(length);
for (var i = 0; i < length; i++) {
pairs[i] = [keys[i], obj[keys[i]]];
}
return pairs; return pairs;
}; };
// Invert the keys and values of an object. The values must be serializable. // Invert the keys and values of an object. The values must be serializable.
_.invert = function(obj) { _.invert = function(obj) {
var result = {}; var result = {};
for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key; var keys = _.keys(obj);
for (var i = 0, length = keys.length; i < length; i++) {
result[obj[keys[i]]] = keys[i];
}
return result; return result;
}; };
@ -890,7 +948,8 @@
// from different frames are. // from different frames are.
var aCtor = a.constructor, bCtor = b.constructor; var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
_.isFunction(bCtor) && (bCtor instanceof bCtor))) { _.isFunction(bCtor) && (bCtor instanceof bCtor))
&& ('constructor' in a && 'constructor' in b)) {
return false; return false;
} }
// Add the first object to the stack of traversed objects. // Add the first object to the stack of traversed objects.
@ -1030,6 +1089,30 @@
return value; return value;
}; };
_.constant = function(value) {
return function () {
return value;
};
};
_.property = function(key) {
return function(obj) {
return obj[key];
};
};
// Returns a predicate for checking whether an object has a given set of `key:value` pairs.
_.matches = function(attrs) {
return function(obj) {
if (obj === attrs) return true; //avoid comparing an object to itself.
for (var key in attrs) {
if (attrs[key] !== obj[key])
return false;
}
return true;
}
};
// Run a function **n** times. // Run a function **n** times.
_.times = function(n, iterator, context) { _.times = function(n, iterator, context) {
var accum = Array(Math.max(0, n)); var accum = Array(Math.max(0, n));
@ -1046,6 +1129,9 @@
return min + Math.floor(Math.random() * (max - min + 1)); return min + Math.floor(Math.random() * (max - min + 1));
}; };
// A (possibly faster) way to get the current timestamp as an integer.
_.now = Date.now || function() { return new Date().getTime(); };
// List of HTML entities for escaping. // List of HTML entities for escaping.
var entityMap = { var entityMap = {
escape: { escape: {
@ -1053,8 +1139,7 @@
'<': '&lt;', '<': '&lt;',
'>': '&gt;', '>': '&gt;',
'"': '&quot;', '"': '&quot;',
"'": '&#x27;', "'": '&#x27;'
'/': '&#x2F;'
} }
}; };
entityMap.unescape = _.invert(entityMap.escape); entityMap.unescape = _.invert(entityMap.escape);
@ -1085,7 +1170,7 @@
// Add your own custom functions to the Underscore object. // Add your own custom functions to the Underscore object.
_.mixin = function(obj) { _.mixin = function(obj) {
each(_.functions(obj), function(name){ each(_.functions(obj), function(name) {
var func = _[name] = obj[name]; var func = _[name] = obj[name];
_.prototype[name] = function() { _.prototype[name] = function() {
var args = [this._wrapped]; var args = [this._wrapped];
@ -1243,4 +1328,16 @@
}); });
// AMD registration happens at the end for compatibility with AMD loaders
// that may not enforce next-turn semantics on modules. Even though general
// practice for AMD registration is to be anonymous, underscore registers
// as a named module because, like jQuery, it is a base library that is
// popular enough to be bundled in a third party lib, but not be part of
// an AMD load request. Those cases could generate an error when an
// anonymous define() is called outside of a loader request.
if (typeof define === 'function' && define.amd) {
define('underscore', [], function() {
return _;
});
}
}).call(this); }).call(this);