Skip to content

Instantly share code, notes, and snippets.

@sbellity
Created November 18, 2011 17:10
Show Gist options
  • Save sbellity/1377079 to your computer and use it in GitHub Desktop.
Save sbellity/1377079 to your computer and use it in GitHub Desktop.
Knockit = Knockout + Backbone
class KnockItObservables
constructor: ->
@reset({})
make: (ref, attrs)->
return false unless ref && attrs
@_viewModels[ref] ?= ko.mapping.fromJS(attrs)
@_viewModels[ref].ref = ref
@_viewModels[ref]
change: (ref, attrs)->
return unless @_viewModels[ref]
ko.mapping.fromJS(attrs, @_viewModels[ref])
get: (ref)->
return unless ref
@_viewModels[ref]
remove: (ref)->
delete @_viewModels[ref]
reset: (vals={})->
@_viewModels = vals
collectionEventCallbacks =
# All those methods are called in the context of the collection...
# so, @ = collection here
add: (model, collection, options)->
ret = @_knockit.make(model.cid, model.attributes)
obs = @getObservable()
index = @indexOf(model)
index = @length if index == -1
obs.models.splice(index, 0, ret) unless _.contains(_.pluck(obs.models(), "ref"), ret.ref)
ret
remove: (model, collection, options)->
@getObservable().models.remove(@_knockit.get(model.cid))
@_knockit.remove(model.cid)
change: (model, options)->
obs = @_knockit.change(model.cid, model.changedAttributes())
reset: (collection, options)->
obs = @_knockit._viewModels.me
@_knockit.reset({ me: obs })
obs.models.removeAll()
for m in @models
ret = @_knockit.make(m.cid, m.attributes)
obs.models.push ret unless _.contains(_.pluck(obs.models(), "ref"), ret.ref)
method_missing: (eventName)->
()->
console.warn("No handler defined for #{eventName}, with: ", arguments)
onCollectionEvent = ()->
eventName = Array.prototype.shift.call arguments, 1
cb = collectionEventCallbacks[eventName] || collectionEventCallbacks.method_missing(eventName)
cb?.apply(this, arguments)
class Backbone.ObservableCollection extends Backbone.Collection
getObservable: ()->
@_knockit ?= new KnockItObservables
unless ret = @_knockit.get("me")
@bind "all", => onCollectionEvent.apply(this, arguments)
ret = @_knockit._viewModels["me"] = { models: ko.observableArray([]) }
collectionEventCallbacks.reset.apply(this)
ret
getObservableModel: (cid)->
model = @getByCid(cid)
return unless model && model instanceof Backbone.Model
@_knockit.get(model.cid) || @_knockit.make(model.cid, model.attributes)
Backbone.Model::getObservable = ()->
unless @collection instanceof Backbone.ObservableCollection
throw "The model has to be linked to an observable collection to get an Observable"
@collection.getObservableModel(@cid)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment