forked from rse/componentjs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcomponent.plugin.values.js
82 lines (74 loc) · 3.57 KB
/
component.plugin.values.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
** ComponentJS -- Component System for JavaScript <http://componentjs.com>
** Copyright (c) 2009-2013 Ralf S. Engelschall <http://engelschall.com>
**
** This Source Code Form is subject to the terms of the Mozilla Public
** License, v. 2.0. If a copy of the MPL was not distributed with this
** file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*
* This is a small ComponentJS plugin which adds a "values" method
* to all components which is like the regular "value" method,
* but instead of getter/setter-based access to a particular
* model value, it provides an ECMAScript/5 property-based object
* for direct access to all model values. Getting a property via
* component.values().foo is equivalent to component.value("foo").
* Setting a property via component.values().foo = "bar" is equivalent
* to component.value("foo", "bar"). As ECMAScript/5 properties are
* still not available in every environment, this functionality has to
* stay in an optional plugin, of course.
*/
/* global ComponentJS:false */
/* jshint unused:false */
ComponentJS.plugin("values", function (_cs, $cs, GLOBAL) {
/* sanity check run-time environment */
if (_cs.istypeof(Object.defineProperty) !== "function")
throw _cs.exception("plugin:values", "sorry, mandatory ECMAScript/5 " +
"Object.defineProperty() method not supported by run-time environment");
/* define the extra trait for components */
var trait = $cs.trait({
protos: {
/* retrieve a property-based values object */
values: function () {
/* attempt to retrieve cached values object */
var values = this.property({ name: "ComponentJS:model:values" });
if (!_cs.isdefined(values)) {
/* create initial values object */
values = {};
/* iterate over all models towards the root component */
var found = false;
var comp = this;
var owner, model;
while (comp !== null) {
owner = comp.property({ name: "ComponentJS:model", returnowner: true });
if (!_cs.isdefined(owner))
break;
found = true;
model = owner.property("ComponentJS:model");
comp = owner.parent();
/* enhance values object with properties of all models */
for (var name in model) {
var symbol = name.replace(/[^a-zA-Z0-9_]+/g, "_");
(function (comp, name, symbol) {
Object.defineProperty(values, symbol, {
enumerable: false,
configurable: false,
writeable: true,
get: function () { return comp.value(name); },
set: function (value) { return comp.value(name, value); }
});
})(comp, name, symbol);
}
}
if (!found)
throw _cs.exception("values", "no models found at all");
}
return values;
}
}
});
/* mixin this trait to all components */
_cs.latch("ComponentJS:bootstrap:comp:mixin", function (mixins) {
mixins.push(trait);
});
});