/
filtered_collection.coffee
58 lines (45 loc) · 1.64 KB
/
filtered_collection.coffee
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
Collection = require './collection'
# Creates a mirroed copy of a collection that filters can be appiled to. It
# should keep itself in sync with the given collection. When model instances
# transition from shown to filtered, a "remove" event will be triggered. In
# the other direction, the event will be "add"
class FilteredCollection extends Collection
constructor: (@collection) ->
super()
@model = @collection.model
@filters = {}
@collection.on('add', @addUnfiltered, this)
@collection.on('remove', @remove, this)
@collection.on('reset', @collectionReset, this)
@collection.on('sync', (-> @trigger('sync')), this)
@reset(@collection.models)
collectionReset: (c) ->
@collection = c
@reset([])
@update()
addUnfiltered: (model) ->
if @isValid(model) then @add(model)
removeFilter: (name) ->
delete @filters[name]
@update()
addFilter: (name, filter) ->
@filters[name] = filter
@update()
isValid: (model) ->
for _, filter of @filters
if not filter(model) then return false
return true
# Perform an internal update, adding models which are now valid and removing
# models which are now invalid.
update: =>
for model in @collection.models
# When the model is valid, see if we hold a copy of it. If so, do
# nothing. Otherwise, add it.
if @isValid(model)
if not @get(model.id) then @add(model)
# When the model is invalid, see if a copy is held in this colleciton.
# If so, remove it. Otherwise, do nothing.
else
if @get(model.id) then @remove(model)
@trigger('change')
module.exports = FilteredCollection