UNPKG

halo

Version:

Keeping your Backbone.js straight with Socket.io

190 lines (153 loc) 5.46 kB
"use strict"; var View = require('./view.js').View; var Storable = require('../storable.js').Storable; var Collection = require('../collection.js').Collection; var Model = require('../model.js').Model; var und = require('underscore'); var SocketView = View.extend({ initializer : function(obj, name, routes) { this.parent(View).constructor(name); this._clients = {}; this.obj = obj || this.obj; this.routes = routes || this.routes; if(this.obj && this.obj.inheritsFrom(Storable) && this.obj.getCollection) { this.container = this.obj.getCollection(); if(!this.container) { throw "Socket View requires a class with a collection defined." } } else { throw "Socket view requires an obj to be set to a Storable class." } }, properties : { routes : undefined, obj : undefined, bindToClient : function(client, object) { client.bindOnce(object, 'change', function(event) { this._processEvent(client, event); }, this, this.name); client.bindOnce(object, 'add', function(event) { this._processEvent(client, event); }, this, this.name); client.bindOnce(object, 'remove', function(event) { this._processEvent(client, event); }, this, this.name); client.bindOnce(object, 'destroy', function(event) { this._processEvent(client, event); }, this, this.name); }, unbindFromClient : function (client, object) { client.unbindOnce(object, 'change'); client.unbindOnce(object, 'add'); client.unbindOnce(object, 'remove'); client.unbindOnce(object, 'destroy'); }, _processEvent : function(client, event) { var serialized = false; var view = false; // Check if it's the container. If so, render each object // in the event if (event.sender === this.container) { serialized = this.renderAll(client, event.payload); view = this; } // If not, is it and instance of the view obj or one of its sub-itemview's objs? else { view = this; while(view) { if (event.sender instanceof view.obj) { // We found the view that can render the object(s) in this event if(view.obj.inheritsFrom(Collection)) { serialized = view.render(client, event.sender, false, event.payload); } else if(view.obj.inheritsFrom(Model)) { serialized = view.render(client, event.sender, event.payload); } break; } view = view.itemView; } } if(view && serialized && !und.isEmpty(serialized)) { event.payload = serialized; view._forwardEventToClient(client, event); } }, _forwardEventToClient : function(client, event) { var eventName = "" if(event.sender.id) { eventName = this.name + "/" + event.sender.id + ":server" + event.name; } else { eventName = this.name + ":server" + event.name; } if(event.payload && !und.isEmpty(event.payload)) { client.emit(eventName, event.payload); } }, openRoutes : function(client) { if (!this._clients[client.id]) { this._clients[client.id] = client; if(this.routes) { und.each(this.routes, function(func, action) { var route = this.name + ":" + action; client.onMessage(route, this[func], this); }, this); } client.onMessage(this.name + ":disconnect", function(client, data) { if(data && data.id) { var object = this.container.get(data.id); this.unbindFromClient(client, object); } else { this.unbindFromClient(client, this.container); } }, this); client.onMessage('disconnect', function() { if (this._clients[client.id]) { delete this._clients[client.id]; this.disconnect(client); } }, this); } }, render : function() { return false; }, renderAll : function(client, items) { var serialized = []; var requestedItems = (items) ? und.intersection(this.container.items, items) : this.container.items und.each(requestedItems, function(item) { var object = this.render(client, item); if (object && !und.isEmpty(object)) { serialized.push(object); } }, this); return serialized; }, create : function(client, data) { var object = this.container.create(data); this.bindToClient(client, object); return this.render(client, object); }, read : function(client, data) { var object = this.container.get(data.id); this.bindToClient(client, object) return this.render(client, object); }, destroy : function(client, data) { var object = this.container.get(data.id); object.destroy(); this.unbindFromClient(client, object); return data; }, list : function(client, data) { this.bindToClient(client, this.container); return this.renderAll(client);; }, disconnect : function() { } } }); exports.SocketView = SocketView;