-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathindex.js
More file actions
84 lines (78 loc) · 2.75 KB
/
index.js
File metadata and controls
84 lines (78 loc) · 2.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
module.exports = fuzzy;
/**
* Filter an array of objects (or an array of just about anything) down
* to only include those objects with properties somewhat matching the provided query.
*
* A "fuzzy" match...
* - matches any string that contains the query being insensitive to punctuation, spacing, and capitalization
* - matches numbers exactly
* - matches objects who contains a value fuzzy-matching the query
*
* When filtering an array of objects, the fuzzy matching can optionally be restricted to only
* match values that are associated with the specified key or keys.
*
* @param {string|number} query The filter query to use to reduce an array down to objects matching the query.
* @param {string|array=} keys Optionally restrict the search to a set of keys; only applied when filtering objects.
*
* @return {Function} A filter predicate suitable for passing to Array.prototype.filter.
*/
function fuzzy(query, keys) {
if (typeof query !== "string" &&
(typeof query !== "number" || isNaN(query))) {
throw new TypeError("The query is required and must be a string or number");
}
if (typeof keys === "undefined") {
keys = [];
} else if (typeof keys === "string") {
keys = [keys];
} else if (!Array.isArray(keys)) {
throw new TypeError("keys should either be an array or a single value as a string");
}
return function(element) {
return _search(element, query, keys);
};
}
/**
* Recursively searches through a haystack to find the specified needle.
*
* @param {*} haystack Searches this object for the needle.
* @param {string|number} needle The value to search for within the haystack.
* @param {array} keys Restrict searching an object to only match values associated with the specified keys.
*
* @return {boolean} True if a match was found; false otherwise.
*/
function _search(haystack, needle, keys) {
switch (typeof haystack) {
case "number":
return haystack == needle; // eslint-disable-line eqeqeq
case "string":
return _normalize(haystack).indexOf(_normalize(needle)) >= 0;
case "object":
for (var key in haystack) {
if (haystack.hasOwnProperty(key) && (keys.length === 0 || keys.indexOf(key) >= 0)) {
if (_search(haystack[key], needle, keys)) {
return true;
}
}
}
return false;
default:
return false;
}
}
/**
* Normalizes a value.
*
* Converts strings to lower case and removes all punctuation and spacing.
* For all other values, it simply returns the passed-in value without modification.
*
* @param {*} value The value to normalize.
*
* @return {*} The normalized value.
*/
function _normalize(value) {
if (value.toLowerCase) {
return value.toLowerCase().replace(/[\W_]/g, "");
}
return value;
}