1 | dojo.provide("dojox.lang.oo.mixin"); |
---|
2 | |
---|
3 | dojo.experimental("dojox.lang.oo.mixin"); |
---|
4 | |
---|
5 | dojo.require("dojox.lang.oo.Filter"); |
---|
6 | dojo.require("dojox.lang.oo.Decorator"); |
---|
7 | |
---|
8 | (function(){ |
---|
9 | var oo = dojox.lang.oo, Filter = oo.Filter, Decorator = oo.Decorator, empty = {}, |
---|
10 | defaultFilter = function(name){ return name; }, |
---|
11 | defaultDecorator = function(name, newValue, oldValue){ return newValue; }, |
---|
12 | defaultMixer = function(target, name, newValue, oldValue){ target[name] = newValue; }, |
---|
13 | defaults = {}, // for the internal use in the mixin() |
---|
14 | extraNames = dojo._extraNames, extraLen = extraNames.length, |
---|
15 | |
---|
16 | applyDecorator = oo.applyDecorator = function(decorator, name, newValue, oldValue){ |
---|
17 | // summary: |
---|
18 | // applies a decorator unraveling all embedded decorators |
---|
19 | // decorator: Function: |
---|
20 | // top-level decorator to apply |
---|
21 | // name: String: |
---|
22 | // name of the property |
---|
23 | // newValue: Object: |
---|
24 | // new value of the property |
---|
25 | // oldValue: Object: |
---|
26 | // old value of the property |
---|
27 | // returns: Object: |
---|
28 | // returns the final value of the property |
---|
29 | if(newValue instanceof Decorator){ |
---|
30 | var d = newValue.decorator; |
---|
31 | newValue = applyDecorator(decorator, name, newValue.value, oldValue); |
---|
32 | return d(name, newValue, oldValue); |
---|
33 | } |
---|
34 | return decorator(name, newValue, oldValue); |
---|
35 | }; |
---|
36 | |
---|
37 | /*===== |
---|
38 | dojox.lang.oo.__MixinDefaults = function(){ |
---|
39 | // summary: |
---|
40 | // a dict of default parameters for dojox.lang.oo._mixin |
---|
41 | // decorator: Function: |
---|
42 | // a decorator function to be used in absence of other decorators |
---|
43 | // filter: Function: |
---|
44 | // a filter function to be used in absence of other filters |
---|
45 | // mixer: Function: |
---|
46 | // a mixer function to be used to mix in new properties |
---|
47 | this.decorator = decorator; |
---|
48 | this.filter = filter; |
---|
49 | this.mixer = mixer; |
---|
50 | }; |
---|
51 | =====*/ |
---|
52 | |
---|
53 | oo.__mixin = function(target, source, decorator, filter, mixer){ |
---|
54 | // summary: |
---|
55 | // mixes in two objects processing decorators and filters |
---|
56 | // target: Object: |
---|
57 | // target to receive new/updated properties |
---|
58 | // source: Object: |
---|
59 | // source of properties |
---|
60 | // defaults: dojox.lang.oo.__MixinDefaults?: |
---|
61 | // default functions for various aspects of mixing |
---|
62 | // returns: Object: |
---|
63 | // target |
---|
64 | |
---|
65 | var name, targetName, prop, newValue, oldValue, i; |
---|
66 | |
---|
67 | // start mixing in properties |
---|
68 | for(name in source){ |
---|
69 | prop = source[name]; |
---|
70 | if(!(name in empty) || empty[name] !== prop){ |
---|
71 | targetName = filter(name, target, source, prop); |
---|
72 | if(targetName && (!(targetName in target) || !(targetName in empty) || empty[targetName] !== prop)){ |
---|
73 | // name is accepted |
---|
74 | oldValue = target[targetName]; |
---|
75 | newValue = applyDecorator(decorator, targetName, prop, oldValue); |
---|
76 | if(oldValue !== newValue){ |
---|
77 | mixer(target, targetName, newValue, oldValue); |
---|
78 | } |
---|
79 | } |
---|
80 | } |
---|
81 | } |
---|
82 | if(extraLen){ |
---|
83 | for(i = 0; i < extraLen; ++i){ |
---|
84 | name = extraNames[i]; |
---|
85 | // repeating the body above |
---|
86 | prop = source[name]; |
---|
87 | if(!(name in empty) || empty[name] !== prop){ |
---|
88 | targetName = filter(name, target, source, prop); |
---|
89 | if(targetName && (!(targetName in target) || !(targetName in empty) || empty[targetName] !== prop)){ |
---|
90 | // name is accepted |
---|
91 | oldValue = target[targetName]; |
---|
92 | newValue = applyDecorator(decorator, targetName, prop, oldValue); |
---|
93 | if(oldValue !== newValue){ |
---|
94 | mixer(target, targetName, newValue, oldValue); |
---|
95 | } |
---|
96 | } |
---|
97 | } |
---|
98 | } |
---|
99 | } |
---|
100 | |
---|
101 | return target; // Object |
---|
102 | }; |
---|
103 | |
---|
104 | oo.mixin = function(target, source){ |
---|
105 | // summary: |
---|
106 | // mixes in two or more objects processing decorators and filters |
---|
107 | // using defaults as a fallback |
---|
108 | // target: Object: |
---|
109 | // target to receive new/updated properties |
---|
110 | // source: Object...: |
---|
111 | // source of properties, more than one source is allowed |
---|
112 | // returns: Object: |
---|
113 | // target |
---|
114 | |
---|
115 | var decorator, filter, i = 1, l = arguments.length; |
---|
116 | for(; i < l; ++i){ |
---|
117 | source = arguments[i]; |
---|
118 | if(source instanceof Filter){ |
---|
119 | filter = source.filter; |
---|
120 | source = source.bag; |
---|
121 | }else{ |
---|
122 | filter = defaultFilter; |
---|
123 | } |
---|
124 | if(source instanceof Decorator){ |
---|
125 | decorator = source.decorator; |
---|
126 | source = source.value; |
---|
127 | }else{ |
---|
128 | decorator = defaultDecorator; |
---|
129 | } |
---|
130 | oo.__mixin(target, source, decorator, filter, defaultMixer); |
---|
131 | } |
---|
132 | return target; // Object |
---|
133 | }; |
---|
134 | })(); |
---|