From cabbb384728f3590167fdca199c6e177d0bb4b34 Mon Sep 17 00:00:00 2001
From: Benjamin Delespierre Links & Suggested Reading
- Underscore.php, - a PHP port of the functions that are applicable in both languages. - Includes OOP-wrapping and chaining. - (source) + Underscore.php, + a PHP port of the functions that are applicable in both languages. Tailored for PHP 5.4 and made with data-type tolerance in mind. + (source)
From 13e93b41b89dc61f95cbfdfe055e9806bc579d3d Mon Sep 17 00:00:00 2001
From: Jordan Eldredge
+ isSymbol
diff --git a/test/objects.js b/test/objects.js
index 027e42b6c..6ca0a106f 100644
--- a/test/objects.js
+++ b/test/objects.js
@@ -639,6 +639,17 @@
assert.strictEqual(_.isString(1), false);
});
+ QUnit.test('isSymbol', function(assert) {
+ assert.ok(!_.isSymbol(0), 'numbers are not symbols');
+ assert.ok(!_.isSymbol(''), 'strings are not symbols');
+ assert.ok(!_.isSymbol(_.isSymbol), 'functions are not symbols');
+ if (typeof Symbol === 'function') {
+ assert.ok(_.isSymbol(Symbol()), 'symbols are symbols');
+ assert.ok(_.isSymbol(Symbol('description')), 'described symbols are symbols');
+ assert.ok(_.isSymbol(Object(Symbol())), 'boxed symbols are symbols');
+ }
+ });
+
QUnit.test('isNumber', function(assert) {
assert.ok(!_.isNumber('string'), 'a string is not a number');
assert.ok(!_.isNumber(arguments), 'the arguments object is not a number');
diff --git a/underscore.js b/underscore.js
index 19b3f7c9c..d8c741b22 100644
--- a/underscore.js
+++ b/underscore.js
@@ -1286,7 +1286,7 @@
};
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
- _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
+ _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error', 'Symbol'], function(name) {
_['is' + name] = function(obj) {
return toString.call(obj) === '[object ' + name + ']';
};
From dd19d54709dbe4abe1641623722bfe80d8564748 Mon Sep 17 00:00:00 2001
From: Michael Ficarra Object Functions
_.isError(o_O)
}
=> true
+
+
+ _.isSymbol(object)
+
+ Returns true if object is a Symbol.
+
+_.isSymbol(Symbol());
+=> true
Object Functions
try {
throw new TypeError("Example");
} catch (o_O) {
- _.isError(o_O)
+ _.isError(o_O);
}
=> true
From 8f3d0507e885f64a05424fdc09a07cf77e2f676b Mon Sep 17 00:00:00 2001
From: Paul Falgout Utility Functions
through _.iteratee is map, find,
filter, reject, every, some, max,
min, sortBy, groupBy, indexBy,
- countBy, sortedIndex, partition, and unique.
+ countBy, sortedIndex, partition, and uniq.
var stooges = [{name: 'curly', age: 25}, {name: 'moe', age: 21}, {name: 'larry', age: 23}];
From 9de10a86878598f8d99cec2865e4a55a62051595 Mon Sep 17 00:00:00 2001
From: Nuno Arruda Utility Functions
identity, an arbitrary callback, a property matcher, or a property accessor.
The full list of Underscore methods that transform predicates
- through _.iteratee is map, find,
- filter, reject, every, some, max,
- min, sortBy, groupBy, indexBy,
- countBy, sortedIndex, partition, and uniq.
+ through _.iteratee is countBy, every, filter,
+ find, findIndex, findKey, findLastIndex,
+ groupBy, indexBy, map, mapObject, max,
+ min, partition, reject, some, sortBy,
+ sortedIndex, and uniq
var stooges = [{name: 'curly', age: 25}, {name: 'moe', age: 21}, {name: 'larry', age: 23}];
From 1f607d47c207acef34030eb3e7bfe69d3f16c92d Mon Sep 17 00:00:00 2001
From: Jordan Eldredge
Date: Tue, 19 Jan 2016 18:16:47 -0800
Subject: [PATCH 011/498] Clean up assertions for _.intersection()
---
test/arrays.js | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/test/arrays.js b/test/arrays.js
index 6f9cd67b6..41931c64a 100644
--- a/test/arrays.js
+++ b/test/arrays.js
@@ -186,20 +186,18 @@
QUnit.test('intersection', function(assert) {
var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho'];
- assert.deepEqual(_.intersection(stooges, leaders), ['moe'], 'can take the set intersection of two arrays');
+ assert.deepEqual(_.intersection(stooges, leaders), ['moe'], 'can find the set intersection of two arrays');
assert.deepEqual(_(stooges).intersection(leaders), ['moe'], 'can perform an OO-style intersection');
var result = (function(){ return _.intersection(arguments, leaders); }('moe', 'curly', 'larry'));
assert.deepEqual(result, ['moe'], 'works on an arguments object');
var theSixStooges = ['moe', 'moe', 'curly', 'curly', 'larry', 'larry'];
assert.deepEqual(_.intersection(theSixStooges, leaders), ['moe'], 'returns a duplicate-free array');
result = _.intersection([2, 4, 3, 1], [1, 2, 3]);
- assert.deepEqual(result, [2, 3, 1], 'preserves order of first array');
+ assert.deepEqual(result, [2, 3, 1], 'preserves the order of the first array');
result = _.intersection(null, [1, 2, 3]);
- assert.equal(Object.prototype.toString.call(result), '[object Array]', 'returns an empty array when passed null as first argument');
- assert.equal(result.length, 0, 'returns an empty array when passed null as first argument');
+ assert.deepEqual(result, [], 'returns an empty array when passed null as the first argument');
result = _.intersection([1, 2, 3], null);
- assert.equal(Object.prototype.toString.call(result), '[object Array]', 'returns an empty array when passed null as argument beyond the first');
- assert.equal(result.length, 0, 'returns an empty array when passed null as argument beyond the first');
+ assert.deepEqual(result, [], 'returns an empty array when passed null as an argument beyond the first');
});
QUnit.test('union', function(assert) {
From 2e3cc40d06ad3c49a9996f13e481fca67b369c06 Mon Sep 17 00:00:00 2001
From: Jordan Eldredge
Date: Wed, 20 Jan 2016 09:16:30 -0800
Subject: [PATCH 012/498] Clean up assertions for _.union()
---
test/arrays.js | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/test/arrays.js b/test/arrays.js
index 6f9cd67b6..ee4c92e2b 100644
--- a/test/arrays.js
+++ b/test/arrays.js
@@ -204,18 +204,21 @@
QUnit.test('union', function(assert) {
var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]);
- assert.deepEqual(result, [1, 2, 3, 30, 40], 'takes the union of a list of arrays');
+ assert.deepEqual(result, [1, 2, 3, 30, 40], 'can find the union of a list of arrays');
+
+ result = _([1, 2, 3]).union([2, 30, 1], [1, 40]);
+ assert.deepEqual(result, [1, 2, 3, 30, 40], 'can perform an OO-style union');
result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]);
- assert.deepEqual(result, [1, 2, 3, 30, 40, [1]], 'takes the union of a list of nested arrays');
+ assert.deepEqual(result, [1, 2, 3, 30, 40, [1]], 'can find the union of a list of nested arrays');
+
+ result = _.union([10, 20], [1, 30, 10], [0, 40]);
+ assert.deepEqual(result, [10, 20, 1, 30, 0, 40], 'orders values by their first encounter');
- var args = null;
- (function(){ args = arguments; }(1, 2, 3));
- result = _.union(args, [2, 30, 1], [1, 40]);
- assert.deepEqual(result, [1, 2, 3, 30, 40], 'takes the union of a list of arrays');
+ result = (function(){ return _.union(arguments, [2, 30, 1], [1, 40]); }(1, 2, 3));
+ assert.deepEqual(result, [1, 2, 3, 30, 40], 'works on an arguments object');
- result = _.union([1, 2, 3], 4);
- assert.deepEqual(result, [1, 2, 3], 'restrict the union to arrays only');
+ assert.deepEqual(_.union([1, 2, 3], 4), [1, 2, 3], 'restricts the union to arrays only');
});
QUnit.test('difference', function(assert) {
From 1e69d38a5a8f24c1330c29e748fa6174436c122b Mon Sep 17 00:00:00 2001
From: Jordan Eldredge
Date: Wed, 20 Jan 2016 09:58:48 -0800
Subject: [PATCH 013/498] Clean up assertions for _.difference()
---
test/arrays.js | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/test/arrays.js b/test/arrays.js
index 90e2a4b91..748edea4f 100644
--- a/test/arrays.js
+++ b/test/arrays.js
@@ -221,10 +221,19 @@
QUnit.test('difference', function(assert) {
var result = _.difference([1, 2, 3], [2, 30, 40]);
- assert.deepEqual(result, [1, 3], 'takes the difference of two arrays');
+ assert.deepEqual(result, [1, 3], 'can find the difference of two arrays');
+
+ result = _([1, 2, 3]).difference([2, 30, 40]);
+ assert.deepEqual(result, [1, 3], 'can perform an OO-style difference');
result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]);
- assert.deepEqual(result, [3, 4], 'takes the difference of three arrays');
+ assert.deepEqual(result, [3, 4], 'can find the difference of three arrays');
+
+ result = _.difference([8, 9, 3, 1], [3, 8]);
+ assert.deepEqual(result, [9, 1], 'preserves the order of the first array');
+
+ result = (function(){ return _.difference(arguments, [2, 30, 40]); }(1, 2, 3));
+ assert.deepEqual(result, [1, 3], 'works on an arguments object');
result = _.difference([1, 2, 3], 1);
assert.deepEqual(result, [1, 2, 3], 'restrict the difference to arrays only');
From 34b45d8b6110a4ea18ed2b4629877fb4a2002333 Mon Sep 17 00:00:00 2001
From: Craig Martin
Date: Thu, 21 Jan 2016 08:58:28 -0500
Subject: [PATCH 014/498] add gitter and stackoverflow links to readme
---
README.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/README.md b/README.md
index c2ba2590c..f29a03c51 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,10 @@ without extending any core JavaScript objects.
For Docs, License, Tests, and pre-packed downloads, see:
http://underscorejs.org
+For support and questions, please use
+[the gitter channel](https://gitter.im/jashkenas/underscore)
+or [stackoverflow](http://stackoverflow.com/search?q=underscore.js)
+
Underscore is an open-sourced component of DocumentCloud:
https://github.com/documentcloud
From b7925e0819557abe4f113df5ee2e19ff64e77776 Mon Sep 17 00:00:00 2001
From: Craig Martin
Date: Wed, 27 Jan 2016 09:38:50 -0500
Subject: [PATCH 015/498] disable npm's progress bar in travis ci for quicker
install
---
.travis.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.travis.yml b/.travis.yml
index 172af86c3..f0e6ad148 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -23,6 +23,7 @@ notifications:
email: false
env:
global:
+ - NPM_CONFIG_PROGRESS="false"
- secure: bDZSBQfqr21hCayjcZ20IxrV6+XGhxQPFIfwWqEKLrF93Gu8LLVjZRxXE/mE8I8N4Z5WtDNb4ZHrm/TTzmcPa5MuHgIxEdknQCncobH8oimwc83SHwEPk6okeNKl39VlCjvvnmoe/V/KpnknuYn3Rqghtl/Uv9KLpCwskwjTtcw=
- secure: SRECgXuwcZTcD3GVxTS2bYNgRyye4vq6BLrV2PH9FyNenowsKQR2EwlC/dppc1Q8NWMgv79J/R96q9JOFh+mEH9L5dlBb2yhnGH8amVeM/ChAJHT/F8YktKM453uVpz5fR00QcCQDDUOx6Pvx374ID0OKNpWKAkQBWA9mPTsLnE=
matrix: BROWSER=false
From 65b5398d432083727e3f8f0461f781e6c5fe3001 Mon Sep 17 00:00:00 2001
From: Jordan Eldredge
Date: Wed, 27 Jan 2016 08:05:06 -0800
Subject: [PATCH 016/498] Fix closing tags in _.iteratee docs
I forgot to close these tags in the #2414.
---
index.html | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/index.html b/index.html
index f9f4271e9..6897cbeaf 100644
--- a/index.html
+++ b/index.html
@@ -1902,11 +1902,11 @@ Utility Functions
identity, an arbitrary callback, a property matcher, or a property accessor.
The full list of Underscore methods that transform predicates
- through _.iteratee is countBy, every, filter,
- find, findIndex, findKey, findLastIndex,
- groupBy, indexBy, map, mapObject, max,
- min, partition, reject, some, sortBy,
- sortedIndex, and uniq
+ through _.iteratee is countBy, every, filter,
+ find, findIndex, findKey, findLastIndex,
+ groupBy, indexBy, map, mapObject, max,
+ min, partition, reject, some, sortBy,
+ sortedIndex, and uniq
var stooges = [{name: 'curly', age: 25}, {name: 'moe', age: 21}, {name: 'larry', age: 23}];
From ed96600c23798168f998eb873bde629f4bbbcc67 Mon Sep 17 00:00:00 2001
From: Jordan Eldredge
Date: Wed, 27 Jan 2016 08:18:10 -0800
Subject: [PATCH 017/498] Separate object-oriented style and chaining in docs
I think the fact that the object-oriented style and chaining share
implementation details has lead us to conflate them in the docs. In practice,
the two features have almost nothing to do with each other.
The existing documentation could easily lead one to believe that they could
start a chain using the OOP style.
This confusion is compounded by a few factors:
1. Lodash supports chains starting with the OOP wrapper.
2. The fact that we share names with native Array methods can lead to manual
tests that appear to work.
For example:
_([1,2,3]).reverse().map(function(n){ return n * 2; });
This appears to be an example of successfully starting a chain with the OOP
style. The astute observer will note that the lack of a `.value()` call, proves
this is not Underscore chaining, but a new user attempting to clarify the
behavior for herself may not catch that detail.
---
index.html | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/index.html b/index.html
index 6897cbeaf..60c290e5a 100644
--- a/index.html
+++ b/index.html
@@ -334,6 +334,9 @@
- template
+
+ OOP Style
+
Chaining
@@ -1861,7 +1864,7 @@ Utility Functions
iteratee is called with an index argument. Produces an
array of the returned values.
- Note: this example uses the chaining syntax.
+ Note: this example uses the object-oriented syntax.
_(3).times(function(n){ genie.grantWishNumber(n); });
@@ -2055,7 +2058,7 @@ Utility Functions
</script>
- Chaining
+ Object-Oriented Style
You can use Underscore in either an object-oriented or a functional style,
@@ -2067,6 +2070,8 @@
Chaining
_.map([1, 2, 3], function(n){ return n * 2; });
_([1, 2, 3]).map(function(n){ return n * 2; });
+ Calling chain will cause all future method calls to return wrapped objects. When you've finished the computation, call @@ -2119,13 +2124,13 @@
- value_(obj).value()
+ value_.chain(obj).value()
Extracts the value of a wrapped object.
-_([1, 2, 3]).value(); -=> [1, 2, 3] +_.chain([1, 2, 3]).reverse().value(); +=> [3, 2, 1]
-_.unzip([['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]]) -=> ["moe", 30, true], ["larry", 40, false], ["curly", 50, false] +_.unzip([["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]); +=> [['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]]
From 723aaff63df45520eeea4daabf35623427c712d1 Mon Sep 17 00:00:00 2001
From: Adam Krebs
Underscore.php,
- a PHP port of the functions that are applicable in both languages. Tailored for PHP 5.4 and made with data-type tolerance in mind.
+ a PHP port of the functions that are applicable in both languages.
+ Tailored for PHP 5.4 and made with data-type tolerance in mind.
(source)
Links & Suggested Reading
Links & Suggested Reading
reverse, sprintf, and more.
+ Underscore-java, + a java port of the functions that are applicable in both languages. + Includes OOP-wrapping and chaining. + (source) +
+Ruby's Enumerable module.
From 15f10acf2b9a2b2df3a30551f87e67c095202908 Mon Sep 17 00:00:00 2001 From: Jordan Eldredge
iteratee_.iteratee(value, [context])
- A mostly-internal function to generate callbacks that can be applied
- to each element in a collection, returning the desired result — either
- identity, an arbitrary callback, a property matcher, or a property accessor.
-
- The full list of Underscore methods that transform predicates
- through _.iteratee is countBy, every, filter,
- find, findIndex, findKey, findLastIndex,
- groupBy, indexBy, map, mapObject, max,
- min, partition, reject, some, sortBy,
- sortedIndex, and uniq
+ Generates a callback that can be applied to each element in
+ a collection. _.iteratee supports a number of shorthand
+ syntaxes for common callback use cases. Depending value's type
+ _.iteratee will return:
-var stooges = [{name: 'curly', age: 25}, {name: 'moe', age: 21}, {name: 'larry', age: 23}];
-_.map(stooges, _.iteratee('age'));
-=> [25, 21, 23];
-
+// No value
+_.iteratee();
+=> _.identity()
+
+// Function
+_.iteratee(function(n) { return n * 2; });
+=> function(n) { return n * 2; }
+
+// Object
+_.iteratee({firstName: 'Chelsea'});
+=> _.matcher({firstName: 'Chelsea'});
+
+// Anything else
+_.iteratee('firstName');
+=> _.property('firstName');
+
+ + The following Underscore methods transform their predicates through + _.iteratee: countBy, every, + filter, find, findIndex, findKey, + findLastIndex, groupBy, indexBy, + map, mapObject, max, min, + partition, reject, some, sortBy, + sortedIndex, and uniq +
uniqueId_.uniqueId([prefix])
From b51863962a5d9246bb054106d3bf94f2d5e75929 Mon Sep 17 00:00:00 2001
From: Jordan Eldredge Utility Functions
Generates a callback that can be applied to each element in
a collection. _.iteratee supports a number of shorthand
- syntaxes for common callback use cases. Depending value's type
- _.iteratee will return:
+ syntaxes for common callback use cases. Depending upon value's
+ type, _.iteratee will return:
// No value From f32dfc6fde825976a3126b12cc81dad4e42cfcc5 Mon Sep 17 00:00:00 2001 From: Jordan EldredgeDate: Wed, 30 Mar 2016 08:53:01 -0700 Subject: [PATCH 042/498] Document customizing `_.iteratee` --- index.html | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/index.html b/index.html index 17ee2e2af..04f129aaf 100644 --- a/index.html +++ b/index.html @@ -1932,6 +1932,17 @@ Utility Functions
sortedIndex, and uniq ++ You may overwrite _.iteratee with your own custom function, + if you want additional or different shorthand syntaxes: +
++// Support `RegExp` predicate shorthand. +var builtinIteratee = _.iteratee; +_.iteratee = function(value, context) { + if (_.isRegExp(value)) return function(obj) { return value.test(obj) }; + return builtinIteratee(value, context); +};uniqueId
_.uniqueId([prefix])
From 012fe2b77e3d206d763c0c078d3b97a63639fc24 Mon Sep 17 00:00:00 2001 From: Jordan EldredgeDate: Sun, 3 Apr 2016 18:45:44 -0700 Subject: [PATCH 043/498] Cleanup comment indentation --- underscore.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/underscore.js b/underscore.js index f2f04dc24..db5d62845 100644 --- a/underscore.js +++ b/underscore.js @@ -1099,7 +1099,7 @@ return result; }); - // Return a copy of the object without the blacklisted properties. + // Return a copy of the object without the blacklisted properties. _.omit = restArgs(function(obj, keys) { var iteratee = keys[0], context; if (_.isFunction(iteratee)) { @@ -1408,7 +1408,7 @@ return new Date().getTime(); }; - // List of HTML entities for escaping. + // List of HTML entities for escaping. var escapeMap = { '&': '&', '<': '<', From 0c10935623cd378d15ec3b04f82c6a5359274a7e Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Sun, 3 Apr 2016 22:48:48 -0700 Subject: [PATCH 044/498] Fix the argument order of some assertions Error messages assume the order `actual, expected`. Using https://github.com/platinumazure/eslint-plugin-qunit/blob/master/docs/rules/literal-compare-order.md I was able to automatically detect some of our tests which don't follow this convention. I'm sure there are others. --- test/collections.js | 54 ++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/test/collections.js b/test/collections.js index 182f7a218..b3e4f8623 100644 --- a/test/collections.js +++ b/test/collections.js @@ -549,7 +549,7 @@ assert.equal(-Infinity, _.max(void 0), 'can handle null/undefined'); assert.equal(-Infinity, _.max(null, _.identity), 'can handle null/undefined'); - assert.equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max'); + assert.equal(_.max([1, 2, 3]), 3, 'can perform a regular Math.max'); var neg = _.max([1, 2, 3], function(num){ return -num; }); assert.equal(neg, 1, 'can perform a computation-based max'); @@ -558,24 +558,24 @@ assert.equal(-Infinity, _.max([]), 'Maximum value of an empty array'); assert.equal(_.max({a: 'a'}), -Infinity, 'Maximum value of a non-numeric collection'); - assert.equal(299999, _.max(_.range(1, 300000)), 'Maximum value of a too-big array'); + assert.equal(_.max(_.range(1, 300000)), 299999, 'Maximum value of a too-big array'); - assert.equal(3, _.max([1, 2, 3, 'test']), 'Finds correct max in array starting with num and containing a NaN'); - assert.equal(3, _.max(['test', 1, 2, 3]), 'Finds correct max in array starting with NaN'); + assert.equal(_.max([1, 2, 3, 'test']), 3, 'Finds correct max in array starting with num and containing a NaN'); + assert.equal(_.max(['test', 1, 2, 3]), 3, 'Finds correct max in array starting with NaN'); - assert.equal(3, _.max([1, 2, 3, null]), 'Finds correct max in array starting with num and containing a `null`'); - assert.equal(3, _.max([null, 1, 2, 3]), 'Finds correct max in array starting with a `null`'); + assert.equal(_.max([1, 2, 3, null]), 3, 'Finds correct max in array starting with num and containing a `null`'); + assert.equal(_.max([null, 1, 2, 3]), 3, 'Finds correct max in array starting with a `null`'); - assert.equal(3, _.max([1, 2, 3, '']), 'Finds correct max in array starting with num and containing an empty string'); - assert.equal(3, _.max(['', 1, 2, 3]), 'Finds correct max in array starting with an empty string'); + assert.equal(_.max([1, 2, 3, '']), 3, 'Finds correct max in array starting with num and containing an empty string'); + assert.equal(_.max(['', 1, 2, 3]), 3, 'Finds correct max in array starting with an empty string'); - assert.equal(3, _.max([1, 2, 3, false]), 'Finds correct max in array starting with num and containing a false'); - assert.equal(3, _.max([false, 1, 2, 3]), 'Finds correct max in array starting with a false'); + assert.equal(_.max([1, 2, 3, false]), 3, 'Finds correct max in array starting with num and containing a false'); + assert.equal(_.max([false, 1, 2, 3]), 3, 'Finds correct max in array starting with a false'); - assert.equal(4, _.max([0, 1, 2, 3, 4]), 'Finds correct max in array containing a zero'); - assert.equal(0, _.max([-3, -2, -1, 0]), 'Finds correct max in array containing negative numbers'); + assert.equal(_.max([0, 1, 2, 3, 4]), 4, 'Finds correct max in array containing a zero'); + assert.equal(_.max([-3, -2, -1, 0]), 0, 'Finds correct max in array containing negative numbers'); - assert.deepEqual([3, 6], _.map([[1, 2, 3], [4, 5, 6]], _.max), 'Finds correct max in array when mapping through multiple arrays'); + assert.deepEqual(_.map([[1, 2, 3], [4, 5, 6]], _.max), [3, 6], 'Finds correct max in array when mapping through multiple arrays'); var a = {x: -Infinity}; var b = {x: -Infinity}; @@ -590,35 +590,35 @@ }); QUnit.test('min', function(assert) { - assert.equal(Infinity, _.min(null), 'can handle null/undefined'); - assert.equal(Infinity, _.min(void 0), 'can handle null/undefined'); - assert.equal(Infinity, _.min(null, _.identity), 'can handle null/undefined'); + assert.equal(_.min(null), Infinity, 'can handle null/undefined'); + assert.equal(_.min(void 0), Infinity, 'can handle null/undefined'); + assert.equal(_.min(null, _.identity), Infinity, 'can handle null/undefined'); - assert.equal(1, _.min([1, 2, 3]), 'can perform a regular Math.min'); + assert.equal(_.min([1, 2, 3]), 1, 'can perform a regular Math.min'); var neg = _.min([1, 2, 3], function(num){ return -num; }); assert.equal(neg, 3, 'can perform a computation-based min'); - assert.equal(Infinity, _.min({}), 'Minimum value of an empty object'); - assert.equal(Infinity, _.min([]), 'Minimum value of an empty array'); + assert.equal(_.min({}), Infinity, 'Minimum value of an empty object'); + assert.equal(_.min([]), Infinity, 'Minimum value of an empty array'); assert.equal(_.min({a: 'a'}), Infinity, 'Minimum value of a non-numeric collection'); - assert.deepEqual([1, 4], _.map([[1, 2, 3], [4, 5, 6]], _.min), 'Finds correct min in array when mapping through multiple arrays'); + assert.deepEqual(_.map([[1, 2, 3], [4, 5, 6]], _.min), [1, 4], 'Finds correct min in array when mapping through multiple arrays'); var now = new Date(9999999999); var then = new Date(0); assert.equal(_.min([now, then]), then); - assert.equal(1, _.min(_.range(1, 300000)), 'Minimum value of a too-big array'); + assert.equal(_.min(_.range(1, 300000)), 1, 'Minimum value of a too-big array'); - assert.equal(1, _.min([1, 2, 3, 'test']), 'Finds correct min in array starting with num and containing a NaN'); - assert.equal(1, _.min(['test', 1, 2, 3]), 'Finds correct min in array starting with NaN'); + assert.equal(_.min([1, 2, 3, 'test']), 1, 'Finds correct min in array starting with num and containing a NaN'); + assert.equal(_.min(['test', 1, 2, 3]), 1, 'Finds correct min in array starting with NaN'); - assert.equal(1, _.min([1, 2, 3, null]), 'Finds correct min in array starting with num and containing a `null`'); - assert.equal(1, _.min([null, 1, 2, 3]), 'Finds correct min in array starting with a `null`'); + assert.equal(_.min([1, 2, 3, null]), 1, 'Finds correct min in array starting with num and containing a `null`'); + assert.equal(_.min([null, 1, 2, 3]), 1, 'Finds correct min in array starting with a `null`'); - assert.equal(0, _.min([0, 1, 2, 3, 4]), 'Finds correct min in array containing a zero'); - assert.equal(-3, _.min([-3, -2, -1, 0]), 'Finds correct min in array containing negative numbers'); + assert.equal(_.min([0, 1, 2, 3, 4]), 0, 'Finds correct min in array containing a zero'); + assert.equal(_.min([-3, -2, -1, 0]), -3, 'Finds correct min in array containing negative numbers'); var a = {x: Infinity}; var b = {x: Infinity}; From 7943530568a94af59f36804cf82c9aaff7afbc89 Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Sun, 3 Apr 2016 22:34:54 -0700 Subject: [PATCH 045/498] Use descriptive assertions Using descriptive assertions can help give better failure messages. These were found using @platinumazure's [`eslint-plugin-qunit`](https://github.com/platinumazure/eslint-plugin-qunit). Once it reaches version 1.0, we could consider including it as part of our linting. --- test/collections.js | 24 ++++++++++++------------ test/objects.js | 4 ++-- test/utility.js | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/test/collections.js b/test/collections.js index 182f7a218..00f1a8a22 100644 --- a/test/collections.js +++ b/test/collections.js @@ -188,7 +188,7 @@ var prod = _.reduce([1, 2, 3, 4], function(memo, num){ return memo * num; }); assert.equal(prod, 24, 'can reduce via multiplication'); - assert.ok(_.reduce(null, _.noop, 138) === 138, 'handles a null (with initial value) properly'); + assert.strictEqual(_.reduce(null, _.noop, 138), 138, 'handles a null (with initial value) properly'); assert.equal(_.reduce([], _.noop, void 0), void 0, 'undefined can be passed as a special case'); assert.equal(_.reduce([_], _.noop), _, 'collection of length one with no initial value returns the first item'); assert.equal(_.reduce([], _.noop), void 0, 'returns undefined when collection is empty and no initial value'); @@ -212,7 +212,7 @@ var sum = _.reduceRight({a: 1, b: 2, c: 3}, function(memo, num){ return memo + num; }); assert.equal(sum, 6, 'default initial value on object'); - assert.ok(_.reduceRight(null, _.noop, 138) === 138, 'handles a null (with initial value) properly'); + assert.strictEqual(_.reduceRight(null, _.noop, 138), 138, 'handles a null (with initial value) properly'); assert.equal(_.reduceRight([_], _.noop), _, 'collection of length one with no initial value returns the first item'); assert.equal(_.reduceRight([], _.noop, void 0), void 0, 'undefined can be passed as a special case'); @@ -351,8 +351,8 @@ assert.ok(!_.every([true, false, true], _.identity), 'one false value'); assert.ok(_.every([0, 10, 28], function(num){ return num % 2 === 0; }), 'even numbers'); assert.ok(!_.every([0, 11, 28], function(num){ return num % 2 === 0; }), 'an odd number'); - assert.ok(_.every([1], _.identity) === true, 'cast to boolean - true'); - assert.ok(_.every([0], _.identity) === false, 'cast to boolean - false'); + assert.strictEqual(_.every([1], _.identity), true, 'cast to boolean - true'); + assert.strictEqual(_.every([0], _.identity), false, 'cast to boolean - false'); assert.ok(!_.every([void 0, void 0, void 0], _.identity), 'works with arrays of undefined'); var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; @@ -381,8 +381,8 @@ assert.ok(!_.some([null, 0, '', false]), 'falsy values'); assert.ok(!_.some([1, 11, 29], function(num){ return num % 2 === 0; }), 'all odd numbers'); assert.ok(_.some([1, 10, 29], function(num){ return num % 2 === 0; }), 'an even number'); - assert.ok(_.some([1], _.identity) === true, 'cast to boolean - true'); - assert.ok(_.some([0], _.identity) === false, 'cast to boolean - false'); + assert.strictEqual(_.some([1], _.identity), true, 'cast to boolean - true'); + assert.strictEqual(_.some([0], _.identity), false, 'cast to boolean - false'); assert.ok(_.some([false, false, true])); var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; @@ -412,7 +412,7 @@ assert.strictEqual(_.includes([5, 4, 3, 2, 1], 5, true), true, 'doesn\'t delegate to binary search'); - assert.ok(_.includes({moe: 1, larry: 3, curly: 9}, 3) === true, '_.includes on objects checks their values'); + assert.strictEqual(_.includes({moe: 1, larry: 3, curly: 9}, 3), true, '_.includes on objects checks their values'); assert.ok(_([1, 2, 3]).includes(2), 'OO-style includes'); var numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3]; @@ -692,7 +692,7 @@ assert.deepEqual(grouped['5'], ['three', 'seven', 'eight']); var context = {}; - _.groupBy([{}], function(){ assert.ok(this === context); }, context); + _.groupBy([{}], function(){ assert.strictEqual(this, context); }, context); grouped = _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; @@ -701,7 +701,7 @@ assert.equal(grouped.hasOwnProperty.length, 2); var array = [{}]; - _.groupBy(array, function(value, index, obj){ assert.ok(obj === array); }); + _.groupBy(array, function(value, index, obj){ assert.strictEqual(obj, array); }); array = [1, 2, 1, 2, 3]; grouped = _.groupBy(array); @@ -747,7 +747,7 @@ assert.equal(grouped['5'], 3); var context = {}; - _.countBy([{}], function(){ assert.ok(this === context); }, context); + _.countBy([{}], function(){ assert.strictEqual(this, context); }, context); grouped = _.countBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; @@ -756,7 +756,7 @@ assert.equal(grouped.hasOwnProperty, 2); var array = [{}]; - _.countBy(array, function(value, index, obj){ assert.ok(obj === array); }); + _.countBy(array, function(value, index, obj){ assert.strictEqual(obj, array); }); array = [1, 2, 1, 2, 3]; grouped = _.countBy(array); @@ -800,7 +800,7 @@ assert.ok(!_.isArray(arguments), 'arguments object is not an array'); assert.ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array'); var a = [1, 2, 3]; - assert.ok(_.toArray(a) !== a, 'array is cloned'); + assert.notStrictEqual(_.toArray(a), a, 'array is cloned'); assert.deepEqual(_.toArray(a), [1, 2, 3], 'cloned array contains same elements'); var numbers = _.toArray({one: 1, two: 2, three: 3}); diff --git a/test/objects.js b/test/objects.js index fa1d9e3e3..059a9b28c 100644 --- a/test/objects.js +++ b/test/objects.js @@ -958,8 +958,8 @@ assert.equal(_.matcher({})(null), true, 'Empty spec called with null object returns true'); assert.equal(_.matcher({a: 1})(null), false, 'Non-empty spec called with null object returns false'); - assert.ok(_.find(stooges, _.matcher({hair: false})) === curly, 'returns a predicate that can be used by finding functions.'); - assert.ok(_.find(stooges, _.matcher(moe)) === moe, 'can be used to locate an object exists in a collection.'); + assert.strictEqual(_.find(stooges, _.matcher({hair: false})), curly, 'returns a predicate that can be used by finding functions.'); + assert.strictEqual(_.find(stooges, _.matcher(moe)), moe, 'can be used to locate an object exists in a collection.'); assert.deepEqual(_.filter([null, void 0], _.matcher({a: 1})), [], 'Do not throw on null values.'); assert.deepEqual(_.filter([null, void 0], _.matcher(null)), [null, void 0], 'null matches null'); diff --git a/test/utility.js b/test/utility.js index fbd54df31..60d387597 100644 --- a/test/utility.js +++ b/test/utility.js @@ -52,8 +52,8 @@ QUnit.test('#750 - Return _ instance.', function(assert) { assert.expect(2); var instance = _([]); - assert.ok(_(instance) === instance); - assert.ok(new _(instance) === instance); + assert.strictEqual(_(instance), instance); + assert.strictEqual(new _(instance), instance); }); QUnit.test('identity', function(assert) { @@ -188,7 +188,7 @@ var str = 'some string & another string & yet another'; var escaped = _.escape(str); - assert.ok(escaped.indexOf('&') !== -1, 'handles & aka &'); + assert.notStrictEqual(escaped.indexOf('&'), -1, 'handles & aka &'); assert.equal(_.unescape(str), str, 'can unescape &'); }); From cc1cb526bc8d6d9d0e9ef6c6b2b3b0905cffe04e Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Sun, 3 Apr 2016 21:58:52 -0700 Subject: [PATCH 046/498] Prefer `assert.notOk()` to `assert.ok(!)` In #2389 we upgraded our browser tests to QUnit 1.18.0 which means we can now use the `assert.notOk()` assertion. Using this gives a less confusing error message when the assertion fails. Assuming my `shouldBeFalse()` function is failing: assert.ok(!shouldBeFalse()); => failed, expected argument to be truthy, was: false assert.notOk(shouldBeFalse()); => failed, expected argument to be falsy, was: true --- test/collections.js | 40 +++--- test/cross-document.js | 20 +-- test/functions.js | 2 +- test/objects.js | 316 ++++++++++++++++++++--------------------- test/utility.js | 8 +- 5 files changed, 193 insertions(+), 193 deletions(-) diff --git a/test/collections.js b/test/collections.js index 320f323d0..76ed98c94 100644 --- a/test/collections.js +++ b/test/collections.js @@ -268,8 +268,8 @@ var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 4}]; assert.deepEqual(_.find(list, {a: 1}), {a: 1, b: 2}, 'can be used as findWhere'); assert.deepEqual(_.find(list, {b: 4}), {a: 1, b: 4}); - assert.ok(!_.find(list, {c: 1}), 'undefined when not found'); - assert.ok(!_.find([], {c: 1}), 'undefined when searching empty list'); + assert.notOk(_.find(list, {c: 1}), 'undefined when not found'); + assert.notOk(_.find([], {c: 1}), 'undefined when searching empty list'); var result = _.find([1, 2, 3], function(num){ return num * 2 === 4; }); assert.equal(result, 2, 'found the first "2" and broke the loop'); @@ -348,25 +348,25 @@ QUnit.test('every', function(assert) { assert.ok(_.every([], _.identity), 'the empty set'); assert.ok(_.every([true, true, true], _.identity), 'every true values'); - assert.ok(!_.every([true, false, true], _.identity), 'one false value'); + assert.notOk(_.every([true, false, true], _.identity), 'one false value'); assert.ok(_.every([0, 10, 28], function(num){ return num % 2 === 0; }), 'even numbers'); - assert.ok(!_.every([0, 11, 28], function(num){ return num % 2 === 0; }), 'an odd number'); + assert.notOk(_.every([0, 11, 28], function(num){ return num % 2 === 0; }), 'an odd number'); assert.strictEqual(_.every([1], _.identity), true, 'cast to boolean - true'); assert.strictEqual(_.every([0], _.identity), false, 'cast to boolean - false'); - assert.ok(!_.every([void 0, void 0, void 0], _.identity), 'works with arrays of undefined'); + assert.notOk(_.every([void 0, void 0, void 0], _.identity), 'works with arrays of undefined'); var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; - assert.ok(!_.every(list, {a: 1, b: 2}), 'Can be called with object'); + assert.notOk(_.every(list, {a: 1, b: 2}), 'Can be called with object'); assert.ok(_.every(list, 'a'), 'String mapped to object property'); list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}]; assert.ok(_.every(list, {b: 2}), 'Can be called with object'); - assert.ok(!_.every(list, 'c'), 'String mapped to object property'); + assert.notOk(_.every(list, 'c'), 'String mapped to object property'); assert.ok(_.every({a: 1, b: 2, c: 3, d: 4}, _.isNumber), 'takes objects'); - assert.ok(!_.every({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); + assert.notOk(_.every({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); assert.ok(_.every(['a', 'b', 'c', 'd'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); - assert.ok(!_.every(['a', 'b', 'c', 'd', 'f'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); + assert.notOk(_.every(['a', 'b', 'c', 'd', 'f'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); }); QUnit.test('all', function(assert) { @@ -374,29 +374,29 @@ }); QUnit.test('some', function(assert) { - assert.ok(!_.some([]), 'the empty set'); - assert.ok(!_.some([false, false, false]), 'all false values'); + assert.notOk(_.some([]), 'the empty set'); + assert.notOk(_.some([false, false, false]), 'all false values'); assert.ok(_.some([false, false, true]), 'one true value'); assert.ok(_.some([null, 0, 'yes', false]), 'a string'); - assert.ok(!_.some([null, 0, '', false]), 'falsy values'); - assert.ok(!_.some([1, 11, 29], function(num){ return num % 2 === 0; }), 'all odd numbers'); + assert.notOk(_.some([null, 0, '', false]), 'falsy values'); + assert.notOk(_.some([1, 11, 29], function(num){ return num % 2 === 0; }), 'all odd numbers'); assert.ok(_.some([1, 10, 29], function(num){ return num % 2 === 0; }), 'an even number'); assert.strictEqual(_.some([1], _.identity), true, 'cast to boolean - true'); assert.strictEqual(_.some([0], _.identity), false, 'cast to boolean - false'); assert.ok(_.some([false, false, true])); var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; - assert.ok(!_.some(list, {a: 5, b: 2}), 'Can be called with object'); + assert.notOk(_.some(list, {a: 5, b: 2}), 'Can be called with object'); assert.ok(_.some(list, 'a'), 'String mapped to object property'); list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}]; assert.ok(_.some(list, {b: 2}), 'Can be called with object'); - assert.ok(!_.some(list, 'd'), 'String mapped to object property'); + assert.notOk(_.some(list, 'd'), 'String mapped to object property'); assert.ok(_.some({a: '1', b: '2', c: '3', d: '4', e: 6}, _.isNumber), 'takes objects'); - assert.ok(!_.some({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); + assert.notOk(_.some({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); assert.ok(_.some(['a', 'b', 'c', 'd'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); - assert.ok(!_.some(['x', 'y', 'z'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); + assert.notOk(_.some(['x', 'y', 'z'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); }); QUnit.test('any', function(assert) { @@ -408,7 +408,7 @@ assert.strictEqual(_.includes(val, 'hasOwnProperty'), false); }); assert.strictEqual(_.includes([1, 2, 3], 2), true, 'two is in the array'); - assert.ok(!_.includes([1, 3, 9], 2), 'two is not in the array'); + assert.notOk(_.includes([1, 3, 9], 2), 'two is not in the array'); assert.strictEqual(_.includes([5, 4, 3, 2, 1], 5, true), true, 'doesn\'t delegate to binary search'); @@ -797,7 +797,7 @@ }); QUnit.test('toArray', function(assert) { - assert.ok(!_.isArray(arguments), 'arguments object is not an array'); + assert.notOk(_.isArray(arguments), 'arguments object is not an array'); assert.ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array'); var a = [1, 2, 3]; assert.notStrictEqual(_.toArray(a), a, 'array is cloned'); @@ -882,7 +882,7 @@ assert.deepEqual(_.map(elementChildren, 'id'), ['id1', 'id2']); assert.deepEqual(_.map(parent.childNodes, 'nodeType'), [1, 3, 1]); - assert.ok(!_.every(parent.childNodes, _.isElement)); + assert.notOk(_.every(parent.childNodes, _.isElement)); assert.ok(_.some(parent.childNodes, _.isElement)); function compareNode(node) { diff --git a/test/cross-document.js b/test/cross-document.js index cb68a3d9b..bc3ab77f1 100644 --- a/test/cross-document.js +++ b/test/cross-document.js @@ -35,7 +35,7 @@ QUnit.test('isEqual', function(assert) { - assert.ok(!_.isEqual(iNumber, 101)); + assert.notOk(_.isEqual(iNumber, 101)); assert.ok(_.isEqual(iNumber, 100)); // Objects from another frame. @@ -46,13 +46,13 @@ }); QUnit.test('isEmpty', function(assert) { - assert.ok(!_([iNumber]).isEmpty(), '[1] is not empty'); - assert.ok(!_.isEmpty(iArray), '[] is empty'); + assert.notOk(_([iNumber]).isEmpty(), '[1] is not empty'); + assert.notOk(_.isEmpty(iArray), '[] is empty'); assert.ok(_.isEmpty(iObject), '{} is empty'); }); QUnit.test('isElement', function(assert) { - assert.ok(!_.isElement('div'), 'strings are not dom elements'); + assert.notOk(_.isElement('div'), 'strings are not dom elements'); assert.ok(_.isElement(document.body), 'the body tag is a DOM element'); assert.ok(_.isElement(iElement), 'even from another frame'); }); @@ -113,12 +113,12 @@ if (typeof ActiveXObject != 'undefined') { QUnit.test('IE host objects', function(assert) { var xml = new ActiveXObject('Msxml2.DOMDocument.3.0'); - assert.ok(!_.isNumber(xml)); - assert.ok(!_.isBoolean(xml)); - assert.ok(!_.isNaN(xml)); - assert.ok(!_.isFunction(xml)); - assert.ok(!_.isNull(xml)); - assert.ok(!_.isUndefined(xml)); + assert.notOk(_.isNumber(xml)); + assert.notOk(_.isBoolean(xml)); + assert.notOk(_.isNaN(xml)); + assert.notOk(_.isFunction(xml)); + assert.notOk(_.isNull(xml)); + assert.notOk(_.isUndefined(xml)); }); QUnit.test('#1621 IE 11 compat mode DOM elements are not functions', function(assert) { diff --git a/test/functions.js b/test/functions.js index e31d1d355..f73f5d382 100644 --- a/test/functions.js +++ b/test/functions.js @@ -180,7 +180,7 @@ var done = assert.async(); var delayed = false; _.delay(function(){ delayed = true; }, 100); - setTimeout(function(){ assert.ok(!delayed, "didn't delay the function quite yet"); }, 50); + setTimeout(function(){ assert.notOk(delayed, "didn't delay the function quite yet"); }, 50); setTimeout(function(){ assert.ok(delayed, 'delayed the function'); done(); }, 150); }); diff --git a/test/objects.js b/test/objects.js index 059a9b28c..91c49a4cc 100644 --- a/test/objects.js +++ b/test/objects.js @@ -123,7 +123,7 @@ subObj.c = 'd'; assert.deepEqual(_.extend({}, subObj), {a: 'b', c: 'd'}, 'extend copies all properties from source'); _.extend(subObj, {}); - assert.ok(!subObj.hasOwnProperty('a'), "extend does not convert destination object's 'in' properties to 'own' properties"); + assert.notOk(subObj.hasOwnProperty('a'), "extend does not convert destination object's 'in' properties to 'own' properties"); try { result = {}; @@ -205,7 +205,7 @@ return this[key] === 3 && this === instance; }, instance), {c: 3}, 'function is given context'); - assert.ok(!_.has(_.pick({}, 'foo'), 'foo'), 'does not set own property if property not in object'); + assert.notOk(_.has(_.pick({}, 'foo'), 'foo'), 'does not set own property if property not in object'); _.pick(data, function(value, key, obj) { assert.equal(obj, data, 'passes same object as third parameter of iteratee'); }); @@ -309,7 +309,7 @@ Child.prototype.foo = 'foo'; var created = _.create(Child.prototype, new Child); - assert.ok(!created.hasOwnProperty('foo'), 'should only add own properties'); + assert.notOk(created.hasOwnProperty('foo'), 'should only add own properties'); }); QUnit.test('isEqual', function(assert) { @@ -326,10 +326,10 @@ assert.ok(_.isEqual(null, null), '`null` is equal to `null`'); assert.ok(_.isEqual(), '`undefined` is equal to `undefined`'); - assert.ok(!_.isEqual(0, -0), '`0` is not equal to `-0`'); - assert.ok(!_.isEqual(-0, 0), 'Commutative equality is implemented for `0` and `-0`'); - assert.ok(!_.isEqual(null, void 0), '`null` is not equal to `undefined`'); - assert.ok(!_.isEqual(void 0, null), 'Commutative equality is implemented for `null` and `undefined`'); + assert.notOk(_.isEqual(0, -0), '`0` is not equal to `-0`'); + assert.notOk(_.isEqual(-0, 0), 'Commutative equality is implemented for `0` and `-0`'); + assert.notOk(_.isEqual(null, void 0), '`null` is not equal to `undefined`'); + assert.notOk(_.isEqual(void 0, null), 'Commutative equality is implemented for `null` and `undefined`'); // String object and primitive comparisons. assert.ok(_.isEqual('Curly', 'Curly'), 'Identical string primitives are equal'); @@ -337,76 +337,76 @@ assert.ok(_.isEqual(new String('Curly'), 'Curly'), 'String primitives and their corresponding object wrappers are equal'); assert.ok(_.isEqual('Curly', new String('Curly')), 'Commutative equality is implemented for string objects and primitives'); - assert.ok(!_.isEqual('Curly', 'Larry'), 'String primitives with different values are not equal'); - assert.ok(!_.isEqual(new String('Curly'), new String('Larry')), 'String objects with different primitive values are not equal'); - assert.ok(!_.isEqual(new String('Curly'), {toString: function(){ return 'Curly'; }}), 'String objects and objects with a custom `toString` method are not equal'); + assert.notOk(_.isEqual('Curly', 'Larry'), 'String primitives with different values are not equal'); + assert.notOk(_.isEqual(new String('Curly'), new String('Larry')), 'String objects with different primitive values are not equal'); + assert.notOk(_.isEqual(new String('Curly'), {toString: function(){ return 'Curly'; }}), 'String objects and objects with a custom `toString` method are not equal'); // Number object and primitive comparisons. assert.ok(_.isEqual(75, 75), 'Identical number primitives are equal'); assert.ok(_.isEqual(new Number(75), new Number(75)), 'Number objects with identical primitive values are equal'); assert.ok(_.isEqual(75, new Number(75)), 'Number primitives and their corresponding object wrappers are equal'); assert.ok(_.isEqual(new Number(75), 75), 'Commutative equality is implemented for number objects and primitives'); - assert.ok(!_.isEqual(new Number(0), -0), '`new Number(0)` and `-0` are not equal'); - assert.ok(!_.isEqual(0, new Number(-0)), 'Commutative equality is implemented for `new Number(0)` and `-0`'); + assert.notOk(_.isEqual(new Number(0), -0), '`new Number(0)` and `-0` are not equal'); + assert.notOk(_.isEqual(0, new Number(-0)), 'Commutative equality is implemented for `new Number(0)` and `-0`'); - assert.ok(!_.isEqual(new Number(75), new Number(63)), 'Number objects with different primitive values are not equal'); - assert.ok(!_.isEqual(new Number(63), {valueOf: function(){ return 63; }}), 'Number objects and objects with a `valueOf` method are not equal'); + assert.notOk(_.isEqual(new Number(75), new Number(63)), 'Number objects with different primitive values are not equal'); + assert.notOk(_.isEqual(new Number(63), {valueOf: function(){ return 63; }}), 'Number objects and objects with a `valueOf` method are not equal'); // Comparisons involving `NaN`. assert.ok(_.isEqual(NaN, NaN), '`NaN` is equal to `NaN`'); assert.ok(_.isEqual(new Number(NaN), NaN), 'Object(`NaN`) is equal to `NaN`'); - assert.ok(!_.isEqual(61, NaN), 'A number primitive is not equal to `NaN`'); - assert.ok(!_.isEqual(new Number(79), NaN), 'A number object is not equal to `NaN`'); - assert.ok(!_.isEqual(Infinity, NaN), '`Infinity` is not equal to `NaN`'); + assert.notOk(_.isEqual(61, NaN), 'A number primitive is not equal to `NaN`'); + assert.notOk(_.isEqual(new Number(79), NaN), 'A number object is not equal to `NaN`'); + assert.notOk(_.isEqual(Infinity, NaN), '`Infinity` is not equal to `NaN`'); // Boolean object and primitive comparisons. assert.ok(_.isEqual(true, true), 'Identical boolean primitives are equal'); assert.ok(_.isEqual(new Boolean, new Boolean), 'Boolean objects with identical primitive values are equal'); assert.ok(_.isEqual(true, new Boolean(true)), 'Boolean primitives and their corresponding object wrappers are equal'); assert.ok(_.isEqual(new Boolean(true), true), 'Commutative equality is implemented for booleans'); - assert.ok(!_.isEqual(new Boolean(true), new Boolean), 'Boolean objects with different primitive values are not equal'); + assert.notOk(_.isEqual(new Boolean(true), new Boolean), 'Boolean objects with different primitive values are not equal'); // Common type coercions. - assert.ok(!_.isEqual(new Boolean(false), true), '`new Boolean(false)` is not equal to `true`'); - assert.ok(!_.isEqual('75', 75), 'String and number primitives with like values are not equal'); - assert.ok(!_.isEqual(new Number(63), new String(63)), 'String and number objects with like values are not equal'); - assert.ok(!_.isEqual(75, '75'), 'Commutative equality is implemented for like string and number values'); - assert.ok(!_.isEqual(0, ''), 'Number and string primitives with like values are not equal'); - assert.ok(!_.isEqual(1, true), 'Number and boolean primitives with like values are not equal'); - assert.ok(!_.isEqual(new Boolean(false), new Number(0)), 'Boolean and number objects with like values are not equal'); - assert.ok(!_.isEqual(false, new String('')), 'Boolean primitives and string objects with like values are not equal'); - assert.ok(!_.isEqual(12564504e5, new Date(2009, 9, 25)), 'Dates and their corresponding numeric primitive values are not equal'); + assert.notOk(_.isEqual(new Boolean(false), true), '`new Boolean(false)` is not equal to `true`'); + assert.notOk(_.isEqual('75', 75), 'String and number primitives with like values are not equal'); + assert.notOk(_.isEqual(new Number(63), new String(63)), 'String and number objects with like values are not equal'); + assert.notOk(_.isEqual(75, '75'), 'Commutative equality is implemented for like string and number values'); + assert.notOk(_.isEqual(0, ''), 'Number and string primitives with like values are not equal'); + assert.notOk(_.isEqual(1, true), 'Number and boolean primitives with like values are not equal'); + assert.notOk(_.isEqual(new Boolean(false), new Number(0)), 'Boolean and number objects with like values are not equal'); + assert.notOk(_.isEqual(false, new String('')), 'Boolean primitives and string objects with like values are not equal'); + assert.notOk(_.isEqual(12564504e5, new Date(2009, 9, 25)), 'Dates and their corresponding numeric primitive values are not equal'); // Dates. assert.ok(_.isEqual(new Date(2009, 9, 25), new Date(2009, 9, 25)), 'Date objects referencing identical times are equal'); - assert.ok(!_.isEqual(new Date(2009, 9, 25), new Date(2009, 11, 13)), 'Date objects referencing different times are not equal'); - assert.ok(!_.isEqual(new Date(2009, 11, 13), { + assert.notOk(_.isEqual(new Date(2009, 9, 25), new Date(2009, 11, 13)), 'Date objects referencing different times are not equal'); + assert.notOk(_.isEqual(new Date(2009, 11, 13), { getTime: function(){ return 12606876e5; } }), 'Date objects and objects with a `getTime` method are not equal'); - assert.ok(!_.isEqual(new Date('Curly'), new Date('Curly')), 'Invalid dates are not equal'); + assert.notOk(_.isEqual(new Date('Curly'), new Date('Curly')), 'Invalid dates are not equal'); // Functions. - assert.ok(!_.isEqual(First, Second), 'Different functions with identical bodies and source code representations are not equal'); + assert.notOk(_.isEqual(First, Second), 'Different functions with identical bodies and source code representations are not equal'); // RegExps. assert.ok(_.isEqual(/(?:)/gim, /(?:)/gim), 'RegExps with equivalent patterns and flags are equal'); assert.ok(_.isEqual(/(?:)/gi, /(?:)/ig), 'Flag order is not significant'); - assert.ok(!_.isEqual(/(?:)/g, /(?:)/gi), 'RegExps with equivalent patterns and different flags are not equal'); - assert.ok(!_.isEqual(/Moe/gim, /Curly/gim), 'RegExps with different patterns and equivalent flags are not equal'); - assert.ok(!_.isEqual(/(?:)/gi, /(?:)/g), 'Commutative equality is implemented for RegExps'); - assert.ok(!_.isEqual(/Curly/g, {source: 'Larry', global: true, ignoreCase: false, multiline: false}), 'RegExps and RegExp-like objects are not equal'); + assert.notOk(_.isEqual(/(?:)/g, /(?:)/gi), 'RegExps with equivalent patterns and different flags are not equal'); + assert.notOk(_.isEqual(/Moe/gim, /Curly/gim), 'RegExps with different patterns and equivalent flags are not equal'); + assert.notOk(_.isEqual(/(?:)/gi, /(?:)/g), 'Commutative equality is implemented for RegExps'); + assert.notOk(_.isEqual(/Curly/g, {source: 'Larry', global: true, ignoreCase: false, multiline: false}), 'RegExps and RegExp-like objects are not equal'); // Empty arrays, array-like objects, and object literals. assert.ok(_.isEqual({}, {}), 'Empty object literals are equal'); assert.ok(_.isEqual([], []), 'Empty array literals are equal'); assert.ok(_.isEqual([{}], [{}]), 'Empty nested arrays and objects are equal'); - assert.ok(!_.isEqual({length: 0}, []), 'Array-like objects and arrays are not equal.'); - assert.ok(!_.isEqual([], {length: 0}), 'Commutative equality is implemented for array-like objects'); + assert.notOk(_.isEqual({length: 0}, []), 'Array-like objects and arrays are not equal.'); + assert.notOk(_.isEqual([], {length: 0}), 'Commutative equality is implemented for array-like objects'); - assert.ok(!_.isEqual({}, []), 'Object literals and array literals are not equal'); - assert.ok(!_.isEqual([], {}), 'Commutative equality is implemented for objects and arrays'); + assert.notOk(_.isEqual({}, []), 'Object literals and array literals are not equal'); + assert.notOk(_.isEqual([], {}), 'Commutative equality is implemented for objects and arrays'); // Arrays with primitive and object values. assert.ok(_.isEqual([1, 'Larry', true], [1, 'Larry', true]), 'Arrays containing identical primitives are equal'); @@ -424,14 +424,14 @@ // Array elements and properties. assert.ok(_.isEqual(a, b), 'Arrays containing equivalent elements and different non-numeric properties are equal'); a.push('White Rocks'); - assert.ok(!_.isEqual(a, b), 'Arrays of different lengths are not equal'); + assert.notOk(_.isEqual(a, b), 'Arrays of different lengths are not equal'); a.push('East Boulder'); b.push('Gunbarrel Ranch', 'Teller Farm'); - assert.ok(!_.isEqual(a, b), 'Arrays of identical lengths containing different elements are not equal'); + assert.notOk(_.isEqual(a, b), 'Arrays of identical lengths containing different elements are not equal'); // Sparse arrays. assert.ok(_.isEqual(Array(3), Array(3)), 'Sparse arrays of identical lengths are equal'); - assert.ok(!_.isEqual(Array(3), Array(6)), 'Sparse arrays of different lengths are not equal when both are empty'); + assert.notOk(_.isEqual(Array(3), Array(6)), 'Sparse arrays of different lengths are not equal when both are empty'); var sparse = []; sparse[1] = 5; @@ -440,11 +440,11 @@ // Simple objects. assert.ok(_.isEqual({a: 'Curly', b: 1, c: true}, {a: 'Curly', b: 1, c: true}), 'Objects containing identical primitives are equal'); assert.ok(_.isEqual({a: /Curly/g, b: new Date(2009, 11, 13)}, {a: /Curly/g, b: new Date(2009, 11, 13)}), 'Objects containing equivalent members are equal'); - assert.ok(!_.isEqual({a: 63, b: 75}, {a: 61, b: 55}), 'Objects of identical sizes with different values are not equal'); - assert.ok(!_.isEqual({a: 63, b: 75}, {a: 61, c: 55}), 'Objects of identical sizes with different property names are not equal'); - assert.ok(!_.isEqual({a: 1, b: 2}, {a: 1}), 'Objects of different sizes are not equal'); - assert.ok(!_.isEqual({a: 1}, {a: 1, b: 2}), 'Commutative equality is implemented for objects'); - assert.ok(!_.isEqual({x: 1, y: void 0}, {x: 1, z: 2}), 'Objects with identical keys and different values are not equivalent'); + assert.notOk(_.isEqual({a: 63, b: 75}, {a: 61, b: 55}), 'Objects of identical sizes with different values are not equal'); + assert.notOk(_.isEqual({a: 63, b: 75}, {a: 61, c: 55}), 'Objects of identical sizes with different property names are not equal'); + assert.notOk(_.isEqual({a: 1, b: 2}, {a: 1}), 'Objects of different sizes are not equal'); + assert.notOk(_.isEqual({a: 1}, {a: 1, b: 2}), 'Commutative equality is implemented for objects'); + assert.notOk(_.isEqual({x: 1, y: void 0}, {x: 1, z: 2}), 'Objects with identical keys and different values are not equivalent'); // `A` contains nested objects and arrays. a = { @@ -479,9 +479,9 @@ // Instances. assert.ok(_.isEqual(new First, new First), 'Object instances are equal'); - assert.ok(!_.isEqual(new First, new Second), 'Objects with different constructors and identical own properties are not equal'); - assert.ok(!_.isEqual({value: 1}, new First), 'Object instances and objects sharing equivalent properties are not equal'); - assert.ok(!_.isEqual({value: 2}, new Second), 'The prototype chain of objects should not be examined'); + assert.notOk(_.isEqual(new First, new Second), 'Objects with different constructors and identical own properties are not equal'); + assert.notOk(_.isEqual({value: 1}, new First), 'Object instances and objects sharing equivalent properties are not equal'); + assert.notOk(_.isEqual({value: 2}, new Second), 'The prototype chain of objects should not be examined'); // Circular Arrays. (a = []).push(a); @@ -492,13 +492,13 @@ assert.ok(_.isEqual(a, b), 'Arrays containing circular references and equivalent properties are equal'); a.push('Shemp'); b.push('Curly'); - assert.ok(!_.isEqual(a, b), 'Arrays containing circular references and different properties are not equal'); + assert.notOk(_.isEqual(a, b), 'Arrays containing circular references and different properties are not equal'); // More circular arrays #767. a = ['everything is checked but', 'this', 'is not']; a[1] = a; b = ['everything is checked but', ['this', 'array'], 'is not']; - assert.ok(!_.isEqual(a, b), 'Comparison of circular references with non-circular references are not equal'); + assert.notOk(_.isEqual(a, b), 'Comparison of circular references with non-circular references are not equal'); // Circular Objects. a = {abc: null}; @@ -511,13 +511,13 @@ assert.ok(_.isEqual(a, b), 'Objects containing circular references and equivalent properties are equal'); a.def = new Number(75); b.def = new Number(63); - assert.ok(!_.isEqual(a, b), 'Objects containing circular references and different properties are not equal'); + assert.notOk(_.isEqual(a, b), 'Objects containing circular references and different properties are not equal'); // More circular objects #767. a = {everything: 'is checked', but: 'this', is: 'not'}; a.but = a; b = {everything: 'is checked', but: {that: 'object'}, is: 'not'}; - assert.ok(!_.isEqual(a, b), 'Comparison of circular references with non-circular object references are not equal'); + assert.notOk(_.isEqual(a, b), 'Comparison of circular references with non-circular object references are not equal'); // Cyclic Structures. a = [{abc: null}]; @@ -530,7 +530,7 @@ assert.ok(_.isEqual(a, b), 'Cyclic structures containing equivalent properties are equal'); a[0].def = new String('Larry'); b[0].def = new String('Curly'); - assert.ok(!_.isEqual(a, b), 'Cyclic structures containing different properties are not equal'); + assert.notOk(_.isEqual(a, b), 'Cyclic structures containing different properties are not equal'); // Complex Circular References. a = {foo: {b: {foo: {c: {foo: null}}}}}; @@ -540,7 +540,7 @@ assert.ok(_.isEqual(a, b), 'Cyclic structures with nested and identically-named properties are equal'); // Chaining. - assert.ok(!_.isEqual(_({x: 1, y: void 0}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal'); + assert.notOk(_.isEqual(_({x: 1, y: void 0}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal'); a = _({x: 1, y: 2}).chain(); b = _({x: 1, y: 2}).chain(); @@ -576,15 +576,15 @@ }); QUnit.test('isEmpty', function(assert) { - assert.ok(!_([1]).isEmpty(), '[1] is not empty'); + assert.notOk(_([1]).isEmpty(), '[1] is not empty'); assert.ok(_.isEmpty([]), '[] is empty'); - assert.ok(!_.isEmpty({one: 1}), '{one: 1} is not empty'); + assert.notOk(_.isEmpty({one: 1}), '{one: 1} is not empty'); assert.ok(_.isEmpty({}), '{} is empty'); assert.ok(_.isEmpty(new RegExp('')), 'objects with prototype properties are empty'); assert.ok(_.isEmpty(null), 'null is empty'); assert.ok(_.isEmpty(), 'undefined is empty'); assert.ok(_.isEmpty(''), 'the empty string is empty'); - assert.ok(!_.isEmpty('moe'), 'but other strings are not'); + assert.notOk(_.isEmpty('moe'), 'but other strings are not'); var obj = {one: 1}; delete obj.one; @@ -592,27 +592,27 @@ var args = function(){ return arguments; }; assert.ok(_.isEmpty(args()), 'empty arguments object is empty'); - assert.ok(!_.isEmpty(args('')), 'non-empty arguments object is not empty'); + assert.notOk(_.isEmpty(args('')), 'non-empty arguments object is not empty'); // covers collecting non-enumerable properties in IE < 9 var nonEnumProp = {toString: 5}; - assert.ok(!_.isEmpty(nonEnumProp), 'non-enumerable property is not empty'); + assert.notOk(_.isEmpty(nonEnumProp), 'non-enumerable property is not empty'); }); if (typeof document === 'object') { QUnit.test('isElement', function(assert) { - assert.ok(!_.isElement('div'), 'strings are not dom elements'); + assert.notOk(_.isElement('div'), 'strings are not dom elements'); assert.ok(_.isElement(testElement), 'an element is a DOM element'); }); } QUnit.test('isArguments', function(assert) { var args = (function(){ return arguments; }(1, 2, 3)); - assert.ok(!_.isArguments('string'), 'a string is not an arguments object'); - assert.ok(!_.isArguments(_.isArguments), 'a function is not an arguments object'); + assert.notOk(_.isArguments('string'), 'a string is not an arguments object'); + assert.notOk(_.isArguments(_.isArguments), 'a function is not an arguments object'); assert.ok(_.isArguments(args), 'but the arguments object is an arguments object'); - assert.ok(!_.isArguments(_.toArray(args)), 'but not when it\'s converted into an array'); - assert.ok(!_.isArguments([1, 2, 3]), 'and not vanilla arrays.'); + assert.notOk(_.isArguments(_.toArray(args)), 'but not when it\'s converted into an array'); + assert.notOk(_.isArguments([1, 2, 3]), 'and not vanilla arrays.'); }); QUnit.test('isObject', function(assert) { @@ -622,24 +622,24 @@ assert.ok(_.isObject(testElement), 'and DOM element'); } assert.ok(_.isObject(function() {}), 'and functions'); - assert.ok(!_.isObject(null), 'but not null'); - assert.ok(!_.isObject(void 0), 'and not undefined'); - assert.ok(!_.isObject('string'), 'and not string'); - assert.ok(!_.isObject(12), 'and not number'); - assert.ok(!_.isObject(true), 'and not boolean'); + assert.notOk(_.isObject(null), 'but not null'); + assert.notOk(_.isObject(void 0), 'and not undefined'); + assert.notOk(_.isObject('string'), 'and not string'); + assert.notOk(_.isObject(12), 'and not number'); + assert.notOk(_.isObject(true), 'and not boolean'); assert.ok(_.isObject(new String('string')), 'but new String()'); }); QUnit.test('isArray', function(assert) { - assert.ok(!_.isArray(void 0), 'undefined vars are not arrays'); - assert.ok(!_.isArray(arguments), 'the arguments object is not an array'); + assert.notOk(_.isArray(void 0), 'undefined vars are not arrays'); + assert.notOk(_.isArray(arguments), 'the arguments object is not an array'); assert.ok(_.isArray([1, 2, 3]), 'but arrays are'); }); QUnit.test('isString', function(assert) { var obj = new String('I am a string object'); if (testElement) { - assert.ok(!_.isString(testElement), 'an element is not a string'); + assert.notOk(_.isString(testElement), 'an element is not a string'); } assert.ok(_.isString([1, 2, 3].join(', ')), 'but strings are'); assert.strictEqual(_.isString('I am a string literal'), true, 'string literals are'); @@ -648,9 +648,9 @@ }); QUnit.test('isSymbol', function(assert) { - assert.ok(!_.isSymbol(0), 'numbers are not symbols'); - assert.ok(!_.isSymbol(''), 'strings are not symbols'); - assert.ok(!_.isSymbol(_.isSymbol), 'functions are not symbols'); + assert.notOk(_.isSymbol(0), 'numbers are not symbols'); + assert.notOk(_.isSymbol(''), 'strings are not symbols'); + assert.notOk(_.isSymbol(_.isSymbol), 'functions are not symbols'); if (typeof Symbol === 'function') { assert.ok(_.isSymbol(Symbol()), 'symbols are symbols'); assert.ok(_.isSymbol(Symbol('description')), 'described symbols are symbols'); @@ -659,43 +659,43 @@ }); QUnit.test('isNumber', function(assert) { - assert.ok(!_.isNumber('string'), 'a string is not a number'); - assert.ok(!_.isNumber(arguments), 'the arguments object is not a number'); - assert.ok(!_.isNumber(void 0), 'undefined is not a number'); + assert.notOk(_.isNumber('string'), 'a string is not a number'); + assert.notOk(_.isNumber(arguments), 'the arguments object is not a number'); + assert.notOk(_.isNumber(void 0), 'undefined is not a number'); assert.ok(_.isNumber(3 * 4 - 7 / 10), 'but numbers are'); assert.ok(_.isNumber(NaN), 'NaN *is* a number'); assert.ok(_.isNumber(Infinity), 'Infinity is a number'); - assert.ok(!_.isNumber('1'), 'numeric strings are not numbers'); + assert.notOk(_.isNumber('1'), 'numeric strings are not numbers'); }); QUnit.test('isBoolean', function(assert) { - assert.ok(!_.isBoolean(2), 'a number is not a boolean'); - assert.ok(!_.isBoolean('string'), 'a string is not a boolean'); - assert.ok(!_.isBoolean('false'), 'the string "false" is not a boolean'); - assert.ok(!_.isBoolean('true'), 'the string "true" is not a boolean'); - assert.ok(!_.isBoolean(arguments), 'the arguments object is not a boolean'); - assert.ok(!_.isBoolean(void 0), 'undefined is not a boolean'); - assert.ok(!_.isBoolean(NaN), 'NaN is not a boolean'); - assert.ok(!_.isBoolean(null), 'null is not a boolean'); + assert.notOk(_.isBoolean(2), 'a number is not a boolean'); + assert.notOk(_.isBoolean('string'), 'a string is not a boolean'); + assert.notOk(_.isBoolean('false'), 'the string "false" is not a boolean'); + assert.notOk(_.isBoolean('true'), 'the string "true" is not a boolean'); + assert.notOk(_.isBoolean(arguments), 'the arguments object is not a boolean'); + assert.notOk(_.isBoolean(void 0), 'undefined is not a boolean'); + assert.notOk(_.isBoolean(NaN), 'NaN is not a boolean'); + assert.notOk(_.isBoolean(null), 'null is not a boolean'); assert.ok(_.isBoolean(true), 'but true is'); assert.ok(_.isBoolean(false), 'and so is false'); }); QUnit.test('isMap', function(assert) { - assert.ok(!_.isMap('string'), 'a string is not a map'); - assert.ok(!_.isMap(2), 'a number is not a map'); - assert.ok(!_.isMap({}), 'an object is not a map'); - assert.ok(!_.isMap(false), 'a boolean is not a map'); - assert.ok(!_.isMap(void 0), 'undefined is not a map'); - assert.ok(!_.isMap([1, 2, 3]), 'an array is not a map'); + assert.notOk(_.isMap('string'), 'a string is not a map'); + assert.notOk(_.isMap(2), 'a number is not a map'); + assert.notOk(_.isMap({}), 'an object is not a map'); + assert.notOk(_.isMap(false), 'a boolean is not a map'); + assert.notOk(_.isMap(void 0), 'undefined is not a map'); + assert.notOk(_.isMap([1, 2, 3]), 'an array is not a map'); if (typeof Set === 'function') { - assert.ok(!_.isMap(new Set()), 'a set is not a map'); + assert.notOk(_.isMap(new Set()), 'a set is not a map'); } if (typeof WeakSet === 'function') { - assert.ok(!_.isMap(new WeakSet()), 'a weakset is not a map'); + assert.notOk(_.isMap(new WeakSet()), 'a weakset is not a map'); } if (typeof WeakMap === 'function') { - assert.ok(!_.isMap(new WeakMap()), 'a weakmap is not a map'); + assert.notOk(_.isMap(new WeakMap()), 'a weakmap is not a map'); } if (typeof Map === 'function') { var keyString = 'a string'; @@ -706,20 +706,20 @@ }); QUnit.test('isWeakMap', function(assert) { - assert.ok(!_.isWeakMap('string'), 'a string is not a weakmap'); - assert.ok(!_.isWeakMap(2), 'a number is not a weakmap'); - assert.ok(!_.isWeakMap({}), 'an object is not a weakmap'); - assert.ok(!_.isWeakMap(false), 'a boolean is not a weakmap'); - assert.ok(!_.isWeakMap(void 0), 'undefined is not a weakmap'); - assert.ok(!_.isWeakMap([1, 2, 3]), 'an array is not a weakmap'); + assert.notOk(_.isWeakMap('string'), 'a string is not a weakmap'); + assert.notOk(_.isWeakMap(2), 'a number is not a weakmap'); + assert.notOk(_.isWeakMap({}), 'an object is not a weakmap'); + assert.notOk(_.isWeakMap(false), 'a boolean is not a weakmap'); + assert.notOk(_.isWeakMap(void 0), 'undefined is not a weakmap'); + assert.notOk(_.isWeakMap([1, 2, 3]), 'an array is not a weakmap'); if (typeof Set === 'function') { - assert.ok(!_.isWeakMap(new Set()), 'a set is not a weakmap'); + assert.notOk(_.isWeakMap(new Set()), 'a set is not a weakmap'); } if (typeof WeakSet === 'function') { - assert.ok(!_.isWeakMap(new WeakSet()), 'a weakset is not a weakmap'); + assert.notOk(_.isWeakMap(new WeakSet()), 'a weakset is not a weakmap'); } if (typeof Map === 'function') { - assert.ok(!_.isWeakMap(new Map()), 'a map is not a weakmap'); + assert.notOk(_.isWeakMap(new Map()), 'a map is not a weakmap'); } if (typeof WeakMap === 'function') { var keyObj = {}, obj = new WeakMap(); @@ -729,20 +729,20 @@ }); QUnit.test('isSet', function(assert) { - assert.ok(!_.isSet('string'), 'a string is not a set'); - assert.ok(!_.isSet(2), 'a number is not a set'); - assert.ok(!_.isSet({}), 'an object is not a set'); - assert.ok(!_.isSet(false), 'a boolean is not a set'); - assert.ok(!_.isSet(void 0), 'undefined is not a set'); - assert.ok(!_.isSet([1, 2, 3]), 'an array is not a set'); + assert.notOk(_.isSet('string'), 'a string is not a set'); + assert.notOk(_.isSet(2), 'a number is not a set'); + assert.notOk(_.isSet({}), 'an object is not a set'); + assert.notOk(_.isSet(false), 'a boolean is not a set'); + assert.notOk(_.isSet(void 0), 'undefined is not a set'); + assert.notOk(_.isSet([1, 2, 3]), 'an array is not a set'); if (typeof Map === 'function') { - assert.ok(!_.isSet(new Map()), 'a map is not a set'); + assert.notOk(_.isSet(new Map()), 'a map is not a set'); } if (typeof WeakMap === 'function') { - assert.ok(!_.isSet(new WeakMap()), 'a weakmap is not a set'); + assert.notOk(_.isSet(new WeakMap()), 'a weakmap is not a set'); } if (typeof WeakSet === 'function') { - assert.ok(!_.isSet(new WeakSet()), 'a weakset is not a set'); + assert.notOk(_.isSet(new WeakSet()), 'a weakset is not a set'); } if (typeof Set === 'function') { var obj = new Set(); @@ -753,20 +753,20 @@ QUnit.test('isWeakSet', function(assert) { - assert.ok(!_.isWeakSet('string'), 'a string is not a weakset'); - assert.ok(!_.isWeakSet(2), 'a number is not a weakset'); - assert.ok(!_.isWeakSet({}), 'an object is not a weakset'); - assert.ok(!_.isWeakSet(false), 'a boolean is not a weakset'); - assert.ok(!_.isWeakSet(void 0), 'undefined is not a weakset'); - assert.ok(!_.isWeakSet([1, 2, 3]), 'an array is not a weakset'); + assert.notOk(_.isWeakSet('string'), 'a string is not a weakset'); + assert.notOk(_.isWeakSet(2), 'a number is not a weakset'); + assert.notOk(_.isWeakSet({}), 'an object is not a weakset'); + assert.notOk(_.isWeakSet(false), 'a boolean is not a weakset'); + assert.notOk(_.isWeakSet(void 0), 'undefined is not a weakset'); + assert.notOk(_.isWeakSet([1, 2, 3]), 'an array is not a weakset'); if (typeof Map === 'function') { - assert.ok(!_.isWeakSet(new Map()), 'a map is not a weakset'); + assert.notOk(_.isWeakSet(new Map()), 'a map is not a weakset'); } if (typeof WeakMap === 'function') { - assert.ok(!_.isWeakSet(new WeakMap()), 'a weakmap is not a weakset'); + assert.notOk(_.isWeakSet(new WeakMap()), 'a weakmap is not a weakset'); } if (typeof Set === 'function') { - assert.ok(!_.isWeakSet(new Set()), 'a set is not a weakset'); + assert.notOk(_.isWeakSet(new Set()), 'a set is not a weakset'); } if (typeof WeakSet === 'function') { var obj = new WeakSet(); @@ -776,19 +776,19 @@ }); QUnit.test('isFunction', function(assert) { - assert.ok(!_.isFunction(void 0), 'undefined vars are not functions'); - assert.ok(!_.isFunction([1, 2, 3]), 'arrays are not functions'); - assert.ok(!_.isFunction('moe'), 'strings are not functions'); + assert.notOk(_.isFunction(void 0), 'undefined vars are not functions'); + assert.notOk(_.isFunction([1, 2, 3]), 'arrays are not functions'); + assert.notOk(_.isFunction('moe'), 'strings are not functions'); assert.ok(_.isFunction(_.isFunction), 'but functions are'); assert.ok(_.isFunction(function(){}), 'even anonymous ones'); if (testElement) { - assert.ok(!_.isFunction(testElement), 'elements are not functions'); + assert.notOk(_.isFunction(testElement), 'elements are not functions'); } var nodelist = typeof document != 'undefined' && document.childNodes; if (nodelist) { - assert.ok(!_.isFunction(nodelist)); + assert.notOk(_.isFunction(nodelist)); } }); @@ -806,65 +806,65 @@ } QUnit.test('isDate', function(assert) { - assert.ok(!_.isDate(100), 'numbers are not dates'); - assert.ok(!_.isDate({}), 'objects are not dates'); + assert.notOk(_.isDate(100), 'numbers are not dates'); + assert.notOk(_.isDate({}), 'objects are not dates'); assert.ok(_.isDate(new Date()), 'but dates are'); }); QUnit.test('isRegExp', function(assert) { - assert.ok(!_.isRegExp(_.identity), 'functions are not RegExps'); + assert.notOk(_.isRegExp(_.identity), 'functions are not RegExps'); assert.ok(_.isRegExp(/identity/), 'but RegExps are'); }); QUnit.test('isFinite', function(assert) { - assert.ok(!_.isFinite(void 0), 'undefined is not finite'); - assert.ok(!_.isFinite(null), 'null is not finite'); - assert.ok(!_.isFinite(NaN), 'NaN is not finite'); - assert.ok(!_.isFinite(Infinity), 'Infinity is not finite'); - assert.ok(!_.isFinite(-Infinity), '-Infinity is not finite'); + assert.notOk(_.isFinite(void 0), 'undefined is not finite'); + assert.notOk(_.isFinite(null), 'null is not finite'); + assert.notOk(_.isFinite(NaN), 'NaN is not finite'); + assert.notOk(_.isFinite(Infinity), 'Infinity is not finite'); + assert.notOk(_.isFinite(-Infinity), '-Infinity is not finite'); assert.ok(_.isFinite('12'), 'Numeric strings are numbers'); - assert.ok(!_.isFinite('1a'), 'Non numeric strings are not numbers'); - assert.ok(!_.isFinite(''), 'Empty strings are not numbers'); + assert.notOk(_.isFinite('1a'), 'Non numeric strings are not numbers'); + assert.notOk(_.isFinite(''), 'Empty strings are not numbers'); var obj = new Number(5); assert.ok(_.isFinite(obj), 'Number instances can be finite'); assert.ok(_.isFinite(0), '0 is finite'); assert.ok(_.isFinite(123), 'Ints are finite'); assert.ok(_.isFinite(-12.44), 'Floats are finite'); if (typeof Symbol === 'function') { - assert.ok(!_.isFinite(Symbol()), 'symbols are not numbers'); - assert.ok(!_.isFinite(Symbol('description')), 'described symbols are not numbers'); - assert.ok(!_.isFinite(Object(Symbol())), 'boxed symbols are not numbers'); + assert.notOk(_.isFinite(Symbol()), 'symbols are not numbers'); + assert.notOk(_.isFinite(Symbol('description')), 'described symbols are not numbers'); + assert.notOk(_.isFinite(Object(Symbol())), 'boxed symbols are not numbers'); } }); QUnit.test('isNaN', function(assert) { - assert.ok(!_.isNaN(void 0), 'undefined is not NaN'); - assert.ok(!_.isNaN(null), 'null is not NaN'); - assert.ok(!_.isNaN(0), '0 is not NaN'); - assert.ok(!_.isNaN(new Number(0)), 'wrapped 0 is not NaN'); + assert.notOk(_.isNaN(void 0), 'undefined is not NaN'); + assert.notOk(_.isNaN(null), 'null is not NaN'); + assert.notOk(_.isNaN(0), '0 is not NaN'); + assert.notOk(_.isNaN(new Number(0)), 'wrapped 0 is not NaN'); assert.ok(_.isNaN(NaN), 'but NaN is'); assert.ok(_.isNaN(new Number(NaN)), 'wrapped NaN is still NaN'); }); QUnit.test('isNull', function(assert) { - assert.ok(!_.isNull(void 0), 'undefined is not null'); - assert.ok(!_.isNull(NaN), 'NaN is not null'); + assert.notOk(_.isNull(void 0), 'undefined is not null'); + assert.notOk(_.isNull(NaN), 'NaN is not null'); assert.ok(_.isNull(null), 'but null is'); }); QUnit.test('isUndefined', function(assert) { - assert.ok(!_.isUndefined(1), 'numbers are defined'); - assert.ok(!_.isUndefined(null), 'null is defined'); - assert.ok(!_.isUndefined(false), 'false is defined'); - assert.ok(!_.isUndefined(NaN), 'NaN is defined'); + assert.notOk(_.isUndefined(1), 'numbers are defined'); + assert.notOk(_.isUndefined(null), 'null is defined'); + assert.notOk(_.isUndefined(false), 'false is defined'); + assert.notOk(_.isUndefined(NaN), 'NaN is defined'); assert.ok(_.isUndefined(), 'nothing is undefined'); assert.ok(_.isUndefined(void 0), 'undefined is undefined'); }); QUnit.test('isError', function(assert) { - assert.ok(!_.isError(1), 'numbers are not Errors'); - assert.ok(!_.isError(null), 'null is not an Error'); - assert.ok(!_.isError(Error), 'functions are not Errors'); + assert.notOk(_.isError(1), 'numbers are not Errors'); + assert.notOk(_.isError(null), 'null is not an Error'); + assert.notOk(_.isError(Error), 'functions are not Errors'); assert.ok(_.isError(new Error()), 'Errors are Errors'); assert.ok(_.isError(new EvalError()), 'EvalErrors are Errors'); assert.ok(_.isError(new RangeError()), 'RangeErrors are Errors'); @@ -893,13 +893,13 @@ QUnit.test('has', function(assert) { var obj = {foo: 'bar', func: function(){}}; assert.ok(_.has(obj, 'foo'), 'has() checks that the object has a property.'); - assert.ok(!_.has(obj, 'baz'), "has() returns false if the object doesn't have the property."); + assert.notOk(_.has(obj, 'baz'), "has() returns false if the object doesn't have the property."); assert.ok(_.has(obj, 'func'), 'has() works for functions too.'); obj.hasOwnProperty = null; assert.ok(_.has(obj, 'foo'), 'has() works even when the hasOwnProperty method is deleted.'); var child = {}; child.prototype = obj; - assert.ok(!_.has(child, 'foo'), 'has() does not check the prototype chain for a property.'); + assert.notOk(_.has(child, 'foo'), 'has() does not check the prototype chain for a property.'); assert.strictEqual(_.has(null, 'foo'), false, 'has() returns false for null'); assert.strictEqual(_.has(void 0, 'foo'), false, 'has() returns false for undefined'); }); diff --git a/test/utility.js b/test/utility.js index 60d387597..b7ded62b1 100644 --- a/test/utility.js +++ b/test/utility.js @@ -370,9 +370,9 @@ }); QUnit.test('#547 - _.templateSettings is unchanged by custom settings.', function(assert) { - assert.ok(!_.templateSettings.variable); + assert.notOk(_.templateSettings.variable); _.template('', {}, {variable: 'x'}); - assert.ok(!_.templateSettings.variable); + assert.notOk(_.templateSettings.variable); }); QUnit.test('#556 - undefined template variables.', function(assert) { @@ -397,11 +397,11 @@ assert.expect(2); var count = 0; var template = _.template('<%= f() %>'); - template({f: function(){ assert.ok(!count++); }}); + template({f: function(){ assert.notOk(count++); }}); var countEscaped = 0; var templateEscaped = _.template('<%- f() %>'); - templateEscaped({f: function(){ assert.ok(!countEscaped++); }}); + templateEscaped({f: function(){ assert.notOk(countEscaped++); }}); }); QUnit.test('#746 - _.template settings are not modified.', function(assert) { From d988667b708592eecdc6fb3348c0f9848535c8d7 Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Tue, 5 Apr 2016 10:37:00 -0700 Subject: [PATCH 047/498] Point users to Gitter instead of IRC --- index.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 68634baa0..366108f1a 100644 --- a/index.html +++ b/index.html @@ -396,8 +396,9 @@ The project is hosted on GitHub. You can report bugs and discuss features on the - issues page, or - on Freenode in the #documentcloud channel. + issues page, + on Freenode in the #documentcloud channel, or in our Gitter + channel. From 10d2d64dc92e8939e64ce38039051870139956ce Mon Sep 17 00:00:00 2001 From: marija
+ added to the Underscore object, as well as the OOP wrapper. Returns the + Underscore object to facilitate chaining.Date: Wed, 13 Apr 2016 15:09:28 +0200 Subject: [PATCH 048/498] optimization of _.isNaN --- underscore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/underscore.js b/underscore.js index 78c709bd3..b39f6733b 100644 --- a/underscore.js +++ b/underscore.js @@ -1316,7 +1316,7 @@ // Is the given value `NaN`? _.isNaN = function(obj) { - return _.isNumber(obj) && isNaN(obj); + return isNaN(obj) && _.isNumber(obj); }; // Is a given value a boolean? From 929fc74b880a87e669229597b9c5cf6cdd2dbf14 Mon Sep 17 00:00:00 2001 From: Amit Evron Date: Sat, 16 Apr 2016 00:03:17 +0300 Subject: [PATCH 049/498] Return self after using mixin() will allow user to chain mixin(), and most importantly use mixin() in the dependency section in the file. --- underscore.js | 1 + 1 file changed, 1 insertion(+) diff --git a/underscore.js b/underscore.js index ad065442b..1630b7286 100644 --- a/underscore.js +++ b/underscore.js @@ -1573,6 +1573,7 @@ return chainResult(this, func.apply(_, args)); }; }); + return _; }; // Add all of the Underscore functions to the wrapper object. From 8707c00bae6a264d58f90de15d67ba5b1aca737d Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Mon, 18 Apr 2016 20:22:11 -0700 Subject: [PATCH 050/498] Add tests and docs for `_.mixin` chaining This change was introduced in #2502 without tests or docs. This commit adds those two missing pieces. --- index.html | 4 ++-- test/utility.js | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 366108f1a..429f0a2d5 100644 --- a/index.html +++ b/index.html @@ -1886,8 +1886,8 @@ Utility Functions
Allows you to extend Underscore with your own utility functions. Pass a hash of {name: function} definitions to have your functions - added to the Underscore object, as well as the OOP wrapper. -_.mixin({ capitalize: function(string) { diff --git a/test/utility.js b/test/utility.js index b7ded62b1..6a81e8735 100644 --- a/test/utility.js +++ b/test/utility.js @@ -137,11 +137,12 @@ }); QUnit.test('mixin', function(assert) { - _.mixin({ + var ret = _.mixin({ myReverse: function(string) { return string.split('').reverse().join(''); } }); + assert.equal(ret, _, 'returns the _ object to facilitate chaining'); assert.equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _'); assert.equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper'); }); From e90055343e86122782cbcc7623dab0770e48c132 Mon Sep 17 00:00:00 2001 From: Jordan EldredgeDate: Sat, 23 Apr 2016 10:51:44 -0700 Subject: [PATCH 051/498] Cleanup docs for methods with multiple aliases Our formatting was a bit inconsistent. --- index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 366108f1a..69a53d139 100644 --- a/index.html +++ b/index.html @@ -499,7 +499,7 @@ Collection Functions (Arrays or Objects)
reduce
_.reduce(list, iteratee, [memo], [context])- Aliases: inject, foldl + Aliases: inject, foldl
Also known as inject and foldl, reduce boils down a list of values into a single value. Memo is the initial state of the reduction, and each successive step of it should be returned by @@ -826,7 +826,7 @@Array Functions
first
_.first(array, [n])- Alias: head, take + Aliases: head, take
Returns the first element of an array. Passing n will return the first n elements of the array. @@ -861,7 +861,7 @@Array Functions
rest
_.rest(array, [index])- Alias: tail, drop + Aliases: tail, drop
Returns the rest of the elements in an array. Pass an index to return the values of the array from that index onward. From 507b858e0ba99d158b1ad61d97f260e7d7ec04f9 Mon Sep 17 00:00:00 2001 From: codefallingDate: Sun, 24 Apr 2016 18:59:51 +0800 Subject: [PATCH 052/498] check length in _.first and _.last, fix #2495 --- test/arrays.js | 8 ++++++++ underscore.js | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/test/arrays.js b/test/arrays.js index 748edea4f..319994aa1 100644 --- a/test/arrays.js +++ b/test/arrays.js @@ -15,6 +15,10 @@ result = _.map([[1, 2, 3], [1, 2, 3]], _.first); assert.deepEqual(result, [1, 1], 'works well with _.map'); assert.equal(_.first(null), void 0, 'returns undefined when called on null'); + + Array.prototype[0] = 'boo'; + assert.equal(_.first([]), void 0, 'return undefined when called on a empty array'); + delete Array.prototype[0]; }); QUnit.test('head', function(assert) { @@ -66,6 +70,10 @@ result = _.map([[1, 2, 3], [1, 2, 3]], _.last); assert.deepEqual(result, [3, 3], 'works well with _.map'); assert.equal(_.last(null), void 0, 'returns undefined when called on null'); + + var arr = []; + arr[-1] = 'boo'; + assert.equal(_.last(arr), void 0, 'return undefined when called on a empty array'); }); QUnit.test('compact', function(assert) { diff --git a/underscore.js b/underscore.js index 1630b7286..84713e688 100644 --- a/underscore.js +++ b/underscore.js @@ -467,7 +467,7 @@ // values in the array. Aliased as `head` and `take`. The **guard** check // allows it to work with `_.map`. _.first = _.head = _.take = function(array, n, guard) { - if (array == null) return void 0; + if (array == null || array.length < 1) return void 0; if (n == null || guard) return array[0]; return _.initial(array, array.length - n); }; @@ -482,7 +482,7 @@ // Get the last element of an array. Passing **n** will return the last N // values in the array. _.last = function(array, n, guard) { - if (array == null) return void 0; + if (array == null || array.length < 1) return void 0; if (n == null || guard) return array[array.length - 1]; return _.rest(array, Math.max(0, array.length - n)); }; From d484f8ff4486c6894684af2bbbb0834a38d69674 Mon Sep 17 00:00:00 2001 From: codefalling Date: Mon, 25 Apr 2016 17:19:25 +0800 Subject: [PATCH 053/498] safer _#toString, fix #2498 --- underscore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/underscore.js b/underscore.js index 84713e688..ab2f75f36 100644 --- a/underscore.js +++ b/underscore.js @@ -1608,7 +1608,7 @@ _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; _.prototype.toString = function() { - return '' + this._wrapped; + return String(this._wrapped); }; // AMD registration happens at the end for compatibility with AMD loaders From ef9ee4b7f54ecf4387f681d54dbca36ad0cb0e85 Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Sat, 23 Apr 2016 10:49:42 -0700 Subject: [PATCH 054/498] Make functions in docs filterable With a utility library like Underscore, it is very common to open the docs with the aim of locating the documentation for a specific function. Currently I use my browser's search functionality, but since many functions reference other functions, I frequently have to cycle through multiple matches before I arrive at the actual function's description. This patch aims to improve this common use case by offering a "filter" input above the list of functions. As a user types, the list of functions (and section titles) is reduced, leaving only the matching functions. If the user presses enter, they are jumped to the documentation for the first matching function. This functionality (and implementation) is greatly inspired by the implementation that is included in the [Ramda docs](http://ramdajs.com/0.21.0/docs/). You can read their source code [here](https://github.com/ramda/ramda.github.io/blob/master/main.js) --- docs/.eslintrc | 5 + docs/main.js | 58 +++++++++ index.html | 339 ++++++++++++++++++++++++++----------------------- 3 files changed, 246 insertions(+), 156 deletions(-) create mode 100644 docs/.eslintrc create mode 100644 docs/main.js diff --git a/docs/.eslintrc b/docs/.eslintrc new file mode 100644 index 000000000..aac42a91c --- /dev/null +++ b/docs/.eslintrc @@ -0,0 +1,5 @@ +{ + "globals": { + "_": true + } +} diff --git a/docs/main.js b/docs/main.js new file mode 100644 index 000000000..b46891fca --- /dev/null +++ b/docs/main.js @@ -0,0 +1,58 @@ +(function() { + var functions = document.querySelectorAll('[data-name]'); + var sections = document.querySelectorAll('.searchable_section'); + var searchInput = document.getElementById('function_filter'); + + function strIn(a, b) { + a = a.toLowerCase(); + b = b.toLowerCase(); + return b.indexOf(a) >= 0; + } + + function doesMatch(element) { + var name = element.getAttribute('data-name'); + var aliases = element.getAttribute('data-aliases') || ''; + return strIn(searchInput.value, name) || strIn(searchInput.value, aliases); + } + + function filterElement(element) { + element.style.display = doesMatch(element) ? '' : 'none'; + } + + function filterToc() { + _.each(functions, filterElement); + + var emptySearch = searchInput.value === ''; + + // Hide the titles of empty sections + _.each(sections, function(section) { + var sectionFunctions = section.querySelectorAll('[data-name]'); + var showSection = emptySearch || _.some(sectionFunctions, doesMatch); + section.style.display = showSection ? '' : 'none'; + }); + } + + function gotoFirst() { + var firstFunction = _.find(functions, doesMatch); + if(firstFunction) { + window.location.hash = firstFunction.getAttribute('data-name'); + searchInput.focus(); + } + } + + searchInput.addEventListener('input', filterToc, false); + + // Press "Enter" to jump to the first matching function + searchInput.addEventListener('keypress', function(e) { + if (e.which === 13) { + gotoFirst(); + } + }); + + // Press "/" to search + document.body.addEventListener('keyup', function(event) { + if (191 === event.which) { + searchInput.focus(); + } + }); +}()); diff --git a/index.html b/index.html index 366108f1a..79b72363f 100644 --- a/index.html +++ b/index.html @@ -64,6 +64,9 @@ .toc_section li a:hover { text-decoration: underline; } + input#function_filter { + width: 80%; + } div.container { width: 550px; margin: 40px 0 50px 260px; @@ -188,170 +191,193 @@ » Underscore-contrib - - Introduction - + - - Collections - --
+- - each
-- - map
-- - reduce
-- - reduceRight
-- - find
-- - filter
-- - where
-- - findWhere
-- - reject
-- - every
-- - some
-- - contains
-- - invoke
-- - pluck
-- - max
-- - min
-- - sortBy
-- - groupBy
-- - indexBy
-- - countBy
-- - shuffle
-- - sample
-- - toArray
-- - size
-- - partition
-+ + Introduction + +- - Arrays - --
+- - first
-- - initial
-- - last
-- - rest
-- - compact
-- - flatten
-- - without
-- - union
-- - intersection
-- - difference
-- - uniq
-- - zip
-- - unzip
-- - object
-- - indexOf
-- - lastIndexOf
-- - sortedIndex
-- - findIndex
-- - findLastIndex
-- - range
-+ + Collections + + +- - Functions - --
+- - bind
-- - bindAll
-- - partial
-- - memoize
-- - delay
-- - defer
-- - throttle
-- - debounce
-- - once
-- - after
-- - before
-- - wrap
-- - negate
-- - compose
-+ + Arrays + +- - Objects - -+
+- - first
+- - initial
+- - last
+- - rest
+- - compact
+- - flatten
+- - without
+- - union
+- - intersection
+- - difference
+- - uniq
+- - zip
+- - unzip
+- - object
+- - indexOf
+- - lastIndexOf
+- - sortedIndex
+- - findIndex
+- - findLastIndex
+- - range
+-
+- - keys
-- - allKeys
-- - values
-- - mapObject
-- - pairs
-- - invert
-- - create
-- - functions
-- - findKey
-- - extend
-- - extendOwn
-- - pick
-- - omit
-- - defaults
-- - clone
-- - tap
-- - has
-- - matcher
-- - property
-- - propertyOf
-- - isEqual
-- - isMatch
-- - isEmpty
-- - isElement
-- - isArray
-- - isObject
-- - isArguments
-- - isFunction
-- - isString
-- - isNumber
-- - isFinite
-- - isBoolean
-- - isDate
-- - isRegExp
-- - isError
-- - isSymbol
-- - isNaN
-- - isNull
-- - isUndefined
-+ + Functions + + +- - Utility - --
+- - noConflict
-- - identity
-- - constant
-- - noop
-- - times
-- - random
-- - mixin
-- - iteratee
-- - uniqueId
-- - escape
-- - unescape
-- - result
-- - now
-- - template
-+ + Objects + +- - OOP Style - - - Chaining - - ++
+- - keys
+- - allKeys
+- - values
+- - mapObject
+- - pairs
+- - invert
+- - create
+- - functions
+- - findKey
+- - extend
+- - extendOwn
+- - pick
+- - omit
+- - defaults
+- - clone
+- - tap
+- - has
+- - matcher
+- - property
+- - propertyOf
+- - isEqual
+- - isMatch
+- - isEmpty
+- - isElement
+- - isArray
+- - isObject
+- - isArguments
+- - isFunction
+- - isString
+- - isNumber
+- - isFinite
+- - isBoolean
+- - isDate
+- - isRegExp
+- - isError
+- - isSymbol
+- - isNaN
+- - isNull
+- - isUndefined
++ + Utility + + +- - Links - ++ + OOP Style + +- - Change Log - ++ + Chaining + + ++ ++ + Links + ++ ++ + Change Log + +@@ -3223,6 +3249,7 @@Change Log
+