This repository has been archived by the owner on Aug 11, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
vega-behavior.html
261 lines (243 loc) · 7.68 KB
/
vega-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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
<html><head><link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../hiveoss-common-libraries/vega.html">
</head><body><script>
'use strict';
(function (Hiveoss) {
/**
* Use `Polymer.NeonSharedElementAnimatableBehavior` to implement elements containing shared element
* animations.
* @polymerBehavior Polymer.NeonSharedElementAnimatableBehavior
*/
Hiveoss.VegaBehavior = {
properties: {
/*
* Notifies whether Vega is still busy.
* As there the DOM listener for SVG is not currently implemented, **loading** will not reflect the status of SVG rendering.
* As *Canvas* rendering is sync, **loading** will reflect then completion of Canvas rendering.
*/
loading: {
type: Boolean,
readonly: true,
notify: true,
value: false
},
/*
* String or an Array of String. Specify the name of the datasets to retrieve from Vega.
* The datasets will be return as attribute **last-data**.
*/
requestData: {
type: Object
},
/*
* Object-map of the dataset requested in attribute **request-data**. The keys are the dataset names.
*/
lastData: {
type: Object,
notify: true,
readonly: true
},
/*
* An object containing named data sets. The data argument can be used to bind data sets at runtime for dynamic, reusable chart components. Data sets whose names do not match any data definitions in the Vega specification will be ignored.
*
* Example data Object
* ```
* {
* dataName: function(data) { data.insert(someArray); }
* }
* ```
* details:
* https://github.com/vega/vega/wiki/Runtime
* https://github.com/vega/vega/wiki/Streaming-Data
*/
data: {
type: Object
},
/*
* Vega view object.
*
* details: https://github.com/vega/vega/wiki/Runtime
*/
view: {
type: Object,
readonly: true,
notify: true
},
/*
* Vega JSON specification or a URL.
*
* details: https://github.com/vega/vega/wiki
*/
spec: {
type: Object
},
/*
* The renderer to use - **canvas** or **svg**.
*/
renderer: {
type: String,
value: 'canvas'
},
/*
* Updates a Vega signal with an object **{signal,value}**, where signal is the signal to update, and value is the value to update with.
*/
signal: {
type: Object
},
/*
* Vega signals to observe - will fire a **signal** event and return an object **{signal,value}**.
*
* e.g.
* ```
* <vega-element observe-signals="[[signals]]"
* on-signal="handleSignal"
* last-signal="{{lastSignal}}"></vega-element>
* ```
*/
observeSignals: {
type: Array,
observer: '_observeSignalsChanged'
},
/*
* The latest signal based on the signals specified in observer-signals.
* Return an object **{signal,value}**.
*/
lastSignal: {
type: Object,
readonly: true,
notify: true
},
/*
* The easing to use for transition.
* See d3 v3 easing doc for possible values:
* [https://github.com/d3/d3-3.x-api-reference/blob/master/Transitions.md#easing](https://github.com/d3/d3-3.x-api-reference/blob/master/Transitions.md#easing)
*/
ease: {
type: String,
value: 'in-out'
},
/*
* The duration in milliseconds to use for transition.
*/
duration: {
type: Number,
value: 300
},
/*
* Vega chart object.
*
* details: https://github.com/vega/vega/wiki/Runtime
*/
_chart: {
type: Object
},
_diff: {
type: Object
}
},
observers: ["parse(spec)", "updateSignal(signal,view)", "getData(requestData,view)", "_updateSignalListeners(_diff.added,_diff.removed,view)", '_updateData(view,data)'],
/*
* Parse a Vega JSON specification or URL. Updates the **_chart** attribute. Automatically called when **spec** is updated.
*/
parse: function parse(spec) {
if (!spec) return;
this.loading = true;
var self = this;
vg.parse.spec(spec, function (error, chart) {
self._chart = chart;
});
},
/*
* Updates a Vega signal. 1st argument takes in a {signal,value} Object, where signal is the signal to update, and value is the value to update with.
* The 2nd argument is the optional **view** Object.
*/
updateSignal: function updateSignal(signal, view) {
if (!signal) return;
view = view || this.view;
if (!view) return;
var self = this;
this.loading = true;
view.signal(signal.signal, signal.value).update({ duration: this.duration, ease: this.ease });
this.async(function () {
self.getData(self.requestData, self.view);
}, 500);
this.loading = false;
},
/*
* Retrieve datasets from Vega. 1st argument is either the dataset name or an Array of dataset names.
* Return a Object-map with the dataset names as keys.
*/
getData: function getData(dataname, view) {
if (!dataname) return;
view = view || this.view;
if (!view) return;
var res = {};
var datanames = Array.isArray(dataname) ? dataname : [dataname];
datanames.forEach(function (d) {
res[d] = view.data(d).values();
});
this.set('lastData', res);
return this.lastData;
},
_updateData: function _updateData(view, data) {
if (!view || !data) return;
view.data(data).update({ duration: this.duration, ease: this.ease });
},
_observeSignalsChanged: function _observeSignalsChanged(val, old) {
this._diff = this._difference(val, old);
},
_difference: function _difference(currArr, oldArr) {
var map = new Map();
// set new values to be 1
currArr = currArr || [];
currArr.forEach(function (d) {
return map.set(d, 1);
});
// set existing values to 3, and removed values to be 2
oldArr = oldArr || [];
oldArr.forEach(function (d) {
return map.set(d, map.has(d) ? 3 : 2);
});
// extract into 2 array, new values, and removed values
var added = [],
removed = [];
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = map[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var k = _step.value;
if (k[1] === 1) added.push(k[0]);
if (k[1] === 2) removed.push(k[0]);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return { added: added, removed: removed };
},
_updateSignalListeners: function _updateSignalListeners(add, remove, view) {
view = view || this.view;
if (!view) return;
var self = this;
add.forEach(function (d) {
view.onSignal(d, function (signal, value) {
var res = { signal: signal, value: value };
self.lastSignal = res;
self.fire('signal', res);
});
});
remove.forEach(view.offSignal);
}
};
})(window.Hiveoss = window.Hiveoss || {});
</script></body></html>