Last active
December 23, 2015 10:39
-
-
Save nh2/6622759 to your computer and use it in GitHub Desktop.
Javascript serializable object filters. Filters a list of objects, with easy selection of the field and value to filter on using regexes.
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
# A filter that can match or not match an object. | |
# It contains: | |
# - field: the field (property) of the object to match on (as a string, will be used as a regex, case-insensitive) | |
# - regex: the regex that this field's value must match (as a string) | |
# - inverted: if true, the result of the filter is inverted (flips the value of `match()`) | |
# | |
# You can use `flattenObject()` to flatten objects before you pass them into `match()`, | |
# which allows you to match `field` anywhere in a nested object. | |
class ObjectFilter | |
constructor: (@field='', @regex='', @inverted=false) -> | |
# Formats the filter to a human-writable query string. | |
# field and regex separated by ':', negation with prefixed '!'. | |
# Example: !tag:mytag | |
toQueryString: -> "#{if @inverted then '!' else ''}#{@field}:#{@regex}" | |
# Parses a filter out of a query string as formatted by `toQueryString`. | |
@fromQueryString: (qs) -> | |
if (qs[0] == '!') | |
invertedSign = true | |
input = qs.substr(1) | |
else | |
invertedSign = false | |
input = qs | |
fs = input.split(':') | |
if (fs[1]?) | |
field = fs[0] | |
regex = fs.splice(1).join(':') | |
else | |
field = '' | |
regex = fs[0] | |
new ObjectFilter field, regex, if invertedSign then true else false # make the filter | |
# Returns whether the given object matches the filter. | |
# | |
# The filter matches is hidden if field matches some field, but `regex` rejects its `value`. | |
# `inverted` flips the result. | |
match: (obj) -> | |
fieldRegex = RegExp(@field, "i") | |
valueRegex = RegExp(@regex) | |
for own k, v of obj | |
if k.match fieldRegex | |
no_field_matched = false | |
# v might be nasty null or undefined | |
if (v or '').toString().match valueRegex | |
return true ^ @inverted | |
return no_field_matched ^ @inverted | |
# Flattens a nested object into a single one. | |
# Example: { a: 1, b: {x: 2, y: 3} } -> { a: 1, b.x: 2, b.y: 3 } | |
# | |
# From http://stackoverflow.com/a/965315/263061, using '.' instead of '_'. | |
@flattenObject = (obj, includePrototype, into, prefix) -> | |
into = into or {} | |
prefix = prefix or "" | |
for k of obj | |
if includePrototype or obj.hasOwnProperty(k) | |
prop = obj[k] | |
if prop and typeof prop is "object" and not (prop instanceof Date or prop instanceof RegExp) | |
@flattenObject prop, includePrototype, into, prefix + k + "." | |
else | |
into[prefix + k] = prop | |
into |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment