/* ** base.js -- base class for better OO inheritance in JavaScript ** Copyright (c) 2006 Dean Edwards ** Copyright (c) 2007 Ralf S. Engelschall ** Licensed under LGPL ** ** 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 */ };