-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmodel-bind-behavior.html
142 lines (108 loc) · 3.32 KB
/
model-bind-behavior.html
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<link rel="import" href="../tangere/tangere.html">
<script>/** @polymerBehavior Tangere.behaviors.modelBind */
Tangere.behaviors.modelBind = {
observers: ['_bindModel(model,modelBind)'],
properties: {
/**
* modelBind
*
* @property modelBind
* @type String
* @default ''
*/
modelBind: {
type: String,
value: ""
},
/**
* model
*
* @property model
* @type Object
* @default null
*/
model: {
type: Object,
value: null
}
},
_updateModel: function(n) {
if (n == this.model) {
// model reference did nor change --> force reevaluation of modelBind
this._bindModel(this.model, this.modelBind);
} else {
this.model = n;
}
},
_bindModel: function(model,modelBind) {
var i = 0;
if (model && modelBind) {
var modelVars = Object.getOwnPropertyNames(this.model);
var vars = "";
for (i = 0; i < modelVars.length; i++) {
var name = modelVars[i];
vars = vars + ", " + name + "=this." + name;
}
if (vars != "") vars = "var " + vars.substring(1);
var binder = this._parseBinder(modelBind);
var binds = Object.getOwnPropertyNames(binder);
for (i = 0; i < binds.length; i++) {
var bind = binds[i];
if (this[bind] == undefined) {
console.warn("cannot bind to unknown property " + bind);
continue;
}
var pre = "(", post = ")";
// ensure that boolean property remains boolean
if (typeof this[bind] == "boolean") {
pre = "!!(";
}
// evaluate binder function on current model and assign result to property
try {
var func = new Function(vars + ";return (" + pre + binder[bind] + post + ");");
this[bind] = func.call(this.model);
} catch (ex) {
console.warn("failed to bind " + bind + " to " + binder[bind] + ": " + ex.message);
}
}
}
// call _modelChanged if present
if (!(this._modelChanged == undefined)) {
this._modelChanged();
}
},
_parseBinder: function(s) {
var binder = {};
if (!s) return binder;
// convert prop1:val,prop2:expr,... to binder: { prop1: val, prop2: expr }
var defs = s.split(",");
for (var i = 0; i < defs.length; i++) {
var def = defs[i];
var split = def.split(":");
if (split.length == 2) {
binder[split[0].trim()] = split[1].trim();
}
}
return binder;
},
actionListener: function (event) {
var oldModel = this.model;
// we now only use the "real" model
this.model = event.detail.model.state.model;
// if this.model is unchanged then a "deep" change happened
// and modelBind needs to invoked directly
if (oldModel == this.model) {
this._bindModel(this.model, this.modelBind);
}
},
__getElementPath: function (element) {
if (element == null) return [];
var pathArr = [element];
while (element.parentElement != null) {
element = element.parentElement;
pathArr.push(element);
}
return pathArr;
}
};
</script>