├── README.markdown ├── tests ├── common.js └── testEvents.js └── Staff.js /README.markdown: -------------------------------------------------------------------------------- 1 | # Staff 2 | 3 | Staff is a tool that helps your websites stand up. It's a port of the excelent 4 | Backbone.JS project by Jeremy Ashkenas from Document Cloud. 5 | 6 | Back when I worked at Document Cloud with Jeremy, the code that was to eventually 7 | become backbone really excited me. Since then I've grown fond of vanilla ES5 8 | APIs and wanted a version of backbone that was standalone and more like plain 9 | JavaScript. 10 | 11 | This is a work in progress of that port. 12 | -------------------------------------------------------------------------------- /tests/common.js: -------------------------------------------------------------------------------- 1 | global.Staff = require('../Staff.js'); 2 | global.Assert = require('assert'); 3 | global.expect = expect; 4 | global.fulfill = fulfill; 5 | 6 | var expected = {}; 7 | function expect(name) { 8 | expected[name] = true; 9 | } 10 | function fulfill(name) { 11 | delete expected[name]; 12 | } 13 | process.on('exit', function () { 14 | Object.keys(expected).forEach(function (name) { 15 | throw new Error("Missing expectation " + JSON.stringify(name)); 16 | }); 17 | }); 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/testEvents.js: -------------------------------------------------------------------------------- 1 | require('./common.js'); 2 | 3 | function Custom() {} 4 | Custom.prototype = Object.create(Staff.Events, {constructor: {value: Custom}}); 5 | 6 | [ 7 | function EmitNonExistant() { 8 | var c = new Custom(); 9 | c.emit("DoesNotExist"); 10 | }, 11 | function CatchEvent() { 12 | var c = new Custom(); 13 | var ballObj = {a:"Ball"}; 14 | expect("catch ball"); 15 | 16 | c.on('ball', function (ball) { 17 | Assert.strictEqual(ball, ballObj, "Event should preserve argument"); 18 | fulfill('catch ball'); 19 | }); 20 | c.emit('ball', ballObj); 21 | }, 22 | function RemoveAllEvents() { 23 | var c = new Custom(); 24 | var ballObj = {a:"Ball"}; 25 | c.on('ball', function (ball) { 26 | throw new Error("Should not have called me"); 27 | }); 28 | c.removeListener(); 29 | c.emit('ball', ballObj); 30 | }, 31 | function RemoveGroupOfEvents() { 32 | var c = new Custom(); 33 | var ballObj = {a:"Ball"}; 34 | c.on('ball', function (ball) { 35 | throw new Error("Should not have called me"); 36 | }); 37 | c.removeListener('ball'); 38 | c.emit('ball', ballObj); 39 | }, 40 | function RemoveSingle() { 41 | var c = new Custom(); 42 | var ballObj = {a:"Ball"}; 43 | function callback(ball) { 44 | throw new Error("Should not have called me"); 45 | } 46 | c.on('ball', callback); 47 | c.removeListener('ball', callback); 48 | c.emit('ball', ballObj); 49 | } 50 | ].forEach(function (fn) { fn() }); 51 | 52 | 53 | -------------------------------------------------------------------------------- /Staff.js: -------------------------------------------------------------------------------- 1 | // Inspired heavily by Backbone.js 2 | // Modified to be more node.js and vanilla DOM style 3 | 4 | (function(){ 5 | 6 | var Staff; 7 | if (typeof exports !== 'undefined') { 8 | Staff = exports; 9 | } else { 10 | Staff = this.Staff = {}; 11 | } 12 | 13 | Staff.VERSION = "0.0.1"; 14 | 15 | var Events = { 16 | 17 | addListener: function addListener(evt, callback) { 18 | var calls = this._callbacks || (this._callbacks = {}); 19 | var list = calls[evt] || (calls[evt] = []); 20 | list[list.length] = callback; 21 | return this; 22 | }, 23 | 24 | removeListener: function removeListener(evt, callback) { 25 | if (!evt) { 26 | this._callbacks = {}; 27 | return this; 28 | } 29 | var calls = this._callbacks; 30 | if (!calls) { return this; } 31 | var list = calls[evt]; 32 | if (!list) { return this; } 33 | if (!callback) { 34 | calls[evt] = []; 35 | return this; 36 | } 37 | var index = list.indexOf(callback); 38 | if (index < 0) { return this; } 39 | list.splice(index, 1); 40 | return this; 41 | }, 42 | 43 | emit: function emit(evt) { 44 | var calls = this._callbacks; 45 | if (!calls) { return this; } 46 | var list = calls[evt]; 47 | if (!list) { return this; } 48 | var args = Array.prototype.slice.call(arguments, 1); 49 | for (var i = 0, l = list.length; i < l; i++) { 50 | list[i].apply(this, args); 51 | } 52 | return this; 53 | } 54 | }; 55 | Events.on = Events.addListener; 56 | function Model(attributes, options) { 57 | attributes || (attributes = {}); 58 | } 59 | Model.prototype = Object.create(Events, {constructor: {value: Model}}); 60 | Model.prototype.initialize = function initialize() {}; 61 | Model.prototype.get = function get(attr) { 62 | return this.attributes[attr]; 63 | } 64 | 65 | function Collection(models, options) { 66 | options || (options = {}); 67 | } 68 | Collection.prototype = Object.create(Events, {constructor: {value: Collection}}); 69 | 70 | function Controller(options) { 71 | options || (options = {}); 72 | } 73 | Controller.prototype = Object.create(Events, {constructor: {value: Controller}}); 74 | 75 | function View(options) { 76 | options || (options = {}); 77 | } 78 | View.prototype = Object.create(Events, {constructor: {value: View}}); 79 | 80 | 81 | Staff.Events = Events; 82 | Staff.Model = Model; 83 | Staff.Collection = Collection; 84 | Staff.Controller = Controller; 85 | Staff.View = View; 86 | 87 | }()); 88 | --------------------------------------------------------------------------------