Skip to content

Commit 07e6737

Browse files
author
Christopher Baker
committed
3.3.7
1 parent f709e0b commit 07e6737

File tree

4 files changed

+5728
-0
lines changed

4 files changed

+5728
-0
lines changed

dist/amd/can-view-scope.js

+283
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
/*[email protected]#can-view-scope*/
2+
define([
3+
'require',
4+
'exports',
5+
'module',
6+
'can-stache-key',
7+
'can-observation',
8+
'./reference-map',
9+
'./compute_data',
10+
'can-util/js/assign',
11+
'can-util/js/each',
12+
'can-namespace',
13+
'can-util/js/dev',
14+
'can-reflect',
15+
'can-util/js/log'
16+
], function (require, exports, module) {
17+
var observeReader = require('can-stache-key');
18+
var Observation = require('can-observation');
19+
var ReferenceMap = require('./reference-map');
20+
var makeComputeData = require('./compute_data');
21+
var assign = require('can-util/js/assign');
22+
var each = require('can-util/js/each');
23+
var namespace = require('can-namespace');
24+
var dev = require('can-util/js/dev');
25+
var canReflect = require('can-reflect');
26+
var canLog = require('can-util/js/log');
27+
function Scope(context, parent, meta) {
28+
this._context = context;
29+
this._parent = parent;
30+
this._meta = meta || {};
31+
this.__cache = {};
32+
}
33+
assign(Scope, {
34+
read: observeReader.read,
35+
Refs: ReferenceMap,
36+
refsScope: function () {
37+
return new Scope(new this.Refs());
38+
},
39+
keyInfo: function (attr) {
40+
var info = {};
41+
info.isDotSlash = attr.substr(0, 2) === './';
42+
info.isThisDot = attr.substr(0, 5) === 'this.';
43+
info.isThisAt = attr.substr(0, 5) === 'this@';
44+
info.isInCurrentContext = info.isDotSlash || info.isThisDot || info.isThisAt;
45+
info.isInParentContext = attr.substr(0, 3) === '../';
46+
info.isCurrentContext = attr === '.' || attr === 'this';
47+
info.isParentContext = attr === '..';
48+
info.isContextBased = info.isInCurrentContext || info.isInParentContext || info.isCurrentContext || info.isParentContext;
49+
return info;
50+
}
51+
});
52+
assign(Scope.prototype, {
53+
add: function (context, meta) {
54+
if (context !== this._context) {
55+
return new this.constructor(context, this, meta);
56+
} else {
57+
return this;
58+
}
59+
},
60+
read: function (attr, options) {
61+
if (attr === '%root') {
62+
return { value: this.getRoot() };
63+
}
64+
if (attr === '%scope') {
65+
return { value: this };
66+
}
67+
var keyInfo = Scope.keyInfo(attr);
68+
if (keyInfo.isContextBased && this._meta.notContext) {
69+
return this._parent.read(attr, options);
70+
}
71+
var currentScopeOnly;
72+
if (keyInfo.isInCurrentContext) {
73+
currentScopeOnly = true;
74+
attr = keyInfo.isDotSlash ? attr.substr(2) : attr.substr(5);
75+
} else if (keyInfo.isInParentContext || keyInfo.isParentContext) {
76+
var parent = this._parent;
77+
while (parent._meta.notContext) {
78+
parent = parent._parent;
79+
}
80+
if (keyInfo.isParentContext) {
81+
return observeReader.read(parent._context, [], options);
82+
}
83+
return parent.read(attr.substr(3) || '.', options);
84+
} else if (keyInfo.isCurrentContext) {
85+
return observeReader.read(this._context, [], options);
86+
}
87+
var keyReads = observeReader.reads(attr);
88+
if (keyReads[0].key.charAt(0) === '*') {
89+
return this.getRefs()._read(keyReads, options, true);
90+
} else {
91+
return this._read(keyReads, options, currentScopeOnly);
92+
}
93+
},
94+
_read: function (keyReads, options, currentScopeOnly) {
95+
var currentScope = this, currentContext, undefinedObserves = [], currentObserve, currentReads, setObserveDepth = -1, currentSetReads, currentSetObserve, readOptions = assign({
96+
foundObservable: function (observe, nameIndex) {
97+
currentObserve = observe;
98+
currentReads = keyReads.slice(nameIndex);
99+
},
100+
earlyExit: function (parentValue, nameIndex) {
101+
if (nameIndex > setObserveDepth || nameIndex === setObserveDepth && (typeof parentValue === 'object' && keyReads[nameIndex].key in parentValue)) {
102+
currentSetObserve = currentObserve;
103+
currentSetReads = currentReads;
104+
setObserveDepth = nameIndex;
105+
}
106+
}
107+
}, options);
108+
while (currentScope) {
109+
currentContext = currentScope._context;
110+
if (currentContext !== null && (typeof currentContext === 'object' || typeof currentContext === 'function')) {
111+
var getObserves = Observation.trap();
112+
var data = observeReader.read(currentContext, keyReads, readOptions);
113+
var observes = getObserves();
114+
if (data.value !== undefined) {
115+
Observation.addAll(observes);
116+
return {
117+
scope: currentScope,
118+
rootObserve: currentObserve,
119+
value: data.value,
120+
reads: currentReads
121+
};
122+
} else {
123+
undefinedObserves.push.apply(undefinedObserves, observes);
124+
}
125+
}
126+
if (currentScopeOnly) {
127+
currentScope = null;
128+
} else {
129+
currentScope = currentScope._parent;
130+
}
131+
}
132+
Observation.addAll(undefinedObserves);
133+
return {
134+
setRoot: currentSetObserve,
135+
reads: currentSetReads,
136+
value: undefined
137+
};
138+
},
139+
get: function (key, options) {
140+
options = assign({ isArgument: true }, options);
141+
var res = this.read(key, options);
142+
return res.value;
143+
},
144+
peek: Observation.ignore(function (key, options) {
145+
return this.get(key, options);
146+
}),
147+
peak: Observation.ignore(function (key, options) {
148+
return this.peek(key, options);
149+
}),
150+
getScope: function (tester) {
151+
var scope = this;
152+
while (scope) {
153+
if (tester(scope)) {
154+
return scope;
155+
}
156+
scope = scope._parent;
157+
}
158+
},
159+
getContext: function (tester) {
160+
var res = this.getScope(tester);
161+
return res && res._context;
162+
},
163+
getRefs: function () {
164+
var lastScope;
165+
var refScope = this.getScope(function (scope) {
166+
lastScope = scope;
167+
return scope._context instanceof Scope.Refs;
168+
});
169+
if (!refScope) {
170+
lastScope._parent = Scope.refsScope();
171+
refScope = lastScope._parent;
172+
}
173+
return refScope;
174+
},
175+
getRoot: function () {
176+
var cur = this, child = this;
177+
while (cur._parent) {
178+
child = cur;
179+
cur = cur._parent;
180+
}
181+
if (cur._context instanceof Scope.Refs) {
182+
cur = child;
183+
}
184+
return cur._context;
185+
},
186+
set: function (key, value, options) {
187+
options = options || {};
188+
var keyInfo = Scope.keyInfo(key);
189+
if (keyInfo.isCurrentContext) {
190+
return canReflect.setValue(this._context, value);
191+
} else if (keyInfo.isInParentContext || keyInfo.isParentContext) {
192+
var parent = this._parent;
193+
while (parent._meta.notContext) {
194+
parent = parent._parent;
195+
}
196+
if (keyInfo.isParentContext) {
197+
return canReflect.setValue(parent._context, value);
198+
}
199+
return parent.set(key.substr(3) || '.', value, options);
200+
}
201+
var dotIndex = key.lastIndexOf('.'), slashIndex = key.lastIndexOf('/'), contextPath, propName;
202+
if (slashIndex > dotIndex) {
203+
contextPath = key.substring(0, slashIndex);
204+
propName = key.substring(slashIndex + 1, key.length);
205+
} else {
206+
if (dotIndex !== -1) {
207+
contextPath = key.substring(0, dotIndex);
208+
propName = key.substring(dotIndex + 1, key.length);
209+
} else {
210+
contextPath = '.';
211+
propName = key;
212+
}
213+
}
214+
if (key.charAt(0) === '*') {
215+
observeReader.write(this.getRefs()._context, key, value, options);
216+
} else {
217+
var context = this.read(contextPath, options).value;
218+
if (context === undefined) {
219+
return;
220+
}
221+
if (!canReflect.isObservableLike(context) && canReflect.isObservableLike(context[propName])) {
222+
if (canReflect.isMapLike(context[propName])) {
223+
dev.warn('can-view-scope: Merging data into "' + propName + '" because its parent is non-observable');
224+
canReflect.updateDeep(context[propName], value);
225+
} else if (canReflect.isValueLike(context[propName])) {
226+
canReflect.setValue(context[propName], value);
227+
} else {
228+
observeReader.write(context, propName, value, options);
229+
}
230+
} else {
231+
observeReader.write(context, propName, value, options);
232+
}
233+
}
234+
},
235+
attr: Observation.ignore(function (key, value, options) {
236+
canLog.warn('can-view-scope::attr is deprecated, please use peek, get or set');
237+
options = assign({ isArgument: true }, options);
238+
if (arguments.length === 2) {
239+
return this.set(key, value, options);
240+
} else {
241+
return this.get(key, options);
242+
}
243+
}),
244+
computeData: function (key, options) {
245+
return makeComputeData(this, key, options);
246+
},
247+
compute: function (key, options) {
248+
return this.computeData(key, options).compute;
249+
},
250+
cloneFromRef: function () {
251+
var contexts = [];
252+
var scope = this, context, parent;
253+
while (scope) {
254+
context = scope._context;
255+
if (context instanceof Scope.Refs) {
256+
parent = scope._parent;
257+
break;
258+
}
259+
contexts.unshift(context);
260+
scope = scope._parent;
261+
}
262+
if (parent) {
263+
each(contexts, function (context) {
264+
parent = parent.add(context);
265+
});
266+
return parent;
267+
} else {
268+
return this;
269+
}
270+
}
271+
});
272+
function Options(data, parent, meta) {
273+
if (!data.helpers && !data.partials && !data.tags) {
274+
data = { helpers: data };
275+
}
276+
Scope.call(this, data, parent, meta);
277+
}
278+
Options.prototype = new Scope();
279+
Options.prototype.constructor = Options;
280+
Scope.Options = Options;
281+
namespace.view = namespace.view || {};
282+
module.exports = namespace.view.Scope = Scope;
283+
});

0 commit comments

Comments
 (0)