Skip to content

Instantly share code, notes, and snippets.

@pavanpodila
Created January 15, 2012 22:02
Show Gist options
  • Select an option

  • Save pavanpodila/1617641 to your computer and use it in GitHub Desktop.

Select an option

Save pavanpodila/1617641 to your computer and use it in GitHub Desktop.

Revisions

  1. pavanpodila revised this gist Jan 20, 2012. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions CollectionView.coffee
    Original file line number Diff line number Diff line change
    @@ -91,5 +91,3 @@ define ->
    filtered = _.filter @collection.models, (item) -> config.predicate(item)
    filteredViews = (@getByModelId(item.cid) for item in filtered)
    config.complete filteredViews

    #--------------------- Sorting --------------------
  2. pavanpodila revised this gist Jan 20, 2012. 1 changed file with 35 additions and 30 deletions.
    65 changes: 35 additions & 30 deletions CollectionView.coffee
    Original file line number Diff line number Diff line change
    @@ -2,11 +2,14 @@ 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 window.CollectionView extends Backbone.View
    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
    @@ -42,49 +45,51 @@ define ->
    @el.append view.el
    view.postRender?()

    renderItem:(model)->
    renderItem:(model, customRender)->
    view = @createView model
    @_byModelId[model.cid] = view
    @renderItemView view
    (customRender or @renderItemView).call @, view

    render: (options) ->
    {defer} = options or { defer: true }

    @_pendingCount = @collection.length
    @collection.each (item) =>
    fn = => @renderItem 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 and Grouping -------------------#
    applyOperations:->
    @applyFilter()

    group:(grouping)->
    @_grouping = grouping or (->'all')
    @groupView = if not grouping then NoGroupView else @options.groupView
    @applyGrouping()
    #----------- Filtering, Grouping and Sorting -------------------#
    applyOperations:(config)->
    config = _.extend { sortFn:(->true), groupFn:(->true), complete:(->) }, config

    applyGrouping:->
    groups = @collection.groupBy(@_grouping)
    @_ready.done =>
    groups = _.groupBy @collection.models, config.groupFn
    for key, items of groups
    sortedItems = _.sortBy items, config.sortFn
    groups[key] = sortedItems

    view.el.detach() for cid, view of @_byModelId
    @el.empty()
    # Collect the views
    groupedViews = {}
    for key, items of groups
    itemViews = (@getByModelId(item.cid) for item in items)
    groupedViews[key] = itemViews

    for key, items of groups
    itemViews = _.map items, (item)=>@_byModelId[item.cid]
    grpView = new @groupView key:key, views:itemViews, parent:@el
    grpView.render()
    config.complete groupedViews

    filter:(predicate) ->
    @_filter = predicate or (->true)
    @applyFilter()
    filter:(config) ->
    config = _.extend { predicate:(->true), complete:(->) }, config

    applyFilter:->
    keepers = []
    nokeepers = []
    @collection.each (item)=>
    if @_filter(item) then keepers.push(item) else nokeepers.push(item)
    @_ready.done =>
    filtered = _.filter @collection.models, (item) -> config.predicate(item)
    filteredViews = (@getByModelId(item.cid) for item in filtered)
    config.complete filteredViews

    _.each nokeepers, (item) => @removeItem item
    _.each keepers, (item) => return if @hasItem(item) else @addItem(item)
    #--------------------- Sorting --------------------
  3. pavanpodila created this gist Jan 15, 2012.
    90 changes: 90 additions & 0 deletions CollectionView.coffee
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,90 @@
    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 window.CollectionView extends Backbone.View

    initialize: (options)->
    throw "collection property must be specified." if not @collection

    @_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)->
    view = @createView model
    @_byModelId[model.cid] = view
    @renderItemView view

    render: (options) ->
    {defer} = options or { defer: true }
    @collection.each (item) =>
    fn = => @renderItem item
    if defer then (_.defer => fn()) else fn()

    remove:->
    view.remove() for cid, view of @_byModelId

    #----------- Filtering and Grouping -------------------#
    applyOperations:->
    @applyFilter()

    group:(grouping)->
    @_grouping = grouping or (->'all')
    @groupView = if not grouping then NoGroupView else @options.groupView
    @applyGrouping()

    applyGrouping:->
    groups = @collection.groupBy(@_grouping)

    view.el.detach() for cid, view of @_byModelId
    @el.empty()

    for key, items of groups
    itemViews = _.map items, (item)=>@_byModelId[item.cid]
    grpView = new @groupView key:key, views:itemViews, parent:@el
    grpView.render()

    filter:(predicate) ->
    @_filter = predicate or (->true)
    @applyFilter()

    applyFilter:->
    keepers = []
    nokeepers = []
    @collection.each (item)=>
    if @_filter(item) then keepers.push(item) else nokeepers.push(item)

    _.each nokeepers, (item) => @removeItem item
    _.each keepers, (item) => return if @hasItem(item) else @addItem(item)