Skip to content

Instantly share code, notes, and snippets.

@pavanpodila
Created January 15, 2012 22:02
Show Gist options
  • Save pavanpodila/1617641 to your computer and use it in GitHub Desktop.
Save pavanpodila/1617641 to your computer and use it in GitHub Desktop.
A CollectionView class that monitors Backbone.Collections and renders the item Views
define ->
# The CollectionView class provides a simple view manager for a Backbone Collection.
# It listens to changes on the collection and reflects that on the view. It also provides
# view filtering, grouping and sorting capabilities.
class CollectionView extends Backbone.View
initialize: (options)->
throw "collection property must be specified." if not @collection
@_ready = $.Deferred()
@_pendingCount = 0
@_byModelId = {}
@createView = options.createView
@renderItemView = options.renderItemView or @defaultRenderItemView
# listen to collection changes
@collection.bind 'add', @addItem, @
@collection.bind 'remove', @removeItem, @
@collection.bind 'reset', @resetItems, @
addItem:(model)->
@renderItem(model)
removeItem:(model)->
view = @_byModelId[model.cid]
delete @_byModelId[model.cid]
view?.remove()
resetItems:(models)->
view.remove() for cid, view of @_byModelId
@_byModelId = {}
getByModelId:(modelId)->
return @_byModelId[modelId]
views:->
(view for key, view of @_byModelId)
hasItem:(item)->
!!@_byModelId[item.model.cid]
defaultRenderItemView:(view)->
view.render()
@el.append view.el
view.postRender?()
renderItem:(model, customRender)->
view = @createView model
@_byModelId[model.cid] = view
(customRender or @renderItemView).call @, view
render: (options) ->
{defer} = options or { defer: true }
@_pendingCount = @collection.length
@collection.each (item) =>
fn = =>
@renderItem item
@_pendingCount--
@_ready.resolve() if not @_ready.isResolved() and @_pendingCount is 0
if defer then (_.defer => fn()) else fn()
remove:->
view.remove() for cid, view of @_byModelId
#----------- Filtering, Grouping and Sorting -------------------#
applyOperations:(config)->
config = _.extend { sortFn:(->true), groupFn:(->true), complete:(->) }, config
@_ready.done =>
groups = _.groupBy @collection.models, config.groupFn
for key, items of groups
sortedItems = _.sortBy items, config.sortFn
groups[key] = sortedItems
# Collect the views
groupedViews = {}
for key, items of groups
itemViews = (@getByModelId(item.cid) for item in items)
groupedViews[key] = itemViews
config.complete groupedViews
filter:(config) ->
config = _.extend { predicate:(->true), complete:(->) }, config
@_ready.done =>
filtered = _.filter @collection.models, (item) -> config.predicate(item)
filteredViews = (@getByModelId(item.cid) for item in filtered)
config.complete filteredViews
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment