tot - javascript/base.js
Not logged in
[Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Timeline
  [Raw
javascript/base.js
/*
**  base.js -- base class for better OO inheritance in JavaScript
**  Copyright (c) 2006 Dean Edwards <http://dean.edwards.name/>
**  Copyright (c) 2007 Ralf S. Engelschall <rse@engelschall.com>
**  Licensed under LGPL <http://www.gnu.org/licenses/lgpl.txt>
**
**  This is derived from Dean Edwards' "Base" implementation, version
**  1.0.2 as available on http://dean.edwards.name/base/Base.js.
**  It was cleaned up, modified and extended with the feedback
**  under http://dean.edwards.name/weblog/2006/03/base/ by Ralf S.
**  Engelschall.
**
**  $LastChangedDate: $
**  $LastChangedRevision: $
*/

/*  class constructor  */
var Base = function() {
    if (arguments.length) {
        if (this == window) {
            // cast an object to this class
            Base.prototype.extend.call(arguments[0], arguments.callee.prototype);
        } else {
            this.extend(arguments[0]);
        }
    }
};

/*  class version  */
Base.version = "1.0.2+FIXES+RSE";

/*  class method for extending  */
Base.extend = function(_instance, _static) {
    var extend = Base.prototype.extend;
    if (!_instance)
         _instance = {};

    /* build the prototype */
    Base._prototyping = true;
    var _prototype = new this;
    extend.call(_prototype, _instance);
    var constructor = _prototype.constructor;
    _prototype.constructor = this;
    delete Base._prototyping;

    /* create the wrapper for the constructor function */
    var klass = function() {
        if (!Base._prototyping) {
            if (this instanceof klass) {
                constructor.apply(this, arguments);
            } else {
                if (arguments.length)
                    return extend.call(arguments[0], _prototype);
            }
        }
    };
    klass.prototype = _prototype;

    /* build the class interface */
    klass.extend = this.extend;
    klass.implement = this.implement;
    klass.toString = function() {
        return String(constructor);
    };
    extend.call(klass, _static);

    /* single instance */
    var object = constructor ? klass : _prototype;

    /* class initialisation */
    if (object.init instanceof Function)
        object.init();

    return object;
};

/*  class method for multipe inheritance support  */
Base.implement = function() {
    for (var i = 0; i < arguments.length; i++) {
        _interface = arguments[i];
        if (_interface instanceof Function)
            _interface = _interface.prototype;
        this.prototype.extend(_interface);
    }
};

/*  instance method for extending  */
Base.prototype.extend = function(source, value) {
        var extend = Base.prototype.extend;
        if (arguments.length == 2) {
            var ancestor = this[source];
            if (   (ancestor instanceof Function)
                && (value instanceof Function)
                && ancestor.valueOf() != value.valueOf()
                && /\bbase\b/.test(value)               ) {
                var method = value;
                value = function() {
                    var previous = this.base;
                    this.base = ancestor;
                    try {
                        var returnValue = method.apply(this, arguments);
                    } catch (ex) {
                        throw ex;
                    }
                    finally {
                        this.base = previous;
                    }
                    return returnValue;
                };
                // point to the underlying method
                value.valueOf = function() {
                    return method;
                };
                value.toString = function() {
                    return String(method);
                };
            }
            return this[source] = value;
        } else if (source) {
            var _prototype = {toSource: null};
            // do the "toString" and other methods manually
            var _protected = ["toString", "valueOf"];
            // if we are prototyping then include the constructor
            if (Base._prototyping)
                 _protected[2] = "constructor";
            for (var i = 0; (name = _protected[i]); i++) {
                if (source[name] != _prototype[name])
                    extend.call(this, name, source[name]);
            }
            // copy each of the source object's properties to this object
            for (var name in source) {
                if (!_prototype[name])
                    extend.call(this, name, source[name]);
            }
        }
        return this;
};

/*  instance method for invoking ancestor method */
Base.prototype.base = function() {
    /* call this method from any other method to invoke that method's ancestor */
};