Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial commit

  • Loading branch information...
commit 5a353b8f242edcf7a95fc6bd6370b89d652928f7 0 parents
@scttnlsn authored
1  .gitignore
@@ -0,0 +1 @@
+node_modules
9 example/app.js
@@ -0,0 +1,9 @@
+var express = require('express'),
+ backboneio = require('../lib/index'),
+ app = express.createServer();
+
+app.use(express.static(__dirname));
+app.listen(3000);
+console.log('http://localhost:3000/');
+
+backboneio.connect(app, { messages: new backboneio.Backend() });
75 example/index.html
@@ -0,0 +1,75 @@
+<html>
+<head>
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
+ <script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
+ <script src="http://documentcloud.github.com/backbone/backbone-min.js"></script>
+ <script src="/socket.io/socket.io.js"></script>
+ <script src="/socket.io/backbone.io.js"></script>
+
+ <script>
+ var Message = Backbone.Model.extend();
+
+ var Messages = Backbone.Collection.extend({
+
+ // Specify the backend with which to sync
+ backend: 'messages',
+
+ model: Message,
+
+ initialize: function() {
+ // Setup default backend bindings
+ // (see lib/browser.js for details).
+ this.bindBackend();
+ }
+
+ });
+
+ var MessagesView = Backbone.View.extend({
+
+ events: {
+ 'click .send': 'send'
+ },
+
+ initialize: function(options) {
+ _.bindAll(this, 'render', 'send');
+
+ this.collection.bind('add', this.render);
+ this.collection.bind('reset', this.render);
+ this.collection.fetch();
+
+ this.template = _.template($('#messages-template').html());
+ },
+
+ render: function() {
+ $(this.el).html(this.template());
+
+ this.collection.each(function(message) {
+ this.$('ul').append($('<li>', { html: message.get('text') }));
+ });
+
+ return this;
+ },
+
+ send: function() {
+ this.collection.create({ text: this.$('.message').val() });
+ this.$('.message').val('');
+ }
+
+ });
+
+ $(function() {
+ new MessagesView({ el: $('#messages'), collection: new Messages() }).render();
+ });
+ </script>
+
+ <script id="messages-template" type="text/template">
+ <ul></ul>
+ <input class="message" type="text">
+ <input class="send" type="submit" value="Send">
+ </script>
+</head>
+<body>
+ <h1>Messages</h1>
+ <div id="messages"></div>
+</body>
+</html>
29 lib/backend.js
@@ -0,0 +1,29 @@
+var _ = require('underscore');
+
+module.exports = function() {
+ var models = {};
+
+ this.create = function(model) {
+ model.id = _.uniqueId('s');
+ models[model.id] = model;
+ return model;
+ };
+
+ this.read = function(model) {
+ if (model.id) {
+ return models[model.id];
+ } else {
+ return _.values(models);
+ }
+ };
+
+ this.update = function(model) {
+ models[model.id] = model;
+ return model;
+ };
+
+ this.delete = function(model) {
+ delete models[model.id];
+ return model;
+ };
+};
75 lib/browser.js
@@ -0,0 +1,75 @@
+(function() {
+ var socket = io.connect();
+ var origSync = Backbone.sync;
+
+ Backbone.sync = function(method, model, options) {
+ var backend = model.backend || model.collection.backend;
+
+ if (backend) {
+ // Use Socket.IO backend
+ socket.of(backend).emit('sync', method, model.toJSON(), function(resp) {
+ if (resp) {
+ options.success(resp);
+ } else {
+ options.error('Record not found');
+ }
+ });
+ } else {
+ // Call the original Backbone.sync
+ origSync(method, model, options);
+ }
+ };
+
+ var Helpers = {
+ // Listen for backend notifications and update the
+ // collection models accordingly.
+ bindBackend: function() {
+ var self = this;
+
+ this.bind('backend:create', function(model) {
+ self.add(model);
+ });
+ this.bind('backend:update', function(model) {
+ self.get(model.id).set(model);
+ });
+ this.bind('backend:delete', function(model) {
+ self.remote(model);
+ });
+ }
+ };
+
+ var inherit = function(Parent, Child, mixins) {
+ var Func = function() {};
+ Func.prototype = Parent.prototype;
+
+ mixins || (mixins = [])
+ mixins.forEach(function(mixin) {
+ _.extend(Func.prototype, mixin);
+ });
+
+ Child.prototype = new Func();
+ Child.prototype.constructor = Child;
+
+ return _.extend(Child, Parent);
+ };
+
+ Backbone.Collection = (function(Parent) {
+ // Override the parent constructor
+ var Child = function() {
+ Parent.apply(this, arguments);
+
+ if (this.backend) {
+ var trigger = this.trigger.bind(this);
+
+ socket.of(this.backend).on('synced', function(event, method, resp) {
+ trigger(event, method, resp);
+ trigger(event + ':' + method, resp);
+ });
+ }
+ };
+
+ // Inherit everything else from the parent
+ return inherit(Parent, Child, [Helpers]);
+ })(Backbone.Collection);
+
+})();
30 lib/index.js
@@ -0,0 +1,30 @@
+var socketio = require('socket.io');
+
+exports.Backend = require('./backend');
+
+exports.connect = function(listen, backends, options) {
+ // Configure default options
+ options || (options = {});
+ options.event || (options.event = 'backend');
+
+ var io = socketio.listen(listen);
+
+ // Serve client-side code
+ io.static.add('/backbone.io.js', { file: __dirname + '/browser.js' });
+
+ // Listen for backend syncs
+ Object.keys(backends).forEach(function(backend) {
+ io.of(backend).on('connection', function(socket) {
+ socket.on('sync', function(method, model, callback) {
+ var resp = backends[backend][method](model);
+ callback(resp);
+
+ if (resp) {
+ socket.broadcast.emit('synced', options.event, method, resp);
+ }
+ });
+ });
+ });
+
+ return io;
+};
18 package.json
@@ -0,0 +1,18 @@
+{
+ "name": "backbone.io",
+ "version": "0.1.0",
+ "description": "Backbone.js sync via Socket.IO",
+ "homepage": "http://github.com/scttnlsn/backbone.io",
+ "author": "Scott Nelson <scottbnel@gmail.com>",
+ "main": "./lib/index",
+
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/scttnlsn/backbone.io.git"
+ },
+
+ "dependencies": {
+ "socket.io": ">= 0.8.7",
+ "underscore": ">= 1.2.1"
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.