Skip to content

Instantly share code, notes, and snippets.

@stephnr
Last active April 15, 2016 20:45
Show Gist options
  • Save stephnr/7cf1638308957b478a4420bf2f352522 to your computer and use it in GitHub Desktop.
Save stephnr/7cf1638308957b478a4420bf2f352522 to your computer and use it in GitHub Desktop.
Custom Fuzzy Filter AngularJS Pipe against ambiguous iterable types (i.e. List of Objects of Arrays of Objects of ... [etc.])
(function () {
'use strict';
angular.module('app')
.filter('fuzzyFilter', FuzzyFilter);
/**
* Flattens an array<any> into an array of elements
* where the elements contain only literals (i.e. Strings, Numbers, Booleans)
* @param {Array<any>} arr an iterable to flatten
* @return {Array<Array<String|Number|Boolean>>} an array of array elements containing literals
*/
function flatten(arr) {
return arr.map(function (el) {
if (el instanceof Array) {
return flatten(el);
} else if (el instanceof Object) {
return flatten(Object.keys(el).map(function (key) { return el[key]; }));
} else {
return el;
}
});
}
/**
* Loops through any nested elements and checks against the callback for matching
* @param {Array<any>} arr an iterable to find a matching element
* @param {Function} cb a callback that must return either truthful or falsy values
* @return {Boolean} the result of whether a match was found or not
*/
function isMatching(arr, cb) {
return arr.reduce(function (prev, next) {
if (next instanceof Array) { return prev || isMatching(next, cb); }
else { return prev || Boolean(cb(next)); }
}, false);
}
/**
* Pipes the input through a flatten and exposes each
* input literal within to a provided callback function
* @return {Array<any>} the filtered list
*/
function FuzzyFilter() {
/**
* Filter function to use in Angular JS pipe operations
* @param {Array<any>} inputArray an iterable list to filter
* @param {Function} cb a callback that must return either truthful or falsy values
* @return {Array<any>} the filtered list
*/
return function (inputArray, cb) {
return flatten(angular.copy(inputArray)).map(function (el, idx) {
if (isMatching(el, cb)) return inputArray[idx];
else return undefined;
}).filter(function (el) { return el !== undefined; });
};
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment