1 | 1 | simandl | /* |
2 | | | common, version 1.0.4 (2005/06/05) |
3 | | | Copyright 2005, Dean Edwards |
4 | | | License: http://creativecommons.org/licenses/LGPL/2.1/ |
5 | | | */ |
6 | | | |
7 | | | // this function may be used to cast any javascript object |
8 | | | // to a common object |
9 | | | function ICommon(that) { |
10 | | | if (that != null) { |
11 | | | that.inherit = Common.prototype.inherit; |
12 | | | that.specialize = Common.prototype.specialize; |
13 | | | } |
14 | | | return that; |
15 | | | }; |
16 | | | |
17 | | | // sub-classing |
18 | | | ICommon.specialize = function($prototype, $constructor) { |
19 | | | // initialise class properties |
20 | | | if (!$prototype) $prototype = {}; |
21 | | | if (!$constructor) $constructor = $prototype.constructor; |
22 | | | if ($constructor == {}.constructor) $constructor = new Function; |
23 | | | // build the inheritance chain |
24 | | | // insert a dummy constructor between the ancestor |
25 | | | // and the new constructor. this allows standard |
26 | | | // prototype inheritance plus chained constructor |
27 | | | // functions. |
28 | | | $constructor.valueOf = new Function("return this"); |
29 | | | $constructor.valueOf.prototype = new this.valueOf; |
30 | | | $constructor.valueOf.prototype.specialize($prototype); |
31 | | | $constructor.prototype = new $constructor.valueOf; |
32 | | | $constructor.valueOf.prototype.constructor = |
33 | | | $constructor.prototype.constructor = $constructor; |
34 | | | $constructor.ancestor = this; |
35 | | | $constructor.specialize = arguments.callee; |
36 | | | $constructor.ancestorOf = this.ancestorOf; |
37 | | | return $constructor; |
38 | | | }; |
39 | | | |
40 | | | // root of the inheritance chain |
41 | | | ICommon.valueOf = new Function("return this"); |
42 | | | |
43 | | | // common interface |
44 | | | ICommon.valueOf.prototype = { |
45 | | | constructor: ICommon, |
46 | | | inherit: function() { |
47 | | | //- |
48 | | | // Call this method from any other method to call that method's ancestor. |
49 | | | // If there is no ancestor function then this function will throw an error. |
50 | | | //- |
51 | | | return arguments.callee.caller.ancestor.apply(this, arguments); |
52 | | | }, |
53 | | | specialize: function(that) { |
54 | | | //- |
55 | | | // Add the interface of another object to this object |
56 | | | //- |
57 | | | // if this object is the prototype then specialize the /real/ prototype |
58 | | | if (this == this.constructor.prototype && this.constructor.specialize) { |
59 | | | return this.constructor.valueOf.prototype.specialize(that); |
60 | | | } |
61 | | | // add each of one of the source object's properties to this object |
62 | | | for (var i in that) { |
63 | | | switch (i) { |
64 | | | case "constructor": // don't do this one! |
65 | | | case "toString": // do this one maually |
66 | | | case "valueOf": // ignore this one... |
67 | | | continue; |
68 | | | } |
69 | | | // implement inheritance |
70 | | | if (typeof that[i] == "function" && that[i] != this[i]) { |
71 | | | that[i].ancestor = this[i]; |
72 | | | } |
73 | | | // add the property |
74 | | | this[i] = that[i]; |
75 | | | } |
76 | | | // do the "toString" function manually |
77 | | | if (that.toString != this.toString && that.toString != {}.toString) { |
78 | | | that.toString.ancestor = this.toString; |
79 | | | this.toString = that.toString; |
80 | | | } |
81 | | | return this; |
82 | | | }}; |
83 | | | |
84 | | | // create the root |
85 | | | function Common() { |
86 | | | //-- |
87 | | | // empty constructor function |
88 | | | //-- |
89 | | | }; |
90 | | | this.Common = ICommon.specialize({ |
91 | | | constructor: Common, |
92 | | | toString: function() { |
93 | | | return "[common " + (this.constructor.className || "Object") + "]"; |
94 | | | }, |
95 | | | instanceOf: function(klass) { |
96 | | | return this.constructor == klass || klass.ancestorOf(this.constructor); |
97 | | | } |
98 | | | }); |
99 | | | Common.className = "Common"; |
100 | | | Common.ancestor = null; |
101 | | | Common.ancestorOf = function(klass) { |
102 | | | // Is this class an ancestor of the supplied class? |
103 | | | while (klass && klass.ancestor != this) klass = klass.ancestor; |
104 | | | return Boolean(klass); |
105 | | | }; |
106 | | | |
107 | | | // preserve the common prototype so that we can tell when a |
108 | | | // property of the root class has changed |
109 | | | Common.valueOf.ancestor = ICommon; |
110 | | | |
111 | | | // c'est fini! |