})(this);
d3 = (function(){
- var d3 = {version: "3.3.8"}; // semver
+ var d3 = {version: "3.3.10"}; // semver
d3.ascending = function(a, b) {
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
};
subgroups.push(subgroup = []);
subgroup.parentNode = (group = this[j]).parentNode;
for (var i = 0, n = group.length; i < n; i++) {
- if ((node = group[i]) && filter.call(node, node.__data__, i)) {
+ if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
subgroup.push(node);
}
}
};
}
-var d3_event_dragSelect = d3_vendorSymbol(d3_documentElement.style, "userSelect"),
+var d3_event_dragSelect = "onselectstart" in d3_document ? null : d3_vendorSymbol(d3_documentElement.style, "userSelect"),
d3_event_dragId = 0;
function d3_event_dragSuppress() {
var name = ".dragsuppress-" + ++d3_event_dragId,
- touchmove = "touchmove" + name,
- selectstart = "selectstart" + name,
- dragstart = "dragstart" + name,
click = "click" + name,
- w = d3.select(d3_window).on(touchmove, d3_eventPreventDefault).on(selectstart, d3_eventPreventDefault).on(dragstart, d3_eventPreventDefault),
- style = d3_documentElement.style,
- select = style[d3_event_dragSelect];
- style[d3_event_dragSelect] = "none";
+ w = d3.select(d3_window)
+ .on("touchmove" + name, d3_eventPreventDefault)
+ .on("dragstart" + name, d3_eventPreventDefault)
+ .on("selectstart" + name, d3_eventPreventDefault);
+ if (d3_event_dragSelect) {
+ var style = d3_documentElement.style,
+ select = style[d3_event_dragSelect];
+ style[d3_event_dragSelect] = "none";
+ }
return function(suppressClick) {
w.on(name, null);
- style[d3_event_dragSelect] = select;
+ if (d3_event_dragSelect) style[d3_event_dragSelect] = select;
if (suppressClick) { // suppress the next click, but only if it’s immediate
function off() { w.on(click, null); }
w.on(click, function() { d3_eventCancel(); off(); }, true);
listener.lineEnd();
listener.lineStart();
listener.point(sλ1, φ0);
- listener.point( λ1, φ0);
+ listener.point(λ1, φ0);
clean = 0;
} else if (sλ0 !== sλ1 && dλ >= π) { // line crosses antimeridian
// handle degeneracies
maxDepth = 16;
function resample(stream) {
+ return (maxDepth ? resampleRecursive : resampleNone)(stream);
+ }
+
+ function resampleNone(stream) {
+ return d3_geo_transformPoint(stream, function(x, y) {
+ x = project(x, y);
+ stream.point(x[0], x[1]);
+ });
+ }
+
+ function resampleRecursive(stream) {
var λ00, φ00, x00, y00, a00, b00, c00, // first point
λ0, x0, y0, a0, b0, c0; // previous point
c = c0 + c1,
m = Math.sqrt(a * a + b * b + c * c),
φ2 = Math.asin(c /= m),
- λ2 = abs(abs(c) - 1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a),
+ λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a),
p = project(λ2, φ2),
x2 = p[0],
y2 = p[1],
return resample;
}
-d3.geo.transform = function(methods) {
- return {
- stream: function(stream) {
- var transform = new d3_geo_transform(stream);
- for (var k in methods) transform[k] = methods[k];
- return transform;
- }
- };
-};
-
-function d3_geo_transform(stream) {
- this.stream = stream;
-}
-
-d3_geo_transform.prototype = {
- point: function(x, y) { this.stream.point(x, y); },
- sphere: function() { this.stream.sphere(); },
- lineStart: function() { this.stream.lineStart(); },
- lineEnd: function() { this.stream.lineEnd(); },
- polygonStart: function() { this.stream.polygonStart(); },
- polygonEnd: function() { this.stream.polygonEnd(); }
-};
-
d3.geo.path = function() {
var pointRadius = 4.5,
projection,
function d3_geo_pathProjectStream(project) {
var resample = d3_geo_resample(function(x, y) { return project([x * d3_degrees, y * d3_degrees]); });
- return function(stream) {
- var transform = new d3_geo_transform(stream = resample(stream));
- transform.point = function(x, y) { stream.point(x * d3_radians, y * d3_radians); };
- return transform;
+ return function(stream) { return d3_geo_projectionRadians(resample(stream)); };
+}
+
+d3.geo.transform = function(methods) {
+ return {
+ stream: function(stream) {
+ var transform = new d3_geo_transform(stream);
+ for (var k in methods) transform[k] = methods[k];
+ return transform;
+ }
+ };
+};
+
+function d3_geo_transform(stream) {
+ this.stream = stream;
+}
+
+d3_geo_transform.prototype = {
+ point: function(x, y) { this.stream.point(x, y); },
+ sphere: function() { this.stream.sphere(); },
+ lineStart: function() { this.stream.lineStart(); },
+ lineEnd: function() { this.stream.lineEnd(); },
+ polygonStart: function() { this.stream.polygonStart(); },
+ polygonEnd: function() { this.stream.polygonEnd(); }
+};
+
+function d3_geo_transformPoint(stream, point) {
+ return {
+ point: point,
+ sphere: function() { stream.sphere(); },
+ lineStart: function() { stream.lineStart(); },
+ lineEnd: function() { stream.lineEnd(); },
+ polygonStart: function() { stream.polygonStart(); },
+ polygonEnd: function() { stream.polygonEnd(); },
};
}
}
function d3_geo_projectionRadians(stream) {
- var transform = new d3_geo_transform(stream);
- transform.point = function(λ, φ) {
- stream.point(λ * d3_radians, φ * d3_radians);
- };
- return transform;
+ return d3_geo_transformPoint(stream, function(x, y) {
+ stream.point(x * d3_radians, y * d3_radians);
+ });
}
function d3_geo_mercator(λ, φ) {
for (var j = 0, m = this.length; j < m; j++) {
subgroups.push(subgroup = []);
for (var group = this[j], i = 0, n = group.length; i < n; i++) {
- if ((node = group[i]) && filter.call(node, node.__data__, i)) {
+ if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
subgroup.push(node);
}
}
// var newDoc = JXON.unbuild(myObject);
// we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc));
-/*!
- * Lo-Dash 1.0.0-rc.3 <http://lodash.com>
- * (c) 2012 John-David Dalton <http://allyoucanleet.com/>
- * Based on Underscore.js 1.4.3 <http://underscorejs.org>
- * (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
+/**
+ * @license
+ * Lo-Dash 2.3.0 (Custom Build) <http://lodash.com/>
+ * Build: `lodash include="any,assign,bind,clone,compact,contains,debounce,difference,each,every,extend,filter,find,first,forEach,groupBy,indexOf,intersection,isEmpty,isEqual,isFunction,keys,last,map,omit,pairs,pluck,reject,some,throttle,union,uniq,unique,values,without,flatten,value,chain,cloneDeep,merge" exports="global,node"`
+ * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
+ * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
+ * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
-;(function(window, undefined) {
-
- /** Detect free variable `exports` */
- var freeExports = typeof exports == 'object' && exports;
-
- /** Detect free variable `global` and use it as `window` */
- var freeGlobal = typeof global == 'object' && global;
- if (freeGlobal.global === freeGlobal) {
- window = freeGlobal;
- }
+;(function() {
- /** Used for array and object method references */
- var arrayRef = [],
- // avoid a Closure Compiler bug by creatively creating an object
- objectRef = new function(){};
+ /** Used as a safe reference for `undefined` in pre ES5 environments */
+ var undefined;
- /** Used to generate unique IDs */
- var idCounter = 0;
+ /** Used to pool arrays and objects used internally */
+ var arrayPool = [],
+ objectPool = [];
/** Used internally to indicate various things */
- var indicatorObject = objectRef;
-
- /** Used by `cachedContains` as the default size when optimizations are enabled for large arrays */
- var largeArraySize = 30;
-
- /** Used to restore the original `_` reference in `noConflict` */
- var oldDash = window._;
+ var indicatorObject = {};
- /** Used to detect template delimiter values that require a with-statement */
- var reComplexDelimiter = /[-?+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/;
+ /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
+ var keyPrefix = +new Date + '';
- /** Used to match HTML entities */
- var reEscapedHtml = /&(?:amp|lt|gt|quot|#x27);/g;
+ /** Used as the size when optimizations are enabled for large arrays */
+ var largeArraySize = 75;
- /** Used to match empty string literals in compiled template source */
- var reEmptyStringLeading = /\b__p \+= '';/g,
- reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
- reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+ /** Used as the max size of the `arrayPool` and `objectPool` */
+ var maxPoolSize = 40;
/** Used to match regexp flags from their coerced string values */
var reFlags = /\w*$/;
- /** Used to insert the data object variable into compiled template source */
- var reInsertVariable = /(?:__e|__t = )\(\s*(?![\d\s"']|this\.)/g;
-
- /** Used to detect if a method is native */
- var reNative = RegExp('^' +
- (objectRef.valueOf + '')
- .replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&')
- .replace(/valueOf|for [^\]]+/g, '.+?') + '$'
- );
-
- /**
- * Used to match ES6 template delimiters
- * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6
- */
- var reEsTemplate = /\$\{((?:(?=\\?)\\?[\s\S])*?)}/g;
-
- /** Used to match "interpolate" template delimiters */
- var reInterpolate = /<%=([\s\S]+?)%>/g;
-
- /** Used to ensure capturing order of template delimiters */
- var reNoMatch = /($^)/;
+ /** Used to detected named functions */
+ var reFuncName = /^\s*function[ \n\r\t]+\w/;
- /** Used to match HTML characters */
- var reUnescapedHtml = /[&<>"']/g;
-
- /** Used to match unescaped characters in compiled string literals */
- var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
+ /** Used to detect functions containing a `this` reference */
+ var reThis = /\bthis\b/;
/** Used to fix the JScript [[DontEnum]] bug */
- var shadowed = [
+ var shadowedProps = [
'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
'toLocaleString', 'toString', 'valueOf'
];
- /** Used to make template sourceURLs easier to identify */
- var templateCounter = 0;
-
- /** Native method shortcuts */
- var ceil = Math.ceil,
- concat = arrayRef.concat,
- floor = Math.floor,
- getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
- hasOwnProperty = objectRef.hasOwnProperty,
- push = arrayRef.push,
- propertyIsEnumerable = objectRef.propertyIsEnumerable,
- toString = objectRef.toString;
-
- /* Native method shortcuts for methods with the same name as other `lodash` methods */
- var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind,
- nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
- nativeIsFinite = window.isFinite,
- nativeIsNaN = window.isNaN,
- nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,
- nativeMax = Math.max,
- nativeMin = Math.min,
- nativeRandom = Math.random;
-
/** `Object#toString` result shortcuts */
var argsClass = '[object Arguments]',
arrayClass = '[object Array]',
boolClass = '[object Boolean]',
dateClass = '[object Date]',
+ errorClass = '[object Error]',
funcClass = '[object Function]',
numberClass = '[object Number]',
objectClass = '[object Object]',
regexpClass = '[object RegExp]',
stringClass = '[object String]';
- /** Detect various environments */
- var isIeOpera = !!window.attachEvent,
- isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera);
-
- /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
- var isBindFast = nativeBind && !isV8;
-
- /* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */
- var isKeysFast = nativeKeys && (isIeOpera || isV8);
-
- /**
- * Detect the JScript [[DontEnum]] bug:
- *
- * In IE < 9 an objects own properties, shadowing non-enumerable ones, are
- * made non-enumerable as well.
- */
- var hasDontEnumBug;
-
- /** Detect if own properties are iterated after inherited properties (IE < 9) */
- var iteratesOwnLast;
-
- /**
- * Detect if `Array#shift` and `Array#splice` augment array-like objects
- * incorrectly:
- *
- * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()`
- * and `splice()` functions that fail to remove the last element, `value[0]`,
- * of array-like objects even though the `length` property is set to `0`.
- * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
- * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
- */
- var hasObjectSpliceBug = (hasObjectSpliceBug = { '0': 1, 'length': 1 },
- arrayRef.splice.call(hasObjectSpliceBug, 0, 1), hasObjectSpliceBug[0]);
-
- /** Detect if an `arguments` object's indexes are non-enumerable (IE < 9) */
- var nonEnumArgs = true;
-
- (function() {
- var props = [];
- function ctor() { this.x = 1; }
- ctor.prototype = { 'valueOf': 1, 'y': 1 };
- for (var prop in new ctor) { props.push(prop); }
- for (prop in arguments) { nonEnumArgs = !prop; }
-
- hasDontEnumBug = !/valueOf/.test(props);
- iteratesOwnLast = props[0] != 'x';
- }(1));
-
- /** Detect if `arguments` objects are `Object` objects (all but Opera < 10.5) */
- var argsAreObjects = arguments.constructor == Object;
-
- /** Detect if `arguments` objects [[Class]] is unresolvable (Firefox < 4, IE < 9) */
- var noArgsClass = !isArguments(arguments);
-
- /**
- * Detect lack of support for accessing string characters by index:
- *
- * IE < 8 can't access characters by index and IE 8 can only access
- * characters by index on string literals.
- */
- var noCharByIndex = ('x'[0] + Object('x')[0]) != 'xx';
-
- /**
- * Detect if a node's [[Class]] is unresolvable (IE < 9)
- * and that the JS engine won't error when attempting to coerce an object to
- * a string without a `toString` property value of `typeof` "function".
- */
- try {
- var noNodeClass = ({ 'toString': 0 } + '', toString.call(document) == objectClass);
- } catch(e) { }
-
- /**
- * Detect if sourceURL syntax is usable without erroring:
- *
- * The JS engine embedded in Adobe products will throw a syntax error when
- * it encounters a single line comment beginning with the `@` symbol.
- *
- * The JS engine in Narwhal will generate the function `function anonymous(){//}`
- * and throw a syntax error.
- *
- * Avoid comments beginning `@` symbols in IE because they are part of its
- * non-standard conditional compilation support.
- * http://msdn.microsoft.com/en-us/library/121hztk3(v=vs.94).aspx
- */
- try {
- var useSourceURL = (Function('//@')(), !isIeOpera);
- } catch(e) { }
-
/** Used to identify object classifications that `_.clone` supports */
var cloneableClasses = {};
cloneableClasses[funcClass] = false;
cloneableClasses[numberClass] = cloneableClasses[objectClass] =
cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
- /** Used to lookup a built-in constructor by [[Class]] */
- var ctorByClass = {};
- ctorByClass[arrayClass] = Array;
- ctorByClass[boolClass] = Boolean;
- ctorByClass[dateClass] = Date;
- ctorByClass[objectClass] = Object;
- ctorByClass[numberClass] = Number;
- ctorByClass[regexpClass] = RegExp;
- ctorByClass[stringClass] = String;
+ /** Used as an internal `_.debounce` options object */
+ var debounceOptions = {
+ 'leading': false,
+ 'maxWait': 0,
+ 'trailing': false
+ };
+
+ /** Used as the property descriptor for `__bindData__` */
+ var descriptor = {
+ 'configurable': false,
+ 'enumerable': false,
+ 'value': null,
+ 'writable': false
+ };
+
+ /** Used as the data object for `iteratorTemplate` */
+ var iteratorData = {
+ 'args': '',
+ 'array': null,
+ 'bottom': '',
+ 'firstArg': '',
+ 'init': '',
+ 'keys': null,
+ 'loop': '',
+ 'shadowedProps': null,
+ 'support': null,
+ 'top': '',
+ 'useHas': false
+ };
/** Used to determine if values are of the language type Object */
var objectTypes = {
'undefined': false
};
- /** Used to escape characters for inclusion in compiled string literals */
- var stringEscapes = {
- '\\': '\\',
- "'": "'",
- '\n': 'n',
- '\r': 'r',
- '\t': 't',
- '\u2028': 'u2028',
- '\u2029': 'u2029'
- };
-
- /*--------------------------------------------------------------------------*/
-
- /**
- * Creates a `lodash` object, that wraps the given `value`, to enable
- * method chaining.
- *
- * The chainable wrapper functions are:
- * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`,
- * `concat`, `countBy`, `debounce`, `defaults`, `defer`, `delay`, `difference`,
- * `filter`, `flatten`, `forEach`, `forIn`, `forOwn`, `functions`, `groupBy`,
- * `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `max`, `memoize`,
- * `merge`, `min`, `object`, `omit`, `once`, `pairs`, `partial`, `pick`, `pluck`,
- * `push`, `range`, `reject`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
- * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `union`, `uniq`,
- * `unshift`, `values`, `where`, `without`, `wrap`, and `zip`
- *
- * The non-chainable wrapper functions are:
- * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`, `identity`,
- * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`,
- * `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`,
- * `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`,
- * `mixin`, `noConflict`, `pop`, `random`, `reduce`, `reduceRight`, `result`,
- * `shift`, `size`, `some`, `sortedIndex`, `template`, `unescape`, and `uniqueId`
- *
- * The wrapper functions `first` and `last` return wrapped values when `n` is
- * passed, otherwise they return unwrapped values.
- *
- * @name _
- * @constructor
- * @category Chaining
- * @param {Mixed} value The value to wrap in a `lodash` instance.
- * @returns {Object} Returns a `lodash` instance.
- */
- function lodash(value) {
- // exit early if already wrapped, even if wrapped by a different `lodash` constructor
- if (value && typeof value == 'object' && value.__wrapped__) {
- return value;
- }
- // allow invoking `lodash` without the `new` operator
- if (!(this instanceof lodash)) {
- return new lodash(value);
- }
- this.__wrapped__ = value;
- }
-
- /**
- * By default, the template delimiters used by Lo-Dash are similar to those in
- * embedded Ruby (ERB). Change the following template settings to use alternative
- * delimiters.
- *
- * @static
- * @memberOf _
- * @type Object
- */
- lodash.templateSettings = {
-
- /**
- * Used to detect `data` property values to be HTML-escaped.
- *
- * @static
- * @memberOf _.templateSettings
- * @type RegExp
- */
- 'escape': /<%-([\s\S]+?)%>/g,
-
- /**
- * Used to detect code to be evaluated.
- *
- * @static
- * @memberOf _.templateSettings
- * @type RegExp
- */
- 'evaluate': /<%([\s\S]+?)%>/g,
-
- /**
- * Used to detect `data` property values to inject.
- *
- * @static
- * @memberOf _.templateSettings
- * @type RegExp
- */
- 'interpolate': reInterpolate,
-
- /**
- * Used to reference the data object in the template text.
- *
- * @static
- * @memberOf _.templateSettings
- * @type String
- */
- 'variable': ''
- };
-
- /*--------------------------------------------------------------------------*/
+ /** Used as a reference to the global object */
+ var root = (objectTypes[typeof window] && window) || this;
- /**
- * The template used to create iterator functions.
- *
- * @private
- * @param {Obect} data The data object used to populate the text.
- * @returns {String} Returns the interpolated text.
- */
- var iteratorTemplate = template(
- // conditional strict mode
- "<% if (obj.useStrict) { %>'use strict';\n<% } %>" +
-
- // the `iteratee` may be reassigned by the `top` snippet
- 'var index, iteratee = <%= firstArg %>, ' +
- // assign the `result` variable an initial value
- 'result = <%= firstArg %>;\n' +
- // exit early if the first argument is falsey
- 'if (!<%= firstArg %>) return result;\n' +
- // add code before the iteration branches
- '<%= top %>;\n' +
-
- // array-like iteration:
- '<% if (arrayLoop) { %>' +
- 'var length = iteratee.length; index = -1;\n' +
- "if (typeof length == 'number') {" +
-
- // add support for accessing string characters by index if needed
- ' <% if (noCharByIndex) { %>\n' +
- ' if (isString(iteratee)) {\n' +
- " iteratee = iteratee.split('')\n" +
- ' }' +
- ' <% } %>\n' +
-
- // iterate over the array-like value
- ' while (++index < length) {\n' +
- ' <%= arrayLoop %>\n' +
- ' }\n' +
- '}\n' +
- 'else {' +
-
- // object iteration:
- // add support for iterating over `arguments` objects if needed
- ' <% } else if (nonEnumArgs) { %>\n' +
- ' var length = iteratee.length; index = -1;\n' +
- ' if (length && isArguments(iteratee)) {\n' +
- ' while (++index < length) {\n' +
- " index += '';\n" +
- ' <%= objectLoop %>\n' +
- ' }\n' +
- ' } else {' +
- ' <% } %>' +
-
- // Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
- // (if the prototype or a property on the prototype has been set)
- // incorrectly sets a function's `prototype` property [[Enumerable]]
- // value to `true`. Because of this Lo-Dash standardizes on skipping
- // the the `prototype` property of functions regardless of its
- // [[Enumerable]] value.
- ' <% if (!hasDontEnumBug) { %>\n' +
- " var skipProto = typeof iteratee == 'function' && \n" +
- " propertyIsEnumerable.call(iteratee, 'prototype');\n" +
- ' <% } %>' +
-
- // iterate own properties using `Object.keys` if it's fast
- ' <% if (isKeysFast && useHas) { %>\n' +
- ' var ownIndex = -1,\n' +
- ' ownProps = objectTypes[typeof iteratee] ? nativeKeys(iteratee) : [],\n' +
- ' length = ownProps.length;\n\n' +
- ' while (++ownIndex < length) {\n' +
- ' index = ownProps[ownIndex];\n' +
- " <% if (!hasDontEnumBug) { %>if (!(skipProto && index == 'prototype')) {\n <% } %>" +
- ' <%= objectLoop %>\n' +
- ' <% if (!hasDontEnumBug) { %>}\n<% } %>' +
- ' }' +
-
- // else using a for-in loop
- ' <% } else { %>\n' +
- ' for (index in iteratee) {<%' +
- ' if (!hasDontEnumBug || useHas) { %>\n if (<%' +
- " if (!hasDontEnumBug) { %>!(skipProto && index == 'prototype')<% }" +
- ' if (!hasDontEnumBug && useHas) { %> && <% }' +
- ' if (useHas) { %>hasOwnProperty.call(iteratee, index)<% }' +
- ' %>) {' +
- ' <% } %>\n' +
- ' <%= objectLoop %>;' +
- ' <% if (!hasDontEnumBug || useHas) { %>\n }<% } %>\n' +
- ' }' +
- ' <% } %>' +
-
- // Because IE < 9 can't set the `[[Enumerable]]` attribute of an
- // existing property and the `constructor` property of a prototype
- // defaults to non-enumerable, Lo-Dash skips the `constructor`
- // property when it infers it's iterating over a `prototype` object.
- ' <% if (hasDontEnumBug) { %>\n\n' +
- ' var ctor = iteratee.constructor;\n' +
- ' <% for (var k = 0; k < 7; k++) { %>\n' +
- " index = '<%= shadowed[k] %>';\n" +
- ' if (<%' +
- " if (shadowed[k] == 'constructor') {" +
- ' %>!(ctor && ctor.prototype === iteratee) && <%' +
- ' } %>hasOwnProperty.call(iteratee, index)) {\n' +
- ' <%= objectLoop %>\n' +
- ' }' +
- ' <% } %>' +
- ' <% } %>' +
- ' <% if (arrayLoop || nonEnumArgs) { %>\n}<% } %>\n' +
-
- // add code to the bottom of the iteration function
- '<%= bottom %>;\n' +
- // finally, return the `result`
- 'return result'
- );
+ /** Detect free variable `exports` */
+ var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
- /** Reusable iterator options for `assign` and `defaults` */
- var assignIteratorOptions = {
- 'args': 'object, source, guard',
- 'top':
- "for (var argsIndex = 1, argsLength = typeof guard == 'number' ? 2 : arguments.length; argsIndex < argsLength; argsIndex++) {\n" +
- ' if ((iteratee = arguments[argsIndex])) {',
- 'objectLoop': 'result[index] = iteratee[index]',
- 'bottom': ' }\n}'
- };
+ /** Detect free variable `module` */
+ var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
- /**
- * Reusable iterator options shared by `each`, `forIn`, and `forOwn`.
- */
- var eachIteratorOptions = {
- 'args': 'collection, callback, thisArg',
- 'top': "callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg)",
- 'arrayLoop': 'if (callback(iteratee[index], index, collection) === false) return result',
- 'objectLoop': 'if (callback(iteratee[index], index, collection) === false) return result'
- };
+ /** Detect the popular CommonJS extension `module.exports` */
+ var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
- /** Reusable iterator options for `forIn` and `forOwn` */
- var forOwnIteratorOptions = {
- 'arrayLoop': null
- };
+ /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
+ var freeGlobal = objectTypes[typeof global] && global;
+ if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
+ root = freeGlobal;
+ }
/*--------------------------------------------------------------------------*/
/**
- * Creates a function optimized to search large arrays for a given `value`,
- * starting at `fromIndex`, using strict equality for comparisons, i.e. `===`.
+ * The base implementation of `_.indexOf` without support for binary searches
+ * or `fromIndex` constraints.
*
* @private
* @param {Array} array The array to search.
- * @param {Mixed} value The value to search for.
- * @param {Number} [fromIndex=0] The index to search from.
- * @param {Number} [largeSize=30] The length at which an array is considered large.
- * @returns {Boolean} Returns `true` if `value` is found, else `false`.
+ * @param {*} value The value to search for.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @returns {number} Returns the index of the matched value or `-1`.
*/
- function cachedContains(array, fromIndex, largeSize) {
- fromIndex || (fromIndex = 0);
-
- var length = array.length,
- isLarge = (length - fromIndex) >= (largeSize || largeArraySize);
-
- if (isLarge) {
- var cache = {},
- index = fromIndex - 1;
+ function baseIndexOf(array, value, fromIndex) {
+ var index = (fromIndex || 0) - 1,
+ length = array ? array.length : 0;
- while (++index < length) {
- // manually coerce `value` to a string because `hasOwnProperty`, in some
- // older versions of Firefox, coerces objects incorrectly
- var key = array[index] + '';
- (hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]);
- }
- }
- return function(value) {
- if (isLarge) {
- var key = value + '';
- return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1;
+ while (++index < length) {
+ if (array[index] === value) {
+ return index;
}
- return indexOf(array, value, fromIndex) > -1;
}
+ return -1;
}
/**
- * Used by `_.max` and `_.min` as the default `callback` when a given
- * `collection` is a string value.
- *
- * @private
- * @param {String} value The character to inspect.
- * @returns {Number} Returns the code unit of given character.
- */
- function charAtCallback(value) {
- return value.charCodeAt(0);
- }
-
- /**
- * Used by `sortBy` to compare transformed `collection` values, stable sorting
- * them in ascending order.
+ * An implementation of `_.contains` for cache objects that mimics the return
+ * signature of `_.indexOf` by returning `0` if the value is found, else `-1`.
*
* @private
- * @param {Object} a The object to compare to `b`.
- * @param {Object} b The object to compare to `a`.
- * @returns {Number} Returns the sort order indicator of `1` or `-1`.
+ * @param {Object} cache The cache object to inspect.
+ * @param {*} value The value to search for.
+ * @returns {number} Returns `0` if `value` is found, else `-1`.
*/
- function compareAscending(a, b) {
- var ai = a.index,
- bi = b.index;
-
- a = a.criteria;
- b = b.criteria;
+ function cacheIndexOf(cache, value) {
+ var type = typeof value;
+ cache = cache.cache;
- // ensure a stable sort in V8 and other engines
- // http://code.google.com/p/v8/issues/detail?id=90
- if (a !== b) {
- if (a > b || typeof a == 'undefined') {
- return 1;
- }
- if (a < b || typeof b == 'undefined') {
- return -1;
- }
+ if (type == 'boolean' || value == null) {
+ return cache[value] ? 0 : -1;
+ }
+ if (type != 'number' && type != 'string') {
+ type = 'object';
}
- return ai < bi ? -1 : 1;
+ var key = type == 'number' ? value : keyPrefix + value;
+ cache = (cache = cache[type]) && cache[key];
+
+ return type == 'object'
+ ? (cache && baseIndexOf(cache, value) > -1 ? 0 : -1)
+ : (cache ? 0 : -1);
}
/**
- * Creates a function that, when called, invokes `func` with the `this`
- * binding of `thisArg` and prepends any `partailArgs` to the arguments passed
- * to the bound function.
+ * Adds a given value to the corresponding cache object.
*
* @private
- * @param {Function|String} func The function to bind or the method name.
- * @param {Mixed} [thisArg] The `this` binding of `func`.
- * @param {Array} partialArgs An array of arguments to be partially applied.
- * @returns {Function} Returns the new bound function.
+ * @param {*} value The value to add to the cache.
*/
- function createBound(func, thisArg, partialArgs) {
- var isFunc = isFunction(func),
- isPartial = !partialArgs,
- key = thisArg;
-
- // juggle arguments
- if (isPartial) {
- partialArgs = thisArg;
- }
- if (!isFunc) {
- thisArg = func;
- }
-
- function bound() {
- // `Function#bind` spec
- // http://es5.github.com/#x15.3.4.5
- var args = arguments,
- thisBinding = isPartial ? this : thisArg;
+ function cachePush(value) {
+ var cache = this.cache,
+ type = typeof value;
- if (!isFunc) {
- func = thisArg[key];
- }
- if (partialArgs.length) {
- args = args.length
- ? partialArgs.concat(slice(args))
- : partialArgs;
+ if (type == 'boolean' || value == null) {
+ cache[value] = true;
+ } else {
+ if (type != 'number' && type != 'string') {
+ type = 'object';
}
- if (this instanceof bound) {
- // ensure `new bound` is an instance of `bound` and `func`
- noop.prototype = func.prototype;
- thisBinding = new noop;
- noop.prototype = null;
+ var key = type == 'number' ? value : keyPrefix + value,
+ typeCache = cache[type] || (cache[type] = {});
- // mimic the constructor's `return` behavior
- // http://es5.github.com/#x13.2.2
- var result = func.apply(thisBinding, args);
- return isObject(result) ? result : thisBinding;
+ if (type == 'object') {
+ (typeCache[key] || (typeCache[key] = [])).push(value);
+ } else {
+ typeCache[key] = true;
}
- return func.apply(thisBinding, args);
}
- return bound;
}
/**
- * Produces an iteration callback bound to an optional `thisArg`. If `func` is
- * a property name, the callback will return the property value for a given element.
+ * Creates a cache object to optimize linear searches of large arrays.
*
* @private
- * @param {Function|String} [func=identity|property] The function called per
- * iteration or property name to query.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @param {Object} [accumulating] Used to indicate that the callback should
- * accept an `accumulator` argument.
- * @returns {Function} Returns a callback function.
+ * @param {Array} [array=[]] The array to search.
+ * @returns {null|Object} Returns the cache object or `null` if caching should not be used.
*/
- function createCallback(func, thisArg, accumulating) {
- if (!func) {
- return identity;
- }
- if (typeof func != 'function') {
- return function(object) {
- return object[func];
- };
- }
- if (typeof thisArg != 'undefined') {
- if (accumulating) {
- return function(accumulator, value, index, object) {
- return func.call(thisArg, accumulator, value, index, object);
- };
- }
- return function(value, index, object) {
- return func.call(thisArg, value, index, object);
- };
+ function createCache(array) {
+ var index = -1,
+ length = array.length,
+ first = array[0],
+ mid = array[(length / 2) | 0],
+ last = array[length - 1];
+
+ if (first && typeof first == 'object' &&
+ mid && typeof mid == 'object' && last && typeof last == 'object') {
+ return false;
}
- return func;
- }
+ var cache = getObject();
+ cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false;
- /**
- * Creates compiled iteration functions.
- *
- * @private
- * @param {Object} [options1, options2, ...] The compile options object(s).
- * useHas - A boolean to specify using `hasOwnProperty` checks in the object loop.
- * args - A string of comma separated arguments the iteration function will accept.
- * top - A string of code to execute before the iteration branches.
- * arrayLoop - A string of code to execute in the array loop.
- * objectLoop - A string of code to execute in the object loop.
- * bottom - A string of code to execute after the iteration branches.
- *
- * @returns {Function} Returns the compiled function.
- */
- function createIterator() {
- var data = {
- 'arrayLoop': '',
- 'bottom': '',
- 'hasDontEnumBug': hasDontEnumBug,
- 'isKeysFast': isKeysFast,
- 'objectLoop': '',
- 'nonEnumArgs': nonEnumArgs,
- 'noCharByIndex': noCharByIndex,
- 'shadowed': shadowed,
- 'top': '',
- 'useHas': true
- };
+ var result = getObject();
+ result.array = array;
+ result.cache = cache;
+ result.push = cachePush;
- // merge options into a template data object
- for (var object, index = 0; object = arguments[index]; index++) {
- for (var key in object) {
- data[key] = object[key];
- }
+ while (++index < length) {
+ result.push(array[index]);
}
- var args = data.args;
- data.firstArg = /^[^,]+/.exec(args)[0];
-
- // create the function factory
- var factory = Function(
- 'createCallback, hasOwnProperty, isArguments, isString, objectTypes, ' +
- 'nativeKeys, propertyIsEnumerable',
- 'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
- );
- // return the compiled function
- return factory(
- createCallback, hasOwnProperty, isArguments, isString, objectTypes,
- nativeKeys, propertyIsEnumerable
- );
+ return result;
}
/**
- * A function compiled to iterate `arguments` objects, arrays, objects, and
- * strings consistenly across environments, executing the `callback` for each
- * element in the `collection`. The `callback` is bound to `thisArg` and invoked
- * with three arguments; (value, index|key, collection). Callbacks may exit
- * iteration early by explicitly returning `false`.
- *
- * @private
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Array|Object|String} Returns `collection`.
- */
- var each = createIterator(eachIteratorOptions);
-
- /**
- * Used by `template` to escape characters for inclusion in compiled
- * string literals.
+ * Gets an array from the array pool or creates a new one if the pool is empty.
*
* @private
- * @param {String} match The matched character to escape.
- * @returns {String} Returns the escaped character.
+ * @returns {Array} The array from the pool.
*/
- function escapeStringChar(match) {
- return '\\' + stringEscapes[match];
+ function getArray() {
+ return arrayPool.pop() || [];
}
/**
- * Used by `escape` to convert characters to HTML entities.
+ * Gets an object from the object pool or creates a new one if the pool is empty.
*
* @private
- * @param {String} match The matched character to escape.
- * @returns {String} Returns the escaped character.
+ * @returns {Object} The object from the pool.
*/
- function escapeHtmlChar(match) {
- return htmlEscapes[match];
+ function getObject() {
+ return objectPool.pop() || {
+ 'array': null,
+ 'cache': null,
+ 'false': false,
+ 'null': false,
+ 'number': null,
+ 'object': null,
+ 'push': null,
+ 'string': null,
+ 'true': false,
+ 'undefined': false
+ };
}
/**
* Checks if `value` is a DOM node in IE < 9.
*
* @private
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if the `value` is a DOM node, else `false`.
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if the `value` is a DOM node, else `false`.
*/
function isNode(value) {
// IE < 9 presents DOM nodes as `Object` objects except they have `toString`
}
/**
- * A no-operation function.
+ * Releases the given array back to the array pool.
*
* @private
+ * @param {Array} [array] The array to release.
*/
- function noop() {
- // no operation performed
+ function releaseArray(array) {
+ array.length = 0;
+ if (arrayPool.length < maxPoolSize) {
+ arrayPool.push(array);
+ }
+ }
+
+ /**
+ * Releases the given object back to the object pool.
+ *
+ * @private
+ * @param {Object} [object] The object to release.
+ */
+ function releaseObject(object) {
+ var cache = object.cache;
+ if (cache) {
+ releaseObject(cache);
+ }
+ object.array = object.cache =object.object = object.number = object.string =null;
+ if (objectPool.length < maxPoolSize) {
+ objectPool.push(object);
+ }
}
/**
* Slices the `collection` from the `start` index up to, but not including,
* the `end` index.
*
- * Note: This function is used, instead of `Array#slice`, to support node lists
+ * Note: This function is used instead of `Array#slice` to support node lists
* in IE < 9 and to ensure dense arrays are returned.
*
* @private
- * @param {Array|Object|String} collection The collection to slice.
- * @param {Number} start The start index.
- * @param {Number} end The end index.
+ * @param {Array|Object|string} collection The collection to slice.
+ * @param {number} start The start index.
+ * @param {number} end The end index.
* @returns {Array} Returns the new array.
*/
function slice(array, start, end) {
return result;
}
+ /*--------------------------------------------------------------------------*/
+
/**
- * Used by `unescape` to convert HTML entities to characters.
+ * Used for `Array` method references.
*
- * @private
- * @param {String} match The matched character to unescape.
- * @returns {String} Returns the unescaped character.
+ * Normally `Array.prototype` would suffice, however, using an array literal
+ * avoids issues in Narwhal.
*/
- function unescapeHtmlChar(match) {
- return htmlUnescapes[match];
- }
+ var arrayRef = [];
+
+ /** Used for native method references */
+ var errorProto = Error.prototype,
+ objectProto = Object.prototype,
+ stringProto = String.prototype;
+
+ /** Used to resolve the internal [[Class]] of values */
+ var toString = objectProto.toString;
+
+ /** Used to detect if a method is native */
+ var reNative = RegExp('^' +
+ String(toString)
+ .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+ .replace(/toString| for [^\]]+/g, '.*?') + '$'
+ );
+
+ /** Native method shortcuts */
+ var fnToString = Function.prototype.toString,
+ getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
+ hasOwnProperty = objectProto.hasOwnProperty,
+ now = reNative.test(now = Date.now) && now || function() { return +new Date; },
+ push = arrayRef.push,
+ propertyIsEnumerable = objectProto.propertyIsEnumerable;
+
+ /** Used to set meta data on functions */
+ var defineProperty = (function() {
+ // IE 8 only accepts DOM elements
+ try {
+ var o = {},
+ func = reNative.test(func = Object.defineProperty) && func,
+ result = func(o, o, o) && func;
+ } catch(e) { }
+ return result;
+ }());
+
+ /* Native method shortcuts for methods with the same name as other `lodash` methods */
+ var nativeCreate = reNative.test(nativeCreate = Object.create) && nativeCreate,
+ nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
+ nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,
+ nativeMax = Math.max,
+ nativeMin = Math.min;
+
+ /** Used to lookup a built-in constructor by [[Class]] */
+ var ctorByClass = {};
+ ctorByClass[arrayClass] = Array;
+ ctorByClass[boolClass] = Boolean;
+ ctorByClass[dateClass] = Date;
+ ctorByClass[funcClass] = Function;
+ ctorByClass[objectClass] = Object;
+ ctorByClass[numberClass] = Number;
+ ctorByClass[regexpClass] = RegExp;
+ ctorByClass[stringClass] = String;
+
+ /** Used to avoid iterating non-enumerable properties in IE < 9 */
+ var nonEnumProps = {};
+ nonEnumProps[arrayClass] = nonEnumProps[dateClass] = nonEnumProps[numberClass] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true };
+ nonEnumProps[boolClass] = nonEnumProps[stringClass] = { 'constructor': true, 'toString': true, 'valueOf': true };
+ nonEnumProps[errorClass] = nonEnumProps[funcClass] = nonEnumProps[regexpClass] = { 'constructor': true, 'toString': true };
+ nonEnumProps[objectClass] = { 'constructor': true };
+
+ (function() {
+ var length = shadowedProps.length;
+ while (length--) {
+ var key = shadowedProps[length];
+ for (var className in nonEnumProps) {
+ if (hasOwnProperty.call(nonEnumProps, className) && !hasOwnProperty.call(nonEnumProps[className], key)) {
+ nonEnumProps[className][key] = false;
+ }
+ }
+ }
+ }());
/*--------------------------------------------------------------------------*/
/**
- * Assigns own enumerable properties of source object(s) to the `destination`
- * object. Subsequent sources will overwrite propery assignments of previous
- * sources.
+ * Creates a `lodash` object which wraps the given value to enable intuitive
+ * method chaining.
*
- * @static
- * @memberOf _
- * @alias extend
- * @category Objects
- * @param {Object} object The destination object.
- * @param {Object} [source1, source2, ...] The source objects.
- * @returns {Object} Returns the destination object.
- * @example
+ * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
+ * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
+ * and `unshift`
*
- * _.assign({ 'name': 'moe' }, { 'age': 40 });
- * // => { 'name': 'moe', 'age': 40 }
- */
- var assign = createIterator(assignIteratorOptions);
-
- /**
- * Checks if `value` is an `arguments` object.
+ * Chaining is supported in custom builds as long as the `value` method is
+ * implicitly or explicitly included in the build.
*
- * @static
- * @memberOf _
- * @category Objects
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
- * @example
+ * The chainable wrapper functions are:
+ * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
+ * `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`,
+ * `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`,
+ * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
+ * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
+ * `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
+ * `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`,
+ * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
+ * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
+ * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
+ * and `zip`
*
- * (function() { return _.isArguments(arguments); })(1, 2, 3);
- * // => true
+ * The non-chainable wrapper functions are:
+ * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`,
+ * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`,
+ * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
+ * `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`,
+ * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`,
+ * `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`,
+ * `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`,
+ * `template`, `unescape`, `uniqueId`, and `value`
*
- * _.isArguments([1, 2, 3]);
- * // => false
- */
- function isArguments(value) {
- return toString.call(value) == argsClass;
- }
- // fallback for browsers that can't detect `arguments` objects by [[Class]]
- if (noArgsClass) {
- isArguments = function(value) {
- return value ? hasOwnProperty.call(value, 'callee') : false;
- };
- }
-
- /**
- * Iterates over `object`'s own and inherited enumerable properties, executing
- * the `callback` for each property. The `callback` is bound to `thisArg` and
- * invoked with three arguments; (value, key, object). Callbacks may exit iteration
- * early by explicitly returning `false`.
+ * The wrapper functions `first` and `last` return wrapped values when `n` is
+ * provided, otherwise they return unwrapped values.
*
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The object to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns `object`.
+ * Explicit chaining can be enabled by using the `_.chain` method.
+ *
+ * @name _
+ * @constructor
+ * @category Chaining
+ * @param {*} value The value to wrap in a `lodash` instance.
+ * @returns {Object} Returns a `lodash` instance.
* @example
*
- * function Dog(name) {
- * this.name = name;
- * }
+ * var wrapped = _([1, 2, 3]);
*
- * Dog.prototype.bark = function() {
- * alert('Woof, woof!');
- * };
+ * // returns an unwrapped value
+ * wrapped.reduce(function(sum, num) {
+ * return sum + num;
+ * });
+ * // => 6
*
- * _.forIn(new Dog('Dagny'), function(value, key) {
- * alert(key);
+ * // returns a wrapped value
+ * var squares = wrapped.map(function(num) {
+ * return num * num;
* });
- * // => alerts 'name' and 'bark' (order is not guaranteed)
- */
- var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, {
- 'useHas': false
- });
-
- /**
- * Iterates over an object's own enumerable properties, executing the `callback`
- * for each property. The `callback` is bound to `thisArg` and invoked with three
- * arguments; (value, key, object). Callbacks may exit iteration early by explicitly
- * returning `false`.
*
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The object to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns `object`.
- * @example
+ * _.isArray(squares);
+ * // => false
*
- * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
- * alert(key);
- * });
- * // => alerts '0', '1', and 'length' (order is not guaranteed)
+ * _.isArray(squares.value());
+ * // => true
*/
- var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions);
+ function lodash(value) {
+ // don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
+ return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
+ ? value
+ : new lodashWrapper(value);
+ }
/**
- * A fallback implementation of `isPlainObject` that checks if a given `value`
- * is an object created by the `Object` constructor, assuming objects created
- * by the `Object` constructor have no inherited enumerable properties and that
- * there are no `Object.prototype` extensions.
+ * A fast path for creating `lodash` wrapper objects.
*
* @private
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if `value` is a plain object, else `false`.
+ * @param {*} value The value to wrap in a `lodash` instance.
+ * @param {boolean} chainAll A flag to enable chaining for all methods
+ * @returns {Object} Returns a `lodash` instance.
*/
- function shimIsPlainObject(value) {
- // avoid non-objects and false positives for `arguments` objects
- var result = false;
- if (!(value && typeof value == 'object') || isArguments(value)) {
- return result;
- }
- // check that the constructor is `Object` (i.e. `Object instanceof Object`)
- var ctor = value.constructor;
- if ((!isFunction(ctor) && (!noNodeClass || !isNode(value))) || ctor instanceof ctor) {
- // IE < 9 iterates inherited properties before own properties. If the first
- // iterated property is an object's own property then there are no inherited
- // enumerable properties.
- if (iteratesOwnLast) {
- forIn(value, function(value, key, object) {
- result = !hasOwnProperty.call(object, key);
- return false;
- });
- return result === false;
- }
- // In most environments an object's own properties are iterated before
- // its inherited properties. If the last iterated property is an object's
- // own property then there are no inherited enumerable properties.
- forIn(value, function(value, key) {
- result = key;
- });
- return result === false || hasOwnProperty.call(value, result);
- }
- return result;
+ function lodashWrapper(value, chainAll) {
+ this.__chain__ = !!chainAll;
+ this.__wrapped__ = value;
}
+ // ensure `new lodashWrapper` is an instance of `lodash`
+ lodashWrapper.prototype = lodash.prototype;
/**
- * A fallback implementation of `Object.keys` that produces an array of the
- * given object's own enumerable property names.
+ * An object used to flag environments features.
*
- * @private
- * @param {Object} object The object to inspect.
- * @returns {Array} Returns a new array of property names.
+ * @static
+ * @memberOf _
+ * @type Object
*/
- function shimKeys(object) {
- var result = [];
- forOwn(object, function(value, key) {
- result.push(key);
- });
- return result;
- }
+ var support = lodash.support = {};
+
+ (function() {
+ var ctor = function() { this.x = 1; },
+ object = { '0': 1, 'length': 1 },
+ props = [];
+
+ ctor.prototype = { 'valueOf': 1, 'y': 1 };
+ for (var key in new ctor) { props.push(key); }
+ for (key in arguments) { }
+
+ /**
+ * Detect if an `arguments` object's [[Class]] is resolvable (all but Firefox < 4, IE < 9).
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.argsClass = toString.call(arguments) == argsClass;
+
+ /**
+ * Detect if `arguments` objects are `Object` objects (all but Narwhal and Opera < 10.5).
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.argsObject = arguments.constructor == Object && !(arguments instanceof Array);
+
+ /**
+ * Detect if `name` or `message` properties of `Error.prototype` are
+ * enumerable by default. (IE < 9, Safari < 5.1)
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || propertyIsEnumerable.call(errorProto, 'name');
+
+ /**
+ * Detect if `prototype` properties are enumerable by default.
+ *
+ * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
+ * (if the prototype or a property on the prototype has been set)
+ * incorrectly sets a function's `prototype` property [[Enumerable]]
+ * value to `true`.
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.enumPrototypes = propertyIsEnumerable.call(ctor, 'prototype');
+
+ /**
+ * Detect if functions can be decompiled by `Function#toString`
+ * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps).
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.funcDecomp = !reNative.test(root.WinRTError) && reThis.test(function() { return this; });
+
+ /**
+ * Detect if `Function#name` is supported (all but IE).
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.funcNames = typeof Function.name == 'string';
+
+ /**
+ * Detect if `arguments` object indexes are non-enumerable
+ * (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1).
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.nonEnumArgs = key != 0;
+
+ /**
+ * Detect if properties shadowing those on `Object.prototype` are non-enumerable.
+ *
+ * In IE < 9 an objects own properties, shadowing non-enumerable ones, are
+ * made non-enumerable as well (a.k.a the JScript [[DontEnum]] bug).
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.nonEnumShadows = !/valueOf/.test(props);
+
+ /**
+ * Detect if own properties are iterated after inherited properties (all but IE < 9).
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.ownLast = props[0] != 'x';
+
+ /**
+ * Detect if `Array#shift` and `Array#splice` augment array-like objects correctly.
+ *
+ * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()`
+ * and `splice()` functions that fail to remove the last element, `value[0]`,
+ * of array-like objects even though the `length` property is set to `0`.
+ * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
+ * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.spliceObjects = (arrayRef.splice.call(object, 0, 1), !object[0]);
+
+ /**
+ * Detect lack of support for accessing string characters by index.
+ *
+ * IE < 8 can't access characters by index and IE 8 can only access
+ * characters by index on string literals.
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx';
+
+ /**
+ * Detect if a DOM node's [[Class]] is resolvable (all but IE < 9)
+ * and that the JS engine errors when attempting to coerce an object to
+ * a string without a `toString` function.
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ try {
+ support.nodeClass = !(toString.call(document) == objectClass && !({ 'toString': 0 } + ''));
+ } catch(e) {
+ support.nodeClass = true;
+ }
+ }(1));
+
+ /*--------------------------------------------------------------------------*/
/**
- * Used to convert characters to HTML entities:
+ * The template used to create iterator functions.
*
- * Though the `>` character is escaped for symmetry, characters like `>` and `/`
- * don't require escaping in HTML and have no special meaning unless they're part
- * of a tag or an unquoted attribute value.
- * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
+ * @private
+ * @param {Object} data The data object used to populate the text.
+ * @returns {string} Returns the interpolated text.
*/
- var htmlEscapes = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": '''
- };
+ var iteratorTemplate = function(obj) {
+
+ var __p = 'var index, iterable = ' +
+ (obj.firstArg) +
+ ', result = ' +
+ (obj.init) +
+ ';\nif (!iterable) return result;\n' +
+ (obj.top) +
+ ';';
+ if (obj.array) {
+ __p += '\nvar length = iterable.length; index = -1;\nif (' +
+ (obj.array) +
+ ') { ';
+ if (support.unindexedChars) {
+ __p += '\n if (isString(iterable)) {\n iterable = iterable.split(\'\')\n } ';
+ }
+ __p += '\n while (++index < length) {\n ' +
+ (obj.loop) +
+ ';\n }\n}\nelse { ';
+ } else if (support.nonEnumArgs) {
+ __p += '\n var length = iterable.length; index = -1;\n if (length && isArguments(iterable)) {\n while (++index < length) {\n index += \'\';\n ' +
+ (obj.loop) +
+ ';\n }\n } else { ';
+ }
- /** Used to convert HTML entities to characters */
- var htmlUnescapes = invert(htmlEscapes);
+ if (support.enumPrototypes) {
+ __p += '\n var skipProto = typeof iterable == \'function\';\n ';
+ }
+
+ if (support.enumErrorProps) {
+ __p += '\n var skipErrorProps = iterable === errorProto || iterable instanceof Error;\n ';
+ }
+
+ var conditions = []; if (support.enumPrototypes) { conditions.push('!(skipProto && index == "prototype")'); } if (support.enumErrorProps) { conditions.push('!(skipErrorProps && (index == "message" || index == "name"))'); }
+
+ if (obj.useHas && obj.keys) {
+ __p += '\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] && keys(iterable),\n length = ownProps ? ownProps.length : 0;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n';
+ if (conditions.length) {
+ __p += ' if (' +
+ (conditions.join(' && ')) +
+ ') {\n ';
+ }
+ __p +=
+ (obj.loop) +
+ '; ';
+ if (conditions.length) {
+ __p += '\n }';
+ }
+ __p += '\n } ';
+ } else {
+ __p += '\n for (index in iterable) {\n';
+ if (obj.useHas) { conditions.push("hasOwnProperty.call(iterable, index)"); } if (conditions.length) {
+ __p += ' if (' +
+ (conditions.join(' && ')) +
+ ') {\n ';
+ }
+ __p +=
+ (obj.loop) +
+ '; ';
+ if (conditions.length) {
+ __p += '\n }';
+ }
+ __p += '\n } ';
+ if (support.nonEnumShadows) {
+ __p += '\n\n if (iterable !== objectProto) {\n var ctor = iterable.constructor,\n isProto = iterable === (ctor && ctor.prototype),\n className = iterable === stringProto ? stringClass : iterable === errorProto ? errorClass : toString.call(iterable),\n nonEnum = nonEnumProps[className];\n ';
+ for (k = 0; k < 7; k++) {
+ __p += '\n index = \'' +
+ (obj.shadowedProps[k]) +
+ '\';\n if ((!(isProto && nonEnum[index]) && hasOwnProperty.call(iterable, index))';
+ if (!obj.useHas) {
+ __p += ' || (!nonEnum[index] && iterable[index] !== objectProto[index])';
+ }
+ __p += ') {\n ' +
+ (obj.loop) +
+ ';\n } ';
+ }
+ __p += '\n } ';
+ }
+
+ }
+
+ if (obj.array || support.nonEnumArgs) {
+ __p += '\n}';
+ }
+ __p +=
+ (obj.bottom) +
+ ';\nreturn result';
+
+ return __p
+ };
/*--------------------------------------------------------------------------*/
/**
- * Creates a clone of `value`. If `deep` is `true`, nested objects will also
- * be cloned, otherwise they will be assigned by reference.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Mixed} value The value to clone.
- * @param {Boolean} deep A flag to indicate a deep clone.
- * @param- {Object} [guard] Internally used to allow this method to work with
- * others like `_.map` without using their callback `index` argument for `deep`.
- * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
- * @param- {Array} [stackB=[]] Internally used to associate clones with their
- * source counterparts.
- * @returns {Mixed} Returns the cloned `value`.
- * @example
+ * The base implementation of `_.bind` that creates the bound function and
+ * sets its meta data.
*
- * var stooges = [
- * { 'name': 'moe', 'age': 40 },
- * { 'name': 'larry', 'age': 50 },
- * { 'name': 'curly', 'age': 60 }
- * ];
- *
- * var shallow = _.clone(stooges);
- * shallow[0] === stooges[0];
- * // => true
- *
- * var deep = _.clone(stooges, true);
- * deep[0] === stooges[0];
- * // => false
+ * @private
+ * @param {Array} bindData The bind data array.
+ * @returns {Function} Returns the new bound function.
*/
- function clone(value, deep, guard, stackA, stackB) {
- if (value == null) {
- return value;
+ function baseBind(bindData) {
+ var func = bindData[0],
+ partialArgs = bindData[2],
+ thisArg = bindData[4];
+
+ function bound() {
+ // `Function#bind` spec
+ // http://es5.github.io/#x15.3.4.5
+ if (partialArgs) {
+ var args = partialArgs.slice();
+ push.apply(args, arguments);
+ }
+ // mimic the constructor's `return` behavior
+ // http://es5.github.io/#x13.2.2
+ if (this instanceof bound) {
+ // ensure `new bound` is an instance of `func`
+ var thisBinding = baseCreate(func.prototype),
+ result = func.apply(thisBinding, args || arguments);
+ return isObject(result) ? result : thisBinding;
+ }
+ return func.apply(thisArg, args || arguments);
}
- if (guard) {
- deep = false;
+ setBindData(bound, bindData);
+ return bound;
+ }
+
+ /**
+ * The base implementation of `_.clone` without argument juggling or support
+ * for `thisArg` binding.
+ *
+ * @private
+ * @param {*} value The value to clone.
+ * @param {boolean} [isDeep=false] Specify a deep clone.
+ * @param {Function} [callback] The function to customize cloning values.
+ * @param {Array} [stackA=[]] Tracks traversed source objects.
+ * @param {Array} [stackB=[]] Associates clones with source counterparts.
+ * @returns {*} Returns the cloned value.
+ */
+ function baseClone(value, isDeep, callback, stackA, stackB) {
+ if (callback) {
+ var result = callback(value);
+ if (typeof result != 'undefined') {
+ return result;
+ }
}
// inspect [[Class]]
var isObj = isObject(value);
if (isObj) {
var className = toString.call(value);
- if (!cloneableClasses[className] || (noNodeClass && isNode(value))) {
+ if (!cloneableClasses[className] || (!support.nodeClass && isNode(value))) {
return value;
}
- var isArr = isArray(value);
- }
- // shallow clone
- if (!isObj || !deep) {
- return isObj
- ? (isArr ? slice(value) : assign({}, value))
- : value;
+ var ctor = ctorByClass[className];
+ switch (className) {
+ case boolClass:
+ case dateClass:
+ return new ctor(+value);
+
+ case numberClass:
+ case stringClass:
+ return new ctor(value);
+
+ case regexpClass:
+ result = ctor(value.source, reFlags.exec(value));
+ result.lastIndex = value.lastIndex;
+ return result;
+ }
+ } else {
+ return value;
}
- var ctor = ctorByClass[className];
- switch (className) {
- case boolClass:
- case dateClass:
- return new ctor(+value);
-
- case numberClass:
- case stringClass:
- return new ctor(value);
+ var isArr = isArray(value);
+ if (isDeep) {
+ // check for circular references and return corresponding clone
+ var initedStack = !stackA;
+ stackA || (stackA = getArray());
+ stackB || (stackB = getArray());
- case regexpClass:
- return ctor(value.source, reFlags.exec(value));
+ var length = stackA.length;
+ while (length--) {
+ if (stackA[length] == value) {
+ return stackB[length];
+ }
+ }
+ result = isArr ? ctor(value.length) : {};
}
- // check for circular references and return corresponding clone
- stackA || (stackA = []);
- stackB || (stackB = []);
-
- var length = stackA.length;
- while (length--) {
- if (stackA[length] == value) {
- return stackB[length];
+ else {
+ result = isArr ? slice(value) : assign({}, value);
+ }
+ // add array properties assigned by `RegExp#exec`
+ if (isArr) {
+ if (hasOwnProperty.call(value, 'index')) {
+ result.index = value.index;
+ }
+ if (hasOwnProperty.call(value, 'input')) {
+ result.input = value.input;
}
}
- // init cloned object
- var result = isArr ? ctor(value.length) : {};
-
+ // exit for shallow clone
+ if (!isDeep) {
+ return result;
+ }
// add the source value to the stack of traversed objects
// and associate it with its clone
stackA.push(value);
stackB.push(result);
// recursively populate clone (susceptible to call stack limits)
- (isArr ? forEach : forOwn)(value, function(objValue, key) {
- result[key] = clone(objValue, deep, null, stackA, stackB);
+ (isArr ? baseEach : forOwn)(value, function(objValue, key) {
+ result[key] = baseClone(objValue, isDeep, callback, stackA, stackB);
});
- // add array properties assigned by `RegExp#exec`
- if (isArr) {
- if (hasOwnProperty.call(value, 'index')) {
- result.index = value.index;
- }
- if (hasOwnProperty.call(value, 'input')) {
- result.input = value.input;
- }
+ if (initedStack) {
+ releaseArray(stackA);
+ releaseArray(stackB);
}
return result;
}
/**
- * Creates a deep clone of `value`. Functions and DOM nodes are **not** cloned.
- * The enumerable properties of `arguments` objects and objects created by
- * constructors other than `Object` are cloned to plain `Object` objects.
- *
- * Note: This function is loosely based on the structured clone algorithm.
- * See http://www.w3.org/TR/html5/common-dom-interfaces.html#internal-structured-cloning-algorithm.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Mixed} value The value to deep clone.
- * @returns {Mixed} Returns the deep cloned `value`.
- * @example
+ * The base implementation of `_.create` without support for assigning
+ * properties to the created object.
*
- * var stooges = [
- * { 'name': 'moe', 'age': 40 },
- * { 'name': 'larry', 'age': 50 },
- * { 'name': 'curly', 'age': 60 }
- * ];
- *
- * var deep = _.cloneDeep(stooges);
- * deep[0] === stooges[0];
- * // => false
+ * @private
+ * @param {Object} prototype The object to inherit from.
+ * @returns {Object} Returns the new object.
*/
- function cloneDeep(value) {
- return clone(value, true);
+ function baseCreate(prototype, properties) {
+ return isObject(prototype) ? nativeCreate(prototype) : {};
+ }
+ // fallback for browsers without `Object.create`
+ if (!nativeCreate) {
+ baseCreate = (function() {
+ function Object() {}
+ return function(prototype) {
+ if (isObject(prototype)) {
+ Object.prototype = prototype;
+ var result = new Object;
+ Object.prototype = null;
+ }
+ return result || root.Object();
+ };
+ }());
}
/**
- * Assigns own enumerable properties of source object(s) to the `destination`
- * object for all `destination` properties that resolve to `null`/`undefined`.
- * Once a property is set, additional defaults of the same property will be
- * ignored.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The destination object.
- * @param {Object} [default1, default2, ...] The default objects.
- * @returns {Object} Returns the destination object.
- * @example
- *
- * var iceCream = { 'flavor': 'chocolate' };
- * _.defaults(iceCream, { 'flavor': 'vanilla', 'sprinkles': 'rainbow' });
- * // => { 'flavor': 'chocolate', 'sprinkles': 'rainbow' }
- */
- var defaults = createIterator(assignIteratorOptions, {
- 'objectLoop': 'if (result[index] == null) ' + assignIteratorOptions.objectLoop
- });
-
- /**
- * Creates a sorted array of all enumerable properties, own and inherited,
- * of `object` that have function values.
- *
- * @static
- * @memberOf _
- * @alias methods
- * @category Objects
- * @param {Object} object The object to inspect.
- * @returns {Array} Returns a new array of property names that have function values.
- * @example
+ * The base implementation of `_.createCallback` without support for creating
+ * "_.pluck" or "_.where" style callbacks.
*
- * _.functions(_);
- * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
+ * @private
+ * @param {*} [func=identity] The value to convert to a callback.
+ * @param {*} [thisArg] The `this` binding of the created callback.
+ * @param {number} [argCount] The number of arguments the callback accepts.
+ * @returns {Function} Returns a callback function.
*/
- function functions(object) {
- var result = [];
- forIn(object, function(value, key) {
- if (isFunction(value)) {
- result.push(key);
+ function baseCreateCallback(func, thisArg, argCount) {
+ if (typeof func != 'function') {
+ return identity;
+ }
+ // exit early for no `thisArg` or already bound by `Function#bind`
+ if (typeof thisArg == 'undefined' || !('prototype' in func)) {
+ return func;
+ }
+ var bindData = func.__bindData__;
+ if (typeof bindData == 'undefined') {
+ if (support.funcNames) {
+ bindData = !func.name;
}
- });
- return result.sort();
+ bindData = bindData || !support.funcDecomp;
+ if (!bindData) {
+ var source = fnToString.call(func);
+ if (!support.funcNames) {
+ bindData = !reFuncName.test(source);
+ }
+ if (!bindData) {
+ // checks if `func` references the `this` keyword and stores the result
+ bindData = reThis.test(source);
+ setBindData(func, bindData);
+ }
+ }
+ }
+ // exit early if there are no `this` references or `func` is bound
+ if (bindData === false || (bindData !== true && bindData[1] & 1)) {
+ return func;
+ }
+ switch (argCount) {
+ case 1: return function(value) {
+ return func.call(thisArg, value);
+ };
+ case 2: return function(a, b) {
+ return func.call(thisArg, a, b);
+ };
+ case 3: return function(value, index, collection) {
+ return func.call(thisArg, value, index, collection);
+ };
+ case 4: return function(accumulator, value, index, collection) {
+ return func.call(thisArg, accumulator, value, index, collection);
+ };
+ }
+ return bind(func, thisArg);
}
/**
- * Checks if the specified object `property` exists and is a direct property,
- * instead of an inherited property.
+ * The base implementation of `createWrapper` that creates the wrapper and
+ * sets its meta data.
*
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The object to check.
- * @param {String} property The property to check for.
- * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
- * @example
- *
- * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
- * // => true
+ * @private
+ * @param {Array} bindData The bind data array.
+ * @returns {Function} Returns the new function.
*/
- function has(object, property) {
- return object ? hasOwnProperty.call(object, property) : false;
- }
+ function baseCreateWrapper(bindData) {
+ var func = bindData[0],
+ bitmask = bindData[1],
+ partialArgs = bindData[2],
+ partialRightArgs = bindData[3],
+ thisArg = bindData[4],
+ arity = bindData[5];
+
+ var isBind = bitmask & 1,
+ isBindKey = bitmask & 2,
+ isCurry = bitmask & 4,
+ isCurryBound = bitmask & 8,
+ key = func;
- /**
- * Creates an object composed of the inverted keys and values of the given `object`.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The object to invert.
- * @returns {Object} Returns the created inverted object.
- * @example
- *
- * _.invert({ 'first': 'Moe', 'second': 'Larry', 'third': 'Curly' });
- * // => { 'Moe': 'first', 'Larry': 'second', 'Curly': 'third' } (order is not guaranteed)
- */
- function invert(object) {
- var result = {};
- forOwn(object, function(value, key) {
- result[value] = key;
- });
- return result;
+ function bound() {
+ var thisBinding = isBind ? thisArg : this;
+ if (partialArgs) {
+ var args = partialArgs.slice();
+ push.apply(args, arguments);
+ }
+ if (partialRightArgs || isCurry) {
+ args || (args = slice(arguments));
+ if (partialRightArgs) {
+ push.apply(args, partialRightArgs);
+ }
+ if (isCurry && args.length < arity) {
+ bitmask |= 16 & ~32;
+ return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]);
+ }
+ }
+ args || (args = arguments);
+ if (isBindKey) {
+ func = thisBinding[key];
+ }
+ if (this instanceof bound) {
+ thisBinding = baseCreate(func.prototype);
+ var result = func.apply(thisBinding, args);
+ return isObject(result) ? result : thisBinding;
+ }
+ return func.apply(thisBinding, args);
+ }
+ setBindData(bound, bindData);
+ return bound;
}
/**
- * Checks if `value` is an array.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if the `value` is an array, else `false`.
- * @example
- *
- * (function() { return _.isArray(arguments); })();
- * // => false
+ * The base implementation of `_.difference` that accepts a single array
+ * of values to exclude.
*
- * _.isArray([1, 2, 3]);
- * // => true
+ * @private
+ * @param {Array} array The array to process.
+ * @param {Array} [values] The array of values to exclude.
+ * @returns {Array} Returns a new array of filtered values.
*/
- var isArray = nativeIsArray || function(value) {
- // `instanceof` may cause a memory leak in IE 7 if `value` is a host object
- // http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak
- return (argsAreObjects && value instanceof Array) || toString.call(value) == arrayClass;
- };
+ function baseDifference(array, values) {
+ var index = -1,
+ indexOf = getIndexOf(),
+ length = array ? array.length : 0,
+ isLarge = length >= largeArraySize && indexOf === baseIndexOf,
+ result = [];
- /**
- * Checks if `value` is a boolean (`true` or `false`) value.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if the `value` is a boolean value, else `false`.
- * @example
- *
- * _.isBoolean(null);
- * // => false
- */
- function isBoolean(value) {
- return value === true || value === false || toString.call(value) == boolClass;
+ if (isLarge) {
+ var cache = createCache(values);
+ if (cache) {
+ indexOf = cacheIndexOf;
+ values = cache;
+ } else {
+ isLarge = false;
+ }
+ }
+ while (++index < length) {
+ var value = array[index];
+ if (indexOf(values, value) < 0) {
+ result.push(value);
+ }
+ }
+ if (isLarge) {
+ releaseObject(values);
+ }
+ return result;
}
/**
- * Checks if `value` is a date.
+ * The base implementation of `_.flatten` without support for callback
+ * shorthands or `thisArg` binding.
*
- * @static
- * @memberOf _
- * @category Objects
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if the `value` is a date, else `false`.
- * @example
- *
- * _.isDate(new Date);
- * // => true
+ * @private
+ * @param {Array} array The array to flatten.
+ * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
+ * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
+ * @param {number} [fromIndex=0] The index to start from.
+ * @returns {Array} Returns a new flattened array.
*/
- function isDate(value) {
- return value instanceof Date || toString.call(value) == dateClass;
- }
+ function baseFlatten(array, isShallow, isStrict, fromIndex) {
+ var index = (fromIndex || 0) - 1,
+ length = array ? array.length : 0,
+ result = [];
- /**
- * Checks if `value` is a DOM element.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if the `value` is a DOM element, else `false`.
- * @example
- *
- * _.isElement(document.body);
- * // => true
- */
- function isElement(value) {
- return value ? value.nodeType === 1 : false;
- }
+ while (++index < length) {
+ var value = array[index];
- /**
- * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
- * length of `0` and objects with no own enumerable properties are considered
- * "empty".
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Array|Object|String} value The value to inspect.
- * @returns {Boolean} Returns `true` if the `value` is empty, else `false`.
- * @example
- *
- * _.isEmpty([1, 2, 3]);
- * // => false
- *
- * _.isEmpty({});
- * // => true
- *
- * _.isEmpty('');
- * // => true
- */
- function isEmpty(value) {
- var result = true;
- if (!value) {
- return result;
- }
- var className = toString.call(value),
- length = value.length;
+ if (value && typeof value == 'object' && typeof value.length == 'number'
+ && (isArray(value) || isArguments(value))) {
+ // recursively flatten arrays (susceptible to call stack limits)
+ if (!isShallow) {
+ value = baseFlatten(value, isShallow, isStrict);
+ }
+ var valIndex = -1,
+ valLength = value.length,
+ resIndex = result.length;
- if ((className == arrayClass || className == stringClass ||
- className == argsClass || (noArgsClass && isArguments(value))) ||
- (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
- return !length;
+ result.length += valLength;
+ while (++valIndex < valLength) {
+ result[resIndex++] = value[valIndex];
+ }
+ } else if (!isStrict) {
+ result.push(value);
+ }
}
- forOwn(value, function() {
- return (result = false);
- });
return result;
}
/**
- * Performs a deep comparison between two values to determine if they are
- * equivalent to each other.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Mixed} a The value to compare.
- * @param {Mixed} b The other value to compare.
- * @param- {Object} [stackA=[]] Internally used track traversed `a` objects.
- * @param- {Object} [stackB=[]] Internally used track traversed `b` objects.
- * @returns {Boolean} Returns `true` if the values are equvalent, else `false`.
- * @example
- *
- * var moe = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
- * var clone = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
- *
- * moe == clone;
- * // => false
+ * The base implementation of `_.isEqual`, without support for `thisArg` binding,
+ * that allows partial "_.where" style comparisons.
*
- * _.isEqual(moe, clone);
- * // => true
+ * @private
+ * @param {*} a The value to compare.
+ * @param {*} b The other value to compare.
+ * @param {Function} [callback] The function to customize comparing values.
+ * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
+ * @param {Array} [stackA=[]] Tracks traversed `a` objects.
+ * @param {Array} [stackB=[]] Tracks traversed `b` objects.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
*/
- function isEqual(a, b, stackA, stackB) {
+ function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
+ // used to indicate that when comparing objects, `a` has at least the properties of `b`
+ if (callback) {
+ var result = callback(a, b);
+ if (typeof result != 'undefined') {
+ return !!result;
+ }
+ }
// exit early for identical values
if (a === b) {
// treat `+0` vs. `-0` as not equal
return a !== 0 || (1 / a == 1 / b);
}
- // a strict comparison is necessary because `null == undefined`
+ var type = typeof a,
+ otherType = typeof b;
+
+ // exit early for unlike primitive values
+ if (a === a &&
+ !(a && objectTypes[type]) &&
+ !(b && objectTypes[otherType])) {
+ return false;
+ }
+ // exit early for `null` and `undefined` avoiding ES3's Function#call behavior
+ // http://es5.github.io/#x15.3.4.4
if (a == null || b == null) {
return a === b;
}
// compare [[Class]] names
var className = toString.call(a),
- otherName = toString.call(b);
+ otherClass = toString.call(b);
if (className == argsClass) {
className = objectClass;
}
- if (otherName == argsClass) {
- otherName = objectClass;
+ if (otherClass == argsClass) {
+ otherClass = objectClass;
}
- if (className != otherName) {
+ if (className != otherClass) {
return false;
}
switch (className) {
case boolClass:
case dateClass:
// coerce dates and booleans to numbers, dates to milliseconds and booleans
- // to `1` or `0`, treating invalid dates coerced to `NaN` as not equal
+ // to `1` or `0` treating invalid dates coerced to `NaN` as not equal
return +a == +b;
case numberClass:
// treat `NaN` vs. `NaN` as equal
- return a != +a
+ return (a != +a)
? b != +b
// but treat `+0` vs. `-0` as not equal
: (a == 0 ? (1 / a == 1 / b) : a == +b);
case regexpClass:
case stringClass:
- // coerce regexes to strings (http://es5.github.com/#x15.10.6.4)
+ // coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
// treat string primitives and their corresponding object instances as equal
- return a == b + '';
+ return a == String(b);
}
var isArr = className == arrayClass;
if (!isArr) {
// unwrap any `lodash` wrapped values
- if (a.__wrapped__ || b.__wrapped__) {
- return isEqual(a.__wrapped__ || a, b.__wrapped__ || b);
+ var aWrapped = hasOwnProperty.call(a, '__wrapped__'),
+ bWrapped = hasOwnProperty.call(b, '__wrapped__');
+
+ if (aWrapped || bWrapped) {
+ return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB);
}
// exit for functions and DOM nodes
- if (className != objectClass || (noNodeClass && (isNode(a) || isNode(b)))) {
+ if (className != objectClass || (!support.nodeClass && (isNode(a) || isNode(b)))) {
return false;
}
// in older versions of Opera, `arguments` objects have `Array` constructors
- var ctorA = !argsAreObjects && isArguments(a) ? Object : a.constructor,
- ctorB = !argsAreObjects && isArguments(b) ? Object : b.constructor;
+ var ctorA = !support.argsObject && isArguments(a) ? Object : a.constructor,
+ ctorB = !support.argsObject && isArguments(b) ? Object : b.constructor;
// non `Object` object instances with different constructors are not equal
- if (ctorA != ctorB && !(
- isFunction(ctorA) && ctorA instanceof ctorA &&
- isFunction(ctorB) && ctorB instanceof ctorB
- )) {
+ if (ctorA != ctorB &&
+ !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
+ ('constructor' in a && 'constructor' in b)
+ ) {
return false;
}
}
// assume cyclic structures are equal
// the algorithm for detecting cyclic structures is adapted from ES 5.1
- // section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3)
- stackA || (stackA = []);
- stackB || (stackB = []);
+ // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
+ var initedStack = !stackA;
+ stackA || (stackA = getArray());
+ stackB || (stackB = getArray());
var length = stackA.length;
while (length--) {
return stackB[length] == b;
}
}
- var index = -1,
- result = true,
- size = 0;
+ var size = 0;
+ result = true;
// add `a` and `b` to the stack of traversed objects
stackA.push(a);
// recursively compare objects and arrays (susceptible to call stack limits)
if (isArr) {
- // compare lengths to determine if a deep comparison is necessary
- size = a.length;
- result = size == b.length;
+ length = a.length;
+ size = b.length;
- if (result) {
- // deep compare the contents, ignoring non-numeric properties
- while (size--) {
- if (!(result = isEqual(a[size], b[size], stackA, stackB))) {
- break;
+ // compare lengths to determine if a deep comparison is necessary
+ result = size == a.length;
+ if (!result && !isWhere) {
+ return result;
+ }
+ // deep compare the contents, ignoring non-numeric properties
+ while (size--) {
+ var index = length,
+ value = b[size];
+
+ if (isWhere) {
+ while (index--) {
+ if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
+ break;
+ }
}
+ } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
+ break;
}
}
return result;
}
// deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
// which, in this case, is more costly
- forIn(a, function(value, key, a) {
- if (hasOwnProperty.call(a, key)) {
+ forIn(b, function(value, key, b) {
+ if (hasOwnProperty.call(b, key)) {
// count the number of properties.
size++;
// deep compare each property value.
- return (result = hasOwnProperty.call(b, key) && isEqual(value, b[key], stackA, stackB));
+ return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
}
});
- if (result) {
+ if (result && !isWhere) {
// ensure both objects have the same number of properties
- forIn(b, function(value, key, b) {
- if (hasOwnProperty.call(b, key)) {
- // `size` will be `-1` if `b` has more properties than `a`
+ forIn(a, function(value, key, a) {
+ if (hasOwnProperty.call(a, key)) {
+ // `size` will be `-1` if `a` has more properties than `b`
return (result = --size > -1);
}
});
}
+ if (initedStack) {
+ releaseArray(stackA);
+ releaseArray(stackB);
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.merge` without argument juggling or support
+ * for `thisArg` binding.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @param {Function} [callback] The function to customize merging properties.
+ * @param {Array} [stackA=[]] Tracks traversed source objects.
+ * @param {Array} [stackB=[]] Associates values with source counterparts.
+ */
+ function baseMerge(object, source, callback, stackA, stackB) {
+ (isArray(source) ? forEach : forOwn)(source, function(source, key) {
+ var found,
+ isArr,
+ result = source,
+ value = object[key];
+
+ if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
+ // avoid merging previously merged cyclic sources
+ var stackLength = stackA.length;
+ while (stackLength--) {
+ if ((found = stackA[stackLength] == source)) {
+ value = stackB[stackLength];
+ break;
+ }
+ }
+ if (!found) {
+ var isShallow;
+ if (callback) {
+ result = callback(value, source);
+ if ((isShallow = typeof result != 'undefined')) {
+ value = result;
+ }
+ }
+ if (!isShallow) {
+ value = isArr
+ ? (isArray(value) ? value : [])
+ : (isPlainObject(value) ? value : {});
+ }
+ // add `source` and associated `value` to the stack of traversed objects
+ stackA.push(source);
+ stackB.push(value);
+
+ // recursively merge objects and arrays (susceptible to call stack limits)
+ if (!isShallow) {
+ baseMerge(value, source, callback, stackA, stackB);
+ }
+ }
+ }
+ else {
+ if (callback) {
+ result = callback(value, source);
+ if (typeof result == 'undefined') {
+ result = source;
+ }
+ }
+ if (typeof result != 'undefined') {
+ value = result;
+ }
+ }
+ object[key] = value;
+ });
+ }
+
+ /**
+ * The base implementation of `_.uniq` without support for callback shorthands
+ * or `thisArg` binding.
+ *
+ * @private
+ * @param {Array} array The array to process.
+ * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
+ * @param {Function} [callback] The function called per iteration.
+ * @returns {Array} Returns a duplicate-value-free array.
+ */
+ function baseUniq(array, isSorted, callback) {
+ var index = -1,
+ indexOf = getIndexOf(),
+ length = array ? array.length : 0,
+ result = [];
+
+ var isLarge = !isSorted && length >= largeArraySize && indexOf === baseIndexOf,
+ seen = (callback || isLarge) ? getArray() : result;
+
+ if (isLarge) {
+ var cache = createCache(seen);
+ if (cache) {
+ indexOf = cacheIndexOf;
+ seen = cache;
+ } else {
+ isLarge = false;
+ seen = callback ? seen : (releaseArray(seen), result);
+ }
+ }
+ while (++index < length) {
+ var value = array[index],
+ computed = callback ? callback(value, index, array) : value;
+
+ if (isSorted
+ ? !index || seen[seen.length - 1] !== computed
+ : indexOf(seen, computed) < 0
+ ) {
+ if (callback || isLarge) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ }
+ if (isLarge) {
+ releaseArray(seen.array);
+ releaseObject(seen);
+ } else if (callback) {
+ releaseArray(seen);
+ }
+ return result;
+ }
+
+ /**
+ * Creates a function that aggregates a collection, creating an object composed
+ * of keys generated from the results of running each element of the collection
+ * through a callback. The given `setter` function sets the keys and values
+ * of the composed object.
+ *
+ * @private
+ * @param {Function} setter The setter function.
+ * @returns {Function} Returns the new aggregator function.
+ */
+ function createAggregator(setter) {
+ return function(collection, callback, thisArg) {
+ var result = {};
+ callback = lodash.createCallback(callback, thisArg, 3);
+
+ if (isArray(collection)) {
+ var index = -1,
+ length = collection.length;
+
+ while (++index < length) {
+ var value = collection[index];
+ setter(result, value, callback(value, index, collection), collection);
+ }
+ } else {
+ baseEach(collection, function(value, key, collection) {
+ setter(result, value, callback(value, key, collection), collection);
+ });
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Creates a function that, when called, either curries or invokes `func`
+ * with an optional `this` binding and partially applied arguments.
+ *
+ * @private
+ * @param {Function|string} func The function or method name to reference.
+ * @param {number} bitmask The bitmask of method flags to compose.
+ * The bitmask may be composed of the following flags:
+ * 1 - `_.bind`
+ * 2 - `_.bindKey`
+ * 4 - `_.curry`
+ * 8 - `_.curry` (bound)
+ * 16 - `_.partial`
+ * 32 - `_.partialRight`
+ * @param {Array} [partialArgs] An array of arguments to prepend to those
+ * provided to the new function.
+ * @param {Array} [partialRightArgs] An array of arguments to append to those
+ * provided to the new function.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {number} [arity] The arity of `func`.
+ * @returns {Function} Returns the new function.
+ */
+ function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) {
+ var isBind = bitmask & 1,
+ isBindKey = bitmask & 2,
+ isCurry = bitmask & 4,
+ isCurryBound = bitmask & 8,
+ isPartial = bitmask & 16,
+ isPartialRight = bitmask & 32;
+
+ if (!isBindKey && !isFunction(func)) {
+ throw new TypeError;
+ }
+ if (isPartial && !partialArgs.length) {
+ bitmask &= ~16;
+ isPartial = partialArgs = false;
+ }
+ if (isPartialRight && !partialRightArgs.length) {
+ bitmask &= ~32;
+ isPartialRight = partialRightArgs = false;
+ }
+ var bindData = func && func.__bindData__;
+ if (bindData && bindData !== true) {
+ bindData = bindData.slice();
+
+ // set `thisBinding` is not previously bound
+ if (isBind && !(bindData[1] & 1)) {
+ bindData[4] = thisArg;
+ }
+ // set if previously bound but not currently (subsequent curried functions)
+ if (!isBind && bindData[1] & 1) {
+ bitmask |= 8;
+ }
+ // set curried arity if not yet set
+ if (isCurry && !(bindData[1] & 4)) {
+ bindData[5] = arity;
+ }
+ // append partial left arguments
+ if (isPartial) {
+ push.apply(bindData[2] || (bindData[2] = []), partialArgs);
+ }
+ // append partial right arguments
+ if (isPartialRight) {
+ push.apply(bindData[3] || (bindData[3] = []), partialRightArgs);
+ }
+ // merge flags
+ bindData[1] |= bitmask;
+ return createWrapper.apply(null, bindData);
+ }
+ // fast path for `_.bind`
+ var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper;
+ return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]);
+ }
+
+ /**
+ * Creates compiled iteration functions.
+ *
+ * @private
+ * @param {...Object} [options] The compile options object(s).
+ * @param {string} [options.array] Code to determine if the iterable is an array or array-like.
+ * @param {boolean} [options.useHas] Specify using `hasOwnProperty` checks in the object loop.
+ * @param {Function} [options.keys] A reference to `_.keys` for use in own property iteration.
+ * @param {string} [options.args] A comma separated string of iteration function arguments.
+ * @param {string} [options.top] Code to execute before the iteration branches.
+ * @param {string} [options.loop] Code to execute in the object loop.
+ * @param {string} [options.bottom] Code to execute after the iteration branches.
+ * @returns {Function} Returns the compiled function.
+ */
+ function createIterator() {
+ // data properties
+ iteratorData.shadowedProps = shadowedProps;
+
+ // iterator options
+ iteratorData.array = iteratorData.bottom = iteratorData.loop = iteratorData.top = '';
+ iteratorData.init = 'iterable';
+ iteratorData.useHas = true;
+
+ // merge options into a template data object
+ for (var object, index = 0; object = arguments[index]; index++) {
+ for (var key in object) {
+ iteratorData[key] = object[key];
+ }
+ }
+ var args = iteratorData.args;
+ iteratorData.firstArg = /^[^,]+/.exec(args)[0];
+
+ // create the function factory
+ var factory = Function(
+ 'baseCreateCallback, errorClass, errorProto, hasOwnProperty, ' +
+ 'indicatorObject, isArguments, isArray, isString, keys, objectProto, ' +
+ 'objectTypes, nonEnumProps, stringClass, stringProto, toString',
+ 'return function(' + args + ') {\n' + iteratorTemplate(iteratorData) + '\n}'
+ );
+
+ // return the compiled function
+ return factory(
+ baseCreateCallback, errorClass, errorProto, hasOwnProperty,
+ indicatorObject, isArguments, isArray, isString, iteratorData.keys, objectProto,
+ objectTypes, nonEnumProps, stringClass, stringProto, toString
+ );
+ }
+
+ /**
+ * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
+ * customized, this method returns the custom method, otherwise it returns
+ * the `baseIndexOf` function.
+ *
+ * @private
+ * @returns {Function} Returns the "indexOf" function.
+ */
+ function getIndexOf() {
+ var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result;
return result;
}
/**
- * Checks if `value` is, or can be coerced to, a finite number.
- *
- * Note: This is not the same as native `isFinite`, which will return true for
- * booleans and empty strings. See http://es5.github.com/#x15.1.2.5.
+ * Sets `this` binding data on a given function.
+ *
+ * @private
+ * @param {Function} func The function to set data on.
+ * @param {Array} value The data array to set.
+ */
+ var setBindData = !defineProperty ? noop : function(func, value) {
+ descriptor.value = value;
+ defineProperty(func, '__bindData__', descriptor);
+ };
+
+ /**
+ * A fallback implementation of `isPlainObject` which checks if a given value
+ * is an object created by the `Object` constructor, assuming objects created
+ * by the `Object` constructor have no inherited enumerable properties and that
+ * there are no `Object.prototype` extensions.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+ */
+ function shimIsPlainObject(value) {
+ var ctor,
+ result;
+
+ // avoid non Object objects, `arguments` objects, and DOM elements
+ if (!(value && toString.call(value) == objectClass) ||
+ (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor)) ||
+ (!support.argsClass && isArguments(value)) ||
+ (!support.nodeClass && isNode(value))) {
+ return false;
+ }
+ // IE < 9 iterates inherited properties before own properties. If the first
+ // iterated property is an object's own property then there are no inherited
+ // enumerable properties.
+ if (support.ownLast) {
+ forIn(value, function(value, key, object) {
+ result = hasOwnProperty.call(object, key);
+ return false;
+ });
+ return result !== false;
+ }
+ // In most environments an object's own properties are iterated before
+ // its inherited properties. If the last iterated property is an object's
+ // own property then there are no inherited enumerable properties.
+ forIn(value, function(value, key) {
+ result = key;
+ });
+ return typeof result == 'undefined' || hasOwnProperty.call(value, result);
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Checks if `value` is an `arguments` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
+ * @example
+ *
+ * (function() { return _.isArguments(arguments); })(1, 2, 3);
+ * // => true
+ *
+ * _.isArguments([1, 2, 3]);
+ * // => false
+ */
+ function isArguments(value) {
+ return value && typeof value == 'object' && typeof value.length == 'number' &&
+ toString.call(value) == argsClass || false;
+ }
+ // fallback for browsers that can't detect `arguments` objects by [[Class]]
+ if (!support.argsClass) {
+ isArguments = function(value) {
+ return value && typeof value == 'object' && typeof value.length == 'number' &&
+ hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee') || false;
+ };
+ }
+
+ /**
+ * Checks if `value` is an array.
+ *
+ * @static
+ * @memberOf _
+ * @type Function
+ * @category Objects
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if the `value` is an array, else `false`.
+ * @example
+ *
+ * (function() { return _.isArray(arguments); })();
+ * // => false
+ *
+ * _.isArray([1, 2, 3]);
+ * // => true
+ */
+ var isArray = nativeIsArray || function(value) {
+ return value && typeof value == 'object' && typeof value.length == 'number' &&
+ toString.call(value) == arrayClass || false;
+ };
+
+ /**
+ * A fallback implementation of `Object.keys` which produces an array of the
+ * given object's own enumerable property names.
+ *
+ * @private
+ * @type Function
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns an array of property names.
+ */
+ var shimKeys = createIterator({
+ 'args': 'object',
+ 'init': '[]',
+ 'top': 'if (!(objectTypes[typeof object])) return result',
+ 'loop': 'result.push(index)'
+ });
+
+ /**
+ * Creates an array composed of the own enumerable property names of an object.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns an array of property names.
+ * @example
+ *
+ * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
+ * // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
+ */
+ var keys = !nativeKeys ? shimKeys : function(object) {
+ if (!isObject(object)) {
+ return [];
+ }
+ if ((support.enumPrototypes && typeof object == 'function') ||
+ (support.nonEnumArgs && object.length && isArguments(object))) {
+ return shimKeys(object);
+ }
+ return nativeKeys(object);
+ };
+
+ /** Reusable iterator options shared by `each`, `forIn`, and `forOwn` */
+ var eachIteratorOptions = {
+ 'args': 'collection, callback, thisArg',
+ 'top': "callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3)",
+ 'array': "typeof length == 'number'",
+ 'keys': keys,
+ 'loop': 'if (callback(iterable[index], index, collection) === false) return result'
+ };
+
+ /** Reusable iterator options for `assign` and `defaults` */
+ var defaultsIteratorOptions = {
+ 'args': 'object, source, guard',
+ 'top':
+ 'var args = arguments,\n' +
+ ' argsIndex = 0,\n' +
+ " argsLength = typeof guard == 'number' ? 2 : args.length;\n" +
+ 'while (++argsIndex < argsLength) {\n' +
+ ' iterable = args[argsIndex];\n' +
+ ' if (iterable && objectTypes[typeof iterable]) {',
+ 'keys': keys,
+ 'loop': "if (typeof result[index] == 'undefined') result[index] = iterable[index]",
+ 'bottom': ' }\n}'
+ };
+
+ /** Reusable iterator options for `forIn` and `forOwn` */
+ var forOwnIteratorOptions = {
+ 'top': 'if (!objectTypes[typeof iterable]) return result;\n' + eachIteratorOptions.top,
+ 'array': false
+ };
+
+ /**
+ * A function compiled to iterate `arguments` objects, arrays, objects, and
+ * strings consistenly across environments, executing the callback for each
+ * element in the collection. The callback is bound to `thisArg` and invoked
+ * with three arguments; (value, index|key, collection). Callbacks may exit
+ * iteration early by explicitly returning `false`.
+ *
+ * @private
+ * @type Function
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} [callback=identity] The function called per iteration.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {Array|Object|string} Returns `collection`.
+ */
+ var baseEach = createIterator(eachIteratorOptions);
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Assigns own enumerable properties of source object(s) to the destination
+ * object. Subsequent sources will overwrite property assignments of previous
+ * sources. If a callback is provided it will be executed to produce the
+ * assigned values. The callback is bound to `thisArg` and invoked with two
+ * arguments; (objectValue, sourceValue).
+ *
+ * @static
+ * @memberOf _
+ * @type Function
+ * @alias extend
+ * @category Objects
+ * @param {Object} object The destination object.
+ * @param {...Object} [source] The source objects.
+ * @param {Function} [callback] The function to customize assigning values.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {Object} Returns the destination object.
+ * @example
+ *
+ * _.assign({ 'name': 'fred' }, { 'employer': 'slate' });
+ * // => { 'name': 'fred', 'employer': 'slate' }
+ *
+ * var defaults = _.partialRight(_.assign, function(a, b) {
+ * return typeof a == 'undefined' ? b : a;
+ * });
+ *
+ * var object = { 'name': 'barney' };
+ * defaults(object, { 'name': 'fred', 'employer': 'slate' });
+ * // => { 'name': 'barney', 'employer': 'slate' }
+ */
+ var assign = createIterator(defaultsIteratorOptions, {
+ 'top':
+ defaultsIteratorOptions.top.replace(';',
+ ';\n' +
+ "if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n" +
+ ' var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);\n' +
+ "} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n" +
+ ' callback = args[--argsLength];\n' +
+ '}'
+ ),
+ 'loop': 'result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]'
+ });
+
+ /**
+ * Creates a clone of `value`. If `isDeep` is `true` nested objects will also
+ * be cloned, otherwise they will be assigned by reference. If a callback
+ * is provided it will be executed to produce the cloned values. If the
+ * callback returns `undefined` cloning will be handled by the method instead.
+ * The callback is bound to `thisArg` and invoked with one argument; (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {*} value The value to clone.
+ * @param {boolean} [isDeep=false] Specify a deep clone.
+ * @param {Function} [callback] The function to customize cloning values.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {*} Returns the cloned value.
+ * @example
+ *
+ * var characters = [
+ * { 'name': 'barney', 'age': 36 },
+ * { 'name': 'fred', 'age': 40 }
+ * ];
+ *
+ * var shallow = _.clone(characters);
+ * shallow[0] === characters[0];
+ * // => true
+ *
+ * var deep = _.clone(characters, true);
+ * deep[0] === characters[0];
+ * // => false
+ *
+ * _.mixin({
+ * 'clone': _.partialRight(_.clone, function(value) {
+ * return _.isElement(value) ? value.cloneNode(false) : undefined;
+ * })
+ * });
+ *
+ * var clone = _.clone(document.body);
+ * clone.childNodes.length;
+ * // => 0
+ */
+ function clone(value, isDeep, callback, thisArg) {
+ // allows working with "Collections" methods without using their `index`
+ // and `collection` arguments for `isDeep` and `callback`
+ if (typeof isDeep != 'boolean' && isDeep != null) {
+ thisArg = callback;
+ callback = isDeep;
+ isDeep = false;
+ }
+ return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
+ }
+
+ /**
+ * Creates a deep clone of `value`. If a callback is provided it will be
+ * executed to produce the cloned values. If the callback returns `undefined`
+ * cloning will be handled by the method instead. The callback is bound to
+ * `thisArg` and invoked with one argument; (value).
+ *
+ * Note: This method is loosely based on the structured clone algorithm. Functions
+ * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
+ * objects created by constructors other than `Object` are cloned to plain `Object` objects.
+ * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {*} value The value to deep clone.
+ * @param {Function} [callback] The function to customize cloning values.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {*} Returns the deep cloned value.
+ * @example
+ *
+ * var characters = [
+ * { 'name': 'barney', 'age': 36 },
+ * { 'name': 'fred', 'age': 40 }
+ * ];
+ *
+ * var deep = _.cloneDeep(characters);
+ * deep[0] === characters[0];
+ * // => false
+ *
+ * var view = {
+ * 'label': 'docs',
+ * 'node': element
+ * };
+ *
+ * var clone = _.cloneDeep(view, function(value) {
+ * return _.isElement(value) ? value.cloneNode(true) : undefined;
+ * });
+ *
+ * clone.node == view.node;
+ * // => false
+ */
+ function cloneDeep(value, callback, thisArg) {
+ return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
+ }
+
+ /**
+ * Iterates over own and inherited enumerable properties of an object,
+ * executing the callback for each property. The callback is bound to `thisArg`
+ * and invoked with three arguments; (value, key, object). Callbacks may exit
+ * iteration early by explicitly returning `false`.
*
* @static
* @memberOf _
+ * @type Function
* @category Objects
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if the `value` is a finite number, else `false`.
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [callback=identity] The function called per iteration.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {Object} Returns `object`.
* @example
*
- * _.isFinite(-101);
- * // => true
+ * function Shape() {
+ * this.x = 0;
+ * this.y = 0;
+ * }
*
- * _.isFinite('10');
- * // => true
+ * Shape.prototype.move = function(x, y) {
+ * this.x += x;
+ * this.y += y;
+ * };
*
- * _.isFinite(true);
- * // => false
+ * _.forIn(new Shape, function(value, key) {
+ * console.log(key);
+ * });
+ * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments)
+ */
+ var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, {
+ 'useHas': false
+ });
+
+ /**
+ * Iterates over own enumerable properties of an object, executing the callback
+ * for each property. The callback is bound to `thisArg` and invoked with three
+ * arguments; (value, key, object). Callbacks may exit iteration early by
+ * explicitly returning `false`.
*
- * _.isFinite('');
- * // => false
+ * @static
+ * @memberOf _
+ * @type Function
+ * @category Objects
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [callback=identity] The function called per iteration.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {Object} Returns `object`.
+ * @example
*
- * _.isFinite(Infinity);
- * // => false
+ * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
+ * console.log(key);
+ * });
+ * // => logs '0', '1', and 'length' (property order is not guaranteed across environments)
*/
- function isFinite(value) {
- return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
- }
+ var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions);
/**
- * Checks if `value` is a function.
+ * Creates a sorted array of property names of all enumerable properties,
+ * own and inherited, of `object` that have function values.
*
* @static
* @memberOf _
+ * @alias methods
* @category Objects
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if the `value` is a function, else `false`.
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns an array of property names that have function values.
* @example
*
- * _.isFunction(_);
- * // => true
+ * _.functions(_);
+ * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
*/
- function isFunction(value) {
- return typeof value == 'function';
- }
- // fallback for older versions of Chrome and Safari
- if (isFunction(/x/)) {
- isFunction = function(value) {
- return value instanceof Function || toString.call(value) == funcClass;
- };
+ function functions(object) {
+ var result = [];
+ forIn(object, function(value, key) {
+ if (isFunction(value)) {
+ result.push(key);
+ }
+ });
+ return result.sort();
}
/**
- * Checks if `value` is the language type of Object.
- * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
+ * length of `0` and objects with no own enumerable properties are considered
+ * "empty".
*
* @static
* @memberOf _
* @category Objects
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if the `value` is an object, else `false`.
+ * @param {Array|Object|string} value The value to inspect.
+ * @returns {boolean} Returns `true` if the `value` is empty, else `false`.
* @example
*
- * _.isObject({});
- * // => true
+ * _.isEmpty([1, 2, 3]);
+ * // => false
*
- * _.isObject([1, 2, 3]);
+ * _.isEmpty({});
* // => true
*
- * _.isObject(1);
- * // => false
+ * _.isEmpty('');
+ * // => true
*/
- function isObject(value) {
- // check if the value is the ECMAScript language type of Object
- // http://es5.github.com/#x8
- // and avoid a V8 bug
- // http://code.google.com/p/v8/issues/detail?id=2291
- return value ? objectTypes[typeof value] : false;
+ function isEmpty(value) {
+ var result = true;
+ if (!value) {
+ return result;
+ }
+ var className = toString.call(value),
+ length = value.length;
+
+ if ((className == arrayClass || className == stringClass ||
+ (support.argsClass ? className == argsClass : isArguments(value))) ||
+ (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
+ return !length;
+ }
+ forOwn(value, function() {
+ return (result = false);
+ });
+ return result;
}
/**
- * Checks if `value` is `NaN`.
- *
- * Note: This is not the same as native `isNaN`, which will return `true` for
- * `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
+ * Performs a deep comparison between two values to determine if they are
+ * equivalent to each other. If a callback is provided it will be executed
+ * to compare values. If the callback returns `undefined` comparisons will
+ * be handled by the method instead. The callback is bound to `thisArg` and
+ * invoked with two arguments; (a, b).
*
* @static
* @memberOf _
* @category Objects
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if the `value` is `NaN`, else `false`.
+ * @param {*} a The value to compare.
+ * @param {*} b The other value to compare.
+ * @param {Function} [callback] The function to customize comparing values.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
* @example
*
- * _.isNaN(NaN);
- * // => true
+ * var object = { 'name': 'fred' };
+ * var copy = { 'name': 'fred' };
*
- * _.isNaN(new Number(NaN));
- * // => true
+ * object == copy;
+ * // => false
*
- * isNaN(undefined);
+ * _.isEqual(object, copy);
* // => true
*
- * _.isNaN(undefined);
- * // => false
+ * var words = ['hello', 'goodbye'];
+ * var otherWords = ['hi', 'goodbye'];
+ *
+ * _.isEqual(words, otherWords, function(a, b) {
+ * var reGreet = /^(?:hello|hi)$/i,
+ * aGreet = _.isString(a) && reGreet.test(a),
+ * bGreet = _.isString(b) && reGreet.test(b);
+ *
+ * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
+ * });
+ * // => true
*/
- function isNaN(value) {
- // `NaN` as a primitive is the only value that is not equal to itself
- // (perform the [[Class]] check first to avoid errors with some host objects in IE)
- return isNumber(value) && value != +value
+ function isEqual(a, b, callback, thisArg) {
+ return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2));
}
/**
- * Checks if `value` is `null`.
+ * Checks if `value` is a function.
*
* @static
* @memberOf _
* @category Objects
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if the `value` is `null`, else `false`.
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if the `value` is a function, else `false`.
* @example
*
- * _.isNull(null);
+ * _.isFunction(_);
* // => true
- *
- * _.isNull(undefined);
- * // => false
*/
- function isNull(value) {
- return value === null;
+ function isFunction(value) {
+ return typeof value == 'function';
+ }
+ // fallback for older versions of Chrome and Safari
+ if (isFunction(/x/)) {
+ isFunction = function(value) {
+ return typeof value == 'function' && toString.call(value) == funcClass;
+ };
}
/**
- * Checks if `value` is a number.
+ * Checks if `value` is the language type of Object.
+ * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static
* @memberOf _
* @category Objects
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if the `value` is a number, else `false`.
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if the `value` is an object, else `false`.
* @example
*
- * _.isNumber(8.4 * 5);
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
* // => true
+ *
+ * _.isObject(1);
+ * // => false
*/
- function isNumber(value) {
- return typeof value == 'number' || toString.call(value) == numberClass;
+ function isObject(value) {
+ // check if the value is the ECMAScript language type of Object
+ // http://es5.github.io/#x8
+ // and avoid a V8 bug
+ // http://code.google.com/p/v8/issues/detail?id=2291
+ return !!(value && objectTypes[typeof value]);
}
/**
- * Checks if a given `value` is an object created by the `Object` constructor.
+ * Checks if `value` is an object created by the `Object` constructor.
*
* @static
* @memberOf _
* @category Objects
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if `value` is a plain object, else `false`.
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
* @example
*
- * function Stooge(name, age) {
- * this.name = name;
- * this.age = age;
+ * function Shape() {
+ * this.x = 0;
+ * this.y = 0;
* }
*
- * _.isPlainObject(new Stooge('moe', 40));
+ * _.isPlainObject(new Shape);
* // => false
*
* _.isPlainObject([1, 2, 3]);
* // => false
*
- * _.isPlainObject({ 'name': 'moe', 'age': 40 });
+ * _.isPlainObject({ 'x': 0, 'y': 0 });
* // => true
*/
var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
- if (!(value && typeof value == 'object')) {
+ if (!(value && toString.call(value) == objectClass) || (!support.argsClass && isArguments(value))) {
return false;
}
var valueOf = value.valueOf,
objProto = typeof valueOf == 'function' && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
return objProto
- ? value == objProto || (getPrototypeOf(value) == objProto && !isArguments(value))
+ ? (value == objProto || getPrototypeOf(value) == objProto)
: shimIsPlainObject(value);
};
- /**
- * Checks if `value` is a regular expression.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if the `value` is a regular expression, else `false`.
- * @example
- *
- * _.isRegExp(/moe/);
- * // => true
- */
- function isRegExp(value) {
- return value instanceof RegExp || toString.call(value) == regexpClass;
- }
-
/**
* Checks if `value` is a string.
*
* @static
* @memberOf _
* @category Objects
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if the `value` is a string, else `false`.
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if the `value` is a string, else `false`.
* @example
*
- * _.isString('moe');
+ * _.isString('fred');
* // => true
*/
function isString(value) {
- return typeof value == 'string' || toString.call(value) == stringClass;
+ return typeof value == 'string' ||
+ value && typeof value == 'object' && toString.call(value) == stringClass || false;
}
/**
- * Checks if `value` is `undefined`.
+ * Recursively merges own enumerable properties of the source object(s), that
+ * don't resolve to `undefined` into the destination object. Subsequent sources
+ * will overwrite property assignments of previous sources. If a callback is
+ * provided it will be executed to produce the merged values of the destination
+ * and source properties. If the callback returns `undefined` merging will
+ * be handled by the method instead. The callback is bound to `thisArg` and
+ * invoked with two arguments; (objectValue, sourceValue).
*
* @static
* @memberOf _
* @category Objects
- * @param {Mixed} value The value to check.
- * @returns {Boolean} Returns `true` if the `value` is `undefined`, else `false`.
+ * @param {Object} object The destination object.
+ * @param {...Object} [source] The source objects.
+ * @param {Function} [callback] The function to customize merging properties.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {Object} Returns the destination object.
* @example
*
- * _.isUndefined(void 0);
- * // => true
- */
- function isUndefined(value) {
- return typeof value == 'undefined';
- }
-
- /**
- * Creates an array composed of the own enumerable property names of `object`.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The object to inspect.
- * @returns {Array} Returns a new array of property names.
- * @example
+ * var names = {
+ * 'characters': [
+ * { 'name': 'barney' },
+ * { 'name': 'fred' }
+ * ]
+ * };
*
- * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
- * // => ['one', 'two', 'three'] (order is not guaranteed)
- */
- var keys = !nativeKeys ? shimKeys : function(object) {
- // avoid iterating over the `prototype` property
- return typeof object == 'function' && propertyIsEnumerable.call(object, 'prototype')
- ? shimKeys(object)
- : (isObject(object) ? nativeKeys(object) : []);
- };
-
- /**
- * Merges enumerable properties of the source object(s) into the `destination`
- * object. Subsequent sources will overwrite propery assignments of previous
- * sources.
+ * var ages = {
+ * 'characters': [
+ * { 'age': 36 },
+ * { 'age': 40 }
+ * ]
+ * };
*
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The destination object.
- * @param {Object} [source1, source2, ...] The source objects.
- * @param- {Object} [indicator] Internally used to indicate that the `stack`
- * argument is an array of traversed objects instead of another source object.
- * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
- * @param- {Array} [stackB=[]] Internally used to associate values with their
- * source counterparts.
- * @returns {Object} Returns the destination object.
- * @example
+ * _.merge(names, ages);
+ * // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] }
*
- * var stooges = [
- * { 'name': 'moe' },
- * { 'name': 'larry' }
- * ];
+ * var food = {
+ * 'fruits': ['apple'],
+ * 'vegetables': ['beet']
+ * };
*
- * var ages = [
- * { 'age': 40 },
- * { 'age': 50 }
- * ];
+ * var otherFood = {
+ * 'fruits': ['banana'],
+ * 'vegetables': ['carrot']
+ * };
*
- * _.merge(stooges, ages);
- * // => [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }]
+ * _.merge(food, otherFood, function(a, b) {
+ * return _.isArray(a) ? a.concat(b) : undefined;
+ * });
+ * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
*/
- function merge(object, source, indicator) {
+ function merge(object) {
var args = arguments,
- index = 0,
- length = 2,
- stackA = args[3],
- stackB = args[4];
-
- if (indicator !== indicatorObject) {
- stackA = [];
- stackB = [];
-
- // work with `_.reduce` by only using its callback `accumulator` and `value` arguments
- if (typeof indicator != 'number') {
- length = args.length;
- }
+ length = 2;
+
+ if (!isObject(object)) {
+ return object;
+ }
+
+ // allows working with `_.reduce` and `_.reduceRight` without using
+ // their `index` and `collection` arguments
+ if (typeof args[2] != 'number') {
+ length = args.length;
+ }
+ if (length > 3 && typeof args[length - 2] == 'function') {
+ var callback = baseCreateCallback(args[--length - 1], args[length--], 2);
+ } else if (length > 2 && typeof args[length - 1] == 'function') {
+ callback = args[--length];
}
+ var sources = slice(arguments, 1, length),
+ index = -1,
+ stackA = getArray(),
+ stackB = getArray();
+
while (++index < length) {
- forOwn(args[index], function(source, key) {
- var found, isArr, value;
- if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
- // avoid merging previously merged cyclic sources
- var stackLength = stackA.length;
- while (stackLength--) {
- found = stackA[stackLength] == source;
- if (found) {
- break;
- }
- }
- if (found) {
- object[key] = stackB[stackLength];
- }
- else {
- // add `source` and associated `value` to the stack of traversed objects
- stackA.push(source);
- stackB.push(value = (value = object[key], isArr)
- ? (isArray(value) ? value : [])
- : (isPlainObject(value) ? value : {})
- );
- // recursively merge objects and arrays (susceptible to call stack limits)
- object[key] = merge(value, source, indicatorObject, stackA, stackB);
- }
- } else if (source != null) {
- object[key] = source;
- }
- });
+ baseMerge(object, sources[index], callback, stackA, stackB);
}
+ releaseArray(stackA);
+ releaseArray(stackB);
return object;
}
/**
* Creates a shallow clone of `object` excluding the specified properties.
* Property names may be specified as individual arguments or as arrays of
- * property names. If `callback` is passed, it will be executed for each property
- * in the `object`, omitting the properties `callback` returns truthy for. The
- * `callback` is bound to `thisArg` and invoked with three arguments; (value, key, object).
+ * property names. If a callback is provided it will be executed for each
+ * property of `object` omitting the properties the callback returns truey
+ * for. The callback is bound to `thisArg` and invoked with three arguments;
+ * (value, key, object).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The source object.
- * @param {Function|String} callback|[prop1, prop2, ...] The properties to omit
- * or the function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @param {Function|...string|string[]} [callback] The properties to omit or the
+ * function called per iteration.
+ * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns an object without the omitted properties.
* @example
*
- * _.omit({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'userid');
- * // => { 'name': 'moe', 'age': 40 }
+ * _.omit({ 'name': 'fred', 'age': 40 }, 'age');
+ * // => { 'name': 'fred' }
*
- * _.omit({ 'name': 'moe', '_hint': 'knucklehead', '_seed': '96c4eb' }, function(value, key) {
- * return key.charAt(0) == '_';
+ * _.omit({ 'name': 'fred', 'age': 40 }, function(value) {
+ * return typeof value == 'number';
* });
- * // => { 'name': 'moe' }
+ * // => { 'name': 'fred' }
*/
function omit(object, callback, thisArg) {
- var isFunc = typeof callback == 'function',
- result = {};
+ var result = {};
+ if (typeof callback != 'function') {
+ var props = [];
+ forIn(object, function(value, key) {
+ props.push(key);
+ });
+ props = baseDifference(props, baseFlatten(arguments, true, false, 1));
+
+ var index = -1,
+ length = props.length;
- if (isFunc) {
- callback = createCallback(callback, thisArg);
+ while (++index < length) {
+ var key = props[index];
+ result[key] = object[key];
+ }
} else {
- var props = concat.apply(arrayRef, arguments);
+ callback = lodash.createCallback(callback, thisArg, 3);
+ forIn(object, function(value, key, object) {
+ if (!callback(value, key, object)) {
+ result[key] = value;
+ }
+ });
}
- forIn(object, function(value, key, object) {
- if (isFunc
- ? !callback(value, key, object)
- : indexOf(props, key, 1) < 0
- ) {
- result[key] = value;
- }
- });
return result;
}
/**
- * Creates a two dimensional array of the given object's key-value pairs,
+ * Creates a two dimensional array of an object's key-value pairs,
* i.e. `[[key1, value1], [key2, value2]]`.
*
* @static
* @returns {Array} Returns new array of key-value pairs.
* @example
*
- * _.pairs({ 'moe': 30, 'larry': 40, 'curly': 50 });
- * // => [['moe', 30], ['larry', 40], ['curly', 50]] (order is not guaranteed)
+ * _.pairs({ 'barney': 36, 'fred': 40 });
+ * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments)
*/
function pairs(object) {
- var result = [];
- forOwn(object, function(value, key) {
- result.push([key, value]);
- });
- return result;
- }
-
- /**
- * Creates a shallow clone of `object` composed of the specified properties.
- * Property names may be specified as individual arguments or as arrays of
- * property names. If `callback` is passed, it will be executed for each property
- * in the `object`, picking the properties `callback` returns truthy for. The
- * `callback` is bound to `thisArg` and invoked with three arguments; (value, key, object).
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The source object.
- * @param {Function|String} callback|[prop1, prop2, ...] The properties to pick
- * or the function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns an object composed of the picked properties.
- * @example
- *
- * _.pick({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'name', 'age');
- * // => { 'name': 'moe', 'age': 40 }
- *
- * _.pick({ 'name': 'moe', '_hint': 'knucklehead', '_seed': '96c4eb' }, function(value, key) {
- * return key.charAt(0) != '_';
- * });
- * // => { 'name': 'moe' }
- */
- function pick(object, callback, thisArg) {
- var result = {};
- if (typeof callback != 'function') {
- var index = 0,
- props = concat.apply(arrayRef, arguments),
- length = props.length;
+ var index = -1,
+ props = keys(object),
+ length = props.length,
+ result = Array(length);
- while (++index < length) {
- var key = props[index];
- if (key in object) {
- result[key] = object[key];
- }
- }
- } else {
- callback = createCallback(callback, thisArg);
- forIn(object, function(value, key, object) {
- if (callback(value, key, object)) {
- result[key] = value;
- }
- });
+ while (++index < length) {
+ var key = props[index];
+ result[index] = [key, object[key]];
}
return result;
}
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
- * @returns {Array} Returns a new array of property values.
+ * @returns {Array} Returns an array of property values.
* @example
*
* _.values({ 'one': 1, 'two': 2, 'three': 3 });
- * // => [1, 2, 3]
+ * // => [1, 2, 3] (property order is not guaranteed across environments)
*/
function values(object) {
- var result = [];
- forOwn(object, function(value) {
- result.push(value);
- });
+ var index = -1,
+ props = keys(object),
+ length = props.length,
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = object[props[index]];
+ }
return result;
}
/*--------------------------------------------------------------------------*/
/**
- * Checks if a given `target` element is present in a `collection` using strict
- * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
- * as the offset from the end of the collection.
+ * Checks if a given value is present in a collection using strict equality
+ * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the
+ * offset from the end of the collection.
*
* @static
* @memberOf _
* @alias include
* @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Mixed} target The value to check for.
- * @param {Number} [fromIndex=0] The index to search from.
- * @returns {Boolean} Returns `true` if the `target` element is found, else `false`.
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {*} target The value to check for.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @returns {boolean} Returns `true` if the `target` element is found, else `false`.
* @example
*
* _.contains([1, 2, 3], 1);
* _.contains([1, 2, 3], 1, 2);
* // => false
*
- * _.contains({ 'name': 'moe', 'age': 40 }, 'moe');
+ * _.contains({ 'name': 'fred', 'age': 40 }, 'fred');
* // => true
*
- * _.contains('curly', 'ur');
+ * _.contains('pebbles', 'eb');
* // => true
*/
function contains(collection, target, fromIndex) {
var index = -1,
+ indexOf = getIndexOf(),
length = collection ? collection.length : 0,
result = false;
fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
- if (typeof length == 'number') {
- result = (isString(collection)
- ? collection.indexOf(target, fromIndex)
- : indexOf(collection, target, fromIndex)
- ) > -1;
+ if (isArray(collection)) {
+ result = indexOf(collection, target, fromIndex) > -1;
+ } else if (typeof length == 'number') {
+ result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1;
} else {
- each(collection, function(value) {
+ baseEach(collection, function(value) {
if (++index >= fromIndex) {
return !(result = value === target);
}
}
/**
- * Creates an object composed of keys returned from running each element of
- * `collection` through a `callback`. The corresponding value of each key is
- * the number of times the key was returned by `callback`. The `callback` is
- * bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
- * The `callback` argument may also be the name of a property to count by (e.g. 'length').
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Function|String} callback|property The function called per iteration
- * or property name to count by.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns the composed aggregate object.
- * @example
- *
- * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
- * // => { '4': 1, '6': 2 }
+ * Checks if the given callback returns truey value for **all** elements of
+ * a collection. The callback is bound to `thisArg` and invoked with three
+ * arguments; (value, index|key, collection).
*
- * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
- * // => { '4': 1, '6': 2 }
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
*
- * _.countBy(['one', 'two', 'three'], 'length');
- * // => { '3': 2, '5': 1 }
- */
- function countBy(collection, callback, thisArg) {
- var result = {};
- callback = createCallback(callback, thisArg);
-
- forEach(collection, function(value, key, collection) {
- key = callback(value, key, collection);
- (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
- });
- return result;
- }
-
- /**
- * Checks if the `callback` returns a truthy value for **all** elements of a
- * `collection`. The `callback` is bound to `thisArg` and invoked with three
- * arguments; (value, index|key, collection).
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
*
* @static
* @memberOf _
* @alias all
* @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Boolean} Returns `true` if all elements pass the callback check,
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [callback=identity] The function called
+ * per iteration. If a property name or object is provided it will be used
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {boolean} Returns `true` if all elements passed the callback check,
* else `false`.
* @example
*
- * _.every([true, 1, null, 'yes'], Boolean);
+ * _.every([true, 1, null, 'yes']);
+ * // => false
+ *
+ * var characters = [
+ * { 'name': 'barney', 'age': 36 },
+ * { 'name': 'fred', 'age': 40 }
+ * ];
+ *
+ * // using "_.pluck" callback shorthand
+ * _.every(characters, 'age');
+ * // => true
+ *
+ * // using "_.where" callback shorthand
+ * _.every(characters, { 'age': 36 });
* // => false
*/
function every(collection, callback, thisArg) {
var result = true;
- callback = createCallback(callback, thisArg);
+ callback = lodash.createCallback(callback, thisArg, 3);
if (isArray(collection)) {
var index = -1,
}
}
} else {
- each(collection, function(value, index, collection) {
+ baseEach(collection, function(value, index, collection) {
return (result = !!callback(value, index, collection));
});
}
}
/**
- * Examines each element in a `collection`, returning an array of all elements
- * the `callback` returns truthy for. The `callback` is bound to `thisArg` and
+ * Iterates over elements of a collection, returning an array of all elements
+ * the callback returns truey for. The callback is bound to `thisArg` and
* invoked with three arguments; (value, index|key, collection).
*
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
+ *
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
+ *
* @static
* @memberOf _
* @alias select
* @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [callback=identity] The function called
+ * per iteration. If a property name or object is provided it will be used
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of elements that passed the callback check.
* @example
*
* var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
* // => [2, 4, 6]
+ *
+ * var characters = [
+ * { 'name': 'barney', 'age': 36, 'blocked': false },
+ * { 'name': 'fred', 'age': 40, 'blocked': true }
+ * ];
+ *
+ * // using "_.pluck" callback shorthand
+ * _.filter(characters, 'blocked');
+ * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
+ *
+ * // using "_.where" callback shorthand
+ * _.filter(characters, { 'age': 36 });
+ * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
*/
function filter(collection, callback, thisArg) {
var result = [];
- callback = createCallback(callback, thisArg);
+ callback = lodash.createCallback(callback, thisArg, 3);
if (isArray(collection)) {
var index = -1,
}
}
} else {
- each(collection, function(value, index, collection) {
+ baseEach(collection, function(value, index, collection) {
if (callback(value, index, collection)) {
result.push(value);
}
}
/**
- * Examines each element in a `collection`, returning the first one the `callback`
- * returns truthy for. The function returns as soon as it finds an acceptable
- * element, and does not iterate over the entire `collection`. The `callback` is
- * bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
+ * Iterates over elements of a collection, returning the first element that
+ * the callback returns truey for. The callback is bound to `thisArg` and
+ * invoked with three arguments; (value, index|key, collection).
+ *
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
+ *
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
*
* @static
* @memberOf _
- * @alias detect
+ * @alias detect, findWhere
* @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Mixed} Returns the element that passed the callback check,
- * else `undefined`.
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [callback=identity] The function called
+ * per iteration. If a property name or object is provided it will be used
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {*} Returns the found element, else `undefined`.
* @example
*
- * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
- * // => 2
+ * var characters = [
+ * { 'name': 'barney', 'age': 36, 'blocked': false },
+ * { 'name': 'fred', 'age': 40, 'blocked': true },
+ * { 'name': 'pebbles', 'age': 1, 'blocked': false }
+ * ];
+ *
+ * _.find(characters, function(chr) {
+ * return chr.age < 40;
+ * });
+ * // => { 'name': 'barney', 'age': 36, 'blocked': false }
+ *
+ * // using "_.where" callback shorthand
+ * _.find(characters, { 'age': 1 });
+ * // => { 'name': 'pebbles', 'age': 1, 'blocked': false }
+ *
+ * // using "_.pluck" callback shorthand
+ * _.find(characters, 'blocked');
+ * // => { 'name': 'fred', 'age': 40, 'blocked': true }
*/
function find(collection, callback, thisArg) {
- var result;
- callback = createCallback(callback, thisArg);
+ callback = lodash.createCallback(callback, thisArg, 3);
- forEach(collection, function(value, index, collection) {
- if (callback(value, index, collection)) {
- result = value;
- return false;
+ if (isArray(collection)) {
+ var index = -1,
+ length = collection.length;
+
+ while (++index < length) {
+ var value = collection[index];
+ if (callback(value, index, collection)) {
+ return value;
+ }
}
- });
- return result;
+ } else {
+ var result;
+ baseEach(collection, function(value, index, collection) {
+ if (callback(value, index, collection)) {
+ result = value;
+ return false;
+ }
+ });
+ return result;
+ }
}
/**
- * Iterates over a `collection`, executing the `callback` for each element in
- * the `collection`. The `callback` is bound to `thisArg` and invoked with three
- * arguments; (value, index|key, collection). Callbacks may exit iteration early
- * by explicitly returning `false`.
+ * Iterates over elements of a collection, executing the callback for each
+ * element. The callback is bound to `thisArg` and invoked with three arguments;
+ * (value, index|key, collection). Callbacks may exit iteration early by
+ * explicitly returning `false`.
+ *
+ * Note: As with other "Collections" methods, objects with a `length` property
+ * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
+ * may be used for object iteration.
*
* @static
* @memberOf _
* @alias each
* @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Array|Object|string} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Array|Object|String} Returns `collection`.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {Array|Object|string} Returns `collection`.
* @example
*
- * _([1, 2, 3]).forEach(alert).join(',');
- * // => alerts each number and returns '1,2,3'
+ * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(',');
+ * // => logs each number and returns '1,2,3'
*
- * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
- * // => alerts each number value (order is not guaranteed)
+ * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
+ * // => logs each number and returns the object (property order is not guaranteed across environments)
*/
function forEach(collection, callback, thisArg) {
if (callback && typeof thisArg == 'undefined' && isArray(collection)) {
}
}
} else {
- each(collection, callback, thisArg);
+ baseEach(collection, callback, thisArg);
}
return collection;
}
/**
- * Creates an object composed of keys returned from running each element of
- * `collection` through a `callback`. The corresponding value of each key is an
- * array of elements passed to `callback` that returned the key. The `callback`
- * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
- * The `callback` argument may also be the name of a property to group by (e.g. 'length').
+ * Creates an object composed of keys generated from the results of running
+ * each element of a collection through the callback. The corresponding value
+ * of each key is an array of the elements responsible for generating the key.
+ * The callback is bound to `thisArg` and invoked with three arguments;
+ * (value, index|key, collection).
+ *
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
+ *
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`
*
* @static
* @memberOf _
* @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Function|String} callback|property The function called per iteration
- * or property name to group by.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [callback=identity] The function called
+ * per iteration. If a property name or object is provided it will be used
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
* // => { '4': [4.2], '6': [6.1, 6.4] }
*
+ * // using "_.pluck" callback shorthand
* _.groupBy(['one', 'two', 'three'], 'length');
* // => { '3': ['one', 'two'], '5': ['three'] }
*/
- function groupBy(collection, callback, thisArg) {
- var result = {};
- callback = createCallback(callback, thisArg);
-
- forEach(collection, function(value, key, collection) {
- key = callback(value, key, collection);
- (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
- });
- return result;
- }
+ var groupBy = createAggregator(function(result, value, key) {
+ (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
+ });
/**
- * Invokes the method named by `methodName` on each element in the `collection`,
- * returning an array of the results of each invoked method. Additional arguments
- * will be passed to each invoked method. If `methodName` is a function it will
- * be invoked for, and `this` bound to, each element in the `collection`.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Function|String} methodName The name of the method to invoke or
- * the function invoked per iteration.
- * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
- * @returns {Array} Returns a new array of the results of each invoked method.
- * @example
+ * Creates an array of values by running each element in the collection
+ * through the callback. The callback is bound to `thisArg` and invoked with
+ * three arguments; (value, index|key, collection).
*
- * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
- * // => [[1, 5, 7], [1, 2, 3]]
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
*
- * _.invoke([123, 456], String.prototype.split, '');
- * // => [['1', '2', '3'], ['4', '5', '6']]
- */
- function invoke(collection, methodName) {
- var args = slice(arguments, 2),
- isFunc = typeof methodName == 'function',
- result = [];
-
- forEach(collection, function(value) {
- result.push((isFunc ? methodName : value[methodName]).apply(value, args));
- });
- return result;
- }
-
- /**
- * Creates an array of values by running each element in the `collection`
- * through a `callback`. The `callback` is bound to `thisArg` and invoked with
- * three arguments; (value, index|key, collection).
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
*
* @static
* @memberOf _
* @alias collect
* @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [callback=identity] The function called
+ * per iteration. If a property name or object is provided it will be used
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of the results of each `callback` execution.
* @example
*
* // => [3, 6, 9]
*
* _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
- * // => [3, 6, 9] (order is not guaranteed)
+ * // => [3, 6, 9] (property order is not guaranteed across environments)
+ *
+ * var characters = [
+ * { 'name': 'barney', 'age': 36 },
+ * { 'name': 'fred', 'age': 40 }
+ * ];
+ *
+ * // using "_.pluck" callback shorthand
+ * _.map(characters, 'name');
+ * // => ['barney', 'fred']
*/
function map(collection, callback, thisArg) {
var index = -1,
length = collection ? collection.length : 0,
result = Array(typeof length == 'number' ? length : 0);
- callback = createCallback(callback, thisArg);
+ callback = lodash.createCallback(callback, thisArg, 3);
if (isArray(collection)) {
while (++index < length) {
result[index] = callback(collection[index], index, collection);
}
} else {
- each(collection, function(value, key, collection) {
+ baseEach(collection, function(value, key, collection) {
result[++index] = callback(value, key, collection);
});
}
}
/**
- * Retrieves the maximum value of an `array`. If `callback` is passed,
- * it will be executed for each value in the `array` to generate the
- * criterion by which the value is ranked. The `callback` is bound to
- * `thisArg` and invoked with three arguments; (value, index, collection).
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Function} [callback] The function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Mixed} Returns the maximum value.
- * @example
- *
- * var stooges = [
- * { 'name': 'moe', 'age': 40 },
- * { 'name': 'larry', 'age': 50 },
- * { 'name': 'curly', 'age': 60 }
- * ];
- *
- * _.max(stooges, function(stooge) { return stooge.age; });
- * // => { 'name': 'curly', 'age': 60 };
- */
- function max(collection, callback, thisArg) {
- var computed = -Infinity,
- index = -1,
- length = collection ? collection.length : 0,
- result = computed;
-
- if (callback || !isArray(collection)) {
- callback = !callback && isString(collection)
- ? charAtCallback
- : createCallback(callback, thisArg);
-
- each(collection, function(value, index, collection) {
- var current = callback(value, index, collection);
- if (current > computed) {
- computed = current;
- result = value;
- }
- });
- } else {
- while (++index < length) {
- if (collection[index] > result) {
- result = collection[index];
- }
- }
- }
- return result;
- }
-
- /**
- * Retrieves the minimum value of an `array`. If `callback` is passed,
- * it will be executed for each value in the `array` to generate the
- * criterion by which the value is ranked. The `callback` is bound to `thisArg`
- * and invoked with three arguments; (value, index, collection).
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Function} [callback] The function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Mixed} Returns the minimum value.
- * @example
- *
- * _.min([10, 5, 100, 2, 1000]);
- * // => 2
- */
- function min(collection, callback, thisArg) {
- var computed = Infinity,
- index = -1,
- length = collection ? collection.length : 0,
- result = computed;
-
- if (callback || !isArray(collection)) {
- callback = !callback && isString(collection)
- ? charAtCallback
- : createCallback(callback, thisArg);
-
- each(collection, function(value, index, collection) {
- var current = callback(value, index, collection);
- if (current < computed) {
- computed = current;
- result = value;
- }
- });
- } else {
- while (++index < length) {
- if (collection[index] < result) {
- result = collection[index];
- }
- }
- }
- return result;
- }
-
- /**
- * Retrieves the value of a specified property from all elements in
- * the `collection`.
+ * Retrieves the value of a specified property from all elements in the collection.
*
* @static
* @memberOf _
+ * @type Function
* @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {String} property The property to pluck.
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {string} property The property to pluck.
* @returns {Array} Returns a new array of property values.
* @example
*
- * var stooges = [
- * { 'name': 'moe', 'age': 40 },
- * { 'name': 'larry', 'age': 50 },
- * { 'name': 'curly', 'age': 60 }
+ * var characters = [
+ * { 'name': 'barney', 'age': 36 },
+ * { 'name': 'fred', 'age': 40 }
* ];
*
- * _.pluck(stooges, 'name');
- * // => ['moe', 'larry', 'curly']
- */
- function pluck(collection, property) {
- return map(collection, property + '');
- }
-
- /**
- * Boils down a `collection` to a single value. The initial state of the
- * reduction is `accumulator` and each successive step of it should be returned
- * by the `callback`. The `callback` is bound to `thisArg` and invoked with 4
- * arguments; for arrays they are (accumulator, value, index|key, collection).
- *
- * @static
- * @memberOf _
- * @alias foldl, inject
- * @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {Mixed} [accumulator] Initial value of the accumulator.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Mixed} Returns the accumulated value.
- * @example
- *
- * var sum = _.reduce([1, 2, 3], function(memo, num) { return memo + num; });
- * // => 6
+ * _.pluck(characters, 'name');
+ * // => ['barney', 'fred']
*/
- function reduce(collection, callback, accumulator, thisArg) {
- var noaccum = arguments.length < 3;
- callback = createCallback(callback, thisArg, indicatorObject);
-
- if (isArray(collection)) {
- var index = -1,
- length = collection.length;
-
- if (noaccum) {
- accumulator = collection[++index];
- }
- while (++index < length) {
- accumulator = callback(accumulator, collection[index], index, collection);
- }
- } else {
- each(collection, function(value, index, collection) {
- accumulator = noaccum
- ? (noaccum = false, value)
- : callback(accumulator, value, index, collection)
- });
- }
- return accumulator;
- }
+ var pluck = map;
/**
- * The right-associative version of `_.reduce`.
+ * The opposite of `_.filter` this method returns the elements of a
+ * collection that the callback does **not** return truey for.
*
- * @static
- * @memberOf _
- * @alias foldr
- * @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {Mixed} [accumulator] Initial value of the accumulator.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Mixed} Returns the accumulated value.
- * @example
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
*
- * var list = [[0, 1], [2, 3], [4, 5]];
- * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
- * // => [4, 5, 2, 3, 0, 1]
- */
- function reduceRight(collection, callback, accumulator, thisArg) {
- var iteratee = collection,
- length = collection ? collection.length : 0,
- noaccum = arguments.length < 3;
-
- if (typeof length != 'number') {
- var props = keys(collection);
- length = props.length;
- } else if (noCharByIndex && isString(collection)) {
- iteratee = collection.split('');
- }
- callback = createCallback(callback, thisArg, indicatorObject);
- forEach(collection, function(value, index, collection) {
- index = props ? props[--length] : --length;
- accumulator = noaccum
- ? (noaccum = false, iteratee[index])
- : callback(accumulator, iteratee[index], index, collection);
- });
- return accumulator;
- }
-
- /**
- * The opposite of `_.filter`, this method returns the values of a
- * `collection` that `callback` does **not** return truthy for.
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
*
* @static
* @memberOf _
* @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns a new array of elements that did **not** pass the
- * callback check.
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [callback=identity] The function called
+ * per iteration. If a property name or object is provided it will be used
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {Array} Returns a new array of elements that failed the callback check.
* @example
*
* var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
* // => [1, 3, 5]
+ *
+ * var characters = [
+ * { 'name': 'barney', 'age': 36, 'blocked': false },
+ * { 'name': 'fred', 'age': 40, 'blocked': true }
+ * ];
+ *
+ * // using "_.pluck" callback shorthand
+ * _.reject(characters, 'blocked');
+ * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
+ *
+ * // using "_.where" callback shorthand
+ * _.reject(characters, { 'age': 36 });
+ * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
*/
function reject(collection, callback, thisArg) {
- callback = createCallback(callback, thisArg);
+ callback = lodash.createCallback(callback, thisArg, 3);
return filter(collection, function(value, index, collection) {
return !callback(value, index, collection);
});
}
/**
- * Creates an array of shuffled `array` values, using a version of the
- * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|String} collection The collection to shuffle.
- * @returns {Array} Returns a new shuffled collection.
- * @example
- *
- * _.shuffle([1, 2, 3, 4, 5, 6]);
- * // => [4, 1, 6, 3, 5, 2]
- */
- function shuffle(collection) {
- var index = -1,
- result = Array(collection ? collection.length : 0);
-
- forEach(collection, function(value) {
- var rand = floor(nativeRandom() * (++index + 1));
- result[index] = result[rand];
- result[rand] = value;
- });
- return result;
- }
-
- /**
- * Gets the size of the `collection` by returning `collection.length` for arrays
- * and array-like objects or the number of own enumerable properties for objects.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|String} collection The collection to inspect.
- * @returns {Number} Returns `collection.length` or number of own enumerable properties.
- * @example
- *
- * _.size([1, 2]);
- * // => 2
+ * Checks if the callback returns a truey value for **any** element of a
+ * collection. The function returns as soon as it finds a passing value and
+ * does not iterate over the entire collection. The callback is bound to
+ * `thisArg` and invoked with three arguments; (value, index|key, collection).
*
- * _.size({ 'one': 1, 'two': 2, 'three': 3 });
- * // => 3
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
*
- * _.size('curly');
- * // => 5
- */
- function size(collection) {
- var length = collection ? collection.length : 0;
- return typeof length == 'number' ? length : keys(collection).length;
- }
-
- /**
- * Checks if the `callback` returns a truthy value for **any** element of a
- * `collection`. The function returns as soon as it finds passing value, and
- * does not iterate over the entire `collection`. The `callback` is bound to
- * `thisArg` and invoked with three arguments; (value, index|key, collection).
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
*
* @static
* @memberOf _
* @alias any
* @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Boolean} Returns `true` if any element passes the callback check,
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [callback=identity] The function called
+ * per iteration. If a property name or object is provided it will be used
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {boolean} Returns `true` if any element passed the callback check,
* else `false`.
* @example
*
* _.some([null, 0, 'yes', false], Boolean);
* // => true
+ *
+ * var characters = [
+ * { 'name': 'barney', 'age': 36, 'blocked': false },
+ * { 'name': 'fred', 'age': 40, 'blocked': true }
+ * ];
+ *
+ * // using "_.pluck" callback shorthand
+ * _.some(characters, 'blocked');
+ * // => true
+ *
+ * // using "_.where" callback shorthand
+ * _.some(characters, { 'age': 1 });
+ * // => false
*/
function some(collection, callback, thisArg) {
var result;
- callback = createCallback(callback, thisArg);
+ callback = lodash.createCallback(callback, thisArg, 3);
if (isArray(collection)) {
var index = -1,
}
}
} else {
- each(collection, function(value, index, collection) {
- return !(result = callback(value, index, collection));
- });
- }
- return !!result;
- }
-
- /**
- * Creates an array, stable sorted in ascending order by the results of
- * running each element of `collection` through a `callback`. The `callback`
- * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
- * The `callback` argument may also be the name of a property to sort by (e.g. 'length').
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Function|String} callback|property The function called per iteration
- * or property name to sort by.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns a new array of sorted elements.
- * @example
- *
- * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
- * // => [3, 1, 2]
- *
- * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
- * // => [3, 1, 2]
- *
- * _.sortBy(['larry', 'brendan', 'moe'], 'length');
- * // => ['moe', 'larry', 'brendan']
- */
- function sortBy(collection, callback, thisArg) {
- var result = [];
- callback = createCallback(callback, thisArg);
-
- forEach(collection, function(value, index, collection) {
- result.push({
- 'criteria': callback(value, index, collection),
- 'index': index,
- 'value': value
- });
- });
-
- var length = result.length;
- result.sort(compareAscending);
- while (length--) {
- result[length] = result[length].value;
- }
- return result;
- }
-
- /**
- * Converts the `collection` to an array.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|String} collection The collection to convert.
- * @returns {Array} Returns the new converted array.
- * @example
- *
- * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
- * // => [2, 3, 4]
- */
- function toArray(collection) {
- var length = collection ? collection.length : 0;
- if (typeof length == 'number') {
- return noCharByIndex && isString(collection)
- ? collection.split('')
- : slice(collection);
- }
- return values(collection);
- }
-
- /**
- * Examines each element in a `collection`, returning an array of all elements
- * that contain the given `properties`.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|String} collection The collection to iterate over.
- * @param {Object} properties The object of property values to filter by.
- * @returns {Array} Returns a new array of elements that contain the given `properties`.
- * @example
- *
- * var stooges = [
- * { 'name': 'moe', 'age': 40 },
- * { 'name': 'larry', 'age': 50 },
- * { 'name': 'curly', 'age': 60 }
- * ];
- *
- * _.where(stooges, { 'age': 40 });
- * // => [{ 'name': 'moe', 'age': 40 }]
- */
- function where(collection, properties) {
- var props = keys(properties);
- return filter(collection, function(object) {
- var length = props.length;
- while (length--) {
- var result = object[props[length]] === properties[props[length]];
- if (!result) {
- break;
- }
- }
- return !!result;
- });
+ baseEach(collection, function(value, index, collection) {
+ return !(result = callback(value, index, collection));
+ });
+ }
+ return !!result;
}
/*--------------------------------------------------------------------------*/
/**
- * Creates an array with all falsey values of `array` removed. The values
- * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
+ * Creates an array with all falsey values removed. The values `false`, `null`,
+ * `0`, `""`, `undefined`, and `NaN` are all falsey.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to compact.
- * @returns {Array} Returns a new filtered array.
+ * @returns {Array} Returns a new array of filtered values.
* @example
*
* _.compact([0, 1, false, 2, '', 3]);
}
/**
- * Creates an array of `array` elements not present in the other arrays
- * using strict equality for comparisons, i.e. `===`.
+ * Creates an array excluding all values of the provided arrays using strict
+ * equality for comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to process.
- * @param {Array} [array1, array2, ...] Arrays to check.
- * @returns {Array} Returns a new array of `array` elements not present in the
- * other arrays.
+ * @param {...Array} [values] The arrays of values to exclude.
+ * @returns {Array} Returns a new array of filtered values.
* @example
*
* _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
* // => [1, 3, 4]
*/
function difference(array) {
- var index = -1,
- length = array ? array.length : 0,
- flattened = concat.apply(arrayRef, arguments),
- contains = cachedContains(flattened, length),
- result = [];
-
- while (++index < length) {
- var value = array[index];
- if (!contains(value)) {
- result.push(value);
- }
- }
- return result;
+ return baseDifference(array, baseFlatten(arguments, true, true, 1));
}
/**
- * Gets the first element of the `array`. Pass `n` to return the first `n`
- * elements of the `array`.
+ * Gets the first element or first `n` elements of an array. If a callback
+ * is provided elements at the beginning of the array are returned as long
+ * as the callback returns truey. The callback is bound to `thisArg` and
+ * invoked with three arguments; (value, index, array).
+ *
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
+ *
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
*
* @static
* @memberOf _
* @alias head, take
* @category Arrays
* @param {Array} array The array to query.
- * @param {Number} [n] The number of elements to return.
- * @param- {Object} [guard] Internally used to allow this method to work with
- * others like `_.map` without using their callback `index` argument for `n`.
- * @returns {Mixed} Returns the first element, or an array of the first `n`
- * elements, of `array`.
+ * @param {Function|Object|number|string} [callback] The function called
+ * per element or the number of elements to return. If a property name or
+ * object is provided it will be used to create a "_.pluck" or "_.where"
+ * style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {*} Returns the first element(s) of `array`.
* @example
*
- * _.first([5, 4, 3, 2, 1]);
- * // => 5
+ * _.first([1, 2, 3]);
+ * // => 1
+ *
+ * _.first([1, 2, 3], 2);
+ * // => [1, 2]
+ *
+ * _.first([1, 2, 3], function(num) {
+ * return num < 3;
+ * });
+ * // => [1, 2]
+ *
+ * var characters = [
+ * { 'name': 'barney', 'blocked': true, 'employer': 'slate' },
+ * { 'name': 'fred', 'blocked': false, 'employer': 'slate' },
+ * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
+ * ];
+ *
+ * // using "_.pluck" callback shorthand
+ * _.first(characters, 'blocked');
+ * // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }]
+ *
+ * // using "_.where" callback shorthand
+ * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name');
+ * // => ['barney', 'fred']
*/
- function first(array, n, guard) {
- if (array) {
- var length = array.length;
- return (n == null || guard)
- ? array[0]
- : slice(array, 0, nativeMin(nativeMax(0, n), length));
+ function first(array, callback, thisArg) {
+ var n = 0,
+ length = array ? array.length : 0;
+
+ if (typeof callback != 'number' && callback != null) {
+ var index = -1;
+ callback = lodash.createCallback(callback, thisArg, 3);
+ while (++index < length && callback(array[index], index, array)) {
+ n++;
+ }
+ } else {
+ n = callback;
+ if (n == null || thisArg) {
+ return array ? array[0] : undefined;
+ }
}
+ return slice(array, 0, nativeMin(nativeMax(0, n), length));
}
/**
- * Flattens a nested array (the nesting can be to any depth). If `shallow` is
- * truthy, `array` will only be flattened a single level.
+ * Flattens a nested array (the nesting can be to any depth). If `isShallow`
+ * is truey, the array will only be flattened a single level. If a callback
+ * is provided each element of the array is passed through the callback before
+ * flattening. The callback is bound to `thisArg` and invoked with three
+ * arguments; (value, index, array).
+ *
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
+ *
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
*
* @static
* @memberOf _
* @category Arrays
- * @param {Array} array The array to compact.
- * @param {Boolean} shallow A flag to indicate only flattening a single level.
+ * @param {Array} array The array to flatten.
+ * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
+ * @param {Function|Object|string} [callback=identity] The function called
+ * per iteration. If a property name or object is provided it will be used
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new flattened array.
* @example
*
*
* _.flatten([1, [2], [3, [[4]]]], true);
* // => [1, 2, 3, [[4]]];
+ *
+ * var characters = [
+ * { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] },
+ * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }
+ * ];
+ *
+ * // using "_.pluck" callback shorthand
+ * _.flatten(characters, 'pets');
+ * // => ['hoppy', 'baby puss', 'dino']
*/
- function flatten(array, shallow) {
- var index = -1,
- length = array ? array.length : 0,
- result = [];
-
- while (++index < length) {
- var value = array[index];
-
- // recursively flatten arrays (susceptible to call stack limits)
- if (isArray(value)) {
- push.apply(result, shallow ? value : flatten(value));
- } else {
- result.push(value);
- }
+ function flatten(array, isShallow, callback, thisArg) {
+ // juggle arguments
+ if (typeof isShallow != 'boolean' && isShallow != null) {
+ thisArg = callback;
+ callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow;
+ isShallow = false;
}
- return result;
+ if (callback != null) {
+ array = map(array, callback, thisArg);
+ }
+ return baseFlatten(array, isShallow);
}
/**
* Gets the index at which the first occurrence of `value` is found using
- * strict equality for comparisons, i.e. `===`. If the `array` is already
- * sorted, passing `true` for `fromIndex` will run a faster binary search.
+ * strict equality for comparisons, i.e. `===`. If the array is already sorted
+ * providing `true` for `fromIndex` will run a faster binary search.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
- * @param {Mixed} value The value to search for.
- * @param {Boolean|Number} [fromIndex=0] The index to search from or `true` to
- * perform a binary search on a sorted `array`.
- * @returns {Number} Returns the index of the matched value or `-1`.
+ * @param {*} value The value to search for.
+ * @param {boolean|number} [fromIndex=0] The index to search from or `true`
+ * to perform a binary search on a sorted array.
+ * @returns {number} Returns the index of the matched value or `-1`.
* @example
*
* _.indexOf([1, 2, 3, 1, 2, 3], 2);
* // => 2
*/
function indexOf(array, value, fromIndex) {
- var index = -1,
- length = array ? array.length : 0;
-
if (typeof fromIndex == 'number') {
- index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0) - 1;
+ var length = array ? array.length : 0;
+ fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0);
} else if (fromIndex) {
- index = sortedIndex(array, value);
+ var index = sortedIndex(array, value);
return array[index] === value ? index : -1;
}
- while (++index < length) {
- if (array[index] === value) {
- return index;
- }
- }
- return -1;
- }
-
- /**
- * Gets all but the last element of `array`. Pass `n` to exclude the last `n`
- * elements from the result.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to query.
- * @param {Number} [n=1] The number of elements to exclude.
- * @param- {Object} [guard] Internally used to allow this method to work with
- * others like `_.map` without using their callback `index` argument for `n`.
- * @returns {Array} Returns all but the last element, or `n` elements, of `array`.
- * @example
- *
- * _.initial([3, 2, 1]);
- * // => [3, 2]
- */
- function initial(array, n, guard) {
- if (!array) {
- return [];
- }
- var length = array.length;
- n = n == null || guard ? 1 : n || 0;
- return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
+ return baseIndexOf(array, value, fromIndex);
}
/**
- * Computes the intersection of all the passed-in arrays using strict equality
- * for comparisons, i.e. `===`.
+ * Creates an array of unique values present in all provided arrays using
+ * strict equality for comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
- * @param {Array} [array1, array2, ...] Arrays to process.
- * @returns {Array} Returns a new array of unique elements that are present
- * in **all** of the arrays.
+ * @param {...Array} [array] The arrays to inspect.
+ * @returns {Array} Returns an array of composite values.
* @example
*
* _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
function intersection(array) {
var args = arguments,
argsLength = args.length,
- cache = { '0': {} },
+ argsIndex = -1,
+ caches = getArray(),
index = -1,
+ indexOf = getIndexOf(),
length = array ? array.length : 0,
- isLarge = length >= 100,
result = [],
- seen = result;
+ seen = getArray();
+ while (++argsIndex < argsLength) {
+ var value = args[argsIndex];
+ caches[argsIndex] = indexOf === baseIndexOf &&
+ (value ? value.length : 0) >= largeArraySize &&
+ createCache(argsIndex ? args[argsIndex] : seen);
+ }
outer:
while (++index < length) {
- var value = array[index];
- if (isLarge) {
- var key = value + '';
- var inited = hasOwnProperty.call(cache[0], key)
- ? !(seen = cache[0][key])
- : (seen = cache[0][key] = []);
- }
- if (inited || indexOf(seen, value) < 0) {
- if (isLarge) {
- seen.push(value);
- }
- var argsIndex = argsLength;
+ var cache = caches[0];
+ value = array[index];
+
+ if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) {
+ argsIndex = argsLength;
+ (cache || seen).push(value);
while (--argsIndex) {
- if (!(cache[argsIndex] || (cache[argsIndex] = cachedContains(args[argsIndex], 0, 100)))(value)) {
+ cache = caches[argsIndex];
+ if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) {
continue outer;
}
}
result.push(value);
}
}
- return result;
- }
-
- /**
- * Gets the last element of the `array`. Pass `n` to return the last `n`
- * elements of the `array`.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to query.
- * @param {Number} [n] The number of elements to return.
- * @param- {Object} [guard] Internally used to allow this method to work with
- * others like `_.map` without using their callback `index` argument for `n`.
- * @returns {Mixed} Returns the last element, or an array of the last `n`
- * elements, of `array`.
- * @example
- *
- * _.last([3, 2, 1]);
- * // => 1
- */
- function last(array, n, guard) {
- if (array) {
- var length = array.length;
- return (n == null || guard) ? array[length - 1] : slice(array, nativeMax(0, length - n));
- }
- }
-
- /**
- * Gets the index at which the last occurrence of `value` is found using strict
- * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
- * as the offset from the end of the collection.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to search.
- * @param {Mixed} value The value to search for.
- * @param {Number} [fromIndex=array.length-1] The index to search from.
- * @returns {Number} Returns the index of the matched value or `-1`.
- * @example
- *
- * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
- * // => 4
- *
- * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
- * // => 1
- */
- function lastIndexOf(array, value, fromIndex) {
- var index = array ? array.length : 0;
- if (typeof fromIndex == 'number') {
- index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
- }
- while (index--) {
- if (array[index] === value) {
- return index;
+ while (argsLength--) {
+ cache = caches[argsLength];
+ if (cache) {
+ releaseObject(cache);
}
}
- return -1;
+ releaseArray(caches);
+ releaseArray(seen);
+ return result;
}
/**
- * Creates an object composed from arrays of `keys` and `values`. Pass either
- * a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or
- * two arrays, one of `keys` and one of corresponding `values`.
+ * Gets the last element or last `n` elements of an array. If a callback is
+ * provided elements at the end of the array are returned as long as the
+ * callback returns truey. The callback is bound to `thisArg` and invoked
+ * with three arguments; (value, index, array).
*
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} keys The array of keys.
- * @param {Array} [values=[]] The array of values.
- * @returns {Object} Returns an object composed of the given keys and
- * corresponding values.
- * @example
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
*
- * _.object(['moe', 'larry', 'curly'], [30, 40, 50]);
- * // => { 'moe': 30, 'larry': 40, 'curly': 50 }
- */
- function object(keys, values) {
- var index = -1,
- length = keys ? keys.length : 0,
- result = {};
-
- while (++index < length) {
- var key = keys[index];
- if (values) {
- result[key] = values[index];
- } else {
- result[key[0]] = key[1];
- }
- }
- return result;
- }
-
- /**
- * Creates an array of numbers (positive and/or negative) progressing from
- * `start` up to but not including `stop`. This method is a port of Python's
- * `range()` function. See http://docs.python.org/library/functions.html#range.
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
*
* @static
* @memberOf _
* @category Arrays
- * @param {Number} [start=0] The start of the range.
- * @param {Number} end The end of the range.
- * @param {Number} [step=1] The value to increment or descrement by.
- * @returns {Array} Returns a new range array.
+ * @param {Array} array The array to query.
+ * @param {Function|Object|number|string} [callback] The function called
+ * per element or the number of elements to return. If a property name or
+ * object is provided it will be used to create a "_.pluck" or "_.where"
+ * style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {*} Returns the last element(s) of `array`.
* @example
*
- * _.range(10);
- * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ * _.last([1, 2, 3]);
+ * // => 3
+ *
+ * _.last([1, 2, 3], 2);
+ * // => [2, 3]
*
- * _.range(1, 11);
- * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ * _.last([1, 2, 3], function(num) {
+ * return num > 1;
+ * });
+ * // => [2, 3]
*
- * _.range(0, 30, 5);
- * // => [0, 5, 10, 15, 20, 25]
+ * var characters = [
+ * { 'name': 'barney', 'blocked': false, 'employer': 'slate' },
+ * { 'name': 'fred', 'blocked': true, 'employer': 'slate' },
+ * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
+ * ];
*
- * _.range(0, -10, -1);
- * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+ * // using "_.pluck" callback shorthand
+ * _.pluck(_.last(characters, 'blocked'), 'name');
+ * // => ['fred', 'pebbles']
*
- * _.range(0);
- * // => []
+ * // using "_.where" callback shorthand
+ * _.last(characters, { 'employer': 'na' });
+ * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
*/
- function range(start, end, step) {
- start = +start || 0;
- step = +step || 1;
-
- if (end == null) {
- end = start;
- start = 0;
- }
- // use `Array(length)` so V8 will avoid the slower "dictionary" mode
- // http://youtu.be/XAqIpGU8ZZk#t=17m25s
- var index = -1,
- length = nativeMax(0, ceil((end - start) / step)),
- result = Array(length);
+ function last(array, callback, thisArg) {
+ var n = 0,
+ length = array ? array.length : 0;
- while (++index < length) {
- result[index] = start;
- start += step;
+ if (typeof callback != 'number' && callback != null) {
+ var index = length;
+ callback = lodash.createCallback(callback, thisArg, 3);
+ while (index-- && callback(array[index], index, array)) {
+ n++;
+ }
+ } else {
+ n = callback;
+ if (n == null || thisArg) {
+ return array ? array[length - 1] : undefined;
+ }
}
- return result;
+ return slice(array, nativeMax(0, length - n));
}
/**
- * The opposite of `_.initial`, this method gets all but the first value of
- * `array`. Pass `n` to exclude the first `n` values from the result.
+ * Uses a binary search to determine the smallest index at which a value
+ * should be inserted into a given sorted array in order to maintain the sort
+ * order of the array. If a callback is provided it will be executed for
+ * `value` and each element of `array` to compute their sort ranking. The
+ * callback is bound to `thisArg` and invoked with one argument; (value).
*
- * @static
- * @memberOf _
- * @alias drop, tail
- * @category Arrays
- * @param {Array} array The array to query.
- * @param {Number} [n=1] The number of elements to exclude.
- * @param- {Object} [guard] Internally used to allow this method to work with
- * others like `_.map` without using their callback `index` argument for `n`.
- * @returns {Array} Returns all but the first element, or `n` elements, of `array`.
- * @example
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
*
- * _.rest([3, 2, 1]);
- * // => [2, 1]
- */
- function rest(array, n, guard) {
- return slice(array, (n == null || guard) ? 1 : nativeMax(0, n));
- }
-
- /**
- * Uses a binary search to determine the smallest index at which the `value`
- * should be inserted into `array` in order to maintain the sort order of the
- * sorted `array`. If `callback` is passed, it will be executed for `value` and
- * each element in `array` to compute their sort ranking. The `callback` is
- * bound to `thisArg` and invoked with one argument; (value). The `callback`
- * argument may also be the name of a property to order by.
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
*
* @static
* @memberOf _
* @category Arrays
- * @param {Array} array The array to iterate over.
- * @param {Mixed} value The value to evaluate.
- * @param {Function|String} [callback=identity|property] The function called
- * per iteration or property name to order by.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Number} Returns the index at which the value should be inserted
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function|Object|string} [callback=identity] The function called
+ * per iteration. If a property name or object is provided it will be used
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
+ * @returns {number} Returns the index at which `value` should be inserted
* into `array`.
* @example
*
* _.sortedIndex([20, 30, 50], 40);
* // => 2
*
+ * // using "_.pluck" callback shorthand
* _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
* // => 2
*
high = array ? array.length : low;
// explicitly reference `identity` for better inlining in Firefox
- callback = callback ? createCallback(callback, thisArg) : identity;
+ callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity;
value = callback(value);
while (low < high) {
var mid = (low + high) >>> 1;
- callback(array[mid]) < value
+ (callback(array[mid]) < value)
? low = mid + 1
: high = mid;
}
}
/**
- * Computes the union of the passed-in arrays using strict equality for
- * comparisons, i.e. `===`.
+ * Creates an array of unique values, in order, of the provided arrays using
+ * strict equality for comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
- * @param {Array} [array1, array2, ...] Arrays to process.
- * @returns {Array} Returns a new array of unique values, in order, that are
- * present in one or more of the arrays.
+ * @param {...Array} [array] The arrays to inspect.
+ * @returns {Array} Returns an array of composite values.
* @example
*
* _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
* // => [1, 2, 3, 101, 10]
*/
- function union() {
- return uniq(concat.apply(arrayRef, arguments));
+ function union(array) {
+ return baseUniq(baseFlatten(arguments, true, true));
}
/**
- * Creates a duplicate-value-free version of the `array` using strict equality
- * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`
- * for `isSorted` will run a faster algorithm. If `callback` is passed, each
- * element of `array` is passed through a callback` before uniqueness is computed.
- * The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array).
+ * Creates a duplicate-value-free version of an array using strict equality
+ * for comparisons, i.e. `===`. If the array is sorted, providing
+ * `true` for `isSorted` will use a faster algorithm. If a callback is provided
+ * each element of `array` is passed through the callback before uniqueness
+ * is computed. The callback is bound to `thisArg` and invoked with three
+ * arguments; (value, index, array).
+ *
+ * If a property name is provided for `callback` the created "_.pluck" style
+ * callback will return the property value of the given element.
+ *
+ * If an object is provided for `callback` the created "_.where" style callback
+ * will return `true` for elements that have the properties of the given object,
+ * else `false`.
*
* @static
* @memberOf _
* @alias unique
* @category Arrays
* @param {Array} array The array to process.
- * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
+ * @param {Function|Object|string} [callback=identity] The function called
+ * per iteration. If a property name or object is provided it will be used
+ * to create a "_.pluck" or "_.where" style callback, respectively.
+ * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a duplicate-value-free array.
* @example
*
* _.uniq([1, 1, 2, 2, 3], true);
* // => [1, 2, 3]
*
- * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); });
- * // => [1, 2, 3]
+ * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); });
+ * // => ['A', 'b', 'C']
*
- * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math);
- * // => [1, 2, 3]
+ * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
+ * // => [1, 2.5, 3]
+ *
+ * // using "_.pluck" callback shorthand
+ * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+ * // => [{ 'x': 1 }, { 'x': 2 }]
*/
function uniq(array, isSorted, callback, thisArg) {
- var index = -1,
- length = array ? array.length : 0,
- result = [],
- seen = result;
-
// juggle arguments
- if (typeof isSorted == 'function') {
+ if (typeof isSorted != 'boolean' && isSorted != null) {
thisArg = callback;
- callback = isSorted;
+ callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted;
isSorted = false;
}
- // init value cache for large arrays
- var isLarge = !isSorted && length >= 75;
- if (isLarge) {
- var cache = {};
- }
- if (callback) {
- seen = [];
- callback = createCallback(callback, thisArg);
- }
- while (++index < length) {
- var value = array[index],
- computed = callback ? callback(value, index, array) : value;
-
- if (isLarge) {
- var key = computed + '';
- var inited = hasOwnProperty.call(cache, key)
- ? !(seen = cache[key])
- : (seen = cache[key] = []);
- }
- if (isSorted
- ? !index || seen[seen.length - 1] !== computed
- : inited || indexOf(seen, computed) < 0
- ) {
- if (callback || isLarge) {
- seen.push(computed);
- }
- result.push(value);
- }
+ if (callback != null) {
+ callback = lodash.createCallback(callback, thisArg, 3);
}
- return result;
+ return baseUniq(array, isSorted, callback);
}
/**
- * Creates an array with all occurrences of the passed values removed using
- * strict equality for comparisons, i.e. `===`.
+ * Creates an array excluding all provided values using strict equality for
+ * comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to filter.
- * @param {Mixed} [value1, value2, ...] Values to remove.
- * @returns {Array} Returns a new filtered array.
+ * @param {...*} [value] The values to exclude.
+ * @returns {Array} Returns a new array of filtered values.
* @example
*
* _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
* // => [2, 3, 4]
*/
function without(array) {
- var index = -1,
- length = array ? array.length : 0,
- contains = cachedContains(arguments, 1, 20),
- result = [];
-
- while (++index < length) {
- var value = array[index];
- if (!contains(value)) {
- result.push(value);
- }
- }
- return result;
- }
-
- /**
- * Groups the elements of each array at their corresponding indexes. Useful for
- * separate data sources that are coordinated through matching array indexes.
- * For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix
- * in a similar fashion.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} [array1, array2, ...] Arrays to process.
- * @returns {Array} Returns a new array of grouped elements.
- * @example
- *
- * _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
- * // => [['moe', 30, true], ['larry', 40, false], ['curly', 50, false]]
- */
- function zip(array) {
- var index = -1,
- length = array ? max(pluck(arguments, 'length')) : 0,
- result = Array(length);
-
- while (++index < length) {
- result[index] = pluck(arguments, index);
- }
- return result;
+ return baseDifference(array, slice(arguments, 1));
}
/*--------------------------------------------------------------------------*/
- /**
- * Creates a function that is restricted to executing `func` only after it is
- * called `n` times. The `func` is executed with the `this` binding of the
- * created function.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Number} n The number of times the function must be called before
- * it is executed.
- * @param {Function} func The function to restrict.
- * @returns {Function} Returns the new restricted function.
- * @example
- *
- * var renderNotes = _.after(notes.length, render);
- * _.forEach(notes, function(note) {
- * note.asyncSave({ 'success': renderNotes });
- * });
- * // `renderNotes` is run once, after all notes have saved
- */
- function after(n, func) {
- if (n < 1) {
- return func();
- }
- return function() {
- if (--n < 1) {
- return func.apply(this, arguments);
- }
- };
- }
-
/**
* Creates a function that, when called, invokes `func` with the `this`
* binding of `thisArg` and prepends any additional `bind` arguments to those
- * passed to the bound function.
+ * provided to the bound function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to bind.
- * @param {Mixed} [thisArg] The `this` binding of `func`.
- * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {...*} [arg] Arguments to be partially applied.
* @returns {Function} Returns the new bound function.
* @example
*
* return greeting + ' ' + this.name;
* };
*
- * func = _.bind(func, { 'name': 'moe' }, 'hi');
+ * func = _.bind(func, { 'name': 'fred' }, 'hi');
* func();
- * // => 'hi moe'
+ * // => 'hi fred'
*/
function bind(func, thisArg) {
- // use `Function#bind` if it exists and is fast
- // (in V8 `Function#bind` is slower except when partially applied)
- return isBindFast || (nativeBind && arguments.length > 2)
- ? nativeBind.call.apply(nativeBind, arguments)
- : createBound(func, thisArg, slice(arguments, 2));
- }
-
- /**
- * Binds methods on `object` to `object`, overwriting the existing method.
- * If no method names are provided, all the function properties of `object`
- * will be bound.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Object} object The object to bind and assign the bound methods to.
- * @param {String} [methodName1, methodName2, ...] Method names on the object to bind.
- * @returns {Object} Returns `object`.
- * @example
- *
- * var buttonView = {
- * 'label': 'lodash',
- * 'onClick': function() { alert('clicked: ' + this.label); }
- * };
- *
- * _.bindAll(buttonView);
- * jQuery('#lodash_button').on('click', buttonView.onClick);
- * // => When the button is clicked, `this.label` will have the correct value
- */
- function bindAll(object) {
- var funcs = arguments,
- index = funcs.length > 1 ? 0 : (funcs = functions(object), -1),
- length = funcs.length;
-
- while (++index < length) {
- var key = funcs[index];
- object[key] = bind(object[key], object);
- }
- return object;
+ return arguments.length > 2
+ ? createWrapper(func, 17, slice(arguments, 2), null, thisArg)
+ : createWrapper(func, 1, null, null, thisArg);
}
/**
- * Creates a function that, when called, invokes the method at `object[key]`
- * and prepends any additional `bindKey` arguments to those passed to the bound
- * function. This method differs from `_.bind` by allowing bound functions to
- * reference methods that will be redefined or don't yet exist.
- * See http://michaux.ca/articles/lazy-function-definition-pattern.
+ * Produces a callback bound to an optional `thisArg`. If `func` is a property
+ * name the created callback will return the property value for a given element.
+ * If `func` is an object the created callback will return `true` for elements
+ * that contain the equivalent object properties, otherwise it will return `false`.
*
* @static
* @memberOf _
* @category Functions
- * @param {Object} object The object the method belongs to.
- * @param {String} key The key of the method.
- * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
- * @returns {Function} Returns the new bound function.
+ * @param {*} [func=identity] The value to convert to a callback.
+ * @param {*} [thisArg] The `this` binding of the created callback.
+ * @param {number} [argCount] The number of arguments the callback accepts.
+ * @returns {Function} Returns a callback function.
* @example
*
- * var object = {
- * 'name': 'moe',
- * 'greet': function(greeting) {
- * return greeting + ' ' + this.name;
- * }
- * };
- *
- * var func = _.bindKey(object, 'greet', 'hi');
- * func();
- * // => 'hi moe'
+ * var characters = [
+ * { 'name': 'barney', 'age': 36 },
+ * { 'name': 'fred', 'age': 40 }
+ * ];
*
- * object.greet = function(greeting) {
- * return greeting + ', ' + this.name + '!';
- * };
+ * // wrap to create custom callback shorthands
+ * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {
+ * var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);
+ * return !match ? func(callback, thisArg) : function(object) {
+ * return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];
+ * };
+ * });
*
- * func();
- * // => 'hi, moe!'
+ * _.filter(characters, 'age__gt38');
+ * // => [{ 'name': 'fred', 'age': 40 }]
*/
- function bindKey(object, key) {
- return createBound(object, key, slice(arguments, 2));
- }
+ function createCallback(func, thisArg, argCount) {
+ var type = typeof func;
+ if (func == null || type == 'function') {
+ return baseCreateCallback(func, thisArg, argCount);
+ }
+ // handle "_.pluck" style callback shorthands
+ if (type != 'object') {
+ return function(object) {
+ return object[func];
+ };
+ }
+ var props = keys(func),
+ key = props[0],
+ a = func[key];
- /**
- * Creates a function that is the composition of the passed functions,
- * where each function consumes the return value of the function that follows.
- * In math terms, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
- * Each function is executed with the `this` binding of the composed function.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} [func1, func2, ...] Functions to compose.
- * @returns {Function} Returns the new composed function.
- * @example
- *
- * var greet = function(name) { return 'hi: ' + name; };
- * var exclaim = function(statement) { return statement + '!'; };
- * var welcome = _.compose(exclaim, greet);
- * welcome('moe');
- * // => 'hi: moe!'
- */
- function compose() {
- var funcs = arguments;
- return function() {
- var args = arguments,
- length = funcs.length;
+ // handle "_.where" style callback shorthands
+ if (props.length == 1 && a === a && !isObject(a)) {
+ // fast path the common case of providing an object with a single
+ // property containing a primitive value
+ return function(object) {
+ var b = object[key];
+ return a === b && (a !== 0 || (1 / a == 1 / b));
+ };
+ }
+ return function(object) {
+ var length = props.length,
+ result = false;
while (length--) {
- args = [funcs[length].apply(this, args)];
+ if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) {
+ break;
+ }
}
- return args[0];
+ return result;
};
}
/**
* Creates a function that will delay the execution of `func` until after
- * `wait` milliseconds have elapsed since the last time it was invoked. Pass
- * `true` for `immediate` to cause debounce to invoke `func` on the leading,
- * instead of the trailing, edge of the `wait` timeout. Subsequent calls to
- * the debounced function will return the result of the last `func` call.
+ * `wait` milliseconds have elapsed since the last time it was invoked.
+ * Provide an options object to indicate that `func` should be invoked on
+ * the leading and/or trailing edge of the `wait` timeout. Subsequent calls
+ * to the debounced function will return the result of the last `func` call.
+ *
+ * Note: If `leading` and `trailing` options are `true` `func` will be called
+ * on the trailing edge of the timeout only if the the debounced function is
+ * invoked more than once during the `wait` timeout.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to debounce.
- * @param {Number} wait The number of milliseconds to delay.
- * @param {Boolean} immediate A flag to indicate execution is on the leading
- * edge of the timeout.
+ * @param {number} wait The number of milliseconds to delay.
+ * @param {Object} [options] The options object.
+ * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout.
+ * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called.
+ * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
* @returns {Function} Returns the new debounced function.
* @example
*
- * var lazyLayout = _.debounce(calculateLayout, 300);
+ * // avoid costly calculations while the window size is in flux
+ * var lazyLayout = _.debounce(calculateLayout, 150);
* jQuery(window).on('resize', lazyLayout);
+ *
+ * // execute `sendMail` when the click event is fired, debouncing subsequent calls
+ * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
+ * 'leading': true,
+ * 'trailing': false
+ * });
+ *
+ * // ensure `batchLog` is executed once after 1 second of debounced calls
+ * var source = new EventSource('/stream');
+ * source.addEventListener('message', _.debounce(batchLog, 250, {
+ * 'maxWait': 1000
+ * }, false);
*/
- function debounce(func, wait, immediate) {
+ function debounce(func, wait, options) {
var args,
+ maxTimeoutId,
result,
+ stamp,
thisArg,
- timeoutId;
+ timeoutId,
+ trailingCall,
+ lastCalled = 0,
+ maxWait = false,
+ trailing = true;
+
+ if (!isFunction(func)) {
+ throw new TypeError;
+ }
+ wait = nativeMax(0, wait) || 0;
+ if (options === true) {
+ var leading = true;
+ trailing = false;
+ } else if (isObject(options)) {
+ leading = options.leading;
+ maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0);
+ trailing = 'trailing' in options ? options.trailing : trailing;
+ }
+ var delayed = function() {
+ var remaining = wait - (now() - stamp);
+ if (remaining <= 0) {
+ if (maxTimeoutId) {
+ clearTimeout(maxTimeoutId);
+ }
+ var isCalled = trailingCall;
+ maxTimeoutId = timeoutId = trailingCall = undefined;
+ if (isCalled) {
+ lastCalled = now();
+ result = func.apply(thisArg, args);
+ if (!timeoutId && !maxTimeoutId) {
+ args = thisArg = null;
+ }
+ }
+ } else {
+ timeoutId = setTimeout(delayed, remaining);
+ }
+ };
- function delayed() {
- timeoutId = null;
- if (!immediate) {
+ var maxDelayed = function() {
+ if (timeoutId) {
+ clearTimeout(timeoutId);
+ }
+ maxTimeoutId = timeoutId = trailingCall = undefined;
+ if (trailing || (maxWait !== wait)) {
+ lastCalled = now();
result = func.apply(thisArg, args);
+ if (!timeoutId && !maxTimeoutId) {
+ args = thisArg = null;
+ }
}
- }
+ };
+
return function() {
- var isImmediate = immediate && !timeoutId;
args = arguments;
+ stamp = now();
thisArg = this;
+ trailingCall = trailing && (timeoutId || !leading);
- clearTimeout(timeoutId);
- timeoutId = setTimeout(delayed, wait);
+ if (maxWait === false) {
+ var leadingCall = leading && !timeoutId;
+ } else {
+ if (!maxTimeoutId && !leading) {
+ lastCalled = stamp;
+ }
+ var remaining = maxWait - (stamp - lastCalled),
+ isCalled = remaining <= 0;
- if (isImmediate) {
+ if (isCalled) {
+ if (maxTimeoutId) {
+ maxTimeoutId = clearTimeout(maxTimeoutId);
+ }
+ lastCalled = stamp;
+ result = func.apply(thisArg, args);
+ }
+ else if (!maxTimeoutId) {
+ maxTimeoutId = setTimeout(maxDelayed, remaining);
+ }
+ }
+ if (isCalled && timeoutId) {
+ timeoutId = clearTimeout(timeoutId);
+ }
+ else if (!timeoutId && wait !== maxWait) {
+ timeoutId = setTimeout(delayed, wait);
+ }
+ if (leadingCall) {
+ isCalled = true;
result = func.apply(thisArg, args);
}
- return result;
- };
- }
-
- /**
- * Executes the `func` function after `wait` milliseconds. Additional arguments
- * will be passed to `func` when it is invoked.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} func The function to delay.
- * @param {Number} wait The number of milliseconds to delay execution.
- * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
- * @returns {Number} Returns the `setTimeout` timeout id.
- * @example
- *
- * var log = _.bind(console.log, console);
- * _.delay(log, 1000, 'logged later');
- * // => 'logged later' (Appears after one second.)
- */
- function delay(func, wait) {
- var args = slice(arguments, 2);
- return setTimeout(function() { func.apply(undefined, args); }, wait);
- }
-
- /**
- * Defers executing the `func` function until the current call stack has cleared.
- * Additional arguments will be passed to `func` when it is invoked.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} func The function to defer.
- * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
- * @returns {Number} Returns the `setTimeout` timeout id.
- * @example
- *
- * _.defer(function() { alert('deferred'); });
- * // returns from the function before `alert` is called
- */
- function defer(func) {
- var args = slice(arguments, 1);
- return setTimeout(function() { func.apply(undefined, args); }, 1);
- }
-
- /**
- * Creates a function that memoizes the result of `func`. If `resolver` is
- * passed, it will be used to determine the cache key for storing the result
- * based on the arguments passed to the memoized function. By default, the first
- * argument passed to the memoized function is used as the cache key. The `func`
- * is executed with the `this` binding of the memoized function.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} func The function to have its output memoized.
- * @param {Function} [resolver] A function used to resolve the cache key.
- * @returns {Function} Returns the new memoizing function.
- * @example
- *
- * var fibonacci = _.memoize(function(n) {
- * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
- * });
- */
- function memoize(func, resolver) {
- var cache = {};
- return function() {
- var key = resolver ? resolver.apply(this, arguments) : arguments[0];
- return hasOwnProperty.call(cache, key)
- ? cache[key]
- : (cache[key] = func.apply(this, arguments));
- };
- }
-
- /**
- * Creates a function that is restricted to execute `func` once. Repeat calls to
- * the function will return the value of the first call. The `func` is executed
- * with the `this` binding of the created function.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} func The function to restrict.
- * @returns {Function} Returns the new restricted function.
- * @example
- *
- * var initialize = _.once(createApplication);
- * initialize();
- * initialize();
- * // Application is only created once.
- */
- function once(func) {
- var result,
- ran = false;
-
- return function() {
- if (ran) {
- return result;
+ if (isCalled && !timeoutId && !maxTimeoutId) {
+ args = thisArg = null;
}
- ran = true;
- result = func.apply(this, arguments);
-
- // clear the `func` variable so the function may be garbage collected
- func = null;
return result;
};
}
/**
- * Creates a function that, when called, invokes `func` with any additional
- * `partial` arguments prepended to those passed to the new function. This
- * method is similar to `bind`, except it does **not** alter the `this` binding.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} func The function to partially apply arguments to.
- * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
- * @returns {Function} Returns the new partially applied function.
- * @example
+ * Creates a function that, when executed, will only call the `func` function
+ * at most once per every `wait` milliseconds. Provide an options object to
+ * indicate that `func` should be invoked on the leading and/or trailing edge
+ * of the `wait` timeout. Subsequent calls to the throttled function will
+ * return the result of the last `func` call.
*
- * var greet = function(greeting, name) { return greeting + ': ' + name; };
- * var hi = _.partial(greet, 'hi');
- * hi('moe');
- * // => 'hi: moe'
- */
- function partial(func) {
- return createBound(func, slice(arguments, 1));
- }
-
- /**
- * Creates a function that, when executed, will only call the `func`
- * function at most once per every `wait` milliseconds. If the throttled
- * function is invoked more than once during the `wait` timeout, `func` will
- * also be called on the trailing edge of the timeout. Subsequent calls to the
- * throttled function will return the result of the last `func` call.
+ * Note: If `leading` and `trailing` options are `true` `func` will be called
+ * on the trailing edge of the timeout only if the the throttled function is
+ * invoked more than once during the `wait` timeout.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to throttle.
- * @param {Number} wait The number of milliseconds to throttle executions to.
+ * @param {number} wait The number of milliseconds to throttle executions to.
+ * @param {Object} [options] The options object.
+ * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout.
+ * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
* @returns {Function} Returns the new throttled function.
* @example
*
+ * // avoid excessively updating the position while scrolling
* var throttled = _.throttle(updatePosition, 100);
* jQuery(window).on('scroll', throttled);
- */
- function throttle(func, wait) {
- var args,
- result,
- thisArg,
- timeoutId,
- lastCalled = 0;
-
- function trailingCall() {
- lastCalled = new Date;
- timeoutId = null;
- result = func.apply(thisArg, args);
- }
- return function() {
- var now = new Date,
- remaining = wait - (now - lastCalled);
-
- args = arguments;
- thisArg = this;
-
- if (remaining <= 0) {
- clearTimeout(timeoutId);
- timeoutId = null;
- lastCalled = now;
- result = func.apply(thisArg, args);
- }
- else if (!timeoutId) {
- timeoutId = setTimeout(trailingCall, remaining);
- }
- return result;
- };
- }
-
- /**
- * Creates a function that passes `value` to the `wrapper` function as its
- * first argument. Additional arguments passed to the function are appended
- * to those passed to the `wrapper` function. The `wrapper` is executed with
- * the `this` binding of the created function.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Mixed} value The value to wrap.
- * @param {Function} wrapper The wrapper function.
- * @returns {Function} Returns the new function.
- * @example
- *
- * var hello = function(name) { return 'hello ' + name; };
- * hello = _.wrap(hello, function(func) {
- * return 'before, ' + func('moe') + ', after';
- * });
- * hello();
- * // => 'before, hello moe, after'
- */
- function wrap(value, wrapper) {
- return function() {
- var args = [value];
- push.apply(args, arguments);
- return wrapper.apply(this, args);
- };
- }
-
- /*--------------------------------------------------------------------------*/
-
- /**
- * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
- * corresponding HTML entities.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {String} string The string to escape.
- * @returns {String} Returns the escaped string.
- * @example
- *
- * _.escape('Moe, Larry & Curly');
- * // => 'Moe, Larry & Curly'
- */
- function escape(string) {
- return string == null ? '' : (string + '').replace(reUnescapedHtml, escapeHtmlChar);
- }
-
- /**
- * This function returns the first argument passed to it.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {Mixed} value Any value.
- * @returns {Mixed} Returns `value`.
- * @example
- *
- * var moe = { 'name': 'moe' };
- * moe === _.identity(moe);
- * // => true
- */
- function identity(value) {
- return value;
- }
-
- /**
- * Adds functions properties of `object` to the `lodash` function and chainable
- * wrapper.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {Object} object The object of function properties to add to `lodash`.
- * @example
- *
- * _.mixin({
- * 'capitalize': function(string) {
- * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
- * }
- * });
- *
- * _.capitalize('larry');
- * // => 'Larry'
- *
- * _('curly').capitalize();
- * // => 'Curly'
- */
- function mixin(object) {
- forEach(functions(object), function(methodName) {
- var func = lodash[methodName] = object[methodName];
-
- lodash.prototype[methodName] = function() {
- var args = [this.__wrapped__];
- push.apply(args, arguments);
-
- var result = func.apply(lodash, args);
- return new lodash(result);
- };
- });
- }
-
- /**
- * Reverts the '_' variable to its previous value and returns a reference to
- * the `lodash` function.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @returns {Function} Returns the `lodash` function.
- * @example
*
- * var lodash = _.noConflict();
+ * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
+ * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
+ * 'trailing': false
+ * }));
*/
- function noConflict() {
- window._ = oldDash;
- return this;
- }
+ function throttle(func, wait, options) {
+ var leading = true,
+ trailing = true;
- /**
- * Produces a random number between `min` and `max` (inclusive). If only one
- * argument is passed, a number between `0` and the given number will be returned.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {Number} [min=0] The minimum possible value.
- * @param {Number} [max=1] The maximum possible value.
- * @returns {Number} Returns a random number.
- * @example
- *
- * _.random(0, 5);
- * // => a number between 1 and 5
- *
- * _.random(5);
- * // => also a number between 1 and 5
- */
- function random(min, max) {
- if (min == null && max == null) {
- max = 1;
+ if (!isFunction(func)) {
+ throw new TypeError;
}
- min = +min || 0;
- if (max == null) {
- max = min;
- min = 0;
+ if (options === false) {
+ leading = false;
+ } else if (isObject(options)) {
+ leading = 'leading' in options ? options.leading : leading;
+ trailing = 'trailing' in options ? options.trailing : trailing;
}
- return min + floor(nativeRandom() * ((+max || 0) - min + 1));
- }
+ debounceOptions.leading = leading;
+ debounceOptions.maxWait = wait;
+ debounceOptions.trailing = trailing;
- /**
- * Resolves the value of `property` on `object`. If `property` is a function
- * it will be invoked and its result returned, else the property value is
- * returned. If `object` is falsey, then `null` is returned.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {Object} object The object to inspect.
- * @param {String} property The property to get the value of.
- * @returns {Mixed} Returns the resolved value.
- * @example
- *
- * var object = {
- * 'cheese': 'crumpets',
- * 'stuff': function() {
- * return 'nonsense';
- * }
- * };
- *
- * _.result(object, 'cheese');
- * // => 'crumpets'
- *
- * _.result(object, 'stuff');
- * // => 'nonsense'
- */
- function result(object, property) {
- // based on Backbone's private `getValue` function
- // https://github.com/documentcloud/backbone/blob/0.9.2/backbone.js#L1419-1424
- var value = object ? object[property] : null;
- return isFunction(value) ? object[property]() : value;
+ return debounce(func, wait, debounceOptions);
}
+ /*--------------------------------------------------------------------------*/
+
/**
- * A micro-templating method that handles arbitrary delimiters, preserves
- * whitespace, and correctly escapes quotes within interpolated code.
- *
- * Note: In the development build `_.template` utilizes sourceURLs for easier
- * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
- *
- * Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp`
- * build and avoiding `_.template` use, or loading Lo-Dash in a sandboxed page.
- * See http://developer.chrome.com/trunk/extensions/sandboxingEval.html
+ * This method returns the first argument provided to it.
*
* @static
* @memberOf _
* @category Utilities
- * @param {String} text The template text.
- * @param {Obect} data The data object used to populate the text.
- * @param {Object} options The options object.
- * escape - The "escape" delimiter regexp.
- * evaluate - The "evaluate" delimiter regexp.
- * interpolate - The "interpolate" delimiter regexp.
- * sourceURL - The sourceURL of the template's compiled source.
- * variable - The data object variable name.
- *
- * @returns {Function|String} Returns a compiled function when no `data` object
- * is given, else it returns the interpolated text.
+ * @param {*} value Any value.
+ * @returns {*} Returns `value`.
* @example
- *
- * // using a compiled template
- * var compiled = _.template('hello <%= name %>');
- * compiled({ 'name': 'moe' });
- * // => 'hello moe'
- *
- * var list = '<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %>';
- * _.template(list, { 'people': ['moe', 'larry', 'curly'] });
- * // => '<li>moe</li><li>larry</li><li>curly</li>'
- *
- * // using the "escape" delimiter to escape HTML in data property values
- * _.template('<b><%- value %></b>', { 'value': '<script>' });
- * // => '<b><script></b>'
- *
- * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
- * _.template('hello ${ name }', { 'name': 'curly' });
- * // => 'hello curly'
- *
- * // using the internal `print` function in "evaluate" delimiters
- * _.template('<% print("hello " + epithet); %>!', { 'epithet': 'stooge' });
- * // => 'hello stooge!'
- *
- * // using custom template delimiters
- * _.templateSettings = {
- * 'interpolate': /{{([\s\S]+?)}}/g
- * };
- *
- * _.template('hello {{ name }}!', { 'name': 'mustache' });
- * // => 'hello mustache!'
- *
- * // using the `sourceURL` option to specify a custom sourceURL for the template
- * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
- * compiled(data);
- * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
- *
- * // using the `variable` option to ensure a with-statement isn't used in the compiled template
- * var compiled = _.template('hello <%= data.name %>!', null, { 'variable': 'data' });
- * compiled.source;
- * // => function(data) {
- * var __t, __p = '', __e = _.escape;
- * __p += 'hello ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
- * return __p;
- * }
- *
- * // using the `source` property to inline compiled templates for meaningful
- * // line numbers in error messages and a stack trace
- * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
- * var JST = {\
- * "main": ' + _.template(mainText).source + '\
- * };\
- * ');
- */
- function template(text, data, options) {
- // based on John Resig's `tmpl` implementation
- // http://ejohn.org/blog/javascript-micro-templating/
- // and Laura Doktorova's doT.js
- // https://github.com/olado/doT
- text || (text = '');
- options || (options = {});
-
- var isEvaluating,
- result,
- settings = lodash.templateSettings,
- index = 0,
- interpolate = options.interpolate || settings.interpolate || reNoMatch,
- source = "__p += '",
- variable = options.variable || settings.variable,
- hasVariable = variable;
-
- // compile regexp to match each delimiter
- var reDelimiters = RegExp(
- (options.escape || settings.escape || reNoMatch).source + '|' +
- interpolate.source + '|' +
- (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
- (options.evaluate || settings.evaluate || reNoMatch).source + '|$'
- , 'g');
-
- text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
- interpolateValue || (interpolateValue = esTemplateValue);
-
- // escape characters that cannot be included in string literals
- source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
-
- // replace delimiters with snippets
- if (escapeValue) {
- source += "' +\n__e(" + escapeValue + ") +\n'";
- }
- if (evaluateValue) {
- source += "';\n" + evaluateValue + ";\n__p += '";
- }
- if (interpolateValue) {
- source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
- }
- isEvaluating || (isEvaluating = evaluateValue || reComplexDelimiter.test(escapeValue || interpolateValue));
- index = offset + match.length;
-
- // the JS engine embedded in Adobe products requires returning the `match`
- // string in order to produce the correct `offset` value
- return match;
- });
-
- source += "';\n";
-
- // if `variable` is not specified and the template contains "evaluate"
- // delimiters, wrap a with-statement around the generated code to add the
- // data object to the top of the scope chain
- if (!hasVariable) {
- variable = 'obj';
- if (isEvaluating) {
- source = 'with (' + variable + ') {\n' + source + '\n}\n';
- }
- else {
- // avoid a with-statement by prepending data object references to property names
- var reDoubleVariable = RegExp('(\\(\\s*)' + variable + '\\.' + variable + '\\b', 'g');
- source = source
- .replace(reInsertVariable, '$&' + variable + '.')
- .replace(reDoubleVariable, '$1__d');
- }
- }
-
- // cleanup code by stripping empty strings
- source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
- .replace(reEmptyStringMiddle, '$1')
- .replace(reEmptyStringTrailing, '$1;');
-
- // frame code as the function body
- source = 'function(' + variable + ') {\n' +
- (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
- "var __t, __p = '', __e = _.escape" +
- (isEvaluating
- ? ', __j = Array.prototype.join;\n' +
- "function print() { __p += __j.call(arguments, '') }\n"
- : (hasVariable ? '' : ', __d = ' + variable + '.' + variable + ' || ' + variable) + ';\n'
- ) +
- source +
- 'return __p\n}';
-
- // use a sourceURL for easier debugging
- // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
- var sourceURL = useSourceURL
- ? '\n//@ sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']')
- : '';
-
- try {
- result = Function('_', 'return ' + source + sourceURL)(lodash);
- } catch(e) {
- e.source = source;
- throw e;
- }
-
- if (data) {
- return result(data);
- }
- // provide the compiled function's source via its `toString` method, in
- // supported environments, or the `source` property as a convenience for
- // inlining compiled templates during the build process
- result.source = source;
- return result;
+ *
+ * var object = { 'name': 'fred' };
+ * _.identity(object) === object;
+ * // => true
+ */
+ function identity(value) {
+ return value;
}
/**
- * Executes the `callback` function `n` times, returning an array of the results
- * of each `callback` execution. The `callback` is bound to `thisArg` and invoked
- * with one argument; (index).
+ * Adds function properties of a source object to the `lodash` function and
+ * chainable wrapper.
*
* @static
* @memberOf _
* @category Utilities
- * @param {Number} n The number of times to execute the callback.
- * @param {Function} callback The function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns a new array of the results of each `callback` execution.
+ * @param {Object} object The object of function properties to add to `lodash`.
+ * @param {Object} object The object of function properties to add to `lodash`.
* @example
*
- * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
- * // => [3, 6, 4]
+ * _.mixin({
+ * 'capitalize': function(string) {
+ * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
+ * }
+ * });
*
- * _.times(3, function(n) { mage.castSpell(n); });
- * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
+ * _.capitalize('fred');
+ * // => 'Fred'
*
- * _.times(3, function(n) { this.cast(n); }, mage);
- * // => also calls `mage.castSpell(n)` three times
+ * _('fred').capitalize();
+ * // => 'Fred'
*/
- function times(n, callback, thisArg) {
- n = +n || 0;
- var index = -1,
- result = Array(n);
-
- while (++index < n) {
- result[index] = callback.call(thisArg, index);
- }
- return result;
+ function mixin(object, source) {
+ var ctor = object,
+ isFunc = !source || isFunction(ctor);
+
+ if (!source) {
+ ctor = lodashWrapper;
+ source = object;
+ object = lodash;
+ }
+ forEach(functions(source), function(methodName) {
+ var func = object[methodName] = source[methodName];
+ if (isFunc) {
+ ctor.prototype[methodName] = function() {
+ var value = this.__wrapped__,
+ args = [value];
+
+ push.apply(args, arguments);
+ var result = func.apply(object, args);
+ if (value && typeof value == 'object' && value === result) {
+ return this;
+ }
+ result = new ctor(result);
+ result.__chain__ = this.__chain__;
+ return result;
+ };
+ }
+ });
}
/**
- * The opposite of `_.escape`, this method converts the HTML entities
- * `&`, `<`, `>`, `"`, and `'` in `string` to their
- * corresponding characters.
+ * A no-operation function.
*
* @static
* @memberOf _
* @category Utilities
- * @param {String} string The string to unescape.
- * @returns {String} Returns the unescaped string.
* @example
*
- * _.unescape('Moe, Larry & Curly');
- * // => 'Moe, Larry & Curly'
+ * var object = { 'name': 'fred' };
+ * _.noop(object) === undefined;
+ * // => true
*/
- function unescape(string) {
- return string == null ? '' : (string + '').replace(reEscapedHtml, unescapeHtmlChar);
+ function noop() {
+ // no operation performed
}
+ /*--------------------------------------------------------------------------*/
+
/**
- * Generates a unique ID. If `prefix` is passed, the ID will be appended to it.
+ * Creates a `lodash` object that wraps the given value with explicit
+ * method chaining enabled.
*
* @static
* @memberOf _
- * @category Utilities
- * @param {String} [prefix] The value to prefix the ID with.
- * @returns {String} Returns the unique ID.
+ * @category Chaining
+ * @param {*} value The value to wrap.
+ * @returns {Object} Returns the wrapper object.
* @example
*
- * _.uniqueId('contact_');
- * // => 'contact_104'
+ * var characters = [
+ * { 'name': 'barney', 'age': 36 },
+ * { 'name': 'fred', 'age': 40 },
+ * { 'name': 'pebbles', 'age': 1 }
+ * ];
*
- * _.uniqueId();
- * // => '105'
+ * var youngest = _.chain(characters)
+ * .sortBy('age')
+ * .map(function(chr) { return chr.name + ' is ' + chr.age; })
+ * .first()
+ * .value();
+ * // => 'pebbles is 1'
*/
- function uniqueId(prefix) {
- return (prefix == null ? '' : prefix + '') + (++idCounter);
+ function chain(value) {
+ value = new lodashWrapper(value);
+ value.__chain__ = true;
+ return value;
}
- /*--------------------------------------------------------------------------*/
-
/**
- * Invokes `interceptor` with the `value` as the first argument, and then
- * returns `value`. The purpose of this method is to "tap into" a method chain,
- * in order to perform operations on intermediate results within the chain.
+ * Enables explicit method chaining on the wrapper object.
*
- * @static
+ * @name chain
* @memberOf _
* @category Chaining
- * @param {Mixed} value The value to pass to `interceptor`.
- * @param {Function} interceptor The function to invoke.
- * @returns {Mixed} Returns `value`.
+ * @returns {*} Returns the wrapper object.
* @example
*
- * _.chain([1, 2, 3, 200])
- * .filter(function(num) { return num % 2 == 0; })
- * .tap(alert)
- * .map(function(num) { return num * num; })
- * .value();
- * // => // [2, 200] (alerted)
- * // => [4, 40000]
+ * var characters = [
+ * { 'name': 'barney', 'age': 36 },
+ * { 'name': 'fred', 'age': 40 }
+ * ];
+ *
+ * // without explicit chaining
+ * _(characters).first();
+ * // => { 'name': 'barney', 'age': 36 }
+ *
+ * // with explicit chaining
+ * _(characters).chain()
+ * .first()
+ * .pick('age')
+ * .value()
+ * // => { 'age': 36 }
*/
- function tap(value, interceptor) {
- interceptor(value);
- return value;
+ function wrapperChain() {
+ this.__chain__ = true;
+ return this;
}
/**
* @name toString
* @memberOf _
* @category Chaining
- * @returns {String} Returns the string result.
+ * @returns {string} Returns the string result.
* @example
*
* _([1, 2, 3]).toString();
* // => '1,2,3'
*/
function wrapperToString() {
- return this.__wrapped__ + '';
+ return String(this.__wrapped__);
}
/**
* @memberOf _
* @alias value
* @category Chaining
- * @returns {Mixed} Returns the wrapped value.
+ * @returns {*} Returns the wrapped value.
* @example
*
* _([1, 2, 3]).valueOf();
/*--------------------------------------------------------------------------*/
- // add functions that return wrapped values when chaining
- lodash.after = after;
lodash.assign = assign;
lodash.bind = bind;
- lodash.bindAll = bindAll;
- lodash.bindKey = bindKey;
+ lodash.chain = chain;
lodash.compact = compact;
- lodash.compose = compose;
- lodash.countBy = countBy;
+ lodash.createCallback = createCallback;
lodash.debounce = debounce;
- lodash.defaults = defaults;
- lodash.defer = defer;
- lodash.delay = delay;
lodash.difference = difference;
lodash.filter = filter;
lodash.flatten = flatten;
lodash.forOwn = forOwn;
lodash.functions = functions;
lodash.groupBy = groupBy;
- lodash.initial = initial;
lodash.intersection = intersection;
- lodash.invert = invert;
- lodash.invoke = invoke;
lodash.keys = keys;
lodash.map = map;
- lodash.max = max;
- lodash.memoize = memoize;
lodash.merge = merge;
- lodash.min = min;
- lodash.object = object;
lodash.omit = omit;
- lodash.once = once;
lodash.pairs = pairs;
- lodash.partial = partial;
- lodash.pick = pick;
lodash.pluck = pluck;
- lodash.range = range;
lodash.reject = reject;
- lodash.rest = rest;
- lodash.shuffle = shuffle;
- lodash.sortBy = sortBy;
- lodash.tap = tap;
lodash.throttle = throttle;
- lodash.times = times;
- lodash.toArray = toArray;
lodash.union = union;
lodash.uniq = uniq;
lodash.values = values;
- lodash.where = where;
lodash.without = without;
- lodash.wrap = wrap;
- lodash.zip = zip;
// add aliases
lodash.collect = map;
- lodash.drop = rest;
lodash.each = forEach;
lodash.extend = assign;
lodash.methods = functions;
lodash.select = filter;
- lodash.tail = rest;
lodash.unique = uniq;
// add functions to `lodash.prototype`
lodash.clone = clone;
lodash.cloneDeep = cloneDeep;
lodash.contains = contains;
- lodash.escape = escape;
lodash.every = every;
lodash.find = find;
- lodash.has = has;
lodash.identity = identity;
lodash.indexOf = indexOf;
lodash.isArguments = isArguments;
lodash.isArray = isArray;
- lodash.isBoolean = isBoolean;
- lodash.isDate = isDate;
- lodash.isElement = isElement;
lodash.isEmpty = isEmpty;
lodash.isEqual = isEqual;
- lodash.isFinite = isFinite;
lodash.isFunction = isFunction;
- lodash.isNaN = isNaN;
- lodash.isNull = isNull;
- lodash.isNumber = isNumber;
lodash.isObject = isObject;
lodash.isPlainObject = isPlainObject;
- lodash.isRegExp = isRegExp;
lodash.isString = isString;
- lodash.isUndefined = isUndefined;
- lodash.lastIndexOf = lastIndexOf;
lodash.mixin = mixin;
- lodash.noConflict = noConflict;
- lodash.random = random;
- lodash.reduce = reduce;
- lodash.reduceRight = reduceRight;
- lodash.result = result;
- lodash.size = size;
+ lodash.noop = noop;
lodash.some = some;
lodash.sortedIndex = sortedIndex;
- lodash.template = template;
- lodash.unescape = unescape;
- lodash.uniqueId = uniqueId;
// add aliases
lodash.all = every;
lodash.any = some;
lodash.detect = find;
- lodash.foldl = reduce;
- lodash.foldr = reduceRight;
+ lodash.findWhere = find;
lodash.include = contains;
- lodash.inject = reduce;
forOwn(lodash, function(func, methodName) {
if (!lodash.prototype[methodName]) {
lodash.prototype[methodName] = function() {
- var args = [this.__wrapped__];
+ var args = [this.__wrapped__],
+ chainAll = this.__chain__;
+
push.apply(args, arguments);
- return func.apply(lodash, args);
+ var result = func.apply(lodash, args);
+ return chainAll
+ ? new lodashWrapper(result, chainAll)
+ : result;
};
}
});
lodash.head = first;
forOwn(lodash, function(func, methodName) {
+ var callbackable = methodName !== 'sample';
if (!lodash.prototype[methodName]) {
lodash.prototype[methodName]= function(n, guard) {
- var result = func(this.__wrapped__, n, guard);
- return (n == null || guard) ? result : new lodash(result);
+ var chainAll = this.__chain__,
+ result = func(this.__wrapped__, n, guard);
+
+ return !chainAll && (n == null || (guard && !(callbackable && typeof n == 'function')))
+ ? result
+ : new lodashWrapper(result, chainAll);
};
}
});
*
* @static
* @memberOf _
- * @type String
+ * @type string
*/
- lodash.VERSION = '1.0.0-rc.3';
+ lodash.VERSION = '2.3.0';
// add "Chaining" functions to the wrapper
+ lodash.prototype.chain = wrapperChain;
lodash.prototype.toString = wrapperToString;
lodash.prototype.value = wrapperValueOf;
lodash.prototype.valueOf = wrapperValueOf;
// add `Array` functions that return unwrapped values
- each(['join', 'pop', 'shift'], function(methodName) {
+ baseEach(['join', 'pop', 'shift'], function(methodName) {
var func = arrayRef[methodName];
lodash.prototype[methodName] = function() {
- return func.apply(this.__wrapped__, arguments);
+ var chainAll = this.__chain__,
+ result = func.apply(this.__wrapped__, arguments);
+
+ return chainAll
+ ? new lodashWrapper(result, chainAll)
+ : result;
};
});
// add `Array` functions that return the wrapped value
- each(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
+ baseEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
var func = arrayRef[methodName];
lodash.prototype[methodName] = function() {
func.apply(this.__wrapped__, arguments);
});
// add `Array` functions that return new wrapped values
- each(['concat', 'slice', 'splice'], function(methodName) {
+ baseEach(['concat', 'slice', 'splice'], function(methodName) {
var func = arrayRef[methodName];
lodash.prototype[methodName] = function() {
- var result = func.apply(this.__wrapped__, arguments);
- return new lodash(result);
+ return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__);
};
});
// avoid array-like object bugs with `Array#shift` and `Array#splice`
- // in Firefox < 10 and IE < 9
- if (hasObjectSpliceBug) {
- each(['pop', 'shift', 'splice'], function(methodName) {
+ // in IE < 9, Firefox < 10, Narwhal, and RingoJS
+ if (!support.spliceObjects) {
+ baseEach(['pop', 'shift', 'splice'], function(methodName) {
var func = arrayRef[methodName],
isSplice = methodName == 'splice';
lodash.prototype[methodName] = function() {
- var value = this.__wrapped__,
+ var chainAll = this.__chain__,
+ value = this.__wrapped__,
result = func.apply(value, arguments);
if (value.length === 0) {
delete value[0];
}
- return isSplice ? new lodash(result) : result;
+ return (chainAll || isSplice)
+ ? new lodashWrapper(result, chainAll)
+ : result;
};
});
}
- // add pseudo private property to be used and removed during the build process
- lodash._each = each;
- lodash._iteratorTemplate = iteratorTemplate;
-
/*--------------------------------------------------------------------------*/
- // expose Lo-Dash
- // some AMD build optimizers, like r.js, check for specific condition patterns like the following:
- if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
- // Expose Lo-Dash to the global object even when an AMD loader is present in
- // case Lo-Dash was injected by a third-party script and not intended to be
- // loaded as a module. The global assignment can be reverted in the Lo-Dash
- // module via its `noConflict()` method.
- window._ = lodash;
-
- // define as an anonymous module so, through path mapping, it can be
- // referenced as the "underscore" module
- define(function() {
- return lodash;
- });
- }
- // check for `exports` after `define` in case a build optimizer adds an `exports` object
- else if (freeExports) {
- // in Node.js or RingoJS v0.8.0+
- if (typeof module == 'object' && module && module.exports == freeExports) {
- (module.exports = lodash)._ = lodash;
- }
- // in Narwhal or RingoJS v0.7.0-
- else {
- freeExports._ = lodash;
+ if (freeExports && freeModule) {
+ // in Node.js or RingoJS
+ if (moduleExports) {
+ (freeModule.exports = lodash)._ = lodash;
}
+
}
else {
// in a browser or Rhino
- window._ = lodash;
+ root._ = lodash;
}
-}(this));
+}.call(this));
(function(e){if("function"==typeof bootstrap)bootstrap("osmauth",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeOsmAuth=e}else"undefined"!=typeof window?window.osmAuth=e():global.osmAuth=e()})(function(){var define,ses,bootstrap,module,exports;
return (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
+'use strict';
+
var ohauth = require('ohauth'),
+ xtend = require('xtend'),
store = require('store');
// # osm-auth
o.oauth_secret, '',
ohauth.baseString('POST', url, params));
- // Create a 600x550 popup window in the center of the screen
- var w = 600, h = 550,
- settings = [
- ['width', w], ['height', h],
- ['left', screen.width / 2 - w / 2],
- ['top', screen.height / 2 - h / 2]].map(function(x) {
- return x.join('=');
- }).join(','),
- popup = window.open('about:blank', 'oauth_window', settings);
+ if (!o.singlepage) {
+ // Create a 600x550 popup window in the center of the screen
+ var w = 600, h = 550,
+ settings = [
+ ['width', w], ['height', h],
+ ['left', screen.width / 2 - w / 2],
+ ['top', screen.height / 2 - h / 2]].map(function(x) {
+ return x.join('=');
+ }).join(','),
+ popup = window.open('about:blank', 'oauth_window', settings);
+ }
// Request a request token. When this is complete, the popup
// window is redirected to OSM's authorization page.
if (err) return callback(err);
var resp = ohauth.stringQs(xhr.response);
token('oauth_request_token_secret', resp.oauth_token_secret);
- popup.location = o.url + '/oauth/authorize?' + ohauth.qsString({
+ var authorize_url = o.url + '/oauth/authorize?' + ohauth.qsString({
oauth_token: resp.oauth_token,
oauth_callback: location.href.replace('index.html', '')
- .replace(/#.+/, '') + o.landing
+ .replace(/#.*/, '') + o.landing
});
+
+ if (o.singlepage) {
+ location.href = authorize_url;
+ } else {
+ popup.location = authorize_url;
+ }
}
// Called by a function in a landing page, in the popup window. The
}
};
+ oauth.bootstrapToken = function(oauth_token, callback) {
+ // ## Getting an request token
+ // At this point we have an `oauth_token`, brought in from a function
+ // call on a landing page popup.
+ function get_access_token(oauth_token) {
+ var url = o.url + '/oauth/access_token',
+ params = timenonce(getAuth(o)),
+ request_token_secret = token('oauth_request_token_secret');
+ params.oauth_token = oauth_token;
+ params.oauth_signature = ohauth.signature(
+ o.oauth_secret,
+ request_token_secret,
+ ohauth.baseString('POST', url, params));
+
+ // ## Getting an access token
+ // The final token required for authentication. At this point
+ // we have a `request token secret`
+ ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
+ o.loading();
+ }
+
+ function accessTokenDone(err, xhr) {
+ o.done();
+ if (err) return callback(err);
+ var access_token = ohauth.stringQs(xhr.response);
+ token('oauth_token', access_token.oauth_token);
+ token('oauth_token_secret', access_token.oauth_token_secret);
+ callback(null, oauth);
+ }
+
+ get_access_token(oauth_token);
+ };
+
// # xhr
//
// A single XMLHttpRequest wrapper that does authenticated calls if the
url = o.url + options.path,
oauth_token_secret = token('oauth_token_secret');
+ // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
+ if ((!options.options || !options.options.header ||
+ options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') &&
+ options.content) {
+ params = xtend(params, ohauth.stringQs(options.content));
+ }
+
params.oauth_token = token('oauth_token');
params.oauth_signature = ohauth.signature(
o.oauth_secret,
o.url = o.url || 'http://www.openstreetmap.org';
o.landing = o.landing || 'land.html';
+ o.singlepage = o.singlepage || false;
+
// Optional loading and loading-done functions for nice UI feedback.
// by default, no-ops
o.loading = o.loading || function() {};
// get/set tokens. These are prefixed with the base URL so that `osm-auth`
// can be used with multiple APIs and the keys in `localStorage`
// will not clash
- function token(x, y) {
- if (arguments.length === 1) return store.get(o.url + x);
- else if (arguments.length === 2) return store.set(o.url + x, y);
+ var token;
+
+ if (store.enabled) {
+ token = function (x, y) {
+ if (arguments.length === 1) return store.get(o.url + x);
+ else if (arguments.length === 2) return store.set(o.url + x, y);
+ };
+ } else {
+ var storage = {};
+ token = function (x, y) {
+ if (arguments.length === 1) return storage[o.url + x];
+ else if (arguments.length === 2) return storage[o.url + x] = y;
+ };
}
// Get an authentication object. If you just add and remove properties
return oauth;
};
-},{"ohauth":2,"store":3}],3:[function(require,module,exports){
-/* Copyright (c) 2010-2012 Marcus Westin
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-;(function(){
+},{"ohauth":2,"store":3,"xtend":4}],3:[function(require,module,exports){
+(function(global){;(function(win){
var store = {},
- win = window,
doc = win.document,
localStorageName = 'localStorage',
- namespace = '__storejs__',
storage
store.disabled = false
store.set(key, val)
}
store.getAll = function() {}
+ store.forEach = function() {}
store.serialize = function(value) {
return JSON.stringify(value)
store.clear = function() { storage.clear() }
store.getAll = function() {
var ret = {}
- for (var i=0; i<storage.length; ++i) {
+ store.forEach(function(key, val) {
+ ret[key] = val
+ })
+ return ret
+ }
+ store.forEach = function(callback) {
+ for (var i=0; i<storage.length; i++) {
var key = storage.key(i)
- ret[key] = store.get(key)
+ callback(key, store.get(key))
}
- return ret
}
} else if (doc.documentElement.addBehavior) {
var storageOwner,
try {
storageContainer = new ActiveXObject('htmlfile')
storageContainer.open()
- storageContainer.write('<s' + 'cript>document.w=window</s' + 'cript><iframe src="/favicon.ico"></frame>')
+ storageContainer.write('<s' + 'cript>document.w=window</s' + 'cript><iframe src="/favicon.ico"></iframe>')
storageContainer.close()
storageOwner = storageContainer.w.frames[0].document
storage = storageOwner.createElement('div')
}
storage.save(localStorageName)
})
- store.getAll = withIEStorage(function(storage) {
- var attributes = storage.XMLDocument.documentElement.attributes
- storage.load(localStorageName)
+ store.getAll = function(storage) {
var ret = {}
+ store.forEach(function(key, val) {
+ ret[key] = val
+ })
+ return ret
+ }
+ store.forEach = withIEStorage(function(storage, callback) {
+ var attributes = storage.XMLDocument.documentElement.attributes
for (var i=0, attr; attr=attributes[i]; ++i) {
- ret[attr] = store.get(attr)
+ callback(attr.name, store.deserialize(storage.getAttribute(attr.name)))
}
- return ret
})
}
try {
- store.set(namespace, namespace)
- if (store.get(namespace) != namespace) { store.disabled = true }
- store.remove(namespace)
+ var testKey = '__storejs__'
+ store.set(testKey, testKey)
+ if (store.get(testKey) != testKey) { store.disabled = true }
+ store.remove(testKey)
} catch(e) {
store.disabled = true
}
store.enabled = !store.disabled
-
- if (typeof module != 'undefined' && typeof module != 'function') { module.exports = store }
+
+ if (typeof module != 'undefined' && module.exports) { module.exports = store }
else if (typeof define === 'function' && define.amd) { define(store) }
- else { this.store = store }
-})();
+ else { win.store = store }
+
+})(this.window || global);
+
+})(window)
+},{}],5:[function(require,module,exports){
+module.exports = hasKeys
+
+function hasKeys(source) {
+ return source !== null &&
+ (typeof source === "object" ||
+ typeof source === "function")
+}
+
+},{}],4:[function(require,module,exports){
+var Keys = require("object-keys")
+var hasKeys = require("./has-keys")
+
+module.exports = extend
+
+function extend() {
+ var target = {}
+
+ for (var i = 0; i < arguments.length; i++) {
+ var source = arguments[i]
+
+ if (!hasKeys(source)) {
+ continue
+ }
+
+ var keys = Keys(source)
+
+ for (var j = 0; j < keys.length; j++) {
+ var name = keys[j]
+ target[name] = source[name]
+ }
+ }
+
+ return target
+}
+
+},{"./has-keys":5,"object-keys":6}],7:[function(require,module,exports){
+(function(global){/**
+ * jsHashes - A fast and independent hashing library pure JavaScript implemented (ES3 compliant) for both server and client side
+ *
+ * @class Hashes
+ * @author Tomas Aparicio <tomas@rijndael-project.com>
+ * @license New BSD (see LICENSE file)
+ * @version 1.0.4
+ *
+ * Algorithms specification:
+ *
+ * MD5 <http://www.ietf.org/rfc/rfc1321.txt>
+ * RIPEMD-160 <http://homes.esat.kuleuven.be/~bosselae/ripemd160.html>
+ * SHA1 <http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf>
+ * SHA256 <http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf>
+ * SHA512 <http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf>
+ * HMAC <http://www.ietf.org/rfc/rfc2104.txt>
+ *
+ */
+(function(){
+ var Hashes;
+
+ // private helper methods
+ function utf8Encode(str) {
+ var x, y, output = '', i = -1, l;
+
+ if (str && str.length) {
+ l = str.length;
+ while ((i+=1) < l) {
+ /* Decode utf-16 surrogate pairs */
+ x = str.charCodeAt(i);
+ y = i + 1 < l ? str.charCodeAt(i + 1) : 0;
+ if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
+ x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
+ i += 1;
+ }
+ /* Encode output as utf-8 */
+ if (x <= 0x7F) {
+ output += String.fromCharCode(x);
+ } else if (x <= 0x7FF) {
+ output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
+ 0x80 | ( x & 0x3F));
+ } else if (x <= 0xFFFF) {
+ output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
+ 0x80 | ((x >>> 6 ) & 0x3F),
+ 0x80 | ( x & 0x3F));
+ } else if (x <= 0x1FFFFF) {
+ output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
+ 0x80 | ((x >>> 12) & 0x3F),
+ 0x80 | ((x >>> 6 ) & 0x3F),
+ 0x80 | ( x & 0x3F));
+ }
+ }
+ }
+ return output;
+ }
+
+ function utf8Decode(str) {
+ var i, ac, c1, c2, c3, arr = [], l;
+ i = ac = c1 = c2 = c3 = 0;
+
+ if (str && str.length) {
+ l = str.length;
+ str += '';
+
+ while (i < l) {
+ c1 = str.charCodeAt(i);
+ ac += 1;
+ if (c1 < 128) {
+ arr[ac] = String.fromCharCode(c1);
+ i+=1;
+ } else if (c1 > 191 && c1 < 224) {
+ c2 = str.charCodeAt(i + 1);
+ arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
+ i += 2;
+ } else {
+ c2 = str.charCodeAt(i + 1);
+ c3 = str.charCodeAt(i + 2);
+ arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+ i += 3;
+ }
+ }
+ }
+ return arr.join('');
+ }
+
+ /**
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+ function safe_add(x, y) {
+ var lsw = (x & 0xFFFF) + (y & 0xFFFF),
+ msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+ return (msw << 16) | (lsw & 0xFFFF);
+ }
+
+ /**
+ * Bitwise rotate a 32-bit number to the left.
+ */
+ function bit_rol(num, cnt) {
+ return (num << cnt) | (num >>> (32 - cnt));
+ }
+
+ /**
+ * Convert a raw string to a hex string
+ */
+ function rstr2hex(input, hexcase) {
+ var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',
+ output = '', x, i = 0, l = input.length;
+ for (; i < l; i+=1) {
+ x = input.charCodeAt(i);
+ output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F);
+ }
+ return output;
+ }
+
+ /**
+ * Encode a string as utf-16
+ */
+ function str2rstr_utf16le(input) {
+ var i, l = input.length, output = '';
+ for (i = 0; i < l; i+=1) {
+ output += String.fromCharCode( input.charCodeAt(i) & 0xFF, (input.charCodeAt(i) >>> 8) & 0xFF);
+ }
+ return output;
+ }
+
+ function str2rstr_utf16be(input) {
+ var i, l = input.length, output = '';
+ for (i = 0; i < l; i+=1) {
+ output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, input.charCodeAt(i) & 0xFF);
+ }
+ return output;
+ }
+
+ /**
+ * Convert an array of big-endian words to a string
+ */
+ function binb2rstr(input) {
+ var i, l = input.length * 32, output = '';
+ for (i = 0; i < l; i += 8) {
+ output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF);
+ }
+ return output;
+ }
+
+ /**
+ * Convert an array of little-endian words to a string
+ */
+ function binl2rstr(input) {
+ var i, l = input.length * 32, output = '';
+ for (i = 0;i < l; i += 8) {
+ output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
+ }
+ return output;
+ }
+
+ /**
+ * Convert a raw string to an array of little-endian words
+ * Characters >255 have their high-byte silently ignored.
+ */
+ function rstr2binl(input) {
+ var i, l = input.length * 8, output = Array(input.length >> 2), lo = output.length;
+ for (i = 0; i < lo; i+=1) {
+ output[i] = 0;
+ }
+ for (i = 0; i < l; i += 8) {
+ output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
+ }
+ return output;
+ }
+
+ /**
+ * Convert a raw string to an array of big-endian words
+ * Characters >255 have their high-byte silently ignored.
+ */
+ function rstr2binb(input) {
+ var i, l = input.length * 8, output = Array(input.length >> 2), lo = output.length;
+ for (i = 0; i < lo; i+=1) {
+ output[i] = 0;
+ }
+ for (i = 0; i < l; i += 8) {
+ output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
+ }
+ return output;
+ }
+
+ /**
+ * Convert a raw string to an arbitrary string encoding
+ */
+ function rstr2any(input, encoding) {
+ var divisor = encoding.length,
+ remainders = Array(),
+ i, q, x, ld, quotient, dividend, output, full_length;
+
+ /* Convert to an array of 16-bit big-endian values, forming the dividend */
+ dividend = Array(Math.ceil(input.length / 2));
+ ld = dividend.length;
+ for (i = 0; i < ld; i+=1) {
+ dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
+ }
+
+ /**
+ * Repeatedly perform a long division. The binary array forms the dividend,
+ * the length of the encoding is the divisor. Once computed, the quotient
+ * forms the dividend for the next step. We stop when the dividend is zerHashes.
+ * All remainders are stored for later use.
+ */
+ while(dividend.length > 0) {
+ quotient = Array();
+ x = 0;
+ for (i = 0; i < dividend.length; i+=1) {
+ x = (x << 16) + dividend[i];
+ q = Math.floor(x / divisor);
+ x -= q * divisor;
+ if (quotient.length > 0 || q > 0) {
+ quotient[quotient.length] = q;
+ }
+ }
+ remainders[remainders.length] = x;
+ dividend = quotient;
+ }
+
+ /* Convert the remainders to the output string */
+ output = '';
+ for (i = remainders.length - 1; i >= 0; i--) {
+ output += encoding.charAt(remainders[i]);
+ }
+
+ /* Append leading zero equivalents */
+ full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
+ for (i = output.length; i < full_length; i+=1) {
+ output = encoding[0] + output;
+ }
+ return output;
+ }
+
+ /**
+ * Convert a raw string to a base-64 string
+ */
+ function rstr2b64(input, b64pad) {
+ var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
+ output = '',
+ len = input.length, i, j, triplet;
+ b64pad= b64pad || '=';
+ for (i = 0; i < len; i += 3) {
+ triplet = (input.charCodeAt(i) << 16)
+ | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
+ | (i + 2 < len ? input.charCodeAt(i+2) : 0);
+ for (j = 0; j < 4; j+=1) {
+ if (i * 8 + j * 6 > input.length * 8) {
+ output += b64pad;
+ } else {
+ output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
+ }
+ }
+ }
+ return output;
+ }
+
+ Hashes = {
+ /**
+ * @property {String} version
+ * @readonly
+ */
+ VERSION : '1.0.3',
+ /**
+ * @member Hashes
+ * @class Base64
+ * @constructor
+ */
+ Base64 : function () {
+ // private properties
+ var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
+ pad = '=', // default pad according with the RFC standard
+ url = false, // URL encoding support @todo
+ utf8 = true; // by default enable UTF-8 support encoding
+
+ // public method for encoding
+ this.encode = function (input) {
+ var i, j, triplet,
+ output = '',
+ len = input.length;
+
+ pad = pad || '=';
+ input = (utf8) ? utf8Encode(input) : input;
+
+ for (i = 0; i < len; i += 3) {
+ triplet = (input.charCodeAt(i) << 16)
+ | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
+ | (i + 2 < len ? input.charCodeAt(i+2) : 0);
+ for (j = 0; j < 4; j+=1) {
+ if (i * 8 + j * 6 > len * 8) {
+ output += pad;
+ } else {
+ output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
+ }
+ }
+ }
+ return output;
+ };
+
+ // public method for decoding
+ this.decode = function (input) {
+ // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+ var i, o1, o2, o3, h1, h2, h3, h4, bits, ac,
+ dec = '',
+ arr = [];
+ if (!input) { return input; }
+
+ i = ac = 0;
+ input = input.replace(new RegExp('\\'+pad,'gi'),''); // use '='
+ //input += '';
+
+ do { // unpack four hexets into three octets using index points in b64
+ h1 = tab.indexOf(input.charAt(i+=1));
+ h2 = tab.indexOf(input.charAt(i+=1));
+ h3 = tab.indexOf(input.charAt(i+=1));
+ h4 = tab.indexOf(input.charAt(i+=1));
+
+ bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
+
+ o1 = bits >> 16 & 0xff;
+ o2 = bits >> 8 & 0xff;
+ o3 = bits & 0xff;
+ ac += 1;
+
+ if (h3 === 64) {
+ arr[ac] = String.fromCharCode(o1);
+ } else if (h4 === 64) {
+ arr[ac] = String.fromCharCode(o1, o2);
+ } else {
+ arr[ac] = String.fromCharCode(o1, o2, o3);
+ }
+ } while (i < input.length);
+
+ dec = arr.join('');
+ dec = (utf8) ? utf8Decode(dec) : dec;
+
+ return dec;
+ };
+
+ // set custom pad string
+ this.setPad = function (str) {
+ pad = str || pad;
+ return this;
+ };
+ // set custom tab string characters
+ this.setTab = function (str) {
+ tab = str || tab;
+ return this;
+ };
+ this.setUTF8 = function (bool) {
+ if (typeof bool === 'boolean') {
+ utf8 = bool;
+ }
+ return this;
+ };
+ },
+
+ /**
+ * CRC-32 calculation
+ * @member Hashes
+ * @method CRC32
+ * @static
+ * @param {String} str Input String
+ * @return {String}
+ */
+ CRC32 : function (str) {
+ var crc = 0, x = 0, y = 0, table, i, iTop;
+ str = utf8Encode(str);
+
+ table = [
+ '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ',
+ '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ',
+ '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ',
+ '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ',
+ 'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ',
+ '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ',
+ 'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ',
+ '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ',
+ 'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ',
+ '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ',
+ 'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ',
+ '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ',
+ 'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ',
+ '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ',
+ '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ',
+ '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ',
+ '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ',
+ 'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ',
+ '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ',
+ 'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ',
+ '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ',
+ 'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ',
+ '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ',
+ 'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ',
+ '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ',
+ 'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'
+ ].join('');
+
+ crc = crc ^ (-1);
+ for (i = 0, iTop = str.length; i < iTop; i+=1 ) {
+ y = ( crc ^ str.charCodeAt( i ) ) & 0xFF;
+ x = '0x' + table.substr( y * 9, 8 );
+ crc = ( crc >>> 8 ) ^ x;
+ }
+ // always return a positive number (that's what >>> 0 does)
+ return (crc ^ (-1)) >>> 0;
+ },
+ /**
+ * @member Hashes
+ * @class MD5
+ * @constructor
+ * @param {Object} [config]
+ *
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * See <http://pajhome.org.uk/crypt/md5> for more infHashes.
+ */
+ MD5 : function (options) {
+ /**
+ * Private config properties. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
+ */
+ var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
+ b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
+ utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
+
+ // privileged (public) methods
+ this.hex = function (s) {
+ return rstr2hex(rstr(s, utf8), hexcase);
+ };
+ this.b64 = function (s) {
+ return rstr2b64(rstr(s), b64pad);
+ };
+ this.any = function(s, e) {
+ return rstr2any(rstr(s, utf8), e);
+ };
+ this.hex_hmac = function (k, d) {
+ return rstr2hex(rstr_hmac(k, d), hexcase);
+ };
+ this.b64_hmac = function (k, d) {
+ return rstr2b64(rstr_hmac(k,d), b64pad);
+ };
+ this.any_hmac = function (k, d, e) {
+ return rstr2any(rstr_hmac(k, d), e);
+ };
+ /**
+ * Perform a simple self-test to see if the VM is working
+ * @return {String} Hexadecimal hash sample
+ */
+ this.vm_test = function () {
+ return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
+ };
+ /**
+ * Enable/disable uppercase hexadecimal returned string
+ * @param {Boolean}
+ * @return {Object} this
+ */
+ this.setUpperCase = function (a) {
+ if (typeof a === 'boolean' ) {
+ hexcase = a;
+ }
+ return this;
+ };
+ /**
+ * Defines a base64 pad string
+ * @param {String} Pad
+ * @return {Object} this
+ */
+ this.setPad = function (a) {
+ b64pad = a || b64pad;
+ return this;
+ };
+ /**
+ * Defines a base64 pad string
+ * @param {Boolean}
+ * @return {Object} [this]
+ */
+ this.setUTF8 = function (a) {
+ if (typeof a === 'boolean') {
+ utf8 = a;
+ }
+ return this;
+ };
+
+ // private methods
+
+ /**
+ * Calculate the MD5 of a raw string
+ */
+ function rstr(s) {
+ s = (utf8) ? utf8Encode(s): s;
+ return binl2rstr(binl(rstr2binl(s), s.length * 8));
+ }
+
+ /**
+ * Calculate the HMAC-MD5, of a key and some data (raw strings)
+ */
+ function rstr_hmac(key, data) {
+ var bkey, ipad, opad, hash, i;
+
+ key = (utf8) ? utf8Encode(key) : key;
+ data = (utf8) ? utf8Encode(data) : data;
+ bkey = rstr2binl(key);
+ if (bkey.length > 16) {
+ bkey = binl(bkey, key.length * 8);
+ }
+
+ ipad = Array(16), opad = Array(16);
+ for (i = 0; i < 16; i+=1) {
+ ipad[i] = bkey[i] ^ 0x36363636;
+ opad[i] = bkey[i] ^ 0x5C5C5C5C;
+ }
+ hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
+ return binl2rstr(binl(opad.concat(hash), 512 + 128));
+ }
+
+ /**
+ * Calculate the MD5 of an array of little-endian words, and a bit length.
+ */
+ function binl(x, len) {
+ var i, olda, oldb, oldc, oldd,
+ a = 1732584193,
+ b = -271733879,
+ c = -1732584194,
+ d = 271733878;
+
+ /* append padding */
+ x[len >> 5] |= 0x80 << ((len) % 32);
+ x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+ for (i = 0; i < x.length; i += 16) {
+ olda = a;
+ oldb = b;
+ oldc = c;
+ oldd = d;
+
+ a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+ d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+ c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
+ b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+ a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+ d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
+ c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+ b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+ a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
+ d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+ c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+ b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+ a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
+ d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+ c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+ b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
+
+ a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+ d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+ c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
+ b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+ a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+ d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
+ c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+ b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+ a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
+ d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+ c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+ b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
+ a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+ d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+ c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
+ b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+ a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+ d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+ c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
+ b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+ a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+ d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
+ c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+ b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+ a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
+ d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+ c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+ b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
+ a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+ d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+ c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
+ b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+ a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+ d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
+ c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+ b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+ a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
+ d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+ c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+ b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+ a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
+ d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+ c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+ b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
+ a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+ d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+ c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
+ b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+ a = safe_add(a, olda);
+ b = safe_add(b, oldb);
+ c = safe_add(c, oldc);
+ d = safe_add(d, oldd);
+ }
+ return Array(a, b, c, d);
+ }
+
+ /**
+ * These functions implement the four basic operations the algorithm uses.
+ */
+ function md5_cmn(q, a, b, x, s, t) {
+ return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+ }
+ function md5_ff(a, b, c, d, x, s, t) {
+ return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+ }
+ function md5_gg(a, b, c, d, x, s, t) {
+ return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+ }
+ function md5_hh(a, b, c, d, x, s, t) {
+ return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+ }
+ function md5_ii(a, b, c, d, x, s, t) {
+ return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+ }
+ },
+ /**
+ * @member Hashes
+ * @class Hashes.SHA1
+ * @param {Object} [config]
+ * @constructor
+ *
+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
+ * Version 2.2 Copyright Paul Johnston 2000 - 2009.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * See http://pajhome.org.uk/crypt/md5 for details.
+ */
+ SHA1 : function (options) {
+ /**
+ * Private config properties. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
+ */
+ var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
+ b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
+ utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
+
+ // public methods
+ this.hex = function (s) {
+ return rstr2hex(rstr(s, utf8), hexcase);
+ };
+ this.b64 = function (s) {
+ return rstr2b64(rstr(s, utf8), b64pad);
+ };
+ this.any = function (s, e) {
+ return rstr2any(rstr(s, utf8), e);
+ };
+ this.hex_hmac = function (k, d) {
+ return rstr2hex(rstr_hmac(k, d));
+ };
+ this.b64_hmac = function (k, d) {
+ return rstr2b64(rstr_hmac(k, d), b64pad);
+ };
+ this.any_hmac = function (k, d, e) {
+ return rstr2any(rstr_hmac(k, d), e);
+ };
+ /**
+ * Perform a simple self-test to see if the VM is working
+ * @return {String} Hexadecimal hash sample
+ * @public
+ */
+ this.vm_test = function () {
+ return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
+ };
+ /**
+ * @description Enable/disable uppercase hexadecimal returned string
+ * @param {boolean}
+ * @return {Object} this
+ * @public
+ */
+ this.setUpperCase = function (a) {
+ if (typeof a === 'boolean') {
+ hexcase = a;
+ }
+ return this;
+ };
+ /**
+ * @description Defines a base64 pad string
+ * @param {string} Pad
+ * @return {Object} this
+ * @public
+ */
+ this.setPad = function (a) {
+ b64pad = a || b64pad;
+ return this;
+ };
+ /**
+ * @description Defines a base64 pad string
+ * @param {boolean}
+ * @return {Object} this
+ * @public
+ */
+ this.setUTF8 = function (a) {
+ if (typeof a === 'boolean') {
+ utf8 = a;
+ }
+ return this;
+ };
+
+ // private methods
+
+ /**
+ * Calculate the SHA-512 of a raw string
+ */
+ function rstr(s) {
+ s = (utf8) ? utf8Encode(s) : s;
+ return binb2rstr(binb(rstr2binb(s), s.length * 8));
+ }
+
+ /**
+ * Calculate the HMAC-SHA1 of a key and some data (raw strings)
+ */
+ function rstr_hmac(key, data) {
+ var bkey, ipad, opad, i, hash;
+ key = (utf8) ? utf8Encode(key) : key;
+ data = (utf8) ? utf8Encode(data) : data;
+ bkey = rstr2binb(key);
+
+ if (bkey.length > 16) {
+ bkey = binb(bkey, key.length * 8);
+ }
+ ipad = Array(16), opad = Array(16);
+ for (i = 0; i < 16; i+=1) {
+ ipad[i] = bkey[i] ^ 0x36363636;
+ opad[i] = bkey[i] ^ 0x5C5C5C5C;
+ }
+ hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
+ return binb2rstr(binb(opad.concat(hash), 512 + 160));
+ }
+
+ /**
+ * Calculate the SHA-1 of an array of big-endian words, and a bit length
+ */
+ function binb(x, len) {
+ var i, j, t, olda, oldb, oldc, oldd, olde,
+ w = Array(80),
+ a = 1732584193,
+ b = -271733879,
+ c = -1732584194,
+ d = 271733878,
+ e = -1009589776;
+
+ /* append padding */
+ x[len >> 5] |= 0x80 << (24 - len % 32);
+ x[((len + 64 >> 9) << 4) + 15] = len;
+
+ for (i = 0; i < x.length; i += 16) {
+ olda = a,
+ oldb = b;
+ oldc = c;
+ oldd = d;
+ olde = e;
+
+ for (j = 0; j < 80; j+=1) {
+ if (j < 16) {
+ w[j] = x[i + j];
+ } else {
+ w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
+ }
+ t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
+ safe_add(safe_add(e, w[j]), sha1_kt(j)));
+ e = d;
+ d = c;
+ c = bit_rol(b, 30);
+ b = a;
+ a = t;
+ }
+
+ a = safe_add(a, olda);
+ b = safe_add(b, oldb);
+ c = safe_add(c, oldc);
+ d = safe_add(d, oldd);
+ e = safe_add(e, olde);
+ }
+ return Array(a, b, c, d, e);
+ }
+
+ /**
+ * Perform the appropriate triplet combination function for the current
+ * iteration
+ */
+ function sha1_ft(t, b, c, d) {
+ if (t < 20) { return (b & c) | ((~b) & d); }
+ if (t < 40) { return b ^ c ^ d; }
+ if (t < 60) { return (b & c) | (b & d) | (c & d); }
+ return b ^ c ^ d;
+ }
+
+ /**
+ * Determine the appropriate additive constant for the current iteration
+ */
+ function sha1_kt(t) {
+ return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
+ (t < 60) ? -1894007588 : -899497514;
+ }
+ },
+ /**
+ * @class Hashes.SHA256
+ * @param {config}
+ *
+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
+ * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * See http://pajhome.org.uk/crypt/md5 for details.
+ * Also http://anmar.eu.org/projects/jssha2/
+ */
+ SHA256 : function (options) {
+ /**
+ * Private properties configuration variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ * @see this.setUpperCase() method
+ * @see this.setPad() method
+ */
+ var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase */
+ b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', /* base-64 pad character. Default '=' for strict RFC compliance */
+ utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, /* enable/disable utf8 encoding */
+ sha256_K;
+
+ /* privileged (public) methods */
+ this.hex = function (s) {
+ return rstr2hex(rstr(s, utf8));
+ };
+ this.b64 = function (s) {
+ return rstr2b64(rstr(s, utf8), b64pad);
+ };
+ this.any = function (s, e) {
+ return rstr2any(rstr(s, utf8), e);
+ };
+ this.hex_hmac = function (k, d) {
+ return rstr2hex(rstr_hmac(k, d));
+ };
+ this.b64_hmac = function (k, d) {
+ return rstr2b64(rstr_hmac(k, d), b64pad);
+ };
+ this.any_hmac = function (k, d, e) {
+ return rstr2any(rstr_hmac(k, d), e);
+ };
+ /**
+ * Perform a simple self-test to see if the VM is working
+ * @return {String} Hexadecimal hash sample
+ * @public
+ */
+ this.vm_test = function () {
+ return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
+ };
+ /**
+ * Enable/disable uppercase hexadecimal returned string
+ * @param {boolean}
+ * @return {Object} this
+ * @public
+ */
+ this.setUpperCase = function (a) {
+ if (typeof a === 'boolean') {
+ hexcase = a;
+ }
+ return this;
+ };
+ /**
+ * @description Defines a base64 pad string
+ * @param {string} Pad
+ * @return {Object} this
+ * @public
+ */
+ this.setPad = function (a) {
+ b64pad = a || b64pad;
+ return this;
+ };
+ /**
+ * Defines a base64 pad string
+ * @param {boolean}
+ * @return {Object} this
+ * @public
+ */
+ this.setUTF8 = function (a) {
+ if (typeof a === 'boolean') {
+ utf8 = a;
+ }
+ return this;
+ };
+
+ // private methods
+
+ /**
+ * Calculate the SHA-512 of a raw string
+ */
+ function rstr(s, utf8) {
+ s = (utf8) ? utf8Encode(s) : s;
+ return binb2rstr(binb(rstr2binb(s), s.length * 8));
+ }
+
+ /**
+ * Calculate the HMAC-sha256 of a key and some data (raw strings)
+ */
+ function rstr_hmac(key, data) {
+ key = (utf8) ? utf8Encode(key) : key;
+ data = (utf8) ? utf8Encode(data) : data;
+ var hash, i = 0,
+ bkey = rstr2binb(key),
+ ipad = Array(16),
+ opad = Array(16);
+
+ if (bkey.length > 16) { bkey = binb(bkey, key.length * 8); }
+
+ for (; i < 16; i+=1) {
+ ipad[i] = bkey[i] ^ 0x36363636;
+ opad[i] = bkey[i] ^ 0x5C5C5C5C;
+ }
+
+ hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
+ return binb2rstr(binb(opad.concat(hash), 512 + 256));
+ }
+
+ /*
+ * Main sha256 function, with its support functions
+ */
+ function sha256_S (X, n) {return ( X >>> n ) | (X << (32 - n));}
+ function sha256_R (X, n) {return ( X >>> n );}
+ function sha256_Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
+ function sha256_Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
+ function sha256_Sigma0256(x) {return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));}
+ function sha256_Sigma1256(x) {return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));}
+ function sha256_Gamma0256(x) {return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));}
+ function sha256_Gamma1256(x) {return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));}
+ function sha256_Sigma0512(x) {return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));}
+ function sha256_Sigma1512(x) {return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));}
+ function sha256_Gamma0512(x) {return (sha256_S(x, 1) ^ sha256_S(x, 8) ^ sha256_R(x, 7));}
+ function sha256_Gamma1512(x) {return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));}
+
+ sha256_K = [
+ 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993,
+ -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
+ 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
+ 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986,
+ -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
+ 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
+ 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885,
+ -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
+ 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
+ 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872,
+ -1866530822, -1538233109, -1090935817, -965641998
+ ];
+
+ function binb(m, l) {
+ var HASH = [1779033703, -1150833019, 1013904242, -1521486534,
+ 1359893119, -1694144372, 528734635, 1541459225];
+ var W = new Array(64);
+ var a, b, c, d, e, f, g, h;
+ var i, j, T1, T2;
+
+ /* append padding */
+ m[l >> 5] |= 0x80 << (24 - l % 32);
+ m[((l + 64 >> 9) << 4) + 15] = l;
+
+ for (i = 0; i < m.length; i += 16)
+ {
+ a = HASH[0];
+ b = HASH[1];
+ c = HASH[2];
+ d = HASH[3];
+ e = HASH[4];
+ f = HASH[5];
+ g = HASH[6];
+ h = HASH[7];
+
+ for (j = 0; j < 64; j+=1)
+ {
+ if (j < 16) {
+ W[j] = m[j + i];
+ } else {
+ W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
+ sha256_Gamma0256(W[j - 15])), W[j - 16]);
+ }
+
+ T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
+ sha256_K[j]), W[j]);
+ T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
+ h = g;
+ g = f;
+ f = e;
+ e = safe_add(d, T1);
+ d = c;
+ c = b;
+ b = a;
+ a = safe_add(T1, T2);
+ }
+
+ HASH[0] = safe_add(a, HASH[0]);
+ HASH[1] = safe_add(b, HASH[1]);
+ HASH[2] = safe_add(c, HASH[2]);
+ HASH[3] = safe_add(d, HASH[3]);
+ HASH[4] = safe_add(e, HASH[4]);
+ HASH[5] = safe_add(f, HASH[5]);
+ HASH[6] = safe_add(g, HASH[6]);
+ HASH[7] = safe_add(h, HASH[7]);
+ }
+ return HASH;
+ }
+
+ },
+ /**
+ * @class Hashes.SHA512
+ * @param {config}
+ *
+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
+ * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * See http://pajhome.org.uk/crypt/md5 for details.
+ */
+ SHA512 : function (options) {
+ /**
+ * Private properties configuration variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ * @see this.setUpperCase() method
+ * @see this.setPad() method
+ */
+ var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false , /* hexadecimal output case format. false - lowercase; true - uppercase */
+ b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', /* base-64 pad character. Default '=' for strict RFC compliance */
+ utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, /* enable/disable utf8 encoding */
+ sha512_k;
+
+ /* privileged (public) methods */
+ this.hex = function (s) {
+ return rstr2hex(rstr(s));
+ };
+ this.b64 = function (s) {
+ return rstr2b64(rstr(s), b64pad);
+ };
+ this.any = function (s, e) {
+ return rstr2any(rstr(s), e);
+ };
+ this.hex_hmac = function (k, d) {
+ return rstr2hex(rstr_hmac(k, d));
+ };
+ this.b64_hmac = function (k, d) {
+ return rstr2b64(rstr_hmac(k, d), b64pad);
+ };
+ this.any_hmac = function (k, d, e) {
+ return rstr2any(rstr_hmac(k, d), e);
+ };
+ /**
+ * Perform a simple self-test to see if the VM is working
+ * @return {String} Hexadecimal hash sample
+ * @public
+ */
+ this.vm_test = function () {
+ return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
+ };
+ /**
+ * @description Enable/disable uppercase hexadecimal returned string
+ * @param {boolean}
+ * @return {Object} this
+ * @public
+ */
+ this.setUpperCase = function (a) {
+ if (typeof a === 'boolean') {
+ hexcase = a;
+ }
+ return this;
+ };
+ /**
+ * @description Defines a base64 pad string
+ * @param {string} Pad
+ * @return {Object} this
+ * @public
+ */
+ this.setPad = function (a) {
+ b64pad = a || b64pad;
+ return this;
+ };
+ /**
+ * @description Defines a base64 pad string
+ * @param {boolean}
+ * @return {Object} this
+ * @public
+ */
+ this.setUTF8 = function (a) {
+ if (typeof a === 'boolean') {
+ utf8 = a;
+ }
+ return this;
+ };
+
+ /* private methods */
+
+ /**
+ * Calculate the SHA-512 of a raw string
+ */
+ function rstr(s) {
+ s = (utf8) ? utf8Encode(s) : s;
+ return binb2rstr(binb(rstr2binb(s), s.length * 8));
+ }
+ /*
+ * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
+ */
+ function rstr_hmac(key, data) {
+ key = (utf8) ? utf8Encode(key) : key;
+ data = (utf8) ? utf8Encode(data) : data;
+
+ var hash, i = 0,
+ bkey = rstr2binb(key),
+ ipad = Array(32), opad = Array(32);
+
+ if (bkey.length > 32) { bkey = binb(bkey, key.length * 8); }
+
+ for (; i < 32; i+=1) {
+ ipad[i] = bkey[i] ^ 0x36363636;
+ opad[i] = bkey[i] ^ 0x5C5C5C5C;
+ }
+
+ hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
+ return binb2rstr(binb(opad.concat(hash), 1024 + 512));
+ }
+
+ /**
+ * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
+ */
+ function binb(x, len) {
+ var j, i, l,
+ W = new Array(80),
+ hash = new Array(16),
+ //Initial hash values
+ H = [
+ new int64(0x6a09e667, -205731576),
+ new int64(-1150833019, -2067093701),
+ new int64(0x3c6ef372, -23791573),
+ new int64(-1521486534, 0x5f1d36f1),
+ new int64(0x510e527f, -1377402159),
+ new int64(-1694144372, 0x2b3e6c1f),
+ new int64(0x1f83d9ab, -79577749),
+ new int64(0x5be0cd19, 0x137e2179)
+ ],
+ T1 = new int64(0, 0),
+ T2 = new int64(0, 0),
+ a = new int64(0,0),
+ b = new int64(0,0),
+ c = new int64(0,0),
+ d = new int64(0,0),
+ e = new int64(0,0),
+ f = new int64(0,0),
+ g = new int64(0,0),
+ h = new int64(0,0),
+ //Temporary variables not specified by the document
+ s0 = new int64(0, 0),
+ s1 = new int64(0, 0),
+ Ch = new int64(0, 0),
+ Maj = new int64(0, 0),
+ r1 = new int64(0, 0),
+ r2 = new int64(0, 0),
+ r3 = new int64(0, 0);
+
+ if (sha512_k === undefined) {
+ //SHA512 constants
+ sha512_k = [
+ new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd),
+ new int64(-1245643825, -330482897), new int64(-373957723, -2121671748),
+ new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031),
+ new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736),
+ new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe),
+ new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302),
+ new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1),
+ new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428),
+ new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3),
+ new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65),
+ new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
+ new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459),
+ new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210),
+ new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340),
+ new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395),
+ new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70),
+ new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
+ new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473),
+ new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8),
+ new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b),
+ new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023),
+ new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30),
+ new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910),
+ new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
+ new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53),
+ new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016),
+ new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893),
+ new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397),
+ new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
+ new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec),
+ new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047),
+ new int64(-1090935817, -1295615723), new int64(-965641998, -479046869),
+ new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207),
+ new int64(-354779690, -840897762), new int64(-176337025, -294727304),
+ new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026),
+ new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b),
+ new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
+ new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620),
+ new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430),
+ new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)
+ ];
+ }
+
+ for (i=0; i<80; i+=1) {
+ W[i] = new int64(0, 0);
+ }
+
+ // append padding to the source string. The format is described in the FIPS.
+ x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
+ x[((len + 128 >> 10)<< 5) + 31] = len;
+ l = x.length;
+ for (i = 0; i<l; i+=32) { //32 dwords is the block size
+ int64copy(a, H[0]);
+ int64copy(b, H[1]);
+ int64copy(c, H[2]);
+ int64copy(d, H[3]);
+ int64copy(e, H[4]);
+ int64copy(f, H[5]);
+ int64copy(g, H[6]);
+ int64copy(h, H[7]);
+
+ for (j=0; j<16; j+=1) {
+ W[j].h = x[i + 2*j];
+ W[j].l = x[i + 2*j + 1];
+ }
+
+ for (j=16; j<80; j+=1) {
+ //sigma1
+ int64rrot(r1, W[j-2], 19);
+ int64revrrot(r2, W[j-2], 29);
+ int64shr(r3, W[j-2], 6);
+ s1.l = r1.l ^ r2.l ^ r3.l;
+ s1.h = r1.h ^ r2.h ^ r3.h;
+ //sigma0
+ int64rrot(r1, W[j-15], 1);
+ int64rrot(r2, W[j-15], 8);
+ int64shr(r3, W[j-15], 7);
+ s0.l = r1.l ^ r2.l ^ r3.l;
+ s0.h = r1.h ^ r2.h ^ r3.h;
+
+ int64add4(W[j], s1, W[j-7], s0, W[j-16]);
+ }
+
+ for (j = 0; j < 80; j+=1) {
+ //Ch
+ Ch.l = (e.l & f.l) ^ (~e.l & g.l);
+ Ch.h = (e.h & f.h) ^ (~e.h & g.h);
+
+ //Sigma1
+ int64rrot(r1, e, 14);
+ int64rrot(r2, e, 18);
+ int64revrrot(r3, e, 9);
+ s1.l = r1.l ^ r2.l ^ r3.l;
+ s1.h = r1.h ^ r2.h ^ r3.h;
+
+ //Sigma0
+ int64rrot(r1, a, 28);
+ int64revrrot(r2, a, 2);
+ int64revrrot(r3, a, 7);
+ s0.l = r1.l ^ r2.l ^ r3.l;
+ s0.h = r1.h ^ r2.h ^ r3.h;
+
+ //Maj
+ Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
+ Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
+
+ int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
+ int64add(T2, s0, Maj);
+
+ int64copy(h, g);
+ int64copy(g, f);
+ int64copy(f, e);
+ int64add(e, d, T1);
+ int64copy(d, c);
+ int64copy(c, b);
+ int64copy(b, a);
+ int64add(a, T1, T2);
+ }
+ int64add(H[0], H[0], a);
+ int64add(H[1], H[1], b);
+ int64add(H[2], H[2], c);
+ int64add(H[3], H[3], d);
+ int64add(H[4], H[4], e);
+ int64add(H[5], H[5], f);
+ int64add(H[6], H[6], g);
+ int64add(H[7], H[7], h);
+ }
+
+ //represent the hash as an array of 32-bit dwords
+ for (i=0; i<8; i+=1) {
+ hash[2*i] = H[i].h;
+ hash[2*i + 1] = H[i].l;
+ }
+ return hash;
+ }
+
+ //A constructor for 64-bit numbers
+ function int64(h, l) {
+ this.h = h;
+ this.l = l;
+ //this.toString = int64toString;
+ }
+
+ //Copies src into dst, assuming both are 64-bit numbers
+ function int64copy(dst, src) {
+ dst.h = src.h;
+ dst.l = src.l;
+ }
+
+ //Right-rotates a 64-bit number by shift
+ //Won't handle cases of shift>=32
+ //The function revrrot() is for that
+ function int64rrot(dst, x, shift) {
+ dst.l = (x.l >>> shift) | (x.h << (32-shift));
+ dst.h = (x.h >>> shift) | (x.l << (32-shift));
+ }
+
+ //Reverses the dwords of the source and then rotates right by shift.
+ //This is equivalent to rotation by 32+shift
+ function int64revrrot(dst, x, shift) {
+ dst.l = (x.h >>> shift) | (x.l << (32-shift));
+ dst.h = (x.l >>> shift) | (x.h << (32-shift));
+ }
+
+ //Bitwise-shifts right a 64-bit number by shift
+ //Won't handle shift>=32, but it's never needed in SHA512
+ function int64shr(dst, x, shift) {
+ dst.l = (x.l >>> shift) | (x.h << (32-shift));
+ dst.h = (x.h >>> shift);
+ }
+
+ //Adds two 64-bit numbers
+ //Like the original implementation, does not rely on 32-bit operations
+ function int64add(dst, x, y) {
+ var w0 = (x.l & 0xffff) + (y.l & 0xffff);
+ var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
+ var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
+ var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
+ dst.l = (w0 & 0xffff) | (w1 << 16);
+ dst.h = (w2 & 0xffff) | (w3 << 16);
+ }
+
+ //Same, except with 4 addends. Works faster than adding them one by one.
+ function int64add4(dst, a, b, c, d) {
+ var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
+ var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
+ var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
+ var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
+ dst.l = (w0 & 0xffff) | (w1 << 16);
+ dst.h = (w2 & 0xffff) | (w3 << 16);
+ }
+
+ //Same, except with 5 addends
+ function int64add5(dst, a, b, c, d, e) {
+ var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
+ w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),
+ w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),
+ w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
+ dst.l = (w0 & 0xffff) | (w1 << 16);
+ dst.h = (w2 & 0xffff) | (w3 << 16);
+ }
+ },
+ /**
+ * @class Hashes.RMD160
+ * @constructor
+ * @param {Object} [config]
+ *
+ * A JavaScript implementation of the RIPEMD-160 Algorithm
+ * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * See http://pajhome.org.uk/crypt/md5 for details.
+ * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
+ */
+ RMD160 : function (options) {
+ /**
+ * Private properties configuration variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ * @see this.setUpperCase() method
+ * @see this.setPad() method
+ */
+ var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, /* hexadecimal output case format. false - lowercase; true - uppercase */
+ b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', /* base-64 pad character. Default '=' for strict RFC compliance */
+ utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, /* enable/disable utf8 encoding */
+ rmd160_r1 = [
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
+ 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
+ 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
+ 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
+ ],
+ rmd160_r2 = [
+ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
+ 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
+ 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
+ 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
+ 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
+ ],
+ rmd160_s1 = [
+ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
+ 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
+ 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
+ 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
+ 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
+ ],
+ rmd160_s2 = [
+ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
+ 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
+ 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
+ 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
+ 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
+ ];
+
+ /* privileged (public) methods */
+ this.hex = function (s) {
+ return rstr2hex(rstr(s, utf8));
+ };
+ this.b64 = function (s) {
+ return rstr2b64(rstr(s, utf8), b64pad);
+ };
+ this.any = function (s, e) {
+ return rstr2any(rstr(s, utf8), e);
+ };
+ this.hex_hmac = function (k, d) {
+ return rstr2hex(rstr_hmac(k, d));
+ };
+ this.b64_hmac = function (k, d) {
+ return rstr2b64(rstr_hmac(k, d), b64pad);
+ };
+ this.any_hmac = function (k, d, e) {
+ return rstr2any(rstr_hmac(k, d), e);
+ };
+ /**
+ * Perform a simple self-test to see if the VM is working
+ * @return {String} Hexadecimal hash sample
+ * @public
+ */
+ this.vm_test = function () {
+ return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
+ };
+ /**
+ * @description Enable/disable uppercase hexadecimal returned string
+ * @param {boolean}
+ * @return {Object} this
+ * @public
+ */
+ this.setUpperCase = function (a) {
+ if (typeof a === 'boolean' ) { hexcase = a; }
+ return this;
+ };
+ /**
+ * @description Defines a base64 pad string
+ * @param {string} Pad
+ * @return {Object} this
+ * @public
+ */
+ this.setPad = function (a) {
+ if (typeof a !== 'undefined' ) { b64pad = a; }
+ return this;
+ };
+ /**
+ * @description Defines a base64 pad string
+ * @param {boolean}
+ * @return {Object} this
+ * @public
+ */
+ this.setUTF8 = function (a) {
+ if (typeof a === 'boolean') { utf8 = a; }
+ return this;
+ };
+
+ /* private methods */
+
+ /**
+ * Calculate the rmd160 of a raw string
+ */
+ function rstr(s) {
+ s = (utf8) ? utf8Encode(s) : s;
+ return binl2rstr(binl(rstr2binl(s), s.length * 8));
+ }
+
+ /**
+ * Calculate the HMAC-rmd160 of a key and some data (raw strings)
+ */
+ function rstr_hmac(key, data) {
+ key = (utf8) ? utf8Encode(key) : key;
+ data = (utf8) ? utf8Encode(data) : data;
+ var i, hash,
+ bkey = rstr2binl(key),
+ ipad = Array(16), opad = Array(16);
+
+ if (bkey.length > 16) {
+ bkey = binl(bkey, key.length * 8);
+ }
+
+ for (i = 0; i < 16; i+=1) {
+ ipad[i] = bkey[i] ^ 0x36363636;
+ opad[i] = bkey[i] ^ 0x5C5C5C5C;
+ }
+ hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
+ return binl2rstr(binl(opad.concat(hash), 512 + 160));
+ }
+
+ /**
+ * Convert an array of little-endian words to a string
+ */
+ function binl2rstr(input) {
+ var i, output = '', l = input.length * 32;
+ for (i = 0; i < l; i += 8) {
+ output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
+ }
+ return output;
+ }
+
+ /**
+ * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
+ */
+ function binl(x, len) {
+ var T, j, i, l,
+ h0 = 0x67452301,
+ h1 = 0xefcdab89,
+ h2 = 0x98badcfe,
+ h3 = 0x10325476,
+ h4 = 0xc3d2e1f0,
+ A1, B1, C1, D1, E1,
+ A2, B2, C2, D2, E2;
+
+ /* append padding */
+ x[len >> 5] |= 0x80 << (len % 32);
+ x[(((len + 64) >>> 9) << 4) + 14] = len;
+ l = x.length;
+
+ for (i = 0; i < l; i+=16) {
+ A1 = A2 = h0; B1 = B2 = h1; C1 = C2 = h2; D1 = D2 = h3; E1 = E2 = h4;
+ for (j = 0; j <= 79; j+=1) {
+ T = safe_add(A1, rmd160_f(j, B1, C1, D1));
+ T = safe_add(T, x[i + rmd160_r1[j]]);
+ T = safe_add(T, rmd160_K1(j));
+ T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
+ A1 = E1; E1 = D1; D1 = bit_rol(C1, 10); C1 = B1; B1 = T;
+ T = safe_add(A2, rmd160_f(79-j, B2, C2, D2));
+ T = safe_add(T, x[i + rmd160_r2[j]]);
+ T = safe_add(T, rmd160_K2(j));
+ T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
+ A2 = E2; E2 = D2; D2 = bit_rol(C2, 10); C2 = B2; B2 = T;
+ }
+
+ T = safe_add(h1, safe_add(C1, D2));
+ h1 = safe_add(h2, safe_add(D1, E2));
+ h2 = safe_add(h3, safe_add(E1, A2));
+ h3 = safe_add(h4, safe_add(A1, B2));
+ h4 = safe_add(h0, safe_add(B1, C2));
+ h0 = T;
+ }
+ return [h0, h1, h2, h3, h4];
+ }
+
+ // specific algorithm methods
+ function rmd160_f(j, x, y, z) {
+ return ( 0 <= j && j <= 15) ? (x ^ y ^ z) :
+ (16 <= j && j <= 31) ? (x & y) | (~x & z) :
+ (32 <= j && j <= 47) ? (x | ~y) ^ z :
+ (48 <= j && j <= 63) ? (x & z) | (y & ~z) :
+ (64 <= j && j <= 79) ? x ^ (y | ~z) :
+ 'rmd160_f: j out of range';
+ }
+
+ function rmd160_K1(j) {
+ return ( 0 <= j && j <= 15) ? 0x00000000 :
+ (16 <= j && j <= 31) ? 0x5a827999 :
+ (32 <= j && j <= 47) ? 0x6ed9eba1 :
+ (48 <= j && j <= 63) ? 0x8f1bbcdc :
+ (64 <= j && j <= 79) ? 0xa953fd4e :
+ 'rmd160_K1: j out of range';
+ }
+
+ function rmd160_K2(j){
+ return ( 0 <= j && j <= 15) ? 0x50a28be6 :
+ (16 <= j && j <= 31) ? 0x5c4dd124 :
+ (32 <= j && j <= 47) ? 0x6d703ef3 :
+ (48 <= j && j <= 63) ? 0x7a6d76e9 :
+ (64 <= j && j <= 79) ? 0x00000000 :
+ 'rmd160_K2: j out of range';
+ }
+ }
+};
+
+ // exposes Hashes
+ (function( window, undefined ) {
+ var freeExports = false;
+ if (typeof exports === 'object' ) {
+ freeExports = exports;
+ if (exports && typeof global === 'object' && global && global === global.global ) { window = global; }
+ }
+
+ if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
+ // define as an anonymous module, so, through path mapping, it can be aliased
+ define(function () { return Hashes; });
+ }
+ else if ( freeExports ) {
+ // in Node.js or RingoJS v0.8.0+
+ if ( typeof module === 'object' && module && module.exports === freeExports ) {
+ module.exports = Hashes;
+ }
+ // in Narwhal or RingoJS v0.7.0-
+ else {
+ freeExports.Hashes = Hashes;
+ }
+ }
+ else {
+ // in a browser or Rhino
+ window.Hashes = Hashes;
+ }
+ }( this ));
+}()); // IIFE
+
+})(window)
},{}],2:[function(require,module,exports){
'use strict';
module.exports = ohauth;
-},{"jshashes":4,"xtend":5}],4:[function(require,module,exports){
-(function(global){/**\r
- * jsHashes - A fast and independent hashing library pure JavaScript implemented (ES5 compliant) for both server and client side\r
- * \r
- * @class Hashes\r
- * @author Tomas Aparicio <tomas@rijndael-project.com>\r
- * @license New BSD (see LICENSE file)\r
- * @version 1.0.3\r
- *\r
- * Algorithms specification:\r
- *\r
- * MD5 <http://www.ietf.org/rfc/rfc1321.txt>\r
- * RIPEMD-160 <http://homes.esat.kuleuven.be/~bosselae/ripemd160.html>\r
- * SHA1 <http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf>\r
- * SHA256 <http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf>\r
- * SHA512 <http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf>\r
- * HMAC <http://www.ietf.org/rfc/rfc2104.txt>\r
- *\r
- */\r
-(function(){\r
- var Hashes;\r
- \r
- // private helper methods\r
- function utf8Encode(input) {\r
- var x, y, output = '', i = -1, l = input.length;\r
- while ((i+=1) < l) {\r
- /* Decode utf-16 surrogate pairs */\r
- x = input.charCodeAt(i);\r
- y = i + 1 < l ? input.charCodeAt(i + 1) : 0;\r
- if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {\r
- x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);\r
- i += 1;\r
- }\r
- /* Encode output as utf-8 */\r
- if (x <= 0x7F) {\r
- output += String.fromCharCode(x);\r
- } else if (x <= 0x7FF) {\r
- output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),\r
- 0x80 | ( x & 0x3F));\r
- } else if (x <= 0xFFFF) {\r
- output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),\r
- 0x80 | ((x >>> 6 ) & 0x3F),\r
- 0x80 | ( x & 0x3F));\r
- } else if (x <= 0x1FFFFF) {\r
- output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),\r
- 0x80 | ((x >>> 12) & 0x3F),\r
- 0x80 | ((x >>> 6 ) & 0x3F),\r
- 0x80 | ( x & 0x3F));\r
- }\r
- }\r
- return output;\r
- }\r
- \r
- function utf8Decode(str_data) {\r
- var i, ac, c1, c2, c3, arr = [], l = str_data.length;\r
- i = ac = c1 = c2 = c3 = 0;\r
- str_data += '';\r
-\r
- while (i < l) {\r
- c1 = str_data.charCodeAt(i);\r
- ac += 1;\r
- if (c1 < 128) {\r
- arr[ac] = String.fromCharCode(c1);\r
- i+=1;\r
- } else if (c1 > 191 && c1 < 224) {\r
- c2 = str_data.charCodeAt(i + 1);\r
- arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));\r
- i += 2;\r
- } else {\r
- c2 = str_data.charCodeAt(i + 1);\r
- c3 = str_data.charCodeAt(i + 2);\r
- arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));\r
- i += 3;\r
- }\r
- }\r
- return arr.join('');\r
- }\r
-\r
- /**\r
- * Add integers, wrapping at 2^32. This uses 16-bit operations internally\r
- * to work around bugs in some JS interpreters.\r
- */\r
- function safe_add(x, y) {\r
- var lsw = (x & 0xFFFF) + (y & 0xFFFF),\r
- msw = (x >> 16) + (y >> 16) + (lsw >> 16);\r
- return (msw << 16) | (lsw & 0xFFFF);\r
- }\r
-\r
- /**\r
- * Bitwise rotate a 32-bit number to the left.\r
- */\r
- function bit_rol(num, cnt) {\r
- return (num << cnt) | (num >>> (32 - cnt));\r
- }\r
-\r
- /**\r
- * Convert a raw string to a hex string\r
- */\r
- function rstr2hex(input, hexcase) {\r
- var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',\r
- output = '', x, i = 0, l = input.length;\r
- for (; i < l; i+=1) {\r
- x = input.charCodeAt(i);\r
- output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F);\r
- }\r
- return output;\r
- }\r
-\r
- /**\r
- * Encode a string as utf-16\r
- */\r
- function str2rstr_utf16le(input) {\r
- var i, l = input.length, output = '';\r
- for (i = 0; i < l; i+=1) {\r
- output += String.fromCharCode( input.charCodeAt(i) & 0xFF, (input.charCodeAt(i) >>> 8) & 0xFF);\r
- }\r
- return output;\r
- }\r
-\r
- function str2rstr_utf16be(input) {\r
- var i, l = input.length, output = '';\r
- for (i = 0; i < l; i+=1) {\r
- output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, input.charCodeAt(i) & 0xFF);\r
- }\r
- return output;\r
- }\r
-\r
- /**\r
- * Convert an array of big-endian words to a string\r
- */\r
- function binb2rstr(input) {\r
- var i, l = input.length * 32, output = '';\r
- for (i = 0; i < l; i += 8) {\r
- output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF);\r
- }\r
- return output;\r
- }\r
-\r
- /**\r
- * Convert an array of little-endian words to a string\r
- */\r
- function binl2rstr(input) {\r
- var i, l = input.length * 32, output = '';\r
- for (i = 0;i < l; i += 8) {\r
- output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);\r
- }\r
- return output;\r
- }\r
-\r
- /**\r
- * Convert a raw string to an array of little-endian words\r
- * Characters >255 have their high-byte silently ignored.\r
- */\r
- function rstr2binl(input) {\r
- var i, l = input.length * 8, output = Array(input.length >> 2), lo = output.length;\r
- for (i = 0; i < lo; i+=1) {\r
- output[i] = 0;\r
- }\r
- for (i = 0; i < l; i += 8) {\r
- output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);\r
- }\r
- return output;\r
- }\r
- \r
- /**\r
- * Convert a raw string to an array of big-endian words \r
- * Characters >255 have their high-byte silently ignored.\r
- */\r
- function rstr2binb(input) {\r
- var i, l = input.length * 8, output = Array(input.length >> 2), lo = output.length;\r
- for (i = 0; i < lo; i+=1) {\r
- output[i] = 0;\r
- }\r
- for (i = 0; i < l; i += 8) {\r
- output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);\r
- }\r
- return output;\r
- }\r
-\r
- /**\r
- * Convert a raw string to an arbitrary string encoding\r
- */\r
- function rstr2any(input, encoding) {\r
- var divisor = encoding.length,\r
- remainders = Array(),\r
- i, q, x, ld, quotient, dividend, output, full_length;\r
- \r
- /* Convert to an array of 16-bit big-endian values, forming the dividend */\r
- dividend = Array(Math.ceil(input.length / 2));\r
- ld = dividend.length;\r
- for (i = 0; i < ld; i+=1) {\r
- dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);\r
- }\r
- \r
- /**\r
- * Repeatedly perform a long division. The binary array forms the dividend,\r
- * the length of the encoding is the divisor. Once computed, the quotient\r
- * forms the dividend for the next step. We stop when the dividend is zerHashes.\r
- * All remainders are stored for later use.\r
- */\r
- while(dividend.length > 0) {\r
- quotient = Array();\r
- x = 0;\r
- for (i = 0; i < dividend.length; i+=1) {\r
- x = (x << 16) + dividend[i];\r
- q = Math.floor(x / divisor);\r
- x -= q * divisor;\r
- if (quotient.length > 0 || q > 0) {\r
- quotient[quotient.length] = q;\r
- }\r
- }\r
- remainders[remainders.length] = x;\r
- dividend = quotient;\r
- }\r
- \r
- /* Convert the remainders to the output string */\r
- output = '';\r
- for (i = remainders.length - 1; i >= 0; i--) {\r
- output += encoding.charAt(remainders[i]);\r
- }\r
- \r
- /* Append leading zero equivalents */\r
- full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));\r
- for (i = output.length; i < full_length; i+=1) {\r
- output = encoding[0] + output;\r
- }\r
- return output;\r
- }\r
-\r
- /**\r
- * Convert a raw string to a base-64 string\r
- */\r
- function rstr2b64(input, b64pad) {\r
- var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',\r
- output = '',\r
- len = input.length, i, j, triplet;\r
- b64pad= b64pad || '=';\r
- for (i = 0; i < len; i += 3) {\r
- triplet = (input.charCodeAt(i) << 16)\r
- | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)\r
- | (i + 2 < len ? input.charCodeAt(i+2) : 0);\r
- for (j = 0; j < 4; j+=1) {\r
- if (i * 8 + j * 6 > input.length * 8) { \r
- output += b64pad; \r
- } else { \r
- output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); \r
- }\r
- }\r
- }\r
- return output;\r
- }\r
-\r
- Hashes = {\r
- /** \r
- * @property {String} version\r
- * @readonly\r
- */\r
- VERSION : '1.0.3',\r
- /**\r
- * @member Hashes\r
- * @class Base64\r
- * @constructor\r
- */\r
- Base64 : function () {\r
- // private properties\r
- var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',\r
- pad = '=', // default pad according with the RFC standard\r
- url = false, // URL encoding support @todo\r
- utf8 = true; // by default enable UTF-8 support encoding\r
-\r
- // public method for encoding\r
- this.encode = function (input) {\r
- var i, j, triplet,\r
- output = '', \r
- len = input.length;\r
-\r
- pad = pad || '=';\r
- input = (utf8) ? utf8Encode(input) : input;\r
-\r
- for (i = 0; i < len; i += 3) {\r
- triplet = (input.charCodeAt(i) << 16)\r
- | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)\r
- | (i + 2 < len ? input.charCodeAt(i+2) : 0);\r
- for (j = 0; j < 4; j+=1) {\r
- if (i * 8 + j * 6 > len * 8) {\r
- output += pad;\r
- } else {\r
- output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);\r
- }\r
- }\r
- }\r
- return output; \r
- };\r
-\r
- // public method for decoding\r
- this.decode = function (input) {\r
- // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\r
- var i, o1, o2, o3, h1, h2, h3, h4, bits, ac,\r
- dec = '',\r
- arr = [];\r
- if (!input) { return input; }\r
-\r
- i = ac = 0;\r
- input = input.replace(new RegExp('\\'+pad,'gi'),''); // use '='\r
- //input += '';\r
-\r
- do { // unpack four hexets into three octets using index points in b64\r
- h1 = tab.indexOf(input.charAt(i+=1));\r
- h2 = tab.indexOf(input.charAt(i+=1));\r
- h3 = tab.indexOf(input.charAt(i+=1));\r
- h4 = tab.indexOf(input.charAt(i+=1));\r
-\r
- bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;\r
-\r
- o1 = bits >> 16 & 0xff;\r
- o2 = bits >> 8 & 0xff;\r
- o3 = bits & 0xff;\r
- ac += 1;\r
-\r
- if (h3 === 64) {\r
- arr[ac] = String.fromCharCode(o1);\r
- } else if (h4 === 64) {\r
- arr[ac] = String.fromCharCode(o1, o2);\r
- } else {\r
- arr[ac] = String.fromCharCode(o1, o2, o3);\r
- }\r
- } while (i < input.length);\r
-\r
- dec = arr.join('');\r
- dec = (utf8) ? utf8Decode(dec) : dec;\r
-\r
- return dec;\r
- };\r
-\r
- // set custom pad string\r
- this.setPad = function (str) {\r
- pad = str || pad;\r
- return this;\r
- };\r
- // set custom tab string characters\r
- this.setTab = function (str) {\r
- tab = str || tab;\r
- return this;\r
- };\r
- this.setUTF8 = function (bool) {\r
- if (typeof bool === 'boolean') {\r
- utf8 = bool;\r
- }\r
- return this;\r
- };\r
- },\r
-\r
- /**\r
- * CRC-32 calculation\r
- * @member Hashes\r
- * @method CRC32\r
- * @static\r
- * @param {String} str Input String\r
- * @return {String}\r
- */\r
- CRC32 : function (str) {\r
- var crc = 0, x = 0, y = 0, table, i, iTop;\r
- str = utf8Encode(str);\r
- \r
- table = [ \r
- '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ',\r
- '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ',\r
- '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ',\r
- '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ',\r
- 'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ',\r
- '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ',\r
- 'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ',\r
- '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ',\r
- 'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ',\r
- '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ',\r
- 'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ',\r
- '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ',\r
- 'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ',\r
- '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ',\r
- '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ',\r
- '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ',\r
- '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ',\r
- 'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ', \r
- '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ',\r
- 'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ',\r
- '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ',\r
- 'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ',\r
- '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ',\r
- 'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ',\r
- '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ',\r
- 'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'\r
- ].join('');\r
-\r
- crc = crc ^ (-1);\r
- for (i = 0, iTop = str.length; i < iTop; i+=1 ) {\r
- y = ( crc ^ str.charCodeAt( i ) ) & 0xFF;\r
- x = '0x' + table.substr( y * 9, 8 );\r
- crc = ( crc >>> 8 ) ^ x;\r
- }\r
- // always return a positive number (that's what >>> 0 does)\r
- return (crc ^ (-1)) >>> 0;\r
- },\r
- /**\r
- * @member Hashes\r
- * @class MD5\r
- * @constructor\r
- * @param {Object} [config]\r
- * \r
- * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message\r
- * Digest Algorithm, as defined in RFC 1321.\r
- * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009\r
- * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\r
- * See <http://pajhome.org.uk/crypt/md5> for more infHashes.\r
- */\r
- MD5 : function (options) { \r
- /**\r
- * Private config properties. You may need to tweak these to be compatible with\r
- * the server-side, but the defaults work in most cases.\r
- * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}\r
- */\r
- var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase\r
- b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance\r
- utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding\r
-\r
- // privileged (public) methods \r
- this.hex = function (s) { \r
- return rstr2hex(rstr(s, utf8), hexcase);\r
- };\r
- this.b64 = function (s) { \r
- return rstr2b64(rstr(s), b64pad);\r
- };\r
- this.any = function(s, e) { \r
- return rstr2any(rstr(s, utf8), e); \r
- };\r
- this.hex_hmac = function (k, d) { \r
- return rstr2hex(rstr_hmac(k, d), hexcase); \r
- };\r
- this.b64_hmac = function (k, d) { \r
- return rstr2b64(rstr_hmac(k,d), b64pad); \r
- };\r
- this.any_hmac = function (k, d, e) { \r
- return rstr2any(rstr_hmac(k, d), e); \r
- };\r
- /**\r
- * Perform a simple self-test to see if the VM is working\r
- * @return {String} Hexadecimal hash sample\r
- */\r
- this.vm_test = function () {\r
- return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';\r
- };\r
- /** \r
- * Enable/disable uppercase hexadecimal returned string \r
- * @param {Boolean} \r
- * @return {Object} this\r
- */ \r
- this.setUpperCase = function (a) {\r
- if (typeof a === 'boolean' ) {\r
- hexcase = a;\r
- }\r
- return this;\r
- };\r
- /** \r
- * Defines a base64 pad string \r
- * @param {String} Pad\r
- * @return {Object} this\r
- */ \r
- this.setPad = function (a) {\r
- b64pad = a || b64pad;\r
- return this;\r
- };\r
- /** \r
- * Defines a base64 pad string \r
- * @param {Boolean} \r
- * @return {Object} [this]\r
- */ \r
- this.setUTF8 = function (a) {\r
- if (typeof a === 'boolean') { \r
- utf8 = a;\r
- }\r
- return this;\r
- };\r
-\r
- // private methods\r
-\r
- /**\r
- * Calculate the MD5 of a raw string\r
- */\r
- function rstr(s) {\r
- s = (utf8) ? utf8Encode(s): s;\r
- return binl2rstr(binl(rstr2binl(s), s.length * 8));\r
- }\r
- \r
- /**\r
- * Calculate the HMAC-MD5, of a key and some data (raw strings)\r
- */\r
- function rstr_hmac(key, data) {\r
- var bkey, ipad, opad, hash, i;\r
-\r
- key = (utf8) ? utf8Encode(key) : key;\r
- data = (utf8) ? utf8Encode(data) : data;\r
- bkey = rstr2binl(key);\r
- if (bkey.length > 16) { \r
- bkey = binl(bkey, key.length * 8); \r
- }\r
-\r
- ipad = Array(16), opad = Array(16); \r
- for (i = 0; i < 16; i+=1) {\r
- ipad[i] = bkey[i] ^ 0x36363636;\r
- opad[i] = bkey[i] ^ 0x5C5C5C5C;\r
- }\r
- hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);\r
- return binl2rstr(binl(opad.concat(hash), 512 + 128));\r
- }\r
-\r
- /**\r
- * Calculate the MD5 of an array of little-endian words, and a bit length.\r
- */\r
- function binl(x, len) {\r
- var i, olda, oldb, oldc, oldd,\r
- a = 1732584193,\r
- b = -271733879,\r
- c = -1732584194,\r
- d = 271733878;\r
- \r
- /* append padding */\r
- x[len >> 5] |= 0x80 << ((len) % 32);\r
- x[(((len + 64) >>> 9) << 4) + 14] = len;\r
-\r
- for (i = 0; i < x.length; i += 16) {\r
- olda = a;\r
- oldb = b;\r
- oldc = c;\r
- oldd = d;\r
-\r
- a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);\r
- d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);\r
- c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);\r
- b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);\r
- a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);\r
- d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);\r
- c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);\r
- b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);\r
- a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);\r
- d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);\r
- c = md5_ff(c, d, a, b, x[i+10], 17, -42063);\r
- b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);\r
- a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);\r
- d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);\r
- c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);\r
- b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);\r
-\r
- a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);\r
- d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);\r
- c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);\r
- b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);\r
- a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);\r
- d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);\r
- c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);\r
- b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);\r
- a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);\r
- d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);\r
- c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);\r
- b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);\r
- a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);\r
- d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);\r
- c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);\r
- b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);\r
-\r
- a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);\r
- d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);\r
- c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);\r
- b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);\r
- a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);\r
- d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);\r
- c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);\r
- b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);\r
- a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);\r
- d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);\r
- c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);\r
- b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);\r
- a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);\r
- d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);\r
- c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);\r
- b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);\r
-\r
- a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);\r
- d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);\r
- c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);\r
- b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);\r
- a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);\r
- d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);\r
- c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);\r
- b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);\r
- a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);\r
- d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);\r
- c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);\r
- b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);\r
- a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);\r
- d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);\r
- c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);\r
- b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);\r
-\r
- a = safe_add(a, olda);\r
- b = safe_add(b, oldb);\r
- c = safe_add(c, oldc);\r
- d = safe_add(d, oldd);\r
- }\r
- return Array(a, b, c, d);\r
- }\r
-\r
- /**\r
- * These functions implement the four basic operations the algorithm uses.\r
- */\r
- function md5_cmn(q, a, b, x, s, t) {\r
- return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);\r
- }\r
- function md5_ff(a, b, c, d, x, s, t) {\r
- return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);\r
- }\r
- function md5_gg(a, b, c, d, x, s, t) {\r
- return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);\r
- }\r
- function md5_hh(a, b, c, d, x, s, t) {\r
- return md5_cmn(b ^ c ^ d, a, b, x, s, t);\r
- }\r
- function md5_ii(a, b, c, d, x, s, t) {\r
- return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);\r
- }\r
- },\r
- /**\r
- * @member Hashes\r
- * @class Hashes.SHA1\r
- * @param {Object} [config]\r
- * @constructor\r
- * \r
- * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1\r
- * Version 2.2 Copyright Paul Johnston 2000 - 2009.\r
- * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\r
- * See http://pajhome.org.uk/crypt/md5 for details.\r
- */\r
- SHA1 : function (options) {\r
- /**\r
- * Private config properties. You may need to tweak these to be compatible with\r
- * the server-side, but the defaults work in most cases.\r
- * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}\r
- */\r
- var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase\r
- b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance\r
- utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding\r
-\r
- // public methods\r
- this.hex = function (s) { \r
- return rstr2hex(rstr(s, utf8), hexcase); \r
- };\r
- this.b64 = function (s) { \r
- return rstr2b64(rstr(s, utf8), b64pad);\r
- };\r
- this.any = function (s, e) { \r
- return rstr2any(rstr(s, utf8), e);\r
- };\r
- this.hex_hmac = function (k, d) {\r
- return rstr2hex(rstr_hmac(k, d));\r
- };\r
- this.b64_hmac = function (k, d) { \r
- return rstr2b64(rstr_hmac(k, d), b64pad); \r
- };\r
- this.any_hmac = function (k, d, e) { \r
- return rstr2any(rstr_hmac(k, d), e);\r
- };\r
- /**\r
- * Perform a simple self-test to see if the VM is working\r
- * @return {String} Hexadecimal hash sample\r
- * @public\r
- */\r
- this.vm_test = function () {\r
- return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';\r
- };\r
- /** \r
- * @description Enable/disable uppercase hexadecimal returned string \r
- * @param {boolean} \r
- * @return {Object} this\r
- * @public\r
- */ \r
- this.setUpperCase = function (a) {\r
- if (typeof a === 'boolean') {\r
- hexcase = a;\r
- }\r
- return this;\r
- };\r
- /** \r
- * @description Defines a base64 pad string \r
- * @param {string} Pad\r
- * @return {Object} this\r
- * @public\r
- */ \r
- this.setPad = function (a) {\r
- b64pad = a || b64pad;\r
- return this;\r
- };\r
- /** \r
- * @description Defines a base64 pad string \r
- * @param {boolean} \r
- * @return {Object} this\r
- * @public\r
- */ \r
- this.setUTF8 = function (a) {\r
- if (typeof a === 'boolean') {\r
- utf8 = a;\r
- }\r
- return this;\r
- };\r
-\r
- // private methods\r
-\r
- /**\r
- * Calculate the SHA-512 of a raw string\r
- */\r
- function rstr(s) {\r
- s = (utf8) ? utf8Encode(s) : s;\r
- return binb2rstr(binb(rstr2binb(s), s.length * 8));\r
- }\r
-\r
- /**\r
- * Calculate the HMAC-SHA1 of a key and some data (raw strings)\r
- */\r
- function rstr_hmac(key, data) {\r
- var bkey, ipad, opad, i, hash;\r
- key = (utf8) ? utf8Encode(key) : key;\r
- data = (utf8) ? utf8Encode(data) : data;\r
- bkey = rstr2binb(key);\r
-\r
- if (bkey.length > 16) {\r
- bkey = binb(bkey, key.length * 8);\r
- }\r
- ipad = Array(16), opad = Array(16);\r
- for (i = 0; i < 16; i+=1) {\r
- ipad[i] = bkey[i] ^ 0x36363636;\r
- opad[i] = bkey[i] ^ 0x5C5C5C5C;\r
- }\r
- hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);\r
- return binb2rstr(binb(opad.concat(hash), 512 + 160));\r
- }\r
-\r
- /**\r
- * Calculate the SHA-1 of an array of big-endian words, and a bit length\r
- */\r
- function binb(x, len) {\r
- var i, j, t, olda, oldb, oldc, oldd, olde,\r
- w = Array(80),\r
- a = 1732584193,\r
- b = -271733879,\r
- c = -1732584194,\r
- d = 271733878,\r
- e = -1009589776;\r
-\r
- /* append padding */\r
- x[len >> 5] |= 0x80 << (24 - len % 32);\r
- x[((len + 64 >> 9) << 4) + 15] = len;\r
-\r
- for (i = 0; i < x.length; i += 16) {\r
- olda = a,\r
- oldb = b;\r
- oldc = c;\r
- oldd = d;\r
- olde = e;\r
- \r
- for (j = 0; j < 80; j+=1) {\r
- if (j < 16) { \r
- w[j] = x[i + j]; \r
- } else { \r
- w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); \r
- }\r
- t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),\r
- safe_add(safe_add(e, w[j]), sha1_kt(j)));\r
- e = d;\r
- d = c;\r
- c = bit_rol(b, 30);\r
- b = a;\r
- a = t;\r
- }\r
-\r
- a = safe_add(a, olda);\r
- b = safe_add(b, oldb);\r
- c = safe_add(c, oldc);\r
- d = safe_add(d, oldd);\r
- e = safe_add(e, olde);\r
- }\r
- return Array(a, b, c, d, e);\r
- }\r
-\r
- /**\r
- * Perform the appropriate triplet combination function for the current\r
- * iteration\r
- */\r
- function sha1_ft(t, b, c, d) {\r
- if (t < 20) { return (b & c) | ((~b) & d); }\r
- if (t < 40) { return b ^ c ^ d; }\r
- if (t < 60) { return (b & c) | (b & d) | (c & d); }\r
- return b ^ c ^ d;\r
- }\r
-\r
- /**\r
- * Determine the appropriate additive constant for the current iteration\r
- */\r
- function sha1_kt(t) {\r
- return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :\r
- (t < 60) ? -1894007588 : -899497514;\r
- }\r
- },\r
- /**\r
- * @class Hashes.SHA256\r
- * @param {config}\r
- * \r
- * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2\r
- * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.\r
- * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\r
- * See http://pajhome.org.uk/crypt/md5 for details.\r
- * Also http://anmar.eu.org/projects/jssha2/\r
- */\r
- SHA256 : function (options) {\r
- /**\r
- * Private properties configuration variables. You may need to tweak these to be compatible with\r
- * the server-side, but the defaults work in most cases.\r
- * @see this.setUpperCase() method\r
- * @see this.setPad() method\r
- */\r
- var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase */\r
- b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', /* base-64 pad character. Default '=' for strict RFC compliance */\r
- utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, /* enable/disable utf8 encoding */\r
- sha256_K;\r
-\r
- /* privileged (public) methods */\r
- this.hex = function (s) { \r
- return rstr2hex(rstr(s, utf8)); \r
- };\r
- this.b64 = function (s) { \r
- return rstr2b64(rstr(s, utf8), b64pad);\r
- };\r
- this.any = function (s, e) { \r
- return rstr2any(rstr(s, utf8), e); \r
- };\r
- this.hex_hmac = function (k, d) { \r
- return rstr2hex(rstr_hmac(k, d)); \r
- };\r
- this.b64_hmac = function (k, d) { \r
- return rstr2b64(rstr_hmac(k, d), b64pad);\r
- };\r
- this.any_hmac = function (k, d, e) { \r
- return rstr2any(rstr_hmac(k, d), e); \r
- };\r
- /**\r
- * Perform a simple self-test to see if the VM is working\r
- * @return {String} Hexadecimal hash sample\r
- * @public\r
- */\r
- this.vm_test = function () {\r
- return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';\r
- };\r
- /** \r
- * Enable/disable uppercase hexadecimal returned string \r
- * @param {boolean} \r
- * @return {Object} this\r
- * @public\r
- */ \r
- this.setUpperCase = function (a) {\r
- if (typeof a === 'boolean') { \r
- hexcase = a;\r
- }\r
- return this;\r
- };\r
- /** \r
- * @description Defines a base64 pad string \r
- * @param {string} Pad\r
- * @return {Object} this\r
- * @public\r
- */ \r
- this.setPad = function (a) {\r
- b64pad = a || b64pad;\r
- return this;\r
- };\r
- /** \r
- * Defines a base64 pad string \r
- * @param {boolean} \r
- * @return {Object} this\r
- * @public\r
- */ \r
- this.setUTF8 = function (a) {\r
- if (typeof a === 'boolean') {\r
- utf8 = a;\r
- }\r
- return this;\r
- };\r
- \r
- // private methods\r
-\r
- /**\r
- * Calculate the SHA-512 of a raw string\r
- */\r
- function rstr(s, utf8) {\r
- s = (utf8) ? utf8Encode(s) : s;\r
- return binb2rstr(binb(rstr2binb(s), s.length * 8));\r
- }\r
-\r
- /**\r
- * Calculate the HMAC-sha256 of a key and some data (raw strings)\r
- */\r
- function rstr_hmac(key, data) {\r
- key = (utf8) ? utf8Encode(key) : key;\r
- data = (utf8) ? utf8Encode(data) : data;\r
- var hash, i = 0,\r
- bkey = rstr2binb(key), \r
- ipad = Array(16), \r
- opad = Array(16);\r
-\r
- if (bkey.length > 16) { bkey = binb(bkey, key.length * 8); }\r
- \r
- for (; i < 16; i+=1) {\r
- ipad[i] = bkey[i] ^ 0x36363636;\r
- opad[i] = bkey[i] ^ 0x5C5C5C5C;\r
- }\r
- \r
- hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);\r
- return binb2rstr(binb(opad.concat(hash), 512 + 256));\r
- }\r
- \r
- /*\r
- * Main sha256 function, with its support functions\r
- */\r
- function sha256_S (X, n) {return ( X >>> n ) | (X << (32 - n));}\r
- function sha256_R (X, n) {return ( X >>> n );}\r
- function sha256_Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}\r
- function sha256_Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}\r
- function sha256_Sigma0256(x) {return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));}\r
- function sha256_Sigma1256(x) {return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));}\r
- function sha256_Gamma0256(x) {return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));}\r
- function sha256_Gamma1256(x) {return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));}\r
- function sha256_Sigma0512(x) {return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));}\r
- function sha256_Sigma1512(x) {return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));}\r
- function sha256_Gamma0512(x) {return (sha256_S(x, 1) ^ sha256_S(x, 8) ^ sha256_R(x, 7));}\r
- function sha256_Gamma1512(x) {return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));}\r
- \r
- sha256_K = [\r
- 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993,\r
- -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,\r
- 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,\r
- 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986,\r
- -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,\r
- 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,\r
- 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885,\r
- -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,\r
- 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,\r
- 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872,\r
- -1866530822, -1538233109, -1090935817, -965641998\r
- ];\r
- \r
- function binb(m, l) {\r
- var HASH = [1779033703, -1150833019, 1013904242, -1521486534,\r
- 1359893119, -1694144372, 528734635, 1541459225];\r
- var W = new Array(64);\r
- var a, b, c, d, e, f, g, h;\r
- var i, j, T1, T2;\r
- \r
- /* append padding */\r
- m[l >> 5] |= 0x80 << (24 - l % 32);\r
- m[((l + 64 >> 9) << 4) + 15] = l;\r
- \r
- for (i = 0; i < m.length; i += 16)\r
- {\r
- a = HASH[0];\r
- b = HASH[1];\r
- c = HASH[2];\r
- d = HASH[3];\r
- e = HASH[4];\r
- f = HASH[5];\r
- g = HASH[6];\r
- h = HASH[7];\r
- \r
- for (j = 0; j < 64; j+=1)\r
- {\r
- if (j < 16) { \r
- W[j] = m[j + i];\r
- } else { \r
- W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),\r
- sha256_Gamma0256(W[j - 15])), W[j - 16]);\r
- }\r
- \r
- T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),\r
- sha256_K[j]), W[j]);\r
- T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));\r
- h = g;\r
- g = f;\r
- f = e;\r
- e = safe_add(d, T1);\r
- d = c;\r
- c = b;\r
- b = a;\r
- a = safe_add(T1, T2);\r
- }\r
- \r
- HASH[0] = safe_add(a, HASH[0]);\r
- HASH[1] = safe_add(b, HASH[1]);\r
- HASH[2] = safe_add(c, HASH[2]);\r
- HASH[3] = safe_add(d, HASH[3]);\r
- HASH[4] = safe_add(e, HASH[4]);\r
- HASH[5] = safe_add(f, HASH[5]);\r
- HASH[6] = safe_add(g, HASH[6]);\r
- HASH[7] = safe_add(h, HASH[7]);\r
- }\r
- return HASH;\r
- }\r
-\r
- },\r
-\r
- /**\r
- * @class Hashes.SHA512\r
- * @param {config}\r
- * \r
- * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2\r
- * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.\r
- * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\r
- * See http://pajhome.org.uk/crypt/md5 for details. \r
- */\r
- SHA512 : function (options) {\r
- /**\r
- * Private properties configuration variables. You may need to tweak these to be compatible with\r
- * the server-side, but the defaults work in most cases.\r
- * @see this.setUpperCase() method\r
- * @see this.setPad() method\r
- */\r
- var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false , /* hexadecimal output case format. false - lowercase; true - uppercase */\r
- b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', /* base-64 pad character. Default '=' for strict RFC compliance */\r
- utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, /* enable/disable utf8 encoding */\r
- sha512_k;\r
-\r
- /* privileged (public) methods */\r
- this.hex = function (s) { \r
- return rstr2hex(rstr(s)); \r
- };\r
- this.b64 = function (s) { \r
- return rstr2b64(rstr(s), b64pad); \r
- };\r
- this.any = function (s, e) { \r
- return rstr2any(rstr(s), e);\r
- };\r
- this.hex_hmac = function (k, d) {\r
- return rstr2hex(rstr_hmac(k, d));\r
- };\r
- this.b64_hmac = function (k, d) { \r
- return rstr2b64(rstr_hmac(k, d), b64pad);\r
- };\r
- this.any_hmac = function (k, d, e) { \r
- return rstr2any(rstr_hmac(k, d), e);\r
- };\r
- /**\r
- * Perform a simple self-test to see if the VM is working\r
- * @return {String} Hexadecimal hash sample\r
- * @public\r
- */\r
- this.vm_test = function () {\r
- return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';\r
- };\r
- /** \r
- * @description Enable/disable uppercase hexadecimal returned string \r
- * @param {boolean} \r
- * @return {Object} this\r
- * @public\r
- */ \r
- this.setUpperCase = function (a) {\r
- if (typeof a === 'boolean') {\r
- hexcase = a;\r
- }\r
- return this;\r
- };\r
- /** \r
- * @description Defines a base64 pad string \r
- * @param {string} Pad\r
- * @return {Object} this\r
- * @public\r
- */ \r
- this.setPad = function (a) {\r
- b64pad = a || b64pad;\r
- return this;\r
- };\r
- /** \r
- * @description Defines a base64 pad string \r
- * @param {boolean} \r
- * @return {Object} this\r
- * @public\r
- */ \r
- this.setUTF8 = function (a) {\r
- if (typeof a === 'boolean') {\r
- utf8 = a;\r
- }\r
- return this;\r
- };\r
-\r
- /* private methods */\r
- \r
- /**\r
- * Calculate the SHA-512 of a raw string\r
- */\r
- function rstr(s) {\r
- s = (utf8) ? utf8Encode(s) : s;\r
- return binb2rstr(binb(rstr2binb(s), s.length * 8));\r
- }\r
- /*\r
- * Calculate the HMAC-SHA-512 of a key and some data (raw strings)\r
- */\r
- function rstr_hmac(key, data) {\r
- key = (utf8) ? utf8Encode(key) : key;\r
- data = (utf8) ? utf8Encode(data) : data;\r
- \r
- var hash, i = 0, \r
- bkey = rstr2binb(key),\r
- ipad = Array(32), opad = Array(32);\r
-\r
- if (bkey.length > 32) { bkey = binb(bkey, key.length * 8); }\r
- \r
- for (; i < 32; i+=1) {\r
- ipad[i] = bkey[i] ^ 0x36363636;\r
- opad[i] = bkey[i] ^ 0x5C5C5C5C;\r
- }\r
- \r
- hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);\r
- return binb2rstr(binb(opad.concat(hash), 1024 + 512));\r
- }\r
- \r
- /**\r
- * Calculate the SHA-512 of an array of big-endian dwords, and a bit length\r
- */\r
- function binb(x, len) {\r
- var j, i, l,\r
- W = new Array(80),\r
- hash = new Array(16),\r
- //Initial hash values\r
- H = [\r
- new int64(0x6a09e667, -205731576),\r
- new int64(-1150833019, -2067093701),\r
- new int64(0x3c6ef372, -23791573),\r
- new int64(-1521486534, 0x5f1d36f1),\r
- new int64(0x510e527f, -1377402159),\r
- new int64(-1694144372, 0x2b3e6c1f),\r
- new int64(0x1f83d9ab, -79577749),\r
- new int64(0x5be0cd19, 0x137e2179)\r
- ],\r
- T1 = new int64(0, 0),\r
- T2 = new int64(0, 0),\r
- a = new int64(0,0),\r
- b = new int64(0,0),\r
- c = new int64(0,0),\r
- d = new int64(0,0),\r
- e = new int64(0,0),\r
- f = new int64(0,0),\r
- g = new int64(0,0),\r
- h = new int64(0,0),\r
- //Temporary variables not specified by the document\r
- s0 = new int64(0, 0),\r
- s1 = new int64(0, 0),\r
- Ch = new int64(0, 0),\r
- Maj = new int64(0, 0),\r
- r1 = new int64(0, 0),\r
- r2 = new int64(0, 0),\r
- r3 = new int64(0, 0);\r
-\r
- if (sha512_k === undefined) {\r
- //SHA512 constants\r
- sha512_k = [\r
- new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd),\r
- new int64(-1245643825, -330482897), new int64(-373957723, -2121671748),\r
- new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031),\r
- new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736),\r
- new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe),\r
- new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302),\r
- new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1),\r
- new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428),\r
- new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3),\r
- new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65),\r
- new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),\r
- new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459),\r
- new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210),\r
- new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340),\r
- new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395),\r
- new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70),\r
- new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),\r
- new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473),\r
- new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8),\r
- new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b),\r
- new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023),\r
- new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30),\r
- new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910),\r
- new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),\r
- new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53),\r
- new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016),\r
- new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893),\r
- new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397),\r
- new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),\r
- new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec),\r
- new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047),\r
- new int64(-1090935817, -1295615723), new int64(-965641998, -479046869),\r
- new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207),\r
- new int64(-354779690, -840897762), new int64(-176337025, -294727304),\r
- new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026),\r
- new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b),\r
- new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),\r
- new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620),\r
- new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430),\r
- new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)\r
- ];\r
- }\r
- \r
- for (i=0; i<80; i+=1) {\r
- W[i] = new int64(0, 0);\r
- }\r
- \r
- // append padding to the source string. The format is described in the FIPS.\r
- x[len >> 5] |= 0x80 << (24 - (len & 0x1f));\r
- x[((len + 128 >> 10)<< 5) + 31] = len;\r
- l = x.length;\r
- for (i = 0; i<l; i+=32) { //32 dwords is the block size\r
- int64copy(a, H[0]);\r
- int64copy(b, H[1]);\r
- int64copy(c, H[2]);\r
- int64copy(d, H[3]);\r
- int64copy(e, H[4]);\r
- int64copy(f, H[5]);\r
- int64copy(g, H[6]);\r
- int64copy(h, H[7]);\r
- \r
- for (j=0; j<16; j+=1) {\r
- W[j].h = x[i + 2*j];\r
- W[j].l = x[i + 2*j + 1];\r
- }\r
- \r
- for (j=16; j<80; j+=1) {\r
- //sigma1\r
- int64rrot(r1, W[j-2], 19);\r
- int64revrrot(r2, W[j-2], 29);\r
- int64shr(r3, W[j-2], 6);\r
- s1.l = r1.l ^ r2.l ^ r3.l;\r
- s1.h = r1.h ^ r2.h ^ r3.h;\r
- //sigma0\r
- int64rrot(r1, W[j-15], 1);\r
- int64rrot(r2, W[j-15], 8);\r
- int64shr(r3, W[j-15], 7);\r
- s0.l = r1.l ^ r2.l ^ r3.l;\r
- s0.h = r1.h ^ r2.h ^ r3.h;\r
- \r
- int64add4(W[j], s1, W[j-7], s0, W[j-16]);\r
- }\r
- \r
- for (j = 0; j < 80; j+=1) {\r
- //Ch\r
- Ch.l = (e.l & f.l) ^ (~e.l & g.l);\r
- Ch.h = (e.h & f.h) ^ (~e.h & g.h);\r
- \r
- //Sigma1\r
- int64rrot(r1, e, 14);\r
- int64rrot(r2, e, 18);\r
- int64revrrot(r3, e, 9);\r
- s1.l = r1.l ^ r2.l ^ r3.l;\r
- s1.h = r1.h ^ r2.h ^ r3.h;\r
- \r
- //Sigma0\r
- int64rrot(r1, a, 28);\r
- int64revrrot(r2, a, 2);\r
- int64revrrot(r3, a, 7);\r
- s0.l = r1.l ^ r2.l ^ r3.l;\r
- s0.h = r1.h ^ r2.h ^ r3.h;\r
- \r
- //Maj\r
- Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);\r
- Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);\r
- \r
- int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);\r
- int64add(T2, s0, Maj);\r
- \r
- int64copy(h, g);\r
- int64copy(g, f);\r
- int64copy(f, e);\r
- int64add(e, d, T1);\r
- int64copy(d, c);\r
- int64copy(c, b);\r
- int64copy(b, a);\r
- int64add(a, T1, T2);\r
- }\r
- int64add(H[0], H[0], a);\r
- int64add(H[1], H[1], b);\r
- int64add(H[2], H[2], c);\r
- int64add(H[3], H[3], d);\r
- int64add(H[4], H[4], e);\r
- int64add(H[5], H[5], f);\r
- int64add(H[6], H[6], g);\r
- int64add(H[7], H[7], h);\r
- }\r
- \r
- //represent the hash as an array of 32-bit dwords\r
- for (i=0; i<8; i+=1) {\r
- hash[2*i] = H[i].h;\r
- hash[2*i + 1] = H[i].l;\r
- }\r
- return hash;\r
- }\r
- \r
- //A constructor for 64-bit numbers\r
- function int64(h, l) {\r
- this.h = h;\r
- this.l = l;\r
- //this.toString = int64toString;\r
- }\r
- \r
- //Copies src into dst, assuming both are 64-bit numbers\r
- function int64copy(dst, src) {\r
- dst.h = src.h;\r
- dst.l = src.l;\r
- }\r
- \r
- //Right-rotates a 64-bit number by shift\r
- //Won't handle cases of shift>=32\r
- //The function revrrot() is for that\r
- function int64rrot(dst, x, shift) {\r
- dst.l = (x.l >>> shift) | (x.h << (32-shift));\r
- dst.h = (x.h >>> shift) | (x.l << (32-shift));\r
- }\r
- \r
- //Reverses the dwords of the source and then rotates right by shift.\r
- //This is equivalent to rotation by 32+shift\r
- function int64revrrot(dst, x, shift) {\r
- dst.l = (x.h >>> shift) | (x.l << (32-shift));\r
- dst.h = (x.l >>> shift) | (x.h << (32-shift));\r
- }\r
- \r
- //Bitwise-shifts right a 64-bit number by shift\r
- //Won't handle shift>=32, but it's never needed in SHA512\r
- function int64shr(dst, x, shift) {\r
- dst.l = (x.l >>> shift) | (x.h << (32-shift));\r
- dst.h = (x.h >>> shift);\r
- }\r
- \r
- //Adds two 64-bit numbers\r
- //Like the original implementation, does not rely on 32-bit operations\r
- function int64add(dst, x, y) {\r
- var w0 = (x.l & 0xffff) + (y.l & 0xffff);\r
- var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);\r
- var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);\r
- var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);\r
- dst.l = (w0 & 0xffff) | (w1 << 16);\r
- dst.h = (w2 & 0xffff) | (w3 << 16);\r
- }\r
- \r
- //Same, except with 4 addends. Works faster than adding them one by one.\r
- function int64add4(dst, a, b, c, d) {\r
- var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);\r
- var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);\r
- var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);\r
- var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);\r
- dst.l = (w0 & 0xffff) | (w1 << 16);\r
- dst.h = (w2 & 0xffff) | (w3 << 16);\r
- }\r
- \r
- //Same, except with 5 addends\r
- function int64add5(dst, a, b, c, d, e) {\r
- var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),\r
- w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),\r
- w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),\r
- w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);\r
- dst.l = (w0 & 0xffff) | (w1 << 16);\r
- dst.h = (w2 & 0xffff) | (w3 << 16);\r
- }\r
- },\r
- /**\r
- * @class Hashes.RMD160\r
- * @constructor\r
- * @param {Object} [config]\r
- * \r
- * A JavaScript implementation of the RIPEMD-160 Algorithm\r
- * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.\r
- * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\r
- * See http://pajhome.org.uk/crypt/md5 for details.\r
- * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/\r
- */\r
- RMD160 : function (options) {\r
- /**\r
- * Private properties configuration variables. You may need to tweak these to be compatible with\r
- * the server-side, but the defaults work in most cases.\r
- * @see this.setUpperCase() method\r
- * @see this.setPad() method\r
- */\r
- var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, /* hexadecimal output case format. false - lowercase; true - uppercase */\r
- b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', /* base-64 pad character. Default '=' for strict RFC compliance */\r
- utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, /* enable/disable utf8 encoding */\r
- rmd160_r1 = [\r
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\r
- 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,\r
- 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,\r
- 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,\r
- 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13\r
- ],\r
- rmd160_r2 = [\r
- 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,\r
- 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,\r
- 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,\r
- 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,\r
- 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11\r
- ],\r
- rmd160_s1 = [\r
- 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,\r
- 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,\r
- 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,\r
- 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,\r
- 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6\r
- ],\r
- rmd160_s2 = [\r
- 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,\r
- 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,\r
- 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,\r
- 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,\r
- 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11\r
- ];\r
-\r
- /* privileged (public) methods */\r
- this.hex = function (s) {\r
- return rstr2hex(rstr(s, utf8)); \r
- };\r
- this.b64 = function (s) {\r
- return rstr2b64(rstr(s, utf8), b64pad);\r
- };\r
- this.any = function (s, e) { \r
- return rstr2any(rstr(s, utf8), e);\r
- };\r
- this.hex_hmac = function (k, d) { \r
- return rstr2hex(rstr_hmac(k, d));\r
- };\r
- this.b64_hmac = function (k, d) { \r
- return rstr2b64(rstr_hmac(k, d), b64pad);\r
- };\r
- this.any_hmac = function (k, d, e) { \r
- return rstr2any(rstr_hmac(k, d), e); \r
- };\r
- /**\r
- * Perform a simple self-test to see if the VM is working\r
- * @return {String} Hexadecimal hash sample\r
- * @public\r
- */\r
- this.vm_test = function () {\r
- return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';\r
- };\r
- /** \r
- * @description Enable/disable uppercase hexadecimal returned string \r
- * @param {boolean} \r
- * @return {Object} this\r
- * @public\r
- */ \r
- this.setUpperCase = function (a) {\r
- if (typeof a === 'boolean' ) { hexcase = a; }\r
- return this;\r
- };\r
- /** \r
- * @description Defines a base64 pad string \r
- * @param {string} Pad\r
- * @return {Object} this\r
- * @public\r
- */ \r
- this.setPad = function (a) {\r
- if (typeof a !== 'undefined' ) { b64pad = a; }\r
- return this;\r
- };\r
- /** \r
- * @description Defines a base64 pad string \r
- * @param {boolean} \r
- * @return {Object} this\r
- * @public\r
- */ \r
- this.setUTF8 = function (a) {\r
- if (typeof a === 'boolean') { utf8 = a; }\r
- return this;\r
- };\r
-\r
- /* private methods */\r
-\r
- /**\r
- * Calculate the rmd160 of a raw string\r
- */\r
- function rstr(s) {\r
- s = (utf8) ? utf8Encode(s) : s;\r
- return binl2rstr(binl(rstr2binl(s), s.length * 8));\r
- }\r
-\r
- /**\r
- * Calculate the HMAC-rmd160 of a key and some data (raw strings)\r
- */\r
- function rstr_hmac(key, data) {\r
- key = (utf8) ? utf8Encode(key) : key;\r
- data = (utf8) ? utf8Encode(data) : data;\r
- var i, hash,\r
- bkey = rstr2binl(key),\r
- ipad = Array(16), opad = Array(16);\r
-\r
- if (bkey.length > 16) { \r
- bkey = binl(bkey, key.length * 8); \r
- }\r
- \r
- for (i = 0; i < 16; i+=1) {\r
- ipad[i] = bkey[i] ^ 0x36363636;\r
- opad[i] = bkey[i] ^ 0x5C5C5C5C;\r
- }\r
- hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);\r
- return binl2rstr(binl(opad.concat(hash), 512 + 160));\r
- }\r
-\r
- /**\r
- * Convert an array of little-endian words to a string\r
- */\r
- function binl2rstr(input) {\r
- var i, output = '', l = input.length * 32;\r
- for (i = 0; i < l; i += 8) {\r
- output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);\r
- }\r
- return output;\r
- }\r
-\r
- /**\r
- * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.\r
- */\r
- function binl(x, len) {\r
- var T, j, i, l,\r
- h0 = 0x67452301,\r
- h1 = 0xefcdab89,\r
- h2 = 0x98badcfe,\r
- h3 = 0x10325476,\r
- h4 = 0xc3d2e1f0,\r
- A1, B1, C1, D1, E1,\r
- A2, B2, C2, D2, E2;\r
-\r
- /* append padding */\r
- x[len >> 5] |= 0x80 << (len % 32);\r
- x[(((len + 64) >>> 9) << 4) + 14] = len;\r
- l = x.length;\r
- \r
- for (i = 0; i < l; i+=16) {\r
- A1 = A2 = h0; B1 = B2 = h1; C1 = C2 = h2; D1 = D2 = h3; E1 = E2 = h4;\r
- for (j = 0; j <= 79; j+=1) {\r
- T = safe_add(A1, rmd160_f(j, B1, C1, D1));\r
- T = safe_add(T, x[i + rmd160_r1[j]]);\r
- T = safe_add(T, rmd160_K1(j));\r
- T = safe_add(bit_rol(T, rmd160_s1[j]), E1);\r
- A1 = E1; E1 = D1; D1 = bit_rol(C1, 10); C1 = B1; B1 = T;\r
- T = safe_add(A2, rmd160_f(79-j, B2, C2, D2));\r
- T = safe_add(T, x[i + rmd160_r2[j]]);\r
- T = safe_add(T, rmd160_K2(j));\r
- T = safe_add(bit_rol(T, rmd160_s2[j]), E2);\r
- A2 = E2; E2 = D2; D2 = bit_rol(C2, 10); C2 = B2; B2 = T;\r
- }\r
-\r
- T = safe_add(h1, safe_add(C1, D2));\r
- h1 = safe_add(h2, safe_add(D1, E2));\r
- h2 = safe_add(h3, safe_add(E1, A2));\r
- h3 = safe_add(h4, safe_add(A1, B2));\r
- h4 = safe_add(h0, safe_add(B1, C2));\r
- h0 = T;\r
- }\r
- return [h0, h1, h2, h3, h4];\r
- }\r
-\r
- // specific algorithm methods \r
- function rmd160_f(j, x, y, z) {\r
- return ( 0 <= j && j <= 15) ? (x ^ y ^ z) :\r
- (16 <= j && j <= 31) ? (x & y) | (~x & z) :\r
- (32 <= j && j <= 47) ? (x | ~y) ^ z :\r
- (48 <= j && j <= 63) ? (x & z) | (y & ~z) :\r
- (64 <= j && j <= 79) ? x ^ (y | ~z) :\r
- 'rmd160_f: j out of range';\r
- }\r
-\r
- function rmd160_K1(j) {\r
- return ( 0 <= j && j <= 15) ? 0x00000000 :\r
- (16 <= j && j <= 31) ? 0x5a827999 :\r
- (32 <= j && j <= 47) ? 0x6ed9eba1 :\r
- (48 <= j && j <= 63) ? 0x8f1bbcdc :\r
- (64 <= j && j <= 79) ? 0xa953fd4e :\r
- 'rmd160_K1: j out of range';\r
- }\r
-\r
- function rmd160_K2(j){\r
- return ( 0 <= j && j <= 15) ? 0x50a28be6 :\r
- (16 <= j && j <= 31) ? 0x5c4dd124 :\r
- (32 <= j && j <= 47) ? 0x6d703ef3 :\r
- (48 <= j && j <= 63) ? 0x7a6d76e9 :\r
- (64 <= j && j <= 79) ? 0x00000000 :\r
- 'rmd160_K2: j out of range';\r
- }\r
- }\r
-};\r
-\r
- // exposes Hashes\r
- (function( window, undefined ) {\r
- var freeExports = false;\r
- if (typeof exports === 'object' ) {\r
- freeExports = exports;\r
- if (exports && typeof global === 'object' && global && global === global.global ) { window = global; }\r
- }\r
-\r
- if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {\r
- // define as an anonymous module, so, through path mapping, it can be aliased\r
- define(function () { return Hashes; });\r
- }\r
- else if ( freeExports ) {\r
- // in Node.js or RingoJS v0.8.0+\r
- if ( typeof module === 'object' && module && module.exports === freeExports ) {\r
- module.exports = Hashes;\r
- }\r
- // in Narwhal or RingoJS v0.7.0-\r
- else {\r
- freeExports.Hashes = Hashes;\r
- }\r
- }\r
- else {\r
- // in a browser or Rhino\r
- window.Hashes = Hashes;\r
- }\r
- }( this ));\r
-}()); // IIFE
-})(window)
-},{}],5:[function(require,module,exports){
-var Keys = Object.keys || objectKeys
+},{"jshashes":7,"xtend":4}],6:[function(require,module,exports){
+module.exports = Object.keys || require('./shim');
-module.exports = extend
-function extend() {
- var target = {}
+},{"./shim":8}],8:[function(require,module,exports){
+(function () {
+ "use strict";
+
+ // modified from https://github.com/kriskowal/es5-shim
+ var has = Object.prototype.hasOwnProperty,
+ is = require('is'),
+ forEach = require('foreach'),
+ hasDontEnumBug = !({'toString': null}).propertyIsEnumerable('toString'),
+ dontEnums = [
+ "toString",
+ "toLocaleString",
+ "valueOf",
+ "hasOwnProperty",
+ "isPrototypeOf",
+ "propertyIsEnumerable",
+ "constructor"
+ ],
+ keysShim;
+
+ keysShim = function keys(object) {
+ if (!is.object(object) && !is.array(object)) {
+ throw new TypeError("Object.keys called on a non-object");
+ }
- for (var i = 0; i < arguments.length; i++) {
- var source = arguments[i]
+ var name, theKeys = [];
+ for (name in object) {
+ if (has.call(object, name)) {
+ theKeys.push(name);
+ }
+ }
- if (!isObject(source)) {
- continue
- }
+ if (hasDontEnumBug) {
+ forEach(dontEnums, function (dontEnum) {
+ if (has.call(object, dontEnum)) {
+ theKeys.push(dontEnum);
+ }
+ });
+ }
+ return theKeys;
+ };
- var keys = Keys(source)
+ module.exports = keysShim;
+}());
- for (var j = 0; j < keys.length; j++) {
- var name = keys[j]
- target[name] = source[name]
- }
+
+},{"is":9,"foreach":10}],9:[function(require,module,exports){
+
+/**!
+ * is
+ * the definitive JavaScript type testing library
+ *
+ * @copyright 2013 Enrico Marino
+ * @license MIT
+ */
+
+var objProto = Object.prototype;
+var owns = objProto.hasOwnProperty;
+var toString = objProto.toString;
+var isActualNaN = function (value) {
+ return value !== value;
+};
+var NON_HOST_TYPES = {
+ "boolean": 1,
+ "number": 1,
+ "string": 1,
+ "undefined": 1
+};
+
+/**
+ * Expose `is`
+ */
+
+var is = module.exports = {};
+
+/**
+ * Test general.
+ */
+
+/**
+ * is.type
+ * Test if `value` is a type of `type`.
+ *
+ * @param {Mixed} value value to test
+ * @param {String} type type
+ * @return {Boolean} true if `value` is a type of `type`, false otherwise
+ * @api public
+ */
+
+is.a =
+is.type = function (value, type) {
+ return typeof value === type;
+};
+
+/**
+ * is.defined
+ * Test if `value` is defined.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if 'value' is defined, false otherwise
+ * @api public
+ */
+
+is.defined = function (value) {
+ return value !== undefined;
+};
+
+/**
+ * is.empty
+ * Test if `value` is empty.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is empty, false otherwise
+ * @api public
+ */
+
+is.empty = function (value) {
+ var type = toString.call(value);
+ var key;
+
+ if ('[object Array]' === type || '[object Arguments]' === type) {
+ return value.length === 0;
+ }
+
+ if ('[object Object]' === type) {
+ for (key in value) if (owns.call(value, key)) return false;
+ return true;
+ }
+
+ if ('[object String]' === type) {
+ return '' === value;
+ }
+
+ return false;
+};
+
+/**
+ * is.equal
+ * Test if `value` is equal to `other`.
+ *
+ * @param {Mixed} value value to test
+ * @param {Mixed} other value to compare with
+ * @return {Boolean} true if `value` is equal to `other`, false otherwise
+ */
+
+is.equal = function (value, other) {
+ var type = toString.call(value)
+ var key;
+
+ if (type !== toString.call(other)) {
+ return false;
+ }
+
+ if ('[object Object]' === type) {
+ for (key in value) {
+ if (!is.equal(value[key], other[key])) {
+ return false;
+ }
}
+ return true;
+ }
- return target
-}
+ if ('[object Array]' === type) {
+ key = value.length;
+ if (key !== other.length) {
+ return false;
+ }
+ while (--key) {
+ if (!is.equal(value[key], other[key])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ if ('[object Function]' === type) {
+ return value.prototype === other.prototype;
+ }
+
+ if ('[object Date]' === type) {
+ return value.getTime() === other.getTime();
+ }
+
+ return value === other;
+};
+
+/**
+ * is.hosted
+ * Test if `value` is hosted by `host`.
+ *
+ * @param {Mixed} value to test
+ * @param {Mixed} host host to test with
+ * @return {Boolean} true if `value` is hosted by `host`, false otherwise
+ * @api public
+ */
+
+is.hosted = function (value, host) {
+ var type = typeof host[value];
+ return type === 'object' ? !!host[value] : !NON_HOST_TYPES[type];
+};
+
+/**
+ * is.instance
+ * Test if `value` is an instance of `constructor`.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an instance of `constructor`
+ * @api public
+ */
+
+is.instance = is['instanceof'] = function (value, constructor) {
+ return value instanceof constructor;
+};
+
+/**
+ * is.null
+ * Test if `value` is null.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is null, false otherwise
+ * @api public
+ */
+
+is['null'] = function (value) {
+ return value === null;
+};
+
+/**
+ * is.undefined
+ * Test if `value` is undefined.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is undefined, false otherwise
+ * @api public
+ */
+
+is.undefined = function (value) {
+ return value === undefined;
+};
+
+/**
+ * Test arguments.
+ */
+
+/**
+ * is.arguments
+ * Test if `value` is an arguments object.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an arguments object, false otherwise
+ * @api public
+ */
+
+is.arguments = function (value) {
+ var isStandardArguments = '[object Arguments]' === toString.call(value);
+ var isOldArguments = !is.array(value) && is.arraylike(value) && is.object(value) && is.fn(value.callee);
+ return isStandardArguments || isOldArguments;
+};
+
+/**
+ * Test array.
+ */
+
+/**
+ * is.array
+ * Test if 'value' is an array.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an array, false otherwise
+ * @api public
+ */
+
+is.array = function (value) {
+ return '[object Array]' === toString.call(value);
+};
+
+/**
+ * is.arguments.empty
+ * Test if `value` is an empty arguments object.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an empty arguments object, false otherwise
+ * @api public
+ */
+is.arguments.empty = function (value) {
+ return is.arguments(value) && value.length === 0;
+};
+
+/**
+ * is.array.empty
+ * Test if `value` is an empty array.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an empty array, false otherwise
+ * @api public
+ */
+is.array.empty = function (value) {
+ return is.array(value) && value.length === 0;
+};
+
+/**
+ * is.arraylike
+ * Test if `value` is an arraylike object.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an arguments object, false otherwise
+ * @api public
+ */
+
+is.arraylike = function (value) {
+ return !!value && !is.boolean(value)
+ && owns.call(value, 'length')
+ && isFinite(value.length)
+ && is.number(value.length)
+ && value.length >= 0;
+};
+
+/**
+ * Test boolean.
+ */
+
+/**
+ * is.boolean
+ * Test if `value` is a boolean.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is a boolean, false otherwise
+ * @api public
+ */
+
+is.boolean = function (value) {
+ return '[object Boolean]' === toString.call(value);
+};
+
+/**
+ * is.false
+ * Test if `value` is false.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is false, false otherwise
+ * @api public
+ */
+
+is['false'] = function (value) {
+ return is.boolean(value) && (value === false || value.valueOf() === false);
+};
+
+/**
+ * is.true
+ * Test if `value` is true.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is true, false otherwise
+ * @api public
+ */
+
+is['true'] = function (value) {
+ return is.boolean(value) && (value === true || value.valueOf() === true);
+};
+
+/**
+ * Test date.
+ */
+
+/**
+ * is.date
+ * Test if `value` is a date.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is a date, false otherwise
+ * @api public
+ */
+
+is.date = function (value) {
+ return '[object Date]' === toString.call(value);
+};
+
+/**
+ * Test element.
+ */
+
+/**
+ * is.element
+ * Test if `value` is an html element.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an HTML Element, false otherwise
+ * @api public
+ */
+
+is.element = function (value) {
+ return value !== undefined
+ && typeof HTMLElement !== 'undefined'
+ && value instanceof HTMLElement
+ && value.nodeType === 1;
+};
+
+/**
+ * Test error.
+ */
+
+/**
+ * is.error
+ * Test if `value` is an error object.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an error object, false otherwise
+ * @api public
+ */
+
+is.error = function (value) {
+ return '[object Error]' === toString.call(value);
+};
+
+/**
+ * Test function.
+ */
+
+/**
+ * is.fn / is.function (deprecated)
+ * Test if `value` is a function.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is a function, false otherwise
+ * @api public
+ */
+
+is.fn = is['function'] = function (value) {
+ var isAlert = typeof window !== 'undefined' && value === window.alert;
+ return isAlert || '[object Function]' === toString.call(value);
+};
+
+/**
+ * Test number.
+ */
+
+/**
+ * is.number
+ * Test if `value` is a number.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is a number, false otherwise
+ * @api public
+ */
+
+is.number = function (value) {
+ return '[object Number]' === toString.call(value);
+};
+
+/**
+ * is.infinite
+ * Test if `value` is positive or negative infinity.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is positive or negative Infinity, false otherwise
+ * @api public
+ */
+is.infinite = function (value) {
+ return value === Infinity || value === -Infinity;
+};
+
+/**
+ * is.decimal
+ * Test if `value` is a decimal number.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is a decimal number, false otherwise
+ * @api public
+ */
+
+is.decimal = function (value) {
+ return is.number(value) && !isActualNaN(value) && value % 1 !== 0;
+};
+
+/**
+ * is.divisibleBy
+ * Test if `value` is divisible by `n`.
+ *
+ * @param {Number} value value to test
+ * @param {Number} n dividend
+ * @return {Boolean} true if `value` is divisible by `n`, false otherwise
+ * @api public
+ */
+
+is.divisibleBy = function (value, n) {
+ var isDividendInfinite = is.infinite(value);
+ var isDivisorInfinite = is.infinite(n);
+ var isNonZeroNumber = is.number(value) && !isActualNaN(value) && is.number(n) && !isActualNaN(n) && n !== 0;
+ return isDividendInfinite || isDivisorInfinite || (isNonZeroNumber && value % n === 0);
+};
+
+/**
+ * is.int
+ * Test if `value` is an integer.
+ *
+ * @param value to test
+ * @return {Boolean} true if `value` is an integer, false otherwise
+ * @api public
+ */
+
+is.int = function (value) {
+ return is.number(value) && !isActualNaN(value) && value % 1 === 0;
+};
-function objectKeys(obj) {
- var keys = []
- for (var k in obj) {
- keys.push(k)
+/**
+ * is.maximum
+ * Test if `value` is greater than 'others' values.
+ *
+ * @param {Number} value value to test
+ * @param {Array} others values to compare with
+ * @return {Boolean} true if `value` is greater than `others` values
+ * @api public
+ */
+
+is.maximum = function (value, others) {
+ if (isActualNaN(value)) {
+ throw new TypeError('NaN is not a valid value');
+ } else if (!is.arraylike(others)) {
+ throw new TypeError('second argument must be array-like');
+ }
+ var len = others.length;
+
+ while (--len >= 0) {
+ if (value < others[len]) {
+ return false;
}
- return keys
-}
+ }
+
+ return true;
+};
+
+/**
+ * is.minimum
+ * Test if `value` is less than `others` values.
+ *
+ * @param {Number} value value to test
+ * @param {Array} others values to compare with
+ * @return {Boolean} true if `value` is less than `others` values
+ * @api public
+ */
+
+is.minimum = function (value, others) {
+ if (isActualNaN(value)) {
+ throw new TypeError('NaN is not a valid value');
+ } else if (!is.arraylike(others)) {
+ throw new TypeError('second argument must be array-like');
+ }
+ var len = others.length;
+
+ while (--len >= 0) {
+ if (value > others[len]) {
+ return false;
+ }
+ }
+
+ return true;
+};
+
+/**
+ * is.nan
+ * Test if `value` is not a number.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is not a number, false otherwise
+ * @api public
+ */
+
+is.nan = function (value) {
+ return !is.number(value) || value !== value;
+};
+
+/**
+ * is.even
+ * Test if `value` is an even number.
+ *
+ * @param {Number} value value to test
+ * @return {Boolean} true if `value` is an even number, false otherwise
+ * @api public
+ */
+
+is.even = function (value) {
+ return is.infinite(value) || (is.number(value) && value === value && value % 2 === 0);
+};
+
+/**
+ * is.odd
+ * Test if `value` is an odd number.
+ *
+ * @param {Number} value value to test
+ * @return {Boolean} true if `value` is an odd number, false otherwise
+ * @api public
+ */
+
+is.odd = function (value) {
+ return is.infinite(value) || (is.number(value) && value === value && value % 2 !== 0);
+};
+
+/**
+ * is.ge
+ * Test if `value` is greater than or equal to `other`.
+ *
+ * @param {Number} value value to test
+ * @param {Number} other value to compare with
+ * @return {Boolean}
+ * @api public
+ */
+
+is.ge = function (value, other) {
+ if (isActualNaN(value) || isActualNaN(other)) {
+ throw new TypeError('NaN is not a valid value');
+ }
+ return !is.infinite(value) && !is.infinite(other) && value >= other;
+};
+
+/**
+ * is.gt
+ * Test if `value` is greater than `other`.
+ *
+ * @param {Number} value value to test
+ * @param {Number} other value to compare with
+ * @return {Boolean}
+ * @api public
+ */
+
+is.gt = function (value, other) {
+ if (isActualNaN(value) || isActualNaN(other)) {
+ throw new TypeError('NaN is not a valid value');
+ }
+ return !is.infinite(value) && !is.infinite(other) && value > other;
+};
+
+/**
+ * is.le
+ * Test if `value` is less than or equal to `other`.
+ *
+ * @param {Number} value value to test
+ * @param {Number} other value to compare with
+ * @return {Boolean} if 'value' is less than or equal to 'other'
+ * @api public
+ */
+
+is.le = function (value, other) {
+ if (isActualNaN(value) || isActualNaN(other)) {
+ throw new TypeError('NaN is not a valid value');
+ }
+ return !is.infinite(value) && !is.infinite(other) && value <= other;
+};
+
+/**
+ * is.lt
+ * Test if `value` is less than `other`.
+ *
+ * @param {Number} value value to test
+ * @param {Number} other value to compare with
+ * @return {Boolean} if `value` is less than `other`
+ * @api public
+ */
+
+is.lt = function (value, other) {
+ if (isActualNaN(value) || isActualNaN(other)) {
+ throw new TypeError('NaN is not a valid value');
+ }
+ return !is.infinite(value) && !is.infinite(other) && value < other;
+};
+
+/**
+ * is.within
+ * Test if `value` is within `start` and `finish`.
+ *
+ * @param {Number} value value to test
+ * @param {Number} start lower bound
+ * @param {Number} finish upper bound
+ * @return {Boolean} true if 'value' is is within 'start' and 'finish'
+ * @api public
+ */
+is.within = function (value, start, finish) {
+ if (isActualNaN(value) || isActualNaN(start) || isActualNaN(finish)) {
+ throw new TypeError('NaN is not a valid value');
+ } else if (!is.number(value) || !is.number(start) || !is.number(finish)) {
+ throw new TypeError('all arguments must be numbers');
+ }
+ var isAnyInfinite = is.infinite(value) || is.infinite(start) || is.infinite(finish);
+ return isAnyInfinite || (value >= start && value <= finish);
+};
+
+/**
+ * Test object.
+ */
+
+/**
+ * is.object
+ * Test if `value` is an object.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is an object, false otherwise
+ * @api public
+ */
+
+is.object = function (value) {
+ return value && '[object Object]' === toString.call(value);
+};
+
+/**
+ * is.hash
+ * Test if `value` is a hash - a plain object literal.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is a hash, false otherwise
+ * @api public
+ */
+
+is.hash = function (value) {
+ return is.object(value) && value.constructor === Object && !value.nodeType && !value.setInterval;
+};
+
+/**
+ * Test regexp.
+ */
+
+/**
+ * is.regexp
+ * Test if `value` is a regular expression.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if `value` is a regexp, false otherwise
+ * @api public
+ */
+
+is.regexp = function (value) {
+ return '[object RegExp]' === toString.call(value);
+};
+
+/**
+ * Test string.
+ */
+
+/**
+ * is.string
+ * Test if `value` is a string.
+ *
+ * @param {Mixed} value value to test
+ * @return {Boolean} true if 'value' is a string, false otherwise
+ * @api public
+ */
+
+is.string = function (value) {
+ return '[object String]' === toString.call(value);
+};
+
+
+},{}],10:[function(require,module,exports){
+
+var hasOwn = Object.prototype.hasOwnProperty;
+var toString = Object.prototype.toString;
+
+module.exports = function forEach (obj, fn, ctx) {
+ if (toString.call(fn) !== '[object Function]') {
+ throw new TypeError('iterator must be a function');
+ }
+ var l = obj.length;
+ if (l === +l) {
+ for (var i = 0; i < l; i++) {
+ fn.call(ctx, obj[i], i, obj);
+ }
+ } else {
+ for (var k in obj) {
+ if (hasOwn.call(obj, k)) {
+ fn.call(ctx, obj[k], k, obj);
+ }
+ }
+ }
+};
-function isObject(obj) {
- return obj !== null && typeof obj === "object"
-}
},{}]},{},[1])(1)
});
-;
-
-/*
+;/*
(c) 2013, Vladimir Agafonkin
RBush, a JavaScript library for high-performance 2D spatial indexing of points and rectangles.
https://github.com/mourner/rbush
// jshint newcap: false, validthis: true
if (!(this instanceof rbush)) { return new rbush(maxEntries, format); }
+ // max entries in a node is 9 by default; min node fill is 40% for best performance
this._maxEntries = Math.max(4, maxEntries || 9);
this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
- this._initFormat(format);
+ if (format) {
+ this._initFormat(format);
+ }
this.clear();
}
rbush.prototype = {
+ all: function () {
+ return this._all(this.data, []);
+ },
+
search: function (bbox) {
var node = this.data,
while (node) {
for (i = 0, len = node.children.length; i < len; i++) {
child = node.children[i];
- childBBox = node.leaf ? this._toBBox(child) : child.bbox;
+ childBBox = node.leaf ? this.toBBox(child) : child.bbox;
if (this._intersects(bbox, childBBox)) {
- (node.leaf ? result : nodesToSearch).push(child);
+
+ if (node.leaf) {
+ result.push(child);
+
+ } else if (this._contains(bbox, childBBox)) {
+ this._all(child, result);
+
+ } else {
+ nodesToSearch.push(child);
+ }
}
}
// recursively build the tree with the given data from stratch using OMT algorithm
var node = this._build(data.slice(), 0);
- this._calcBBoxes(node, true);
if (!this.data.children.length) {
// save as is if tree is empty
this.data = {
children: [],
leaf: true,
- bbox: this._infinite(),
+ bbox: this._empty(),
height: 1
};
return this;
if (!item) { return this; }
var node = this.data,
- bbox = this._toBBox(item),
+ bbox = this.toBBox(item),
path = [],
indexes = [],
i, parent, index, goingUp;
return this;
},
+ toBBox: function (item) { return item; },
+
+ compareMinX: function (a, b) { return a[0] - b[0]; },
+ compareMinY: function (a, b) { return a[1] - b[1]; },
+
toJSON: function () { return this.data; },
fromJSON: function (data) {
return this;
},
+ _all: function (node, result) {
+ var nodesToSearch = [];
+ while (node) {
+ if (node.leaf) {
+ result.push.apply(result, node.children);
+ } else {
+ nodesToSearch.push.apply(nodesToSearch, node.children);
+ }
+ node = nodesToSearch.pop();
+ }
+ return result;
+ },
+
_build: function (items, level, height) {
var N = items.length,
- M = this._maxEntries;
+ M = this._maxEntries,
+ node;
if (N <= M) {
- return {
+ node = {
children: items,
leaf: true,
height: 1
};
+ this._calcBBox(node);
+ return node;
}
if (!level) {
// target number of root entries to maximize storage utilization
M = Math.ceil(N / Math.pow(M, height - 1));
- items.sort(this._compareMinX);
+ items.sort(this.compareMinX);
}
// TODO eliminate recursion?
- var node = {
+ node = {
children: [],
height: height
};
var N1 = Math.ceil(N / M) * Math.ceil(Math.sqrt(M)),
N2 = Math.ceil(N / M),
- compare = level % 2 === 1 ? this._compareMinX : this._compareMinY,
+ compare = level % 2 === 1 ? this.compareMinX : this.compareMinY,
i, j, slice, sliceLen, childNode;
// split the items into M mostly square tiles
}
}
+ this._calcBBox(node);
+
return node;
},
_insert: function (item, level, isNode, root) {
- var bbox = isNode ? item.bbox : this._toBBox(item),
+ var bbox = isNode ? item.bbox : this.toBBox(item),
insertPath = [];
// find the best node for accommodating the item, saving all nodes along the path too
newNode.leaf = true;
}
- this._calcBBoxes(node);
- this._calcBBoxes(newNode);
+ this._calcBBox(node);
+ this._calcBBox(newNode);
if (level) {
insertPath[level - 1].children.push(newNode);
this.data = {};
this.data.children = [node, newNode];
this.data.height = node.height + 1;
- this._calcBBoxes(this.data);
+ this._calcBBox(this.data);
},
_chooseSplitIndex: function (node, m, M) {
// sorts node children by the best axis for split
_chooseSplitAxis: function (node, m, M) {
- var compareMinX = node.leaf ? this._compareMinX : this._compareNodeMinX,
- compareMinY = node.leaf ? this._compareMinY : this._compareNodeMinY,
+ var compareMinX = node.leaf ? this.compareMinX : this._compareNodeMinX,
+ compareMinY = node.leaf ? this.compareMinY : this._compareNodeMinY,
xMargin = this._allDistMargin(node, m, M, compareMinX),
yMargin = this._allDistMargin(node, m, M, compareMinY);
for (i = m; i < M - m; i++) {
child = node.children[i];
- this._extend(leftBBox, node.leaf ? this._toBBox(child) : child.bbox);
+ this._extend(leftBBox, node.leaf ? this.toBBox(child) : child.bbox);
margin += this._margin(leftBBox);
}
for (i = M - m - 1; i >= 0; i--) {
child = node.children[i];
- this._extend(rightBBox, node.leaf ? this._toBBox(child) : child.bbox);
+ this._extend(rightBBox, node.leaf ? this.toBBox(child) : child.bbox);
margin += this._margin(rightBBox);
}
// min bounding rectangle of node children from k to p-1
_distBBox: function (node, k, p) {
- var bbox = this._infinite();
+ var bbox = this._empty();
for (var i = k, child; i < p; i++) {
child = node.children[i];
- this._extend(bbox, node.leaf ? this._toBBox(child) : child.bbox);
+ this._extend(bbox, node.leaf ? this.toBBox(child) : child.bbox);
}
return bbox;
},
- _calcBBoxes: function (node, recursive) {
- // TODO eliminate recursion
- node.bbox = this._infinite();
+ // calculate node's bbox from bboxes of its children
+ _calcBBox: function (node) {
+ node.bbox = this._empty();
for (var i = 0, len = node.children.length, child; i < len; i++) {
child = node.children[i];
-
- if (node.leaf) {
- this._extend(node.bbox, this._toBBox(child));
- } else {
- if (recursive) {
- this._calcBBoxes(child, recursive);
- }
- this._extend(node.bbox, child.bbox);
- }
+ this._extend(node.bbox, node.leaf ? this.toBBox(child) : child.bbox);
}
},
_condense: function (path) {
// go through the path, removing empty nodes and updating bboxes
for (var i = path.length - 1, parent; i >= 0; i--) {
- if (i > 0 && path[i].children.length === 0) {
- parent = path[i - 1].children;
- parent.splice(parent.indexOf(path[i]), 1);
+ if (path[i].children.length === 0) {
+ if (i > 0) {
+ parent = path[i - 1].children;
+ parent.splice(parent.indexOf(path[i]), 1);
+ } else {
+ this.clear();
+ }
} else {
- this._calcBBoxes(path[i]);
+ this._calcBBox(path[i]);
}
}
},
+ _contains: function(a, b) {
+ return a[0] <= b[0] &&
+ a[1] <= b[1] &&
+ b[2] <= a[2] &&
+ b[3] <= a[3];
+ },
+
_intersects: function (a, b) {
return b[0] <= a[2] &&
b[1] <= a[3] &&
Math.max(0, maxY - minY);
},
- _infinite: function () { return [Infinity, Infinity, -Infinity, -Infinity]; },
+ _empty: function () { return [Infinity, Infinity, -Infinity, -Infinity]; },
_compareNodeMinX: function (a, b) { return a.bbox[0] - b.bbox[0]; },
_compareNodeMinY: function (a, b) { return a.bbox[1] - b.bbox[1]; },
_initFormat: function (format) {
// data format (minX, minY, maxX, maxY accessors)
- format = format || ['[0]', '[1]', '[2]', '[3]'];
// uses eval-type function compilation instead of just accepting a toBBox function
// because the algorithms are very sensitive to sorting functions performance,
var compareArr = ['return a', ' - b', ';'];
- this._compareMinX = new Function('a', 'b', compareArr.join(format[0]));
- this._compareMinY = new Function('a', 'b', compareArr.join(format[1]));
+ this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
+ this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
- this._toBBox = new Function('a', 'return [a' + format.join(', a') + '];');
+ this.toBBox = new Function('a', 'return [a' + format.join(', a') + '];');
}
};
-if (typeof module !== 'undefined') {
+if (typeof define === 'function' && define.amd) {
+ define(function() {
+ return rbush;
+ });
+} else if (typeof module !== 'undefined') {
module.exports = rbush;
+} else if (typeof self !== 'undefined') {
+ self.rbush = rbush;
} else {
window.rbush = rbush;
}
return d3.rebind(context, dispatch, 'on');
};
-iD.version = '1.3.2';
+iD.version = '1.3.3';
(function() {
var detected = {};
parameters = clean(shorten(setSort(setFilter(parameters))));
request(endpoint + 'key/values?' +
iD.util.qsString(_.extend({
- rp: 20,
+ rp: 25,
sortname: 'count_all',
sortorder: 'desc',
page: 1
Relation members:
role=forward ⟺ role=backward
+ role=north ⟺ role=south
+ role=east ⟺ role=west
In addition, numeric-valued `incline` tags are negated.
*/
iD.actions.Reverse = function(wayId) {
var replacements = [
- [/:right$/, ':left'], [/:left$/, ':right'],
- [/:forward$/, ':backward'], [/:backward$/, ':forward']
- ], numeric = /^([+\-]?)(?=[\d.])/;
+ [/:right$/, ':left'], [/:left$/, ':right'],
+ [/:forward$/, ':backward'], [/:backward$/, ':forward']
+ ],
+ numeric = /^([+\-]?)(?=[\d.])/,
+ roleReversals = {
+ forward: 'backward',
+ backward: 'forward',
+ north: 'south',
+ south: 'north',
+ east: 'west',
+ west: 'east'
+ };
function reverseKey(key) {
for (var i = 0; i < replacements.length; ++i) {
graph.parentRelations(way).forEach(function(relation) {
relation.members.forEach(function(member, index) {
- if (member.id === way.id && (role = {forward: 'backward', backward: 'forward'}[member.role])) {
+ if (member.id === way.id && (role = roleReversals[member.role])) {
relation = relation.updateMember({role: role}, index);
graph = graph.replace(relation);
}
var move = _.throttle(function() {
var s1 = formatter(context.map());
if (s0 !== s1) location.replace(s0 = s1); // don't recenter the map!
- }, 500);
+ }, 500, {leading: false});
function hashchange() {
if (location.hash === s0) return; // ignore spurious hashchange events
return operation;
};
-iD.Connection = function() {
+/* jshint -W109 */
+iD.areaKeys = {
+ "aeroway": {
+ "gate": true,
+ "taxiway": true
+ },
+ "amenity": {
+ "atm": true,
+ "bench": true,
+ "drinking_water": true,
+ "post_box": true,
+ "telephone": true,
+ "vending_machine": true,
+ "waste_basket": true
+ },
+ "area": {},
+ "barrier": {
+ "block": true,
+ "bollard": true,
+ "cattle_grid": true,
+ "cycle_barrier": true,
+ "entrance": true,
+ "gate": true,
+ "kissing_gate": true,
+ "lift_gate": true,
+ "stile": true,
+ "toll_booth": true
+ },
+ "building": {
+ "entrance": true
+ },
+ "emergency": {
+ "fire_hydrant": true,
+ "phone": true
+ },
+ "historic": {
+ "boundary_stone": true
+ },
+ "landuse": {},
+ "leisure": {
+ "slipway": true
+ },
+ "man_made": {
+ "cutline": true,
+ "embankment": true,
+ "flagpole": true,
+ "pipeline": true,
+ "survey_point": true
+ },
+ "military": {},
+ "natural": {
+ "coastline": true,
+ "peak": true,
+ "spring": true,
+ "tree": true
+ },
+ "office": {},
+ "place": {},
+ "power": {
+ "line": true,
+ "minor_line": true,
+ "pole": true,
+ "tower": true
+ },
+ "public_transport": {
+ "stop_position": true
+ },
+ "shop": {},
+ "tourism": {
+ "viewpoint": true
+ },
+ "waterway": {
+ "canal": true,
+ "ditch": true,
+ "drain": true,
+ "river": true,
+ "stream": true,
+ "weir": true
+ }
+};iD.Connection = function() {
var event = d3.dispatch('authenticating', 'authenticated', 'auth', 'loading', 'load', 'loaded'),
url = 'http://www.openstreetmap.org',
head.parentWays(entity).forEach(function(parent) {
if (rectangles[parent.id]) {
rtree.remove(rectangles[parent.id]);
- insertions.push(entityRectangle(parent));
+ insertions.push(parent);
}
});
head.parentRelations(entity).forEach(function(parent) {
if (rectangles[parent.id]) {
rtree.remove(rectangles[parent.id]);
- insertions.push(entityRectangle(parent));
+ insertions.push(parent);
}
updateParents(parent, insertions);
});
if (head.entities.hasOwnProperty(entity.id) || rectangles[entity.id])
return;
- insertions.push(entityRectangle(entity));
+ insertions.push(entity);
updateParents(entity, insertions);
});
+ insertions = _.unique(insertions).map(entityRectangle);
rtree.load(insertions);
return tree;
diff.modified().forEach(function(entity) {
rtree.remove(rectangles[entity.id]);
- insertions.push(entityRectangle(entity));
+ insertions.push(entity);
updateParents(entity, insertions);
});
diff.created().forEach(function(entity) {
- insertions.push(entityRectangle(entity));
+ insertions.push(entity);
});
+ insertions = _.unique(insertions).map(entityRectangle);
rtree.load(insertions);
}
if (!this.isClosed() || this.tags.area === 'no')
return false;
for (var key in this.tags)
- if (key in iD.Way.areaKeys && !(this.tags[key] in iD.Way.areaKeys[key]))
+ if (key in iD.areaKeys && !(this.tags[key] in iD.areaKeys[key]))
return true;
return false;
},
});
}
});
-
-// A closed way is considered to be an area if it has a tag with one
-// of the following keys, and the value is _not_ one of the associated
-// values for the respective key.
-iD.Way.areaKeys = {
- aeroway: { taxiway: true},
- amenity: {},
- area: {},
- 'area:highway': {},
- building: {},
- 'building:part': {},
- historic: {},
- landuse: {},
- leisure: {},
- man_made: { cutline: true, embankment: true, pipeline: true},
- military: {},
- natural: { coastline: true },
- office: {},
- place: {},
- power: {},
- public_transport: {},
- ruins: {},
- shop: {},
- tourism: {},
- waterway: {}
-};
iD.Background = function(context) {
var dispatch = d3.dispatch('change'),
baseLayer = iD.TileLayer()
reader.onload = function(e) {
gpxLayer.geojson(toGeoJSON.gpx(toDom(e.target.result)));
dispatch.change();
- context.map().pan([0, 0]);
};
reader.readAsText(f);
if (overlay) background.toggleOverlayLayer(overlay);
});
+ var gpx = q.gpx;
+ if (gpx) {
+ d3.text(gpx, function(err, gpxTxt) {
+ gpxLayer.geojson(toGeoJSON.gpx(toDom(gpxTxt)));
+ dispatch.change();
+ });
+ }
+
return d3.rebind(background, dispatch, 'on');
};
iD.BackgroundSource = function(data) {
.on('change.attribution', update);
context.map()
- .on('move.attribution', _.throttle(update, 400));
+ .on('move.attribution', _.throttle(update, 400, {leading: false}));
update();
};
commentField.node().select();
+ // Warnings
+ var warnings = body.selectAll('div.warning-section')
+ .data([iD.validate(changes, context.graph())])
+ .enter()
+ .append('div')
+ .attr('class', 'modal-section warning-section fillL2')
+ .style('display', function(d) { return _.isEmpty(d) ? 'none' : null; })
+ .style('background', '#ffb');
+
+ warnings.append('h3')
+ .text(t('commit.warnings'));
+
+ var warningLi = warnings.append('ul')
+ .attr('class', 'changeset-list')
+ .selectAll('li')
+ .data(function(d) { return d; })
+ .enter()
+ .append('li')
+ .style()
+ .on('mouseover', mouseover)
+ .on('mouseout', mouseout)
+ .on('click', warningClick);
+
+ warningLi.append('span')
+ .attr('class', 'alert icon icon-pre-text');
+
+ warningLi.append('strong').text(function(d) {
+ return d.message;
+ });
+
// Save Section
var saveSection = body.append('div')
.attr('class','modal-section fillL cf');
.attr('class', 'label')
.text(t('commit.save'));
- // Warnings
- var warnings = body.selectAll('div.warning-section')
- .data([iD.validate(changes, context.graph())])
- .enter()
- .append('div')
- .attr('class', 'modal-section warning-section fillL2')
- .style('display', function(d) { return _.isEmpty(d) ? 'none' : null; });
-
- warnings.append('h3')
- .text(t('commit.warnings'));
-
- var warningLi = warnings.append('ul')
- .attr('class', 'changeset-list')
- .selectAll('li')
- .data(function(d) { return d; })
- .enter()
- .append('li')
- .on('mouseover', mouseover)
- .on('mouseout', mouseout)
- .on('click', warningClick);
-
- warningLi.append('span')
- .attr('class', 'alert icon icon-pre-text');
-
- warningLi.append('strong').text(function(d) {
- return d.message;
- });
-
var changeSection = body.selectAll('div.commit-section')
.data([0])
.enter()
"terms_url": "http://www.osm-tools.org/",
"terms_text": "© osm-tools.org & OpenStreetMap contributors, CC-BY-SA"
},
+ {
+ "name": "City of Kelowna 2012",
+ "type": "tms",
+ "description": "High quality aerial imagery taken for the City of Kelowna",
+ "template": "http://{switch:a,b,c,d}.tile.paulnorman.ca/kelowna2012/{zoom}/{x}/{y}.png",
+ "scaleExtent": [
+ 9,
+ 20
+ ],
+ "polygon": [
+ [
+ [
+ -119.5867318,
+ 49.7928087
+ ],
+ [
+ -119.5465655,
+ 49.7928097
+ ],
+ [
+ -119.5465661,
+ 49.8013837
+ ],
+ [
+ -119.5343374,
+ 49.8013841
+ ],
+ [
+ -119.5343376,
+ 49.8047321
+ ],
+ [
+ -119.5296211,
+ 49.8047322
+ ],
+ [
+ -119.5296216,
+ 49.8119555
+ ],
+ [
+ -119.5104463,
+ 49.811956
+ ],
+ [
+ -119.5115683,
+ 49.8744325
+ ],
+ [
+ -119.5108946,
+ 49.8744904
+ ],
+ [
+ -119.5114111,
+ 49.8843312
+ ],
+ [
+ -119.5114115,
+ 49.9221763
+ ],
+ [
+ -119.49386,
+ 49.9223477
+ ],
+ [
+ -119.4940505,
+ 49.9313031
+ ],
+ [
+ -119.4803936,
+ 49.9317529
+ ],
+ [
+ -119.4804572,
+ 49.9407474
+ ],
+ [
+ -119.4666732,
+ 49.9409927
+ ],
+ [
+ -119.4692775,
+ 49.9913717
+ ],
+ [
+ -119.4551337,
+ 49.9916078
+ ],
+ [
+ -119.4556736,
+ 50.0121242
+ ],
+ [
+ -119.4416673,
+ 50.0123895
+ ],
+ [
+ -119.4417308,
+ 50.0136345
+ ],
+ [
+ -119.4221492,
+ 50.0140377
+ ],
+ [
+ -119.4221042,
+ 50.0119306
+ ],
+ [
+ -119.4121303,
+ 50.012165
+ ],
+ [
+ -119.4126082,
+ 50.0216913
+ ],
+ [
+ -119.4123387,
+ 50.0216913
+ ],
+ [
+ -119.4124772,
+ 50.0250773
+ ],
+ [
+ -119.4120917,
+ 50.0250821
+ ],
+ [
+ -119.4121954,
+ 50.0270769
+ ],
+ [
+ -119.4126083,
+ 50.0270718
+ ],
+ [
+ -119.4128328,
+ 50.0321946
+ ],
+ [
+ -119.3936313,
+ 50.0326418
+ ],
+ [
+ -119.393529,
+ 50.0307781
+ ],
+ [
+ -119.3795727,
+ 50.0310116
+ ],
+ [
+ -119.3795377,
+ 50.0287584
+ ],
+ [
+ -119.3735764,
+ 50.0288621
+ ],
+ [
+ -119.371544,
+ 49.9793618
+ ],
+ [
+ -119.3573506,
+ 49.9793618
+ ],
+ [
+ -119.3548353,
+ 49.9256081
+ ],
+ [
+ -119.3268079,
+ 49.9257238
+ ],
+ [
+ -119.3256573,
+ 49.8804068
+ ],
+ [
+ -119.3138893,
+ 49.8806528
+ ],
+ [
+ -119.3137097,
+ 49.8771651
+ ],
+ [
+ -119.3132156,
+ 49.877223
+ ],
+ [
+ -119.3131482,
+ 49.8749652
+ ],
+ [
+ -119.312452,
+ 49.8749073
+ ],
+ [
+ -119.3122275,
+ 49.87236
+ ],
+ [
+ -119.3117558,
+ 49.872331
+ ],
+ [
+ -119.3115986,
+ 49.8696098
+ ],
+ [
+ -119.3112169,
+ 49.8694217
+ ],
+ [
+ -119.3109199,
+ 49.8632417
+ ],
+ [
+ -119.3103721,
+ 49.8632724
+ ],
+ [
+ -119.3095139,
+ 49.8512388
+ ],
+ [
+ -119.3106368,
+ 49.8512316
+ ],
+ [
+ -119.3103859,
+ 49.8462564
+ ],
+ [
+ -119.3245344,
+ 49.8459957
+ ],
+ [
+ -119.3246018,
+ 49.8450689
+ ],
+ [
+ -119.3367018,
+ 49.844875
+ ],
+ [
+ -119.3367467,
+ 49.8435136
+ ],
+ [
+ -119.337937,
+ 49.8434702
+ ],
+ [
+ -119.3378023,
+ 49.8382055
+ ],
+ [
+ -119.3383637,
+ 49.8381041
+ ],
+ [
+ -119.3383749,
+ 49.8351202
+ ],
+ [
+ -119.3390936,
+ 49.8351058
+ ],
+ [
+ -119.3388016,
+ 49.8321217
+ ],
+ [
+ -119.3391497,
+ 49.8320565
+ ],
+ [
+ -119.3391722,
+ 49.8293331
+ ],
+ [
+ -119.3394641,
+ 49.8293331
+ ],
+ [
+ -119.3395879,
+ 49.8267878
+ ],
+ [
+ -119.3500053,
+ 49.8265829
+ ],
+ [
+ -119.3493701,
+ 49.8180588
+ ],
+ [
+ -119.4046964,
+ 49.8163785
+ ],
+ [
+ -119.4045694,
+ 49.8099022
+ ],
+ [
+ -119.4101592,
+ 49.8099022
+ ],
+ [
+ -119.4102862,
+ 49.8072787
+ ],
+ [
+ -119.4319467,
+ 49.8069098
+ ],
+ [
+ -119.4322643,
+ 49.7907965
+ ],
+ [
+ -119.4459847,
+ 49.7905504
+ ],
+ [
+ -119.445286,
+ 49.7820201
+ ],
+ [
+ -119.4967376,
+ 49.7811587
+ ],
+ [
+ -119.4966105,
+ 49.7784927
+ ],
+ [
+ -119.5418371,
+ 49.7775082
+ ],
+ [
+ -119.5415892,
+ 49.7718277
+ ],
+ [
+ -119.5560296,
+ 49.7714941
+ ],
+ [
+ -119.5561194,
+ 49.7718422
+ ],
+ [
+ -119.5715704,
+ 49.7715086
+ ],
+ [
+ -119.5716153,
+ 49.7717262
+ ],
+ [
+ -119.5819235,
+ 49.7714941
+ ],
+ [
+ -119.5820133,
+ 49.7717697
+ ],
+ [
+ -119.5922991,
+ 49.7715231
+ ],
+ [
+ -119.592344,
+ 49.7718132
+ ],
+ [
+ -119.6003839,
+ 49.7715957
+ ],
+ [
+ -119.6011924,
+ 49.7839081
+ ],
+ [
+ -119.5864365,
+ 49.7843863
+ ]
+ ]
+ ],
+ "id": "kelowna_2012",
+ "default": true
+ },
{
"name": "Freemap.sk Car",
"type": "tms",
]
]
},
+ {
+ "name": "South Tyrol Orthofoto 2011",
+ "type": "tms",
+ "template": "http://sdi.provincia.bz.it/geoserver/gwc/service/tms/1.0.0/WMTS_OF2011_APB-PAB@GoogleMapsCompatible@png8/{z}/{x}/{-y}.png",
+ "polygon": [
+ [
+ [
+ 10.373383,
+ 46.213553
+ ],
+ [
+ 10.373383,
+ 47.098175
+ ],
+ [
+ 12.482758,
+ 47.098175
+ ],
+ [
+ 12.482758,
+ 46.213553
+ ],
+ [
+ 10.373383,
+ 46.213553
+ ]
+ ]
+ ],
+ "id": "sdi.provinz.bz.it-WMTS_OF2011_APB-PAB"
+ },
+ {
+ "name": "South Tyrol Topomap",
+ "type": "tms",
+ "template": "http://sdi.provincia.bz.it/geoserver/gwc/service/tms/1.0.0/WMTS_TOPOMAP_APB-PAB@GoogleMapsCompatible@png8/{z}/{x}/{-y}.png",
+ "polygon": [
+ [
+ [
+ 10.373383,
+ 46.213553
+ ],
+ [
+ 10.373383,
+ 47.098175
+ ],
+ [
+ 12.482758,
+ 47.098175
+ ],
+ [
+ 12.482758,
+ 46.213553
+ ],
+ [
+ 10.373383,
+ 46.213553
+ ]
+ ]
+ ],
+ "id": "sdi.provinz.bz.it-WMTS_TOPOMAP_APB-PAB"
+ },
{
"name": "Stadt Uster Orthophoto 2008 10cm",
"type": "tms",
"fields": [
"operator",
"address",
- "building_yes"
+ "building_area"
],
"geometry": [
"point",
"parking",
"capacity",
"fee",
+ "access_simple",
"supervised",
"park_ride",
"address"
"icon": "place-of-worship",
"fields": [
"denomination",
- "building_yes",
+ "building_area",
"address"
],
"geometry": [
"icon": "religious-christian",
"fields": [
"denomination",
- "building_yes",
+ "building_area",
"address"
],
"geometry": [
"icon": "religious-jewish",
"fields": [
"denomination",
- "building_yes",
+ "building_area",
"address"
],
"geometry": [
"icon": "religious-muslim",
"fields": [
"denomination",
- "building_yes",
+ "building_area",
"address"
],
"geometry": [
"fields": [
"cuisine",
"building_area",
- "address"
+ "address",
+ "capacity"
],
"geometry": [
"point",
},
"amenity/taxi": {
"fields": [
- "operator"
+ "operator",
+ "capacity"
],
"geometry": [
"point",
"tags": {
"amenity": "telephone"
},
+ "terms": [
+ "phone"
+ ],
"name": "Telephone"
},
"amenity/theatre": {
"toilets/disposal",
"operator",
"building_area",
- "access_toilets"
+ "fee",
+ "access_simple"
],
"geometry": [
"point",
"boundary/administrative": {
"name": "Administrative Boundary",
"geometry": [
- "line",
- "area"
+ "line"
],
"tags": {
"boundary": "administrative"
"building": {
"icon": "building",
"fields": [
- "building_yes",
+ "building",
"levels",
"address"
],
"searchable": false
},
"building/garage": {
+ "fields": [
+ "capacity"
+ ],
"geometry": [
"point",
"vertex",
},
"name": "Residential Building"
},
+ "embankment": {
+ "geometry": [
+ "line"
+ ],
+ "tags": {
+ "embankment": "yes"
+ },
+ "name": "Embankment",
+ "matchScore": 0.2
+ },
"emergency/ambulance_station": {
"fields": [
"operator"
},
"fields": [
"entrance",
+ "access_simple",
"address"
],
"name": "Entrance"
},
"footway/crossing": {
"fields": [
- "crossing"
+ "crossing",
+ "access",
+ "surface"
],
"geometry": [
"line"
"name": "Farm",
"icon": "farm"
},
+ "landuse/farmland": {
+ "geometry": [
+ "point",
+ "area"
+ ],
+ "tags": {
+ "landuse": "farmland"
+ },
+ "terms": [],
+ "name": "Farmland",
+ "icon": "farm",
+ "searchable": false
+ },
"landuse/farmyard": {
"geometry": [
"point",
"name": "Stadium"
},
"leisure/swimming_pool": {
+ "fields": [
+ "access_simple"
+ ],
"geometry": [
"point",
"vertex",
},
"name": "Cut line"
},
+ "man_made/embankment": {
+ "geometry": [
+ "line"
+ ],
+ "tags": {
+ "man_made": "embankment"
+ },
+ "name": "Embankment",
+ "searchable": false
+ },
+ "man_made/flagpole": {
+ "geometry": [
+ "point"
+ ],
+ "tags": {
+ "man_made": "flagpole"
+ },
+ "name": "Flagpole",
+ "icon": "embassy"
+ },
"man_made/lighthouse": {
"geometry": [
"point",
},
"name": "Water Works"
},
+ "military/airfield": {
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "tags": {
+ "military": "airfield"
+ },
+ "terms": [],
+ "name": "Airfield",
+ "icon": "airfield"
+ },
+ "military/barracks": {
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "tags": {
+ "military": "barracks"
+ },
+ "terms": [],
+ "name": "Barracks"
+ },
+ "military/bunker": {
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "tags": {
+ "military": "bunker"
+ },
+ "terms": [],
+ "name": "Bunker"
+ },
+ "military/range": {
+ "geometry": [
+ "point",
+ "vertex",
+ "area"
+ ],
+ "tags": {
+ "military": "range"
+ },
+ "terms": [],
+ "name": "Military Range"
+ },
"natural": {
"fields": [
"natural"
},
"name": "Transformer"
},
+ "public_transport/platform": {
+ "fields": [
+ "ref",
+ "operator",
+ "network",
+ "shelter"
+ ],
+ "geometry": [
+ "point",
+ "vertex",
+ "line",
+ "area"
+ ],
+ "tags": {
+ "public_transport": "platform"
+ },
+ "name": "Platform"
+ },
+ "public_transport/stop_position": {
+ "fields": [
+ "ref",
+ "operator",
+ "network"
+ ],
+ "geometry": [
+ "vertex"
+ ],
+ "tags": {
+ "public_transport": "stop_position"
+ },
+ "name": "Stop Position"
+ },
"railway": {
"fields": [
"railway"
}
}
},
- "access_toilets": {
+ "access_simple": {
"key": "access",
"type": "combo",
"label": "Access",
"geometry": "area",
"label": "Building"
},
- "building_yes": {
- "key": "building",
- "type": "combo",
- "default": "yes",
- "label": "Building"
- },
"capacity": {
"key": "capacity",
"type": "number",
}
}
},
- "access_toilets": {
+ "access_simple": {
"label": "Access"
},
"address": {
"building_area": {
"label": "Building"
},
- "building_yes": {
- "label": "Building"
- },
"capacity": {
"label": "Capacity",
"placeholder": "50, 100, 200..."
},
"amenity/telephone": {
"name": "Telephone",
- "terms": ""
+ "terms": "phone"
},
"amenity/theatre": {
"name": "Theater",
"name": "Residential Building",
"terms": ""
},
+ "embankment": {
+ "name": "Embankment",
+ "terms": ""
+ },
"emergency/ambulance_station": {
"name": "Ambulance Station",
"terms": ""
"name": "Farm",
"terms": ""
},
+ "landuse/farmland": {
+ "name": "Farmland",
+ "terms": ""
+ },
"landuse/farmyard": {
"name": "Farmyard",
"terms": ""
"name": "Cut line",
"terms": ""
},
+ "man_made/embankment": {
+ "name": "Embankment",
+ "terms": ""
+ },
+ "man_made/flagpole": {
+ "name": "Flagpole",
+ "terms": ""
+ },
"man_made/lighthouse": {
"name": "Lighthouse",
"terms": ""
"name": "Water Works",
"terms": ""
},
+ "military/airfield": {
+ "name": "Airfield",
+ "terms": ""
+ },
+ "military/barracks": {
+ "name": "Barracks",
+ "terms": ""
+ },
+ "military/bunker": {
+ "name": "Bunker",
+ "terms": ""
+ },
+ "military/range": {
+ "name": "Military Range",
+ "terms": ""
+ },
"natural": {
"name": "Natural",
"terms": ""
"name": "Transformer",
"terms": ""
},
+ "public_transport/platform": {
+ "name": "Platform",
+ "terms": ""
+ },
+ "public_transport/stop_position": {
+ "name": "Stop Position",
+ "terms": ""
+ },
"railway": {
"name": "Railway",
"terms": ""