Skip to content

Instantly share code, notes, and snippets.

@mikeobrien
Created February 21, 2012 04:49
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save mikeobrien/1873752 to your computer and use it in GitHub Desktop.
Save mikeobrien/1873752 to your computer and use it in GitHub Desktop.
Lazy loading backbone collection + infinite scrolling
class LazyCollection extends Backbone.Collection
indexQuerystring: 'index'
index: 1
lastLength: 0
fetch: (options) ->
options or= {}
if options.reset
@index = 1
@lastLength = 0
else
if @lastLength == @length then return
@lastLength = @length
@index++
options.add = true
options.data or= {}
options.data[@indexQuerystring] = @index
success = options.success
options.success = (model, resp) =>
@trigger 'fetch:end'
if success then success model, resp
error = options.error
options.error = (originalModel, resp, options) =>
@trigger 'fetch:end'
if error then error originalModel, resp, options
@trigger 'fetch:start'
Backbone.Collection.prototype.fetch.call @, options
class SearchResults extends LazyCollection
initialize: ->
_.bindAll @, 'search'
@query = ''
model: Entry
url: -> "/directory/entries"
search: (query) ->
@query = query ? @query
@fetch { reset: !!query, data: { query: @query } }
class SearchResultsView extends Backbone.View
initialize: (options) ->
_.bindAll @, 'render', 'renderResult'
@template = options.template
@collection.on 'reset', @render, @
@collection.on 'add', @renderResult, @
render: ->
@$el.empty()
@collection.each @renderResult
renderResult: (result) ->
view = new SearchResultView
template: @template
model: result
@$el.append view.render().el
class SearchView extends Backbone.View
events:
'click .search': 'search'
initialize: (options) ->
_.bindAll @, 'render', 'search', 'toggleSpinner'
@template = options.template
@resultTemplate = options.resultTemplate
options.scrollChannel.subscribe @collection.search
@collection.on 'fetch:start', @toggleSpinner, @
@collection.on 'fetch:end', @toggleSpinner, @
render: ->
@$el.html @template()
@resultsView = new SearchResultsView
el: $ '.search-results'
template: @resultTemplate
collection: @collection
search: (event) ->
@collection.search $('.search-text').val()
event.preventDefault()
toggleSpinner: ->
@$('.spinner').toggle()
...
start: (results) ->
container = $ '#container'
scrollChannel = postal.channel 'scroll.bottom'
# TODO: Make this a jQuery plugin
$window = $ window
$document = $ document
$window.scroll ->
scrollTop = $window.scrollTop()
scrollChannel.publish() unless scrollTop == 0 or scrollTop < ($document.height() - $window.height()) - 100
@searchResults = new SearchResults
@searchView = new SearchView
el: container
collection: @searchResults
template: _.template searchTemplate
resultTemplate: _.template searchResultTemplate
scrollChannel: scrollChannel
@searchResults.reset results
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment