PubSub Mixin

by landau

JavaScript

(function() {
    "use strict";

    function PubSub() {
        // use PubSub.call(this) to ammend this to your object
        this.observers = {};
    }

    PubSub.prototype = {
        sub: function(event, fn, ctx) {
            if (!this.observers[event]) {
                this.observers[event] = [];
            }
            fn.ctx = ctx;
            this.observers[event].push(fn);
        },
        pub: function(event) {
            var args = Array.prototype.slice.call(arguments, 1);
            if (this.observers[event]) {

                this.observers[event].forEach(function(fn) {
                    fn.apply(fn.ctx || this, args);
                }, this);
            }
        }
    };
    PubSub.call(PubSub.prototype);

    PubSub.installTo = function(obj) {
        var proto = PubSub.prototype;
        for (var prop in proto) {
            if (proto.hasOwnProperty(prop) && typeof proto[prop] === 'function') {
                obj[prop] = proto[prop];
            }
        }
    };


    var log = function log() {
        console.log.apply(console, arguments);
    };

    var dir = function dir() {
        console.dir.apply(console, arguments);
    };


    function Person(name) {
        PubSub.call(this);
        Object.defineProperty(this, 'name', {
            set: function(val) {
                name = val;
                this.pub('change:name', val);
            },
            get: function () {
               return name;
            }
        });
    }
    PubSub.installTo(Person.prototype);


    var bob = new Person('bob');

    bob.sub('change:name', function(name) {
        log('Name changed to ' + name, this.name);
    });
    bob.name = 'joe';

}());