/*
 * Introduce a typal object to make classical/prototypal patterns easier
 * plus mixins and AOP sugar
 * */

var typal = (function () {

var regex = /^(before|after)/;

function layerMethod(k, fun) {
    var pos = k.match(regex)[0],
        key = k.replace(regex, ''),
        prop = this[key];

    if (pos === 'after') {
        this[key] = function () { var ret = prop.apply(this, arguments); fun.apply(this, arguments); return ret;}
    } else if (pos === 'before') {
        this[key] = function () { fun.apply(this, arguments); var ret = prop.apply(this, arguments); return ret;}
    }
}

function typal_mix() {
    var self = this;
    for(var i=0,o,k; i<arguments.length; i++) {
        o=arguments[i];
        for(k in o) {
            if ({}.hasOwnProperty.call(o, k)) {
                if(k.match(regex) && this[k.replace(regex, '')])
                    layerMethod.call(this, k, o[k]);
                else
                    this[k] = o[k];
            }
        }
    }
    return this;
}

return {
    // extend object with own typalperties of each argument
    mix: typal_mix,
    // sugar for object begetting and mixing
    // - Object.create(typal).mix(etc, etc);
    // + typal.beget(etc, etc);
    beget: function typal_new() {
        return typal_mix.apply(Object.create(this), arguments);
    },
    // Creates a new Class constructor typald on an object with a constructor method
    construct: function typal_new() {
        var Klass = function(){ return this.constructor.apply(this, arguments); };
        var o = typal_mix.apply(Object.create(this), arguments);
        Klass.prototype = o;
        Klass.prototype.typal = o; // reference to "super"
        return Klass;
    },
    constructor: function typal_constructor() {return this;}
};
})();

if (typeof exports !== 'undefined')
    exports.typal = typal;

/*
 * Introduces a typal object to make classical/prototypal patterns easier
 * Plus some AOP sugar
 *
 * By Zachary Carter <zack.carter@gmail.com>
 * MIT Licensed
 * */

var typal = (function () {

var create = Object.create || function (o) { function F(){}; F.prototype = o; return new F(); };
var position = /^(before|after)/;

// basic method layering
// always returns original method's return value
function layerMethod(k, fun) {
    var pos = k.match(position)[0],
        key = k.replace(position, ''),
        prop = this[key];

    if (pos === 'after') {
        this[key] = function () {
            var ret = prop.apply(this, arguments);
            fun.apply(this, arguments);
            return ret;
        }
    } else if (pos === 'before') {
        this[key] = function () {
            fun.apply(this, arguments); 
            var ret = prop.apply(this, arguments); 
            return ret;
        }
    }
}

// mixes each argument's own properties into calling object,
// overwriting them or layering them. i.e. an object method 'meth' is
// layered by mixin methods 'beforemeth' or 'aftermeth'
function typal_mix() {
    var self = this;
    for(var i=0,o,k; i<arguments.length; i++) {
        o=arguments[i];
        for(k in o) {
            if (Object.prototype.hasOwnProperty.call(o, k)) {
                if(k.match(position) && typeof this[k.replace(position, '')] === 'function')
                    layerMethod.call(this, k, o[k]);
                else
                    this[k] = o[k];
            }
        }
    }
    return this;
}

return {
    // extend object with own typalperties of each argument
    mix: typal_mix,

    // sugar for object begetting and mixing
    // - Object.create(typal).mix(etc, etc);
    // + typal.beget(etc, etc);
    beget: function typal_beget() {
        return arguments.length ? typal_mix.apply(create(this), arguments) : create(this);
    },

    // Creates a new Class constructor based on an object with a constructor method
    construct: function typal_construct() {
        var o = typal_mix.apply(create(this), arguments);
        var constructor = o.constructor;
        var Klass = o.constructor = function () { return constructor.apply(this, arguments); };
        Klass.prototype = o;
        Klass.mix = typal_mix; // allow for easy singleton property extension
        return Klass;
    },

    // no op
    constructor: function typal_constructor() { return this; }
};
})();

if (typeof exports !== 'undefined')
    exports.typal = typal;

Update typal