Last active
April 15, 2016 20:45
-
-
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.])
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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