Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2150 mathias 1
if(!dojo._hasResource["dojo._base.declare"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2
dojo._hasResource["dojo._base.declare"] = true;
3
dojo.provide("dojo._base.declare");
4
dojo.require("dojo._base.lang");
5
 
6
// this file courtesy of the TurboAjax group, licensed under a Dojo CLA
7
 
8
dojo.declare = function(/*String*/ className, /*Function|Function[]*/ superclass, /*Object*/ props){
9
	//	summary:
10
	//		Create a feature-rich constructor from compact notation
11
	//	className:
12
	//		The name of the constructor (loosely, a "class")
13
	//		stored in the "declaredClass" property in the created prototype
14
	//	superclass:
15
	//		May be null, a Function, or an Array of Functions. If an array,
16
	//		the first element is used as the prototypical ancestor and
17
	//		any following Functions become mixin ancestors.
18
	//	props:
19
	//		An object whose properties are copied to the
20
	//		created prototype.
21
	//		Add an instance-initialization function by making it a property
22
	//		named "constructor".
23
	//	description:
24
	//		Create a constructor using a compact notation for inheritance and
25
	//		prototype extension.
26
	//
27
	//		All superclasses (including mixins) must be Functions (not simple Objects).
28
	//
29
	//		Mixin ancestors provide a type of multiple inheritance. Prototypes of mixin
30
	//		ancestors are copied to the new class: changes to mixin prototypes will
31
	//		not affect classes to which they have been mixed in.
32
	//
33
	//		"className" is cached in "declaredClass" property of the new class.
34
	//
35
	//	example:
36
	//	|	dojo.declare("my.classes.bar", my.classes.foo, {
37
	//	|		// properties to be added to the class prototype
38
	//	|		someValue: 2,
39
	//	|		// initialization function
40
	//	|		constructor: function(){
41
	//	|			this.myComplicatedObject = new ReallyComplicatedObject();
42
	//	|		},
43
	//	|		// other functions
44
	//	|		someMethod: function(){
45
	//	|			doStuff();
46
	//	|		}
47
	//	|	);
48
 
49
	// argument juggling (deprecated)
50
	if(dojo.isFunction(props)||(arguments.length>3)){
51
		dojo.deprecated("dojo.declare: for class '" + className + "' pass initializer function as 'constructor' property instead of as a separate argument.", "", "1.0");
52
		var c = props;
53
		props = arguments[3] || {};
54
		props.constructor = c;
55
	}
56
	// process superclass argument
57
	// var dd=dojo.declare, mixins=null;
58
	var dd=arguments.callee, mixins=null;
59
	if(dojo.isArray(superclass)){
60
		mixins = superclass;
61
		superclass = mixins.shift();
62
	}
63
	// construct intermediate classes for mixins
64
	if(mixins){
65
		for(var i=0, m; i<mixins.length; i++){
66
			m = mixins[i];
67
			if(!m){throw("Mixin #" + i + " to declaration of " + className + " is null. It's likely a required module is not loaded.")};
68
			superclass = dd._delegate(superclass, m);
69
		}
70
	}
71
	// prepare values
72
	var init=(props||0).constructor, ctor=dd._delegate(superclass), fn;
73
	// name methods (experimental)
74
	for(var i in props){if(dojo.isFunction(fn=props[i])&&(!0[i])){fn.nom=i;}}
75
	// decorate prototype
76
	dojo.extend(ctor, {declaredClass: className, _constructor: init, preamble: null}, props||0);
77
	// special help for IE
78
	ctor.prototype.constructor = ctor;
79
	// create named reference
80
	return dojo.setObject(className, ctor); // Function
81
}
82
 
83
dojo.mixin(dojo.declare, {
84
	_delegate: function(base, mixin){
85
		var bp = (base||0).prototype, mp = (mixin||0).prototype;
86
		// fresh constructor, fresh prototype
87
		var ctor = dojo.declare._makeCtor();
88
		// cache ancestry
89
		dojo.mixin(ctor, {superclass: bp, mixin: mp, extend: dojo.declare._extend});
90
		// chain prototypes
91
		if(base){ctor.prototype = dojo._delegate(bp);}
92
		// add mixin and core
93
		dojo.extend(ctor, dojo.declare._core, mp||0, {_constructor: null, preamble: null});
94
		// special help for IE
95
		ctor.prototype.constructor = ctor;
96
		// name this class for debugging
97
		ctor.prototype.declaredClass = (bp||0).declaredClass + '_' + (mp||0).declaredClass;
98
		return ctor;
99
	},
100
	_extend: function(props){
101
		for(var i in props){if(dojo.isFunction(fn=props[i])&&(!0[i])){fn.nom=i;}}
102
		dojo.extend(this, props);
103
	},
104
	_makeCtor: function(){
105
		// we have to make a function, but don't want to close over anything
106
		return function(){ this._construct(arguments); }
107
	},
108
	_core: {
109
		_construct: function(args){
110
			var c=args.callee, s=c.superclass, ct=s&&s.constructor, m=c.mixin, mct=m&&m.constructor, a=args, ii, fn;
111
			// side-effect of = used on purpose here, lint may complain, don't try this at home
112
			if(a[0]){
113
				// FIXME: preambles for each mixin should be allowed
114
				// FIXME:
115
				//		should we allow the preamble here NOT to modify the
116
				//		default args, but instead to act on each mixin
117
				//		independently of the class instance being constructed
118
				//		(for impdedence matching)?
119
 
120
				// allow any first argument w/ a "preamble" property to act as a
121
				// class preamble (not exclusive of the prototype preamble)
122
				if(/*dojo.isFunction*/(fn = a[0]["preamble"])){
123
					a = fn.apply(this, a) || a;
124
				}
125
			}
126
			// prototype preamble
127
			if(fn=c.prototype.preamble){a = fn.apply(this, a) || a;}
128
			// FIXME:
129
			//		need to provide an optional prototype-settable
130
			//		"_explicitSuper" property which disables this
131
			// initialize superclass
132
			if(ct&&ct.apply){ct.apply(this, a);}
133
			// initialize mixin
134
			if(mct&&mct.apply){mct.apply(this, a);}
135
			// initialize self
136
			if(ii=c.prototype._constructor){ii.apply(this, args);}
137
			// post construction
138
			if(this.constructor.prototype==c.prototype && (ct=this.postscript)){ct.apply(this, args)};
139
		},
140
		_findMixin: function(mixin){
141
			var c = this.constructor, p, m;
142
			while(c){
143
				p = c.superclass;
144
				m = c.mixin;
145
				if(m==mixin || (m instanceof mixin.constructor)){return p;}
146
				if(m && (m=m._findMixin(mixin))){return m;}
147
				c = p && p.constructor;
148
			}
149
		},
150
		_findMethod: function(name, method, ptype, has){
151
			// consciously trading readability for bytes and speed in this low-level method
152
			var p=ptype, c, m, f;
153
			do{
154
				c = p.constructor;
155
				m = c.mixin;
156
				// find method by name in our mixin ancestor
157
				if(m && (m=this._findMethod(name, method, m, has))){return m};
158
				// if we found a named method that either exactly-is or exactly-is-not 'method'
159
				if((f=p[name])&&(has==(f==method))){return p};
160
				// ascend chain
161
				p = c.superclass;
162
			}while(p);
163
			// if we couldn't find an ancestor in our primary chain, try a mixin chain
164
			return !has && (p=this._findMixin(ptype)) && this._findMethod(name, method, p, has);
165
		},
166
		inherited: function(name, args, newArgs){
167
			// optionalize name argument (experimental)
168
			var a = arguments;
169
			if(!dojo.isString(a[0])){newArgs=args; args=name; name=args.callee.nom;}
170
			var c=args.callee, p=this.constructor.prototype, a=newArgs||args, fn, mp;
171
			// if not an instance override
172
			if(this[name]!=c || p[name]==c){
173
				mp = this._findMethod(name, c, p, true);
174
				if(!mp){throw(this.declaredClass + ': name argument ("' + name + '") to inherited must match callee (declare.js)');}
175
				p = this._findMethod(name, c, mp, false);
176
			}
177
			fn = p && p[name];
178
			// FIXME: perhaps we should throw here?
179
			if(!fn){console.debug(mp.declaredClass + ': no inherited "' + name + '" was found (declare.js)'); return;}
180
			// if the function exists, invoke it in our scope
181
			return fn.apply(this, a);
182
		}
183
	}
184
});
185
 
186
}