Doesn't look like it handles arrays
I haven't tested this code, but I can tell from the part where it's appending dots that it doesn't handle array indexes. It actually might be pretty easy to fix this: instead of appending things with dots, put them in brackets! That should work for both methods of indexing.
I wrote this. I'm new to angular so it may not be perfect but it is working. I'm also new to GitHub. What is the best way to share my array handling code? I'll paste it here for now. I must saw that angular-node-socketio make angular freaking awesome. Forget meteor and Derby. Angular is a real time platform too, but much more mature. I'd like to update this to use socket.io rooms and channels. Also it would be better if I could share a scope object at any level instead of having one big global sharedModel. Then it would be perfect. This is a good start though and my array solution just makes it better.
At first I just passed the entire array. Doing a chat demo quickly showed me that this solution wouldn't be performant. I ended up doing an index by index comparison with the old array and only emitting those index that are new or different. inserting an item to the front of an array will trigger the worst case scenario where every index doesn't match and the whole array must be sync'd. It's better than doing that every time though I suppose.
Here is the code:
services.coffee:
angular.module('app.services', []) .factory( "sharedModel", ($rootScope) -> model = {} lastModel = angular.copy(model)
syncObject = (parent, src, dst) -> for name of src path = ((if parent then parent + "." else "")) + name # do nothing we are in sync if src[name] is dst[name]
else if typeof src[name] is "object" and not Array.isArray(src[name])
# we are an object, so we need to recurse
syncObject path, src[name], dst[name] or {}
else if Array.isArray(src[name]) and Array.isArray(dst[name])
for arrayItem, i in src[name] when dst[name][i] isnt arrayItem
path = path + "[" + i + "]"
socket.emit "channel",
path: path
value: src[name][i]
dst[name] = angular.copy(src[name])
else
socket.emit "channel",
path: path
value: src[name]
dst[name] = angular.copy(src[name])
set = (obj, path, value) -> return angular.copy(value, obj) unless path lastObj = obj property = undefined angular.forEach path.split("."), (name) -> if name if name.indexOf("]") + 1 == name.length tmpName = name.substr(0, name.indexOf("[")) if Array.isArray(obj[tmpName]) index = name.substr( name.indexOf("[") + 1, name.indexOf("]") - name.indexOf("[") - 1) name = name.substr(0, name.indexOf("[")) lastObj = obj return lastObj[name][index] = value else lastObj = obj obj = obj[property = name] lastObj[property] = obj = {} unless obj
if property != undefined
lastObj[property] = angular.copy(value)
TODO: use scoket.io factory
http://www.html5rocks.com/en/tutorials/frameworks/angular-websockets/
socket = io.connect("http://localhost:8889/") socket.on "channel", (message) -> set model, message.path, message.value set lastModel, message.path, message.value $rootScope.sharedModel = model $rootScope.$apply()
$rootScope.$watch "sharedModel", (-> syncObject "", model, lastModel lastModel = angular.copy(model) ), true return model )
server.coffee:
express = require("express") fs = require("fs") io = require("socket.io").listen(8889)
for npm, otherwise use require('./path/to/socket.io')
Reducing socket.io log (debug) statements
io.set "log level", 2
app = express() app.get "/", (req, res) -> res.redirect "index.html"
app.configure -> app.use express.methodOverride() app.use express.bodyParser() app.use express.static(__dirname + "/../_public") app.use express.errorHandler( dumpExceptions: true showStack: true ) app.use app.router
app.listen 3333
set = (obj, path, value) -> lastObj = obj property = undefined path.split(".").forEach (name) -> if name if name.indexOf("]") + 1 == name.length tmpName = name.substr(0, name.indexOf("[")) if Array.isArray(obj[tmpName]) index = name.substr( name.indexOf("[") + 1, name.indexOf("]") - name.indexOf("[") - 1) name = name.substr(0, name.indexOf("[")) lastObj = obj return lastObj[name][index] = value else lastObj = obj obj = obj[property = name] lastObj[property] = obj = {} unless obj
if property != undefined lastObj[property] = value
model = {} clients = []
socket.io
io.sockets.on "connection", (socket) -> clients.push socket
new client is here!
socket.on "channel", (msg) -> console.log "message:" console.log msg set model, msg.path, msg.value clients.forEach (otherClient) -> if socket isnt otherClient console.log "emitting.." otherClient.emit "channel", msg
console.log msg
socket.emit "channel", path: "" value: model