vitro/webapp/web/src/lang/declare.js

156 lines
No EOL
5.1 KiB
JavaScript

/*
Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
modified BSD license. For more information on Dojo licensing, see:
http://dojotoolkit.org/community/licensing.shtml
*/
dojo.provide("dojo.lang.declare");
dojo.require("dojo.lang.common");
dojo.require("dojo.lang.extras");
/*
* Creates a constructor: inherit and extend
*
* - inherits from "superclass(es)"
*
* "superclass" argument may be a Function, or an array of
* Functions.
*
* If "superclass" is an array, the first element is used
* as the prototypical ancestor and any following Functions
* become mixin ancestors.
*
* All "superclass(es)" must be Functions (not mere Objects).
*
* Using mixin ancestors provides a type of multiple
* inheritance. Mixin ancestors prototypical
* properties are copied to the subclass, and any
* inializater/constructor is invoked.
*
* - "props" are copied to the constructor prototype
*
* - name of the class ("className" argument) is stored in
* "declaredClass" property
*
* - An initializer function can be specified in the "init"
* argument, or by including a function called "initializer"
* in "props".
*
* - Superclass methods (inherited methods) can be invoked using "inherited" method:
*
* this.inherited(<method name>[, <argument array>]);
*
* - inherited will continue up the prototype chain until it finds an implementation of method
* - nested calls to inherited are supported (i.e. inherited method "A" can succesfully call inherited("A"), and so on)
*
* Aliased as "dojo.declare"
*
* Usage:
*
* dojo.declare("my.classes.bar", my.classes.foo, {
* initializer: function() {
* this.myComplicatedObject = new ReallyComplicatedObject();
* },
* someValue: 2,
* aMethod: function() { doStuff(); }
* });
*
*/
dojo.lang.declare = function(className /*string*/, superclass /*function || array*/, init /*function*/, props /*object*/){
// FIXME: parameter juggling for backward compat ... deprecate and remove after 0.3.*
// new sig: (className (string)[, superclass (function || array)[, init (function)][, props (object)]])
// old sig: (className (string)[, superclass (function || array), props (object), init (function)])
if ((dojo.lang.isFunction(props))||((!props)&&(!dojo.lang.isFunction(init)))){
var temp = props;
props = init;
init = temp;
}
var mixins = [ ];
if (dojo.lang.isArray(superclass)) {
mixins = superclass;
superclass = mixins.shift();
}
if(!init){
init = dojo.evalObjPath(className, false);
if ((init)&&(!dojo.lang.isFunction(init))){ init = null };
}
var ctor = dojo.lang.declare._makeConstructor();
var scp = (superclass ? superclass.prototype : null);
if(scp){
scp.prototyping = true;
ctor.prototype = new superclass();
scp.prototyping = false;
}
ctor.superclass = scp;
ctor.mixins = mixins;
for(var i=0,l=mixins.length; i<l; i++){
dojo.lang.extend(ctor, mixins[i].prototype);
}
ctor.prototype.initializer = null;
ctor.prototype.declaredClass = className;
if(dojo.lang.isArray(props)){
dojo.lang.extend.apply(dojo.lang, [ctor].concat(props));
}else{
dojo.lang.extend(ctor, (props)||{});
}
dojo.lang.extend(ctor, dojo.lang.declare.base);
ctor.prototype.constructor = ctor;
ctor.prototype.initializer=(ctor.prototype.initializer)||(init)||(function(){});
dojo.lang.setObjPathValue(className, ctor, null, true);
}
dojo.lang.declare._makeConstructor = function() {
return function(){
// get the generational context (which object [or prototype] should be constructed)
var self = this._getPropContext();
var s = self.constructor.superclass;
if((s)&&(s.constructor)){
if(s.constructor==arguments.callee){
// if this constructor is invoked directly (my.ancestor.call(this))
this.inherited("constructor", arguments);
}else{
this._inherited(s, "constructor", arguments);
}
}
var m = (self.constructor.mixins)||([]);
for(var i=0,l=m.length; i<l; i++) {
(((m[i].prototype)&&(m[i].prototype.initializer))||(m[i])).apply(this, arguments);
}
if((!this.prototyping)&&(self.initializer)){
self.initializer.apply(this, arguments);
}
}
}
dojo.lang.declare.base = {
_getPropContext: function() { return (this.___proto||this); },
// caches ptype context and calls method on it
_inherited: function(ptype, method, args){
var stack = this.___proto;
this.___proto = ptype;
var result = ptype[method].apply(this,(args||[]));
this.___proto = stack;
return result;
},
// invokes ctor.prototype.method, with args, in our context
inheritedFrom: function(ctor, prop, args){
var p = ((ctor)&&(ctor.prototype)&&(ctor.prototype[prop]));
return (dojo.lang.isFunction(p) ? p.apply(this, (args||[])) : p);
},
// searches backward thru prototype chain to find nearest ancestral instance of prop
inherited: function(prop, args){
var p = this._getPropContext();
do{
if((!p.constructor)||(!p.constructor.superclass)){return;}
p = p.constructor.superclass;
}while(!(prop in p));
return (dojo.lang.isFunction(p[prop]) ? this._inherited(p, prop, args) : p[prop]);
}
}
dojo.declare = dojo.lang.declare;