Skip to content

Instantly share code, notes, and snippets.

@thelinuxlich
Created February 17, 2011 19:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thelinuxlich/832422 to your computer and use it in GitHub Desktop.
Save thelinuxlich/832422 to your computer and use it in GitHub Desktop.
Knockout.live.plugin.coffee
###
Knockout Live plugin
http://github.com/thelinuxlich/knockout.live.plugin
Copyright 2011, Alisson Cavalcante Agiani
Licensed under the MIT license.
http://github.com/thelinuxlich/knockout.live.plugin/MIT-LICENSE.txt
Date: Mon Feb 01 09:00:29 2011 -0300
###
# isArray helper
ko.utils.isArray = (obj) -> toString.call(obj) is "[object Array]"
# Syntactic sugar
KO = (value) ->
if ko.utils.isArray(value) is true
ko.observableArray value
else if typeof value is "function"
if arguments.length > 1
ko.dependentObservable value,arguments[1]
else
return ko.dependentObservable(value)
else
ko.observable value
# Cache to fasten varname searches
ko.utils.cachedVarnameReferences = {}
# Wraps socket.io client and messaging for knockout observables
ko.utils.socketConnect = (address,port) ->
ko.socket = new io.Socket(address, {port: port, rememberTransport: false})
ko.socket.connect()
ko.socket.on 'message', (obj) ->
if obj.msg.varname in ko.utils.cachedVarnameReferences
temporaryViewModelField = ko.utils.cachedVarnameReferences[obj.msg.varname]
else
obj_tree = obj.msg.varname.split "."
temporaryViewModelField = window[obj_tree.splice(0,1)]
for i in [0..obj_tree.length -1]
temporaryViewModelField = temporaryViewModelField[obj_tree[i]]
if i + 1 < obj_tree.length
if ko.isObservable(temporaryViewModelField)
temporaryViewModelField = temporaryViewModelField()
ko.utils.cachedVarnameReferences[obj.msg.varname] = temporaryViewModelField
temporaryViewModelField({koValue: obj.msg.value,sync: false})
# Custom writable dependent observable that handles synchronizing with node server
Function.prototype.live = (varname) ->
underlyingObservable = @
obs = ko.dependentObservable
read: underlyingObservable
write: (value) ->
if typeof value is "object" and value.sync is false and value.koValue isnt undefined
underlyingObservable value.koValue
else if typeof value is "object" and value.koValue isnt undefined
underlyingObservable value.koValue
ko.socket.send {varname: varname,value: value.koValue}
else
underlyingObservable value
ko.socket.send {varname: varname,value: value}
# This is needed for observableArrays
if ko.utils.isArray(underlyingObservable()) is true
ko.utils.arrayForEach ["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], (methodName) ->
obs[methodName] = ->
methodCallResult = underlyingObservable[methodName].apply underlyingObservable(), arguments
ko.socket.send {varname: varname,value: underlyingObservable()}
underlyingObservable.valueHasMutated()
methodCallResult
obs.slice = -> underlyingObservable[methodName].apply underlyingObservable(), arguments
obs.remove = (valueOrPredicate) ->
underlyingArray = underlyingObservable()
remainingValues = []
removedValues = []
predicate = if typeof valueOrPredicate is "function" then valueOrPredicate else (value) -> value is valueOrPredicate
for i in [0..underlyingArray.length -1]
value = underlyingArray[i]
if !predicate(value)
remainingValues.push value
else
removedValues.push value
underlyingObservable remainingValues
ko.socket.send {varname: varname,value: underlyingObservable()}
removedValues
obs.removeAll = (arrayOfValues) ->
# If you passed zero args, we remove everything
if arrayOfValues is undefined
allValues = underlyingObservable()
underlyingObservable []
ko.socket.send {varname: varname,value: underlyingObservable()}
allValues
# If you passed an arg, we interpret it as an array of entries to remove
if !arrayOfValues
return []
elements = underlyingObservable.remove (value) -> ko.utils.arrayIndexOf(arrayOfValues, value) >= 0
ko.socket.send {varname: varname,value: underlyingObservable()}
elements
obs.destroy = (valueOrPredicate) ->
predicate = if typeof valueOrPredicate is "function" then valueOrPredicate else (value) -> value is valueOrPredicate
for i in [underlyingObservable().length - 1..0]
value = underlyingObservable()[i]
if predicate(value)
underlyingObservable()[i]["_destroy"] = true
underlyingObservable.valueHasMutated()
ko.socket.send {varname: varname,value: underlyingObservable()}
obs.destroyAll = (arrayOfValues) ->
# If you passed zero args, we destroy everything
if arrayOfValues is undefined
result = underlyingObservable.destroy -> true
ko.socket.send {varname: varname,value: underlyingObservable()}
return result
# If you passed an arg, we interpret it as an array of entries to destroy
if !arrayOfValues
return []
result = underlyingObservable.destroy (value) ->
ko.utils.arrayIndexOf(arrayOfValues, value) >= 0
ko.socket.send {varname: varname,value: underlyingObservable()}
result
obs.indexOf = (item) -> ko.utils.arrayIndexOf(underlyingObservable(), item)
obs.replace = (oldItem, newItem) ->
index = underlyingObservable.indexOf(oldItem)
if index >= 0
underlyingObservable()[index] = newItem
underlyingObservable.valueHasMutated()
ko.socket.send {varname: varname,value: underlyingObservable()}
obs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment