]> git.wh0rd.org - tt-rss.git/blame - lib/dojo/_base/declare.js
build custom layer of Dojo to speed up loading of tt-rss (refs #293)
[tt-rss.git] / lib / dojo / _base / declare.js
CommitLineData
2f01fe57
AD
1/*
2 Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
3 Available via Academic Free License >= 2.1 OR the modified BSD license.
4 see: http://dojotoolkit.org/license for details
5*/
6
7
a089699c
AD
8if(!dojo._hasResource["dojo._base.declare"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
9dojo._hasResource["dojo._base.declare"] = true;
2f01fe57 10dojo.provide("dojo._base.declare");
a089699c 11
2f01fe57
AD
12dojo.require("dojo._base.lang");
13dojo.require("dojo._base.array");
a089699c 14
2f01fe57 15(function(){
a089699c
AD
16 var d = dojo, mix = d._mixin, op = Object.prototype, opts = op.toString,
17 xtor = new Function, counter = 0, cname = "constructor";
18
19 function err(msg){ throw new Error("declare: " + msg); }
20
21 // C3 Method Resolution Order (see http://www.python.org/download/releases/2.3/mro/)
22 function c3mro(bases){
23 var result = [], roots = [{cls: 0, refs: []}], nameMap = {}, clsCount = 1,
24 l = bases.length, i = 0, j, lin, base, top, proto, rec, name, refs;
25
26 // build a list of bases naming them if needed
27 for(; i < l; ++i){
28 base = bases[i];
29 if(!base){
30 err("mixin #" + i + " is unknown. Did you use dojo.require to pull it in?");
31 }else if(opts.call(base) != "[object Function]"){
32 err("mixin #" + i + " is not a callable constructor.");
33 }
34 lin = base._meta ? base._meta.bases : [base];
35 top = 0;
36 // add bases to the name map
37 for(j = lin.length - 1; j >= 0; --j){
38 proto = lin[j].prototype;
39 if(!proto.hasOwnProperty("declaredClass")){
40 proto.declaredClass = "uniqName_" + (counter++);
41 }
42 name = proto.declaredClass;
43 if(!nameMap.hasOwnProperty(name)){
44 nameMap[name] = {count: 0, refs: [], cls: lin[j]};
45 ++clsCount;
46 }
47 rec = nameMap[name];
48 if(top && top !== rec){
49 rec.refs.push(top);
50 ++top.count;
51 }
52 top = rec;
53 }
54 ++top.count;
55 roots[0].refs.push(top);
56 }
57
58 // remove classes without external references recursively
59 while(roots.length){
60 top = roots.pop();
61 result.push(top.cls);
62 --clsCount;
63 // optimization: follow a single-linked chain
64 while(refs = top.refs, refs.length == 1){
65 top = refs[0];
66 if(!top || --top.count){
67 // branch or end of chain => do not end to roots
68 top = 0;
69 break;
70 }
71 result.push(top.cls);
72 --clsCount;
73 }
74 if(top){
75 // branch
76 for(i = 0, l = refs.length; i < l; ++i){
77 top = refs[i];
78 if(!--top.count){
79 roots.push(top);
80 }
81 }
82 }
83 }
84 if(clsCount){
85 err("can't build consistent linearization");
86 }
87
88 // calculate the superclass offset
89 base = bases[0];
90 result[0] = base ?
91 base._meta && base === result[result.length - base._meta.bases.length] ?
92 base._meta.bases.length : 1 : 0;
93
94 return result;
95 }
96
97 function inherited(args, a, f){
98 var name, chains, bases, caller, meta, base, proto, opf, pos,
99 cache = this._inherited = this._inherited || {};
100
101 // crack arguments
102 if(typeof args == "string"){
103 name = args;
104 args = a;
105 a = f;
106 }
107 f = 0;
108
109 caller = args.callee;
110 name = name || caller.nom;
111 if(!name){
112 err("can't deduce a name to call inherited()");
113 }
114
115 meta = this.constructor._meta;
116 bases = meta.bases;
117
118 pos = cache.p;
119 if(name != cname){
120 // method
121 if(cache.c !== caller){
122 // cache bust
123 pos = 0;
124 base = bases[0];
125 meta = base._meta;
126 if(meta.hidden[name] !== caller){
127 // error detection
128 chains = meta.chains;
129 if(chains && typeof chains[name] == "string"){
130 err("calling chained method with inherited: " + name);
131 }
132 // find caller
133 do{
134 meta = base._meta;
135 proto = base.prototype;
136 if(meta && (proto[name] === caller && proto.hasOwnProperty(name) || meta.hidden[name] === caller)){
137 break;
138 }
139 }while(base = bases[++pos]); // intentional assignment
140 pos = base ? pos : -1;
141 }
142 }
143 // find next
144 base = bases[++pos];
145 if(base){
146 proto = base.prototype;
147 if(base._meta && proto.hasOwnProperty(name)){
148 f = proto[name];
149 }else{
150 opf = op[name];
151 do{
152 proto = base.prototype;
153 f = proto[name];
154 if(f && (base._meta ? proto.hasOwnProperty(name) : f !== opf)){
155 break;
156 }
157 }while(base = bases[++pos]); // intentional assignment
158 }
159 }
160 f = base && f || op[name];
161 }else{
162 // constructor
163 if(cache.c !== caller){
164 // cache bust
165 pos = 0;
166 meta = bases[0]._meta;
167 if(meta && meta.ctor !== caller){
168 // error detection
169 chains = meta.chains;
170 if(!chains || chains.constructor !== "manual"){
171 err("calling chained constructor with inherited");
172 }
173 // find caller
174 while(base = bases[++pos]){ // intentional assignment
175 meta = base._meta;
176 if(meta && meta.ctor === caller){
177 break;
178 }
179 }
180 pos = base ? pos : -1;
181 }
182 }
183 // find next
184 while(base = bases[++pos]){ // intentional assignment
185 meta = base._meta;
186 f = meta ? meta.ctor : base;
187 if(f){
188 break;
189 }
190 }
191 f = base && f;
192 }
193
194 // cache the found super method
195 cache.c = f;
196 cache.p = pos;
197
198 // now we have the result
199 if(f){
200 return a === true ? f : f.apply(this, a || args);
201 }
202 // intentionally if a super method was not found
203 }
204
205 function getInherited(name, args){
206 if(typeof name == "string"){
207 return this.inherited(name, args, true);
208 }
209 return this.inherited(name, true);
210 }
211
212 // emulation of "instanceof"
213 function isInstanceOf(cls){
214 var bases = this.constructor._meta.bases;
215 for(var i = 0, l = bases.length; i < l; ++i){
216 if(bases[i] === cls){
217 return true;
218 }
219 }
220 return this instanceof cls;
221 }
222
223 function mixOwn(target, source){
224 var name, i = 0, l = d._extraNames.length;
225 // add props adding metadata for incoming functions skipping a constructor
226 for(name in source){
227 if(name != cname && source.hasOwnProperty(name)){
228 target[name] = source[name];
229 }
230 }
231 // process unenumerable methods on IE
232 for(; i < l; ++i){
233 name = d._extraNames[i];
234 if(name != cname && source.hasOwnProperty(name)){
235 target[name] = source[name];
236 }
237 }
238 }
239
240 // implementation of safe mixin function
241 function safeMixin(target, source){
242 var name, t, i = 0, l = d._extraNames.length;
243 // add props adding metadata for incoming functions skipping a constructor
244 for(name in source){
245 t = source[name];
246 if((t !== op[name] || !(name in op)) && name != cname){
247 if(opts.call(t) == "[object Function]"){
248 // non-trivial function method => attach its name
249 t.nom = name;
250 }
251 target[name] = t;
252 }
253 }
254 // process unenumerable methods on IE
255 for(; i < l; ++i){
256 name = d._extraNames[i];
257 t = source[name];
258 if((t !== op[name] || !(name in op)) && name != cname){
259 if(opts.call(t) == "[object Function]"){
260 // non-trivial function method => attach its name
261 t.nom = name;
262 }
263 target[name] = t;
264 }
265 }
266 return target;
267 }
268
269 function extend(source){
270 safeMixin(this.prototype, source);
271 return this;
272 }
273
274 // chained constructor compatible with the legacy dojo.declare()
275 function chainedConstructor(bases, ctorSpecial){
276 return function(){
277 var a = arguments, args = a, a0 = a[0], f, i, m,
278 l = bases.length, preArgs;
279
280 if(!(this instanceof a.callee)){
281 // not called via new, so force it
282 return applyNew(a);
283 }
284
285 //this._inherited = {};
286 // perform the shaman's rituals of the original dojo.declare()
287 // 1) call two types of the preamble
288 if(ctorSpecial && (a0 && a0.preamble || this.preamble)){
289 // full blown ritual
290 preArgs = new Array(bases.length);
291 // prepare parameters
292 preArgs[0] = a;
293 for(i = 0;;){
294 // process the preamble of the 1st argument
295 a0 = a[0];
296 if(a0){
297 f = a0.preamble;
298 if(f){
299 a = f.apply(this, a) || a;
300 }
301 }
302 // process the preamble of this class
303 f = bases[i].prototype;
304 f = f.hasOwnProperty("preamble") && f.preamble;
305 if(f){
306 a = f.apply(this, a) || a;
307 }
308 // one peculiarity of the preamble:
309 // it is called if it is not needed,
310 // e.g., there is no constructor to call
311 // let's watch for the last constructor
312 // (see ticket #9795)
313 if(++i == l){
314 break;
315 }
316 preArgs[i] = a;
317 }
318 }
319 // 2) call all non-trivial constructors using prepared arguments
320 for(i = l - 1; i >= 0; --i){
321 f = bases[i];
322 m = f._meta;
323 f = m ? m.ctor : f;
324 if(f){
325 f.apply(this, preArgs ? preArgs[i] : a);
326 }
327 }
328 // 3) continue the original ritual: call the postscript
329 f = this.postscript;
330 if(f){
331 f.apply(this, args);
332 }
333 };
334 }
335
336
337 // chained constructor compatible with the legacy dojo.declare()
338 function singleConstructor(ctor, ctorSpecial){
339 return function(){
340 var a = arguments, t = a, a0 = a[0], f;
341
342 if(!(this instanceof a.callee)){
343 // not called via new, so force it
344 return applyNew(a);
345 }
346
347 //this._inherited = {};
348 // perform the shaman's rituals of the original dojo.declare()
349 // 1) call two types of the preamble
350 if(ctorSpecial){
351 // full blown ritual
352 if(a0){
353 // process the preamble of the 1st argument
354 f = a0.preamble;
355 if(f){
356 t = f.apply(this, t) || t;
357 }
358 }
359 f = this.preamble;
360 if(f){
361 // process the preamble of this class
362 f.apply(this, t);
363 // one peculiarity of the preamble:
364 // it is called even if it is not needed,
365 // e.g., there is no constructor to call
366 // let's watch for the last constructor
367 // (see ticket #9795)
368 }
369 }
370 // 2) call a constructor
371 if(ctor){
372 ctor.apply(this, a);
373 }
374 // 3) continue the original ritual: call the postscript
375 f = this.postscript;
376 if(f){
377 f.apply(this, a);
378 }
379 };
380 }
381
382 // plain vanilla constructor (can use inherited() to call its base constructor)
383 function simpleConstructor(bases){
384 return function(){
385 var a = arguments, i = 0, f, m;
386
387 if(!(this instanceof a.callee)){
388 // not called via new, so force it
389 return applyNew(a);
390 }
391
392 //this._inherited = {};
393 // perform the shaman's rituals of the original dojo.declare()
394 // 1) do not call the preamble
395 // 2) call the top constructor (it can use this.inherited())
396 for(; f = bases[i]; ++i){ // intentional assignment
397 m = f._meta;
398 f = m ? m.ctor : f;
399 if(f){
400 f.apply(this, a);
401 break;
402 }
403 }
404 // 3) call the postscript
405 f = this.postscript;
406 if(f){
407 f.apply(this, a);
408 }
409 };
410 }
411
412 function chain(name, bases, reversed){
413 return function(){
414 var b, m, f, i = 0, step = 1;
415 if(reversed){
416 i = bases.length - 1;
417 step = -1;
418 }
419 for(; b = bases[i]; i += step){ // intentional assignment
420 m = b._meta;
421 f = (m ? m.hidden : b.prototype)[name];
422 if(f){
423 f.apply(this, arguments);
424 }
425 }
426 };
427 }
428
429 // forceNew(ctor)
430 // return a new object that inherits from ctor.prototype but
431 // without actually running ctor on the object.
432 function forceNew(ctor){
433 // create object with correct prototype using a do-nothing
434 // constructor
435 xtor.prototype = ctor.prototype;
436 var t = new xtor;
437 xtor.prototype = null; // clean up
438 return t;
439 }
440
441 // applyNew(args)
442 // just like 'new ctor()' except that the constructor and its arguments come
443 // from args, which must be an array or an arguments object
444 function applyNew(args){
445 // create an object with ctor's prototype but without
446 // calling ctor on it.
447 var ctor = args.callee, t = forceNew(ctor);
448 // execute the real constructor on the new object
449 ctor.apply(t, args);
450 return t;
451 }
452
453 d.declare = function(className, superclass, props){
454 // crack parameters
455 if(typeof className != "string"){
456 props = superclass;
457 superclass = className;
458 className = "";
459 }
460 props = props || {};
461
462 var proto, i, t, ctor, name, bases, chains, mixins = 1, parents = superclass;
463
464 // build a prototype
465 if(opts.call(superclass) == "[object Array]"){
466 // C3 MRO
467 bases = c3mro(superclass);
468 t = bases[0];
469 mixins = bases.length - t;
470 superclass = bases[mixins];
471 }else{
472 bases = [0];
473 if(superclass){
474 if(opts.call(superclass) == "[object Function]"){
475 t = superclass._meta;
476 bases = bases.concat(t ? t.bases : superclass);
477 }else{
478 err("base class is not a callable constructor.");
479 }
480 }else if(superclass !== null){
481 err("unknown base class. Did you use dojo.require to pull it in?")
482 }
483 }
484 if(superclass){
485 for(i = mixins - 1;; --i){
486 proto = forceNew(superclass);
487 if(!i){
488 // stop if nothing to add (the last base)
489 break;
490 }
491 // mix in properties
492 t = bases[i];
493 (t._meta ? mixOwn : mix)(proto, t.prototype);
494 // chain in new constructor
495 ctor = new Function;
496 ctor.superclass = superclass;
497 ctor.prototype = proto;
498 superclass = proto.constructor = ctor;
499 }
500 }else{
501 proto = {};
502 }
503 // add all properties
504 safeMixin(proto, props);
505 // add constructor
506 t = props.constructor;
507 if(t !== op.constructor){
508 t.nom = cname;
509 proto.constructor = t;
510 }
511
512 // collect chains and flags
513 for(i = mixins - 1; i; --i){ // intentional assignment
514 t = bases[i]._meta;
515 if(t && t.chains){
516 chains = mix(chains || {}, t.chains);
517 }
518 }
519 if(proto["-chains-"]){
520 chains = mix(chains || {}, proto["-chains-"]);
521 }
522
523 // build ctor
524 t = !chains || !chains.hasOwnProperty(cname);
525 bases[0] = ctor = (chains && chains.constructor === "manual") ? simpleConstructor(bases) :
526 (bases.length == 1 ? singleConstructor(props.constructor, t) : chainedConstructor(bases, t));
527
528 // add meta information to the constructor
529 ctor._meta = {bases: bases, hidden: props, chains: chains,
530 parents: parents, ctor: props.constructor};
531 ctor.superclass = superclass && superclass.prototype;
532 ctor.extend = extend;
533 ctor.prototype = proto;
534 proto.constructor = ctor;
535
536 // add "standard" methods to the prototype
537 proto.getInherited = getInherited;
538 proto.inherited = inherited;
539 proto.isInstanceOf = isInstanceOf;
540
541 // add name if specified
542 if(className){
543 proto.declaredClass = className;
544 d.setObject(className, ctor);
545 }
546
547 // build chains and add them to the prototype
548 if(chains){
549 for(name in chains){
550 if(proto[name] && typeof chains[name] == "string" && name != cname){
551 t = proto[name] = chain(name, bases, chains[name] === "after");
552 t.nom = name;
553 }
554 }
555 }
556 // chained methods do not return values
557 // no need to chain "invisible" functions
558
559 return ctor; // Function
560 };
561
562 d.safeMixin = safeMixin;
563
564 /*=====
565 dojo.declare = function(className, superclass, props){
566 // summary:
567 // Create a feature-rich constructor from compact notation.
568 // className: String?:
569 // The optional name of the constructor (loosely, a "class")
570 // stored in the "declaredClass" property in the created prototype.
571 // It will be used as a global name for a created constructor.
572 // superclass: Function|Function[]:
573 // May be null, a Function, or an Array of Functions. This argument
574 // specifies a list of bases (the left-most one is the most deepest
575 // base).
576 // props: Object:
577 // An object whose properties are copied to the created prototype.
578 // Add an instance-initialization function by making it a property
579 // named "constructor".
580 // returns:
581 // New constructor function.
582 // description:
583 // Create a constructor using a compact notation for inheritance and
584 // prototype extension.
585 //
586 // Mixin ancestors provide a type of multiple inheritance.
587 // Prototypes of mixin ancestors are copied to the new class:
588 // changes to mixin prototypes will not affect classes to which
589 // they have been mixed in.
590 //
591 // Ancestors can be compound classes created by this version of
592 // dojo.declare. In complex cases all base classes are going to be
593 // linearized according to C3 MRO algorithm
594 // (see http://www.python.org/download/releases/2.3/mro/ for more
595 // details).
596 //
597 // "className" is cached in "declaredClass" property of the new class,
598 // if it was supplied. The immediate super class will be cached in
599 // "superclass" property of the new class.
600 //
601 // Methods in "props" will be copied and modified: "nom" property
602 // (the declared name of the method) will be added to all copied
603 // functions to help identify them for the internal machinery. Be
604 // very careful, while reusing methods: if you use the same
605 // function under different names, it can produce errors in some
606 // cases.
607 //
608 // It is possible to use constructors created "manually" (without
609 // dojo.declare) as bases. They will be called as usual during the
610 // creation of an instance, their methods will be chained, and even
611 // called by "this.inherited()".
612 //
613 // Special property "-chains-" governs how to chain methods. It is
614 // a dictionary, which uses method names as keys, and hint strings
615 // as values. If a hint string is "after", this method will be
616 // called after methods of its base classes. If a hint string is
617 // "before", this method will be called before methods of its base
618 // classes.
619 //
620 // If "constructor" is not mentioned in "-chains-" property, it will
621 // be chained using the legacy mode: using "after" chaining,
622 // calling preamble() method before each constructor, if available,
623 // and calling postscript() after all constructors were executed.
624 // If the hint is "after", it is chained as a regular method, but
625 // postscript() will be called after the chain of constructors.
626 // "constructor" cannot be chained "before", but it allows
627 // a special hint string: "manual", which means that constructors
628 // are not going to be chained in any way, and programmer will call
629 // them manually using this.inherited(). In the latter case
630 // postscript() will be called after the construction.
631 //
632 // All chaining hints are "inherited" from base classes and
633 // potentially can be overridden. Be very careful when overriding
634 // hints! Make sure that all chained methods can work in a proposed
635 // manner of chaining.
636 //
637 // Once a method was chained, it is impossible to unchain it. The
638 // only exception is "constructor". You don't need to define a
639 // method in order to supply a chaining hint.
640 //
641 // If a method is chained, it cannot use this.inherited() because
642 // all other methods in the hierarchy will be called automatically.
643 //
644 // Usually constructors and initializers of any kind are chained
645 // using "after" and destructors of any kind are chained as
646 // "before". Note that chaining assumes that chained methods do not
647 // return any value: any returned value will be discarded.
648 //
649 // example:
650 // | dojo.declare("my.classes.bar", my.classes.foo, {
651 // | // properties to be added to the class prototype
652 // | someValue: 2,
653 // | // initialization function
654 // | constructor: function(){
655 // | this.myComplicatedObject = new ReallyComplicatedObject();
656 // | },
657 // | // other functions
658 // | someMethod: function(){
659 // | doStuff();
660 // | }
661 // | });
662 //
663 // example:
664 // | var MyBase = dojo.declare(null, {
665 // | // constructor, properties, and methods go here
666 // | // ...
667 // | });
668 // | var MyClass1 = dojo.declare(MyBase, {
669 // | // constructor, properties, and methods go here
670 // | // ...
671 // | });
672 // | var MyClass2 = dojo.declare(MyBase, {
673 // | // constructor, properties, and methods go here
674 // | // ...
675 // | });
676 // | var MyDiamond = dojo.declare([MyClass1, MyClass2], {
677 // | // constructor, properties, and methods go here
678 // | // ...
679 // | });
680 //
681 // example:
682 // | var F = function(){ console.log("raw constructor"); };
683 // | F.prototype.method = function(){
684 // | console.log("raw method");
685 // | };
686 // | var A = dojo.declare(F, {
687 // | constructor: function(){
688 // | console.log("A.constructor");
689 // | },
690 // | method: function(){
691 // | console.log("before calling F.method...");
692 // | this.inherited(arguments);
693 // | console.log("...back in A");
694 // | }
695 // | });
696 // | new A().method();
697 // | // will print:
698 // | // raw constructor
699 // | // A.constructor
700 // | // before calling F.method...
701 // | // raw method
702 // | // ...back in A
703 //
704 // example:
705 // | var A = dojo.declare(null, {
706 // | "-chains-": {
707 // | destroy: "before"
708 // | }
709 // | });
710 // | var B = dojo.declare(A, {
711 // | constructor: function(){
712 // | console.log("B.constructor");
713 // | },
714 // | destroy: function(){
715 // | console.log("B.destroy");
716 // | }
717 // | });
718 // | var C = dojo.declare(B, {
719 // | constructor: function(){
720 // | console.log("C.constructor");
721 // | },
722 // | destroy: function(){
723 // | console.log("C.destroy");
724 // | }
725 // | });
726 // | new C().destroy();
727 // | // prints:
728 // | // B.constructor
729 // | // C.constructor
730 // | // C.destroy
731 // | // B.destroy
732 //
733 // example:
734 // | var A = dojo.declare(null, {
735 // | "-chains-": {
736 // | constructor: "manual"
737 // | }
738 // | });
739 // | var B = dojo.declare(A, {
740 // | constructor: function(){
741 // | // ...
742 // | // call the base constructor with new parameters
743 // | this.inherited(arguments, [1, 2, 3]);
744 // | // ...
745 // | }
746 // | });
747 //
748 // example:
749 // | var A = dojo.declare(null, {
750 // | "-chains-": {
751 // | m1: "before"
752 // | },
753 // | m1: function(){
754 // | console.log("A.m1");
755 // | },
756 // | m2: function(){
757 // | console.log("A.m2");
758 // | }
759 // | });
760 // | var B = dojo.declare(A, {
761 // | "-chains-": {
762 // | m2: "after"
763 // | },
764 // | m1: function(){
765 // | console.log("B.m1");
766 // | },
767 // | m2: function(){
768 // | console.log("B.m2");
769 // | }
770 // | });
771 // | var x = new B();
772 // | x.m1();
773 // | // prints:
774 // | // B.m1
775 // | // A.m1
776 // | x.m2();
777 // | // prints:
778 // | // A.m2
779 // | // B.m2
780 return new Function(); // Function
781 };
782 =====*/
783
784 /*=====
785 dojo.safeMixin = function(target, source){
786 // summary:
787 // Mix in properties skipping a constructor and decorating functions
788 // like it is done by dojo.declare.
789 // target: Object
790 // Target object to accept new properties.
791 // source: Object
792 // Source object for new properties.
793 // description:
794 // This function is used to mix in properties like dojo._mixin does,
795 // but it skips a constructor property and decorates functions like
796 // dojo.declare does.
797 //
798 // It is meant to be used with classes and objects produced with
799 // dojo.declare. Functions mixed in with dojo.safeMixin can use
800 // this.inherited() like normal methods.
801 //
802 // This function is used to implement extend() method of a constructor
803 // produced with dojo.declare().
804 //
805 // example:
806 // | var A = dojo.declare(null, {
807 // | m1: function(){
808 // | console.log("A.m1");
809 // | },
810 // | m2: function(){
811 // | console.log("A.m2");
812 // | }
813 // | });
814 // | var B = dojo.declare(A, {
815 // | m1: function(){
816 // | this.inherited(arguments);
817 // | console.log("B.m1");
818 // | }
819 // | });
820 // | B.extend({
821 // | m2: function(){
822 // | this.inherited(arguments);
823 // | console.log("B.m2");
824 // | }
825 // | });
826 // | var x = new B();
827 // | dojo.safeMixin(x, {
828 // | m1: function(){
829 // | this.inherited(arguments);
830 // | console.log("X.m1");
831 // | },
832 // | m2: function(){
833 // | this.inherited(arguments);
834 // | console.log("X.m2");
835 // | }
836 // | });
837 // | x.m2();
838 // | // prints:
839 // | // A.m1
840 // | // B.m1
841 // | // X.m1
842 };
843 =====*/
844
845 /*=====
846 Object.inherited = function(name, args, newArgs){
847 // summary:
848 // Calls a super method.
849 // name: String?
850 // The optional method name. Should be the same as the caller's
851 // name. Usually "name" is specified in complex dynamic cases, when
852 // the calling method was dynamically added, undecorated by
853 // dojo.declare, and it cannot be determined.
854 // args: Arguments
855 // The caller supply this argument, which should be the original
856 // "arguments".
857 // newArgs: Object?
858 // If "true", the found function will be returned without
859 // executing it.
860 // If Array, it will be used to call a super method. Otherwise
861 // "args" will be used.
862 // returns:
863 // Whatever is returned by a super method, or a super method itself,
864 // if "true" was specified as newArgs.
865 // description:
866 // This method is used inside method of classes produced with
867 // dojo.declare to call a super method (next in the chain). It is
868 // used for manually controlled chaining. Consider using the regular
869 // chaining, because it is faster. Use "this.inherited()" only in
870 // complex cases.
871 //
872 // This method cannot me called from automatically chained
873 // constructors including the case of a special (legacy)
874 // constructor chaining. It cannot be called from chained methods.
875 //
876 // If "this.inherited()" cannot find the next-in-chain method, it
877 // does nothing and returns "undefined". The last method in chain
878 // can be a default method implemented in Object, which will be
879 // called last.
880 //
881 // If "name" is specified, it is assumed that the method that
882 // received "args" is the parent method for this call. It is looked
883 // up in the chain list and if it is found the next-in-chain method
884 // is called. If it is not found, the first-in-chain method is
885 // called.
886 //
887 // If "name" is not specified, it will be derived from the calling
888 // method (using a methoid property "nom").
889 //
890 // example:
891 // | var B = dojo.declare(A, {
892 // | method1: function(a, b, c){
893 // | this.inherited(arguments);
894 // | },
895 // | method2: function(a, b){
896 // | return this.inherited(arguments, [a + b]);
897 // | }
898 // | });
899 // | // next method is not in the chain list because it is added
900 // | // manually after the class was created.
901 // | B.prototype.method3 = function(){
902 // | console.log("This is a dynamically-added method.");
903 // | this.inherited("method3", arguments);
904 // | };
905 // example:
906 // | var B = dojo.declare(A, {
907 // | method: function(a, b){
908 // | var super = this.inherited(arguments, true);
909 // | // ...
910 // | if(!super){
911 // | console.log("there is no super method");
912 // | return 0;
913 // | }
914 // | return super.apply(this, arguments);
915 // | }
916 // | });
917 return {}; // Object
918 }
919 =====*/
920
921 /*=====
922 Object.getInherited = function(name, args){
923 // summary:
924 // Returns a super method.
925 // name: String?
926 // The optional method name. Should be the same as the caller's
927 // name. Usually "name" is specified in complex dynamic cases, when
928 // the calling method was dynamically added, undecorated by
929 // dojo.declare, and it cannot be determined.
930 // args: Arguments
931 // The caller supply this argument, which should be the original
932 // "arguments".
933 // returns:
934 // Returns a super method (Function) or "undefined".
935 // description:
936 // This method is a convenience method for "this.inherited()".
937 // It uses the same algorithm but instead of executing a super
938 // method, it returns it, or "undefined" if not found.
939 //
940 // example:
941 // | var B = dojo.declare(A, {
942 // | method: function(a, b){
943 // | var super = this.getInherited(arguments);
944 // | // ...
945 // | if(!super){
946 // | console.log("there is no super method");
947 // | return 0;
948 // | }
949 // | return super.apply(this, arguments);
950 // | }
951 // | });
952 return {}; // Object
953 }
954 =====*/
955
956 /*=====
957 Object.isInstanceOf = function(cls){
958 // summary:
959 // Checks the inheritance chain to see if it is inherited from this
960 // class.
961 // cls: Function
962 // Class constructor.
963 // returns:
964 // "true", if this object is inherited from this class, "false"
965 // otherwise.
966 // description:
967 // This method is used with instances of classes produced with
968 // dojo.declare to determine of they support a certain interface or
969 // not. It models "instanceof" operator.
970 //
971 // example:
972 // | var A = dojo.declare(null, {
973 // | // constructor, properties, and methods go here
974 // | // ...
975 // | });
976 // | var B = dojo.declare(null, {
977 // | // constructor, properties, and methods go here
978 // | // ...
979 // | });
980 // | var C = dojo.declare([A, B], {
981 // | // constructor, properties, and methods go here
982 // | // ...
983 // | });
984 // | var D = dojo.declare(A, {
985 // | // constructor, properties, and methods go here
986 // | // ...
987 // | });
988 // |
989 // | var a = new A(), b = new B(), c = new C(), d = new D();
990 // |
991 // | console.log(a.isInstanceOf(A)); // true
992 // | console.log(b.isInstanceOf(A)); // false
993 // | console.log(c.isInstanceOf(A)); // true
994 // | console.log(d.isInstanceOf(A)); // true
995 // |
996 // | console.log(a.isInstanceOf(B)); // false
997 // | console.log(b.isInstanceOf(B)); // true
998 // | console.log(c.isInstanceOf(B)); // true
999 // | console.log(d.isInstanceOf(B)); // false
1000 // |
1001 // | console.log(a.isInstanceOf(C)); // false
1002 // | console.log(b.isInstanceOf(C)); // false
1003 // | console.log(c.isInstanceOf(C)); // true
1004 // | console.log(d.isInstanceOf(C)); // false
1005 // |
1006 // | console.log(a.isInstanceOf(D)); // false
1007 // | console.log(b.isInstanceOf(D)); // false
1008 // | console.log(c.isInstanceOf(D)); // false
1009 // | console.log(d.isInstanceOf(D)); // true
1010 return {}; // Object
1011 }
1012 =====*/
1013
1014 /*=====
1015 Object.extend = function(source){
1016 // summary:
1017 // Adds all properties and methods of source to constructor's
1018 // prototype, making them available to all instances created with
1019 // constructor. This method is specific to constructors created with
1020 // dojo.declare.
1021 // source: Object
1022 // Source object which properties are going to be copied to the
1023 // constructor's prototype.
1024 // description:
1025 // Adds source properties to the constructor's prototype. It can
1026 // override existing properties.
1027 //
1028 // This method is similar to dojo.extend function, but it is specific
1029 // to constructors produced by dojo.declare. It is implemented
1030 // using dojo.safeMixin, and it skips a constructor property,
1031 // and properly decorates copied functions.
1032 //
1033 // example:
1034 // | var A = dojo.declare(null, {
1035 // | m1: function(){},
1036 // | s1: "Popokatepetl"
1037 // | });
1038 // | A.extend({
1039 // | m1: function(){},
1040 // | m2: function(){},
1041 // | f1: true,
1042 // | d1: 42
1043 // | });
1044 };
1045 =====*/
2f01fe57 1046})();
a089699c 1047
2f01fe57 1048}