source: Dev/branches/rest-dojo-ui/client/dojo/_base/declare.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 29.9 KB
Line 
1define(["./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});
Note: See TracBrowser for help on using the repository browser.