Source: septima.js

var Septima = {
            
    Class: function () {
        var len = arguments.length;
        var P = arguments[0];
        var F = arguments[len-1];

        var C = typeof F.initialize == "function" ?
            F.initialize :
            function(){ P.apply(this, arguments); };

        if (len > 1) {
            var newArgs = [C, P].concat(
                    Array.prototype.slice.call(arguments).slice(1, len-1), F);
            Septima.inherit.apply(null, newArgs);
        } else {
            C.prototype = F;
        }
        return C;
    },

    bind: function(func, object) {
        // create a reference to all arguments past the second one
        var args = Array.prototype.slice.apply(arguments, [2]);
        return function() {
            // Push on any additional arguments from the actual function call.
            // These will come after those sent to the bind call.
            var newArgs = args.concat(
                Array.prototype.slice.apply(arguments, [0])
            );
            return func.apply(object, newArgs);
        };
    },

    extend: function (destination, source) {
        destination = destination || {};
        if (source) {
            for (var property in source) {
                var value = source[property];
                if (value !== undefined) {
                    destination[property] = value;
                }
            }
            if (source.hasOwnProperty && source.hasOwnProperty("toString")) {
                destination.toString = source.toString;
            }
        }
        return destination;
    },

    inherit: function(C, P) {
        var F = function() {};
        F.prototype = P.prototype;
        C.prototype = new F();
        var i, l, o;
        for(i=2, l=arguments.length; i<l; i++) {
            o = arguments[i];
            if(typeof o === "function") {
                o = o.prototype;
            }
            Septima.extend(C.prototype, o);
        }
    },

    version: 'BUILDVERSION'

};

Septima.Events = Septima.Class({

    _listeners: [],
    
    initialize: function () {
        _listeners = [];
    },
    
    /**
     * APIMethod: on
     * Add an event listener
     * 
     * Parameters:
     * event - {String} Name of the event to listen to
     * callback - {Function} Function to call when event fired
     * 
     * Returns:
     * listener - {object} Reference to the listener 
     */
    on: function (event, callback) {
        var listener = {event:event,callback:callback};
        this._listeners.push (listener);
        return listener;
    },

    /**
     * APIMethod: off
     * Remove an event listener
     * 
     * Parameters:
     * listener - {object} Reference to the listener returned by addListener
     */
    off: function (listener) {
        for (var i=0;i<this._listeners.length;i++) {
            if (this._listeners[i] == listener) {
                this._listeners.splice(i,1);
                break;
            }
        }
    },

    /**
     * APIMethod: fireEvent
     * Fire an event with a optional number of arguments 
     * 
     * Parameters:
     * event - {String} Name of the event to listen to
     * parameters - {Object} Optional object parsed to the listener
     */
    fireEvent: function (event, parameters) {
        for (var i=0;i<this._listeners.length;i++) {
            if (this._listeners[i].event == event) {
                if (typeof this._listeners[i].callback !== 'undefined') {
                    this._listeners[i].callback.apply (this,arguments);
                }
            }
        }
    }
    
});