]> git.wh0rd.org - tt-rss.git/blame - lib/dojo/_base/declare.js.uncompressed.js
make precache_headlines_idle() start slower
[tt-rss.git] / lib / dojo / _base / declare.js.uncompressed.js
CommitLineData
1354d172
AD
1define("dojo/_base/declare", ["./kernel", "../has", "./lang"], function(dojo, has, lang){
2 // module:
3 // dojo/_base/declare
4 // summary:
5 // This module defines dojo.declare.
6
7 var mix = lang.mixin, op = Object.prototype, opts = op.toString,
8 xtor = new Function, counter = 0, cname = "constructor";
9
10 function err(msg, cls){ throw new Error("declare" + (cls ? " " + cls : "") + ": " + msg); }
11
12 // C3 Method Resolution Order (see http://www.python.org/download/releases/2.3/mro/)
13 function c3mro(bases, className){
14 var result = [], roots = [{cls: 0, refs: []}], nameMap = {}, clsCount = 1,
15 l = bases.length, i = 0, j, lin, base, top, proto, rec, name, refs;
16
17 // build a list of bases naming them if needed
18 for(; i < l; ++i){
19 base = bases[i];
20 if(!base){
21 err("mixin #" + i + " is unknown. Did you use dojo.require to pull it in?", className);
22 }else if(opts.call(base) != "[object Function]"){
23 err("mixin #" + i + " is not a callable constructor.", className);
24 }
25 lin = base._meta ? base._meta.bases : [base];
26 top = 0;
27 // add bases to the name map
28 for(j = lin.length - 1; j >= 0; --j){
29 proto = lin[j].prototype;
30 if(!proto.hasOwnProperty("declaredClass")){
31 proto.declaredClass = "uniqName_" + (counter++);
32 }
33 name = proto.declaredClass;
34 if(!nameMap.hasOwnProperty(name)){
35 nameMap[name] = {count: 0, refs: [], cls: lin[j]};
36 ++clsCount;
37 }
38 rec = nameMap[name];
39 if(top && top !== rec){
40 rec.refs.push(top);
41 ++top.count;
42 }
43 top = rec;
44 }
45 ++top.count;
46 roots[0].refs.push(top);
47 }
48
49 // remove classes without external references recursively
50 while(roots.length){
51 top = roots.pop();
52 result.push(top.cls);
53 --clsCount;
54 // optimization: follow a single-linked chain
55 while(refs = top.refs, refs.length == 1){
56 top = refs[0];
57 if(!top || --top.count){
58 // branch or end of chain => do not end to roots
59 top = 0;
60 break;
61 }
62 result.push(top.cls);
63 --clsCount;
64 }
65 if(top){
66 // branch
67 for(i = 0, l = refs.length; i < l; ++i){
68 top = refs[i];
69 if(!--top.count){
70 roots.push(top);
71 }
72 }
73 }
74 }
75 if(clsCount){
76 err("can't build consistent linearization", className);
77 }
78
79 // calculate the superclass offset
80 base = bases[0];
81 result[0] = base ?
82 base._meta && base === result[result.length - base._meta.bases.length] ?
83 base._meta.bases.length : 1 : 0;
84
85 return result;
86 }
87
88 function inherited(args, a, f){
89 var name, chains, bases, caller, meta, base, proto, opf, pos,
90 cache = this._inherited = this._inherited || {};
91
92 // crack arguments
93 if(typeof args == "string"){
94 name = args;
95 args = a;
96 a = f;
97 }
98 f = 0;
99
100 caller = args.callee;
101 name = name || caller.nom;
102 if(!name){
103 err("can't deduce a name to call inherited()", this.declaredClass);
104 }
105
106 meta = this.constructor._meta;
107 bases = meta.bases;
108
109 pos = cache.p;
110 if(name != cname){
111 // method
112 if(cache.c !== caller){
113 // cache bust
114 pos = 0;
115 base = bases[0];
116 meta = base._meta;
117 if(meta.hidden[name] !== caller){
118 // error detection
119 chains = meta.chains;
120 if(chains && typeof chains[name] == "string"){
121 err("calling chained method with inherited: " + name, this.declaredClass);
122 }
123 // find caller
124 do{
125 meta = base._meta;
126 proto = base.prototype;
127 if(meta && (proto[name] === caller && proto.hasOwnProperty(name) || meta.hidden[name] === caller)){
128 break;
129 }
130 }while(base = bases[++pos]); // intentional assignment
131 pos = base ? pos : -1;
132 }
133 }
134 // find next
135 base = bases[++pos];
136 if(base){
137 proto = base.prototype;
138 if(base._meta && proto.hasOwnProperty(name)){
139 f = proto[name];
140 }else{
141 opf = op[name];
142 do{
143 proto = base.prototype;
144 f = proto[name];
145 if(f && (base._meta ? proto.hasOwnProperty(name) : f !== opf)){
146 break;
147 }
148 }while(base = bases[++pos]); // intentional assignment
149 }
150 }
151 f = base && f || op[name];
152 }else{
153 // constructor
154 if(cache.c !== caller){
155 // cache bust
156 pos = 0;
157 meta = bases[0]._meta;
158 if(meta && meta.ctor !== caller){
159 // error detection
160 chains = meta.chains;
161 if(!chains || chains.constructor !== "manual"){
162 err("calling chained constructor with inherited", this.declaredClass);
163 }
164 // find caller
165 while(base = bases[++pos]){ // intentional assignment
166 meta = base._meta;
167 if(meta && meta.ctor === caller){
168 break;
169 }
170 }
171 pos = base ? pos : -1;
172 }
173 }
174 // find next
175 while(base = bases[++pos]){ // intentional assignment
176 meta = base._meta;
177 f = meta ? meta.ctor : base;
178 if(f){
179 break;
180 }
181 }
182 f = base && f;
183 }
184
185 // cache the found super method
186 cache.c = f;
187 cache.p = pos;
188
189 // now we have the result
190 if(f){
191 return a === true ? f : f.apply(this, a || args);
192 }
193 // intentionally no return if a super method was not found
194 }
195
196 function getInherited(name, args){
197 if(typeof name == "string"){
198 return this.__inherited(name, args, true);
199 }
200 return this.__inherited(name, true);
201 }
202
203 function inherited__debug(args, a1, a2){
204 var f = this.getInherited(args, a1);
205 if(f){ return f.apply(this, a2 || a1 || args); }
206 // intentionally no return if a super method was not found
207 }
208
209 var inheritedImpl = dojo.config.isDebug ? inherited__debug : inherited;
210
211 // emulation of "instanceof"
212 function isInstanceOf(cls){
213 var bases = this.constructor._meta.bases;
214 for(var i = 0, l = bases.length; i < l; ++i){
215 if(bases[i] === cls){
216 return true;
217 }
218 }
219 return this instanceof cls;
220 }
221
222 function mixOwn(target, source){
223 // add props adding metadata for incoming functions skipping a constructor
224 for(var name in source){
225 if(name != cname && source.hasOwnProperty(name)){
226 target[name] = source[name];
227 }
228 }
229 if(has("bug-for-in-skips-shadowed")){
230 for(var extraNames= lang._extraNames, i= extraNames.length; i;){
231 name = extraNames[--i];
232 if(name != cname && source.hasOwnProperty(name)){
233 target[name] = source[name];
234 }
235 }
236 }
237 }
238
239 // implementation of safe mixin function
240 function safeMixin(target, source){
241 var name, t;
242 // add props adding metadata for incoming functions skipping a constructor
243 for(name in source){
244 t = source[name];
245 if((t !== op[name] || !(name in op)) && name != cname){
246 if(opts.call(t) == "[object Function]"){
247 // non-trivial function method => attach its name
248 t.nom = name;
249 }
250 target[name] = t;
251 }
252 }
253 if(has("bug-for-in-skips-shadowed")){
254 for(var extraNames= lang._extraNames, i= extraNames.length; i;){
255 name = extraNames[--i];
256 t = source[name];
257 if((t !== op[name] || !(name in op)) && name != cname){
258 if(opts.call(t) == "[object Function]"){
259 // non-trivial function method => attach its name
260 t.nom = name;
261 }
262 target[name] = t;
263 }
264 }
265 }
266 return target;
267 }
268
269 function extend(source){
270 declare.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 function declare(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, className);
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.", className);
479 }
480 }else if(superclass !== null){
481 err("unknown base class. Did you use dojo.require to pull it in?", className);
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 declare.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.isInstanceOf = isInstanceOf;
539 proto.inherited = inheritedImpl;
540 proto.__inherited = inherited;
541
542 // add name if specified
543 if(className){
544 proto.declaredClass = className;
545 lang.setObject(className, ctor);
546 }
547
548 // build chains and add them to the prototype
549 if(chains){
550 for(name in chains){
551 if(proto[name] && typeof chains[name] == "string" && name != cname){
552 t = proto[name] = chain(name, bases, chains[name] === "after");
553 t.nom = name;
554 }
555 }
556 }
557 // chained methods do not return values
558 // no need to chain "invisible" functions
559
560 return ctor; // Function
561 }
562
563 /*=====
564 dojo.declare = function(className, superclass, props){
565 // summary:
566 // Create a feature-rich constructor from compact notation.
567 // className: String?:
568 // The optional name of the constructor (loosely, a "class")
569 // stored in the "declaredClass" property in the created prototype.
570 // It will be used as a global name for a created constructor.
571 // superclass: Function|Function[]:
572 // May be null, a Function, or an Array of Functions. This argument
573 // specifies a list of bases (the left-most one is the most deepest
574 // base).
575 // props: Object:
576 // An object whose properties are copied to the created prototype.
577 // Add an instance-initialization function by making it a property
578 // named "constructor".
579 // returns:
580 // New constructor function.
581 // description:
582 // Create a constructor using a compact notation for inheritance and
583 // prototype extension.
584 //
585 // Mixin ancestors provide a type of multiple inheritance.
586 // Prototypes of mixin ancestors are copied to the new class:
587 // changes to mixin prototypes will not affect classes to which
588 // they have been mixed in.
589 //
590 // Ancestors can be compound classes created by this version of
591 // dojo.declare. In complex cases all base classes are going to be
592 // linearized according to C3 MRO algorithm
593 // (see http://www.python.org/download/releases/2.3/mro/ for more
594 // details).
595 //
596 // "className" is cached in "declaredClass" property of the new class,
597 // if it was supplied. The immediate super class will be cached in
598 // "superclass" property of the new class.
599 //
600 // Methods in "props" will be copied and modified: "nom" property
601 // (the declared name of the method) will be added to all copied
602 // functions to help identify them for the internal machinery. Be
603 // very careful, while reusing methods: if you use the same
604 // function under different names, it can produce errors in some
605 // cases.
606 //
607 // It is possible to use constructors created "manually" (without
608 // dojo.declare) as bases. They will be called as usual during the
609 // creation of an instance, their methods will be chained, and even
610 // called by "this.inherited()".
611 //
612 // Special property "-chains-" governs how to chain methods. It is
613 // a dictionary, which uses method names as keys, and hint strings
614 // as values. If a hint string is "after", this method will be
615 // called after methods of its base classes. If a hint string is
616 // "before", this method will be called before methods of its base
617 // classes.
618 //
619 // If "constructor" is not mentioned in "-chains-" property, it will
620 // be chained using the legacy mode: using "after" chaining,
621 // calling preamble() method before each constructor, if available,
622 // and calling postscript() after all constructors were executed.
623 // If the hint is "after", it is chained as a regular method, but
624 // postscript() will be called after the chain of constructors.
625 // "constructor" cannot be chained "before", but it allows
626 // a special hint string: "manual", which means that constructors
627 // are not going to be chained in any way, and programmer will call
628 // them manually using this.inherited(). In the latter case
629 // postscript() will be called after the construction.
630 //
631 // All chaining hints are "inherited" from base classes and
632 // potentially can be overridden. Be very careful when overriding
633 // hints! Make sure that all chained methods can work in a proposed
634 // manner of chaining.
635 //
636 // Once a method was chained, it is impossible to unchain it. The
637 // only exception is "constructor". You don't need to define a
638 // method in order to supply a chaining hint.
639 //
640 // If a method is chained, it cannot use this.inherited() because
641 // all other methods in the hierarchy will be called automatically.
642 //
643 // Usually constructors and initializers of any kind are chained
644 // using "after" and destructors of any kind are chained as
645 // "before". Note that chaining assumes that chained methods do not
646 // return any value: any returned value will be discarded.
647 //
648 // example:
649 // | dojo.declare("my.classes.bar", my.classes.foo, {
650 // | // properties to be added to the class prototype
651 // | someValue: 2,
652 // | // initialization function
653 // | constructor: function(){
654 // | this.myComplicatedObject = new ReallyComplicatedObject();
655 // | },
656 // | // other functions
657 // | someMethod: function(){
658 // | doStuff();
659 // | }
660 // | });
661 //
662 // example:
663 // | var MyBase = dojo.declare(null, {
664 // | // constructor, properties, and methods go here
665 // | // ...
666 // | });
667 // | var MyClass1 = dojo.declare(MyBase, {
668 // | // constructor, properties, and methods go here
669 // | // ...
670 // | });
671 // | var MyClass2 = dojo.declare(MyBase, {
672 // | // constructor, properties, and methods go here
673 // | // ...
674 // | });
675 // | var MyDiamond = dojo.declare([MyClass1, MyClass2], {
676 // | // constructor, properties, and methods go here
677 // | // ...
678 // | });
679 //
680 // example:
681 // | var F = function(){ console.log("raw constructor"); };
682 // | F.prototype.method = function(){
683 // | console.log("raw method");
684 // | };
685 // | var A = dojo.declare(F, {
686 // | constructor: function(){
687 // | console.log("A.constructor");
688 // | },
689 // | method: function(){
690 // | console.log("before calling F.method...");
691 // | this.inherited(arguments);
692 // | console.log("...back in A");
693 // | }
694 // | });
695 // | new A().method();
696 // | // will print:
697 // | // raw constructor
698 // | // A.constructor
699 // | // before calling F.method...
700 // | // raw method
701 // | // ...back in A
702 //
703 // example:
704 // | var A = dojo.declare(null, {
705 // | "-chains-": {
706 // | destroy: "before"
707 // | }
708 // | });
709 // | var B = dojo.declare(A, {
710 // | constructor: function(){
711 // | console.log("B.constructor");
712 // | },
713 // | destroy: function(){
714 // | console.log("B.destroy");
715 // | }
716 // | });
717 // | var C = dojo.declare(B, {
718 // | constructor: function(){
719 // | console.log("C.constructor");
720 // | },
721 // | destroy: function(){
722 // | console.log("C.destroy");
723 // | }
724 // | });
725 // | new C().destroy();
726 // | // prints:
727 // | // B.constructor
728 // | // C.constructor
729 // | // C.destroy
730 // | // B.destroy
731 //
732 // example:
733 // | var A = dojo.declare(null, {
734 // | "-chains-": {
735 // | constructor: "manual"
736 // | }
737 // | });
738 // | var B = dojo.declare(A, {
739 // | constructor: function(){
740 // | // ...
741 // | // call the base constructor with new parameters
742 // | this.inherited(arguments, [1, 2, 3]);
743 // | // ...
744 // | }
745 // | });
746 //
747 // example:
748 // | var A = dojo.declare(null, {
749 // | "-chains-": {
750 // | m1: "before"
751 // | },
752 // | m1: function(){
753 // | console.log("A.m1");
754 // | },
755 // | m2: function(){
756 // | console.log("A.m2");
757 // | }
758 // | });
759 // | var B = dojo.declare(A, {
760 // | "-chains-": {
761 // | m2: "after"
762 // | },
763 // | m1: function(){
764 // | console.log("B.m1");
765 // | },
766 // | m2: function(){
767 // | console.log("B.m2");
768 // | }
769 // | });
770 // | var x = new B();
771 // | x.m1();
772 // | // prints:
773 // | // B.m1
774 // | // A.m1
775 // | x.m2();
776 // | // prints:
777 // | // A.m2
778 // | // B.m2
779 return new Function(); // Function
780 };
781 =====*/
782
783 /*=====
784 dojo.safeMixin = function(target, source){
785 // summary:
786 // Mix in properties skipping a constructor and decorating functions
787 // like it is done by dojo.declare.
788 // target: Object
789 // Target object to accept new properties.
790 // source: Object
791 // Source object for new properties.
792 // description:
793 // This function is used to mix in properties like lang.mixin does,
794 // but it skips a constructor property and decorates functions like
795 // dojo.declare does.
796 //
797 // It is meant to be used with classes and objects produced with
798 // dojo.declare. Functions mixed in with dojo.safeMixin can use
799 // this.inherited() like normal methods.
800 //
801 // This function is used to implement extend() method of a constructor
802 // produced with dojo.declare().
803 //
804 // example:
805 // | var A = dojo.declare(null, {
806 // | m1: function(){
807 // | console.log("A.m1");
808 // | },
809 // | m2: function(){
810 // | console.log("A.m2");
811 // | }
812 // | });
813 // | var B = dojo.declare(A, {
814 // | m1: function(){
815 // | this.inherited(arguments);
816 // | console.log("B.m1");
817 // | }
818 // | });
819 // | B.extend({
820 // | m2: function(){
821 // | this.inherited(arguments);
822 // | console.log("B.m2");
823 // | }
824 // | });
825 // | var x = new B();
826 // | dojo.safeMixin(x, {
827 // | m1: function(){
828 // | this.inherited(arguments);
829 // | console.log("X.m1");
830 // | },
831 // | m2: function(){
832 // | this.inherited(arguments);
833 // | console.log("X.m2");
834 // | }
835 // | });
836 // | x.m2();
837 // | // prints:
838 // | // A.m1
839 // | // B.m1
840 // | // X.m1
841 };
842 =====*/
843
844 /*=====
845 Object.inherited = function(name, args, newArgs){
846 // summary:
847 // Calls a super method.
848 // name: String?
849 // The optional method name. Should be the same as the caller's
850 // name. Usually "name" is specified in complex dynamic cases, when
851 // the calling method was dynamically added, undecorated by
852 // dojo.declare, and it cannot be determined.
853 // args: Arguments
854 // The caller supply this argument, which should be the original
855 // "arguments".
856 // newArgs: Object?
857 // If "true", the found function will be returned without
858 // executing it.
859 // If Array, it will be used to call a super method. Otherwise
860 // "args" will be used.
861 // returns:
862 // Whatever is returned by a super method, or a super method itself,
863 // if "true" was specified as newArgs.
864 // description:
865 // This method is used inside method of classes produced with
866 // dojo.declare to call a super method (next in the chain). It is
867 // used for manually controlled chaining. Consider using the regular
868 // chaining, because it is faster. Use "this.inherited()" only in
869 // complex cases.
870 //
871 // This method cannot me called from automatically chained
872 // constructors including the case of a special (legacy)
873 // constructor chaining. It cannot be called from chained methods.
874 //
875 // If "this.inherited()" cannot find the next-in-chain method, it
876 // does nothing and returns "undefined". The last method in chain
877 // can be a default method implemented in Object, which will be
878 // called last.
879 //
880 // If "name" is specified, it is assumed that the method that
881 // received "args" is the parent method for this call. It is looked
882 // up in the chain list and if it is found the next-in-chain method
883 // is called. If it is not found, the first-in-chain method is
884 // called.
885 //
886 // If "name" is not specified, it will be derived from the calling
887 // method (using a methoid property "nom").
888 //
889 // example:
890 // | var B = dojo.declare(A, {
891 // | method1: function(a, b, c){
892 // | this.inherited(arguments);
893 // | },
894 // | method2: function(a, b){
895 // | return this.inherited(arguments, [a + b]);
896 // | }
897 // | });
898 // | // next method is not in the chain list because it is added
899 // | // manually after the class was created.
900 // | B.prototype.method3 = function(){
901 // | console.log("This is a dynamically-added method.");
902 // | this.inherited("method3", arguments);
903 // | };
904 // example:
905 // | var B = dojo.declare(A, {
906 // | method: function(a, b){
907 // | var super = this.inherited(arguments, true);
908 // | // ...
909 // | if(!super){
910 // | console.log("there is no super method");
911 // | return 0;
912 // | }
913 // | return super.apply(this, arguments);
914 // | }
915 // | });
916 return {}; // Object
917 }
918 =====*/
919
920 /*=====
921 Object.getInherited = function(name, args){
922 // summary:
923 // Returns a super method.
924 // name: String?
925 // The optional method name. Should be the same as the caller's
926 // name. Usually "name" is specified in complex dynamic cases, when
927 // the calling method was dynamically added, undecorated by
928 // dojo.declare, and it cannot be determined.
929 // args: Arguments
930 // The caller supply this argument, which should be the original
931 // "arguments".
932 // returns:
933 // Returns a super method (Function) or "undefined".
934 // description:
935 // This method is a convenience method for "this.inherited()".
936 // It uses the same algorithm but instead of executing a super
937 // method, it returns it, or "undefined" if not found.
938 //
939 // example:
940 // | var B = dojo.declare(A, {
941 // | method: function(a, b){
942 // | var super = this.getInherited(arguments);
943 // | // ...
944 // | if(!super){
945 // | console.log("there is no super method");
946 // | return 0;
947 // | }
948 // | return super.apply(this, arguments);
949 // | }
950 // | });
951 return {}; // Object
952 }
953 =====*/
954
955 /*=====
956 Object.isInstanceOf = function(cls){
957 // summary:
958 // Checks the inheritance chain to see if it is inherited from this
959 // class.
960 // cls: Function
961 // Class constructor.
962 // returns:
963 // "true", if this object is inherited from this class, "false"
964 // otherwise.
965 // description:
966 // This method is used with instances of classes produced with
967 // dojo.declare to determine of they support a certain interface or
968 // not. It models "instanceof" operator.
969 //
970 // example:
971 // | var A = dojo.declare(null, {
972 // | // constructor, properties, and methods go here
973 // | // ...
974 // | });
975 // | var B = dojo.declare(null, {
976 // | // constructor, properties, and methods go here
977 // | // ...
978 // | });
979 // | var C = dojo.declare([A, B], {
980 // | // constructor, properties, and methods go here
981 // | // ...
982 // | });
983 // | var D = dojo.declare(A, {
984 // | // constructor, properties, and methods go here
985 // | // ...
986 // | });
987 // |
988 // | var a = new A(), b = new B(), c = new C(), d = new D();
989 // |
990 // | console.log(a.isInstanceOf(A)); // true
991 // | console.log(b.isInstanceOf(A)); // false
992 // | console.log(c.isInstanceOf(A)); // true
993 // | console.log(d.isInstanceOf(A)); // true
994 // |
995 // | console.log(a.isInstanceOf(B)); // false
996 // | console.log(b.isInstanceOf(B)); // true
997 // | console.log(c.isInstanceOf(B)); // true
998 // | console.log(d.isInstanceOf(B)); // false
999 // |
1000 // | console.log(a.isInstanceOf(C)); // false
1001 // | console.log(b.isInstanceOf(C)); // false
1002 // | console.log(c.isInstanceOf(C)); // true
1003 // | console.log(d.isInstanceOf(C)); // false
1004 // |
1005 // | console.log(a.isInstanceOf(D)); // false
1006 // | console.log(b.isInstanceOf(D)); // false
1007 // | console.log(c.isInstanceOf(D)); // false
1008 // | console.log(d.isInstanceOf(D)); // true
1009 return {}; // Object
1010 }
1011 =====*/
1012
1013 /*=====
1014 Object.extend = function(source){
1015 // summary:
1016 // Adds all properties and methods of source to constructor's
1017 // prototype, making them available to all instances created with
1018 // constructor. This method is specific to constructors created with
1019 // dojo.declare.
1020 // source: Object
1021 // Source object which properties are going to be copied to the
1022 // constructor's prototype.
1023 // description:
1024 // Adds source properties to the constructor's prototype. It can
1025 // override existing properties.
1026 //
1027 // This method is similar to dojo.extend function, but it is specific
1028 // to constructors produced by dojo.declare. It is implemented
1029 // using dojo.safeMixin, and it skips a constructor property,
1030 // and properly decorates copied functions.
1031 //
1032 // example:
1033 // | var A = dojo.declare(null, {
1034 // | m1: function(){},
1035 // | s1: "Popokatepetl"
1036 // | });
1037 // | A.extend({
1038 // | m1: function(){},
1039 // | m2: function(){},
1040 // | f1: true,
1041 // | d1: 42
1042 // | });
1043 };
1044 =====*/
1045
1046 dojo.safeMixin = declare.safeMixin = safeMixin;
1047 dojo.declare = declare;
1048
1049 return declare;
1050});