mascot-vis 3.0.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/dist/mascot-esm.js +186 -0
  2. package/package.json +3 -6
  3. package/dist/mascot-es.js +0 -27745
  4. package/dist/mascot-min.js +0 -186
  5. package/dist/mascot-umd.js +0 -27781
  6. package/js/depGraphVis.js +0 -66
  7. package/src-new-ts/action/createElement.ts +0 -91
  8. package/src-new-ts/action/encode.js +0 -20
  9. package/src-new-ts/action/repeat.js +0 -128
  10. package/src-new-ts/action/traverseScene.js +0 -41
  11. package/src-new-ts/data/Network.js +0 -2
  12. package/src-new-ts/data/Scope.js +0 -135
  13. package/src-new-ts/data/Table.js +0 -263
  14. package/src-new-ts/data/Tree.js +0 -3
  15. package/src-new-ts/data/field.ts +0 -115
  16. package/src-new-ts/data/import.ts +0 -96
  17. package/src-new-ts/data/predicate.ts +0 -82
  18. package/src-new-ts/depgraph/DepGraph.js +0 -178
  19. package/src-new-ts/depgraph/Edge.js +0 -9
  20. package/src-new-ts/depgraph/SceneGraph2DepGraph.js +0 -110
  21. package/src-new-ts/depgraph/Signal.js +0 -12
  22. package/src-new-ts/depgraph/operator/BoundsEvaluator.js +0 -30
  23. package/src-new-ts/depgraph/operator/Dataflow.js +0 -41
  24. package/src-new-ts/depgraph/operator/DomainBuilder.js +0 -50
  25. package/src-new-ts/depgraph/updateDepGraph.js +0 -45
  26. package/src-new-ts/depgraph/variable/BoundsVar.js +0 -81
  27. package/src-new-ts/depgraph/variable/ChannelVar.js +0 -17
  28. package/src-new-ts/depgraph/variable/DataScopeVar.js +0 -12
  29. package/src-new-ts/depgraph/variable/DomainVar.js +0 -15
  30. package/src-new-ts/depgraph/variable/FieldVar.js +0 -17
  31. package/src-new-ts/depgraph/variable/LayoutParameter.js +0 -8
  32. package/src-new-ts/depgraph/variable/ScaleVar.js +0 -13
  33. package/src-new-ts/depgraph/variable/Variable.js +0 -39
  34. package/src-new-ts/element/gradient/LinearGradient.js +0 -37
  35. package/src-new-ts/element/group/Collection.js +0 -109
  36. package/src-new-ts/element/group/Group.js +0 -307
  37. package/src-new-ts/element/group/Scene.js +0 -98
  38. package/src-new-ts/element/mark/CircleMark.ts +0 -85
  39. package/src-new-ts/element/mark/Mark.ts +0 -233
  40. package/src-new-ts/element/mark/PathMark.js +0 -483
  41. package/src-new-ts/element/mark/Segment.js +0 -29
  42. package/src-new-ts/element/mark/Vertex.js +0 -118
  43. package/src-new-ts/encode/Scale.ts +0 -115
  44. package/src-new-ts/index.ts +0 -19
  45. package/src-new-ts/layout/Layout.ts +0 -3
  46. package/src-new-ts/render/CanvasRenderer.ts +0 -24
  47. package/src-new-ts/render/SVGRenderer.js +0 -316
  48. package/src-new-ts/util.ts +0 -3
  49. package/src-old/action/Classify.js +0 -53
  50. package/src-old/action/Densify.js +0 -199
  51. package/src-old/action/Partition.js +0 -531
  52. package/src-old/action/Repeat.js +0 -106
  53. package/src-old/action/Repopulate.js +0 -44
  54. package/src-old/action/Stratify.js +0 -156
  55. package/src-old/basic/Gradient.js +0 -37
  56. package/src-old/basic/Point.js +0 -51
  57. package/src-old/basic/Rectangle.js +0 -63
  58. package/src-old/bind/bindToAngle.js +0 -56
  59. package/src-old/bind/bindToAreaMark.js +0 -360
  60. package/src-old/bind/bindToColor.js +0 -114
  61. package/src-old/bind/bindToLink.js +0 -81
  62. package/src-old/bind/bindToPosition.js +0 -283
  63. package/src-old/bind/bindToRadialDistance.js +0 -62
  64. package/src-old/bind/bindToSize.js +0 -235
  65. package/src-old/bind/bindToText.js +0 -60
  66. package/src-old/bind/bindToThickness.js +0 -100
  67. package/src-old/constraint/AffixConstraint.js +0 -129
  68. package/src-old/constraint/AlignConstraint.js +0 -58
  69. package/src-old/core/Encoding.js +0 -336
  70. package/src-old/core/Scale.js +0 -322
  71. package/src-old/core/SceneLoader.js +0 -290
  72. package/src-old/core/SceneValidator.js +0 -232
  73. package/src-old/core/SpecExecutor.js +0 -113
  74. package/src-old/core/SpecGenerator.js +0 -350
  75. package/src-old/data/DataImporter.js +0 -64
  76. package/src-old/data/DataScope.js +0 -124
  77. package/src-old/data/DataTable.js +0 -338
  78. package/src-old/data/Network.js +0 -106
  79. package/src-old/data/Tree.js +0 -251
  80. package/src-old/data/transform/Bin.js +0 -46
  81. package/src-old/data/transform/Filter.js +0 -48
  82. package/src-old/data/transform/Groupby.js +0 -18
  83. package/src-old/data/transform/KDE.js +0 -58
  84. package/src-old/data/transform/Sort.js +0 -14
  85. package/src-old/data/transform/Split.js +0 -5
  86. package/src-old/data/transform/partition.js +0 -46
  87. package/src-old/history/UndoRedoStack +0 -0
  88. package/src-old/index.js +0 -271
  89. package/src-old/indexSVG.js +0 -259
  90. package/src-old/interaction/Interaction.js +0 -91
  91. package/src-old/interaction/MouseEvent.js +0 -8
  92. package/src-old/interaction/Selection.js +0 -9
  93. package/src-old/interaction/brush.js +0 -362
  94. package/src-old/item/Segment.js +0 -29
  95. package/src-old/item/Vertex.js +0 -118
  96. package/src-old/item/composite/Collection.js +0 -106
  97. package/src-old/item/composite/Glyph.js +0 -19
  98. package/src-old/item/composite/Group.js +0 -310
  99. package/src-old/item/composite/Scene.js +0 -1251
  100. package/src-old/item/mark/ArcPath.js +0 -181
  101. package/src-old/item/mark/AreaPath.js +0 -78
  102. package/src-old/item/mark/CirclePath.js +0 -102
  103. package/src-old/item/mark/EllipsePath.js +0 -5
  104. package/src-old/item/mark/Image.js +0 -101
  105. package/src-old/item/mark/LinkPath.js +0 -118
  106. package/src-old/item/mark/Mark.js +0 -163
  107. package/src-old/item/mark/Path.js +0 -494
  108. package/src-old/item/mark/PointText.js +0 -201
  109. package/src-old/item/mark/PolygonPath.js +0 -64
  110. package/src-old/item/mark/RectPath.js +0 -88
  111. package/src-old/item/mark/RingPath.js +0 -92
  112. package/src-old/item/refs/Axis.js +0 -362
  113. package/src-old/item/refs/EncodingAxis.js +0 -515
  114. package/src-old/item/refs/Gridlines.js +0 -144
  115. package/src-old/item/refs/LayoutAxis.js +0 -316
  116. package/src-old/item/refs/Legend.js +0 -273
  117. package/src-old/layout/Circular.js +0 -95
  118. package/src-old/layout/Force.js +0 -52
  119. package/src-old/layout/Grid.js +0 -423
  120. package/src-old/layout/Layout.js +0 -13
  121. package/src-old/layout/Packing.js +0 -56
  122. package/src-old/layout/Stack.js +0 -264
  123. package/src-old/layout/Strata.js +0 -88
  124. package/src-old/layout/Sugiyama.js +0 -59
  125. package/src-old/layout/TidyTree.js +0 -105
  126. package/src-old/layout/Treemap.js +0 -87
  127. package/src-old/renderer/SVGInteractionHandler.js +0 -241
  128. package/src-old/renderer/SVGRenderer.js +0 -325
  129. package/src-old/renderer/WebGLRenderer.js +0 -1097
  130. package/src-old/renderer/WebGLRenderer2.js +0 -249
  131. package/src-old/renderer/threejs/Line2.js +0 -18
  132. package/src-old/renderer/threejs/LineGeometry.js +0 -77
  133. package/src-old/renderer/threejs/LineMaterial.js +0 -605
  134. package/src-old/renderer/threejs/LineSegments2.js +0 -281
  135. package/src-old/renderer/threejs/LineSegmentsGeometry.js +0 -226
  136. package/src-old/renderer/threejs/Wireframe.js +0 -51
  137. package/src-old/renderer/threejs/WireframeGeometry2.js +0 -16
  138. package/src-old/scale/areaSize.js +0 -0
  139. package/src-old/scale/domain.js +0 -38
  140. package/src-old/util/Constants.js +0 -180
  141. package/src-old/util/DataUtil.js +0 -35
  142. package/src-old/util/ItemUtil.js +0 -586
  143. package/src-old/util/Numerical.js +0 -33
  144. package/tests/demo-tests/README.md +0 -80
  145. package/tests/demo-tests/SVG2PNG.js +0 -56
  146. package/tests/demo-tests/demos2CanvasPNGs.js +0 -69
  147. package/tests/demo-tests/demos2ScenesSVGs.js +0 -100
  148. package/tests/demo-tests/pathElementWorker.js +0 -91
  149. package/tests/demo-tests/pixelTest.js +0 -62
  150. package/tests/demo-tests/renderDemos.html +0 -132
  151. package/tests/demo-tests/serializationTest.js +0 -36
  152. package/tests/demo-tests/serializeDemos.html +0 -134
  153. package/tests/unit-tests/README.md +0 -4
  154. package/tests/unit-tests/jasmine-browser.json +0 -21
  155. package/tests/unit-tests/jasmine.json +0 -14
  156. package/tests/unit-tests/testSpec.js +0 -274
@@ -1,1251 +0,0 @@
1
- import Group from "./Group";
2
- import { ItemType, Errors, LayoutType, ConstraintType, DataType, Warnings, Orientation } from "../../util/Constants";
3
- import { findItems, getParents, canAlign, getPeers, getEncodingKey, getClosestLayout, getPeersGroupedByParent, isPath, isGuide, isMark, ItemCounter, getAllChildren } from "../../util/ItemUtil";
4
- import { validateField } from "../../util/DataUtil";
5
- import { repeatItem, repeatNodeLink } from "../../action/Repeat";
6
- import { divideItem } from "../../action/Partition";
7
- import { densifyItem } from "../../action/Densify";
8
- import Mark from "../mark/Mark";
9
- import RectPath from "../mark/RectPath";
10
- import CirclePath from "../mark/CirclePath";
11
- import Path from "../mark/Path";
12
- import { bindToSize } from "../../bind/bindToSize";
13
- import { bindToPosition } from "../../bind/bindToPosition";
14
- import { bindToRadialDistance } from "../../bind/bindToRadialDistance";
15
- import { bindToColor } from "../../bind/bindToColor";
16
- import { bindToAngle } from "../../bind/bindToAngle"
17
- import { bindToAreaMark } from "../../bind/bindToAreaMark";
18
- import { bindToText } from "../../bind/bindToText";
19
- import Encoding from "../../core/Encoding";
20
- import DataTable from "../../data/DataTable";
21
- import EncodingAxis from "../refs/EncodingAxis";
22
- import LayoutAxis from "../refs/LayoutAxis";
23
- import Legend from "../refs/Legend";
24
- import Glyph from "./Glyph";
25
- import AreaPath from "../mark/AreaPath";
26
- import RingPath from "../mark/RingPath";
27
- import PolygonPath from "../mark/PolygonPath";
28
- import AlignConstraint from "../../constraint/AlignConstraint";
29
- import AffixConstraint from "../../constraint/AffixConstraint";
30
- import PointText from "../mark/PointText";
31
- import Gridlines from "../refs/Gridlines";
32
- import Collection from "./Collection";
33
- import DataScope from "../../data/DataScope";
34
- import ArcPath from "../mark/ArcPath";
35
- import Image from "../mark/Image";
36
- import LinkPath from "../mark/LinkPath";
37
- import { bindToLink } from "../../bind/bindToLink";
38
- import SceneValidator from "../../core/SceneValidator";
39
- import { repopulateItem } from "../../action/Repopulate";
40
- import { bindToThickness } from "../../bind/bindToThickness";
41
- import Tree from "../../data/Tree";
42
- import { stratifyItem } from "../../action/Stratify";
43
- import { classifiable, classifyCollectionChildren } from "../../action/Classify";
44
-
45
-
46
- export default class Scene extends Group {
47
-
48
- constructor(args) {
49
- super();
50
- if (args && args.fillColor) {
51
- this.fillColor = args.fillColor;
52
- }
53
- this.type = ItemType.Scene;
54
- this._id = this.type + ItemCounter[this.type]++;
55
- //this.cellAlign = {};
56
- this._encodings = {};
57
- this.constraints = {};
58
- this._itemMap = {};
59
- this._interactions = [];
60
- this._interactionsObj = {};
61
- }
62
-
63
- clear() {
64
- this.removeAll();
65
- this._encodings = {};
66
- this.constraints = {};
67
- this._itemMap = {};
68
- }
69
-
70
- group(children) {
71
- let g = new Group();
72
- g.classId = g.id;
73
- this.addChild(g);
74
- if (children && children.length > 0)
75
- for (let c of children)
76
- g.addChild(c);
77
- this._itemMap[g.id] = g;
78
- return g;
79
- }
80
-
81
- mark(type, param) {
82
- let args = param === undefined ? {} : param;
83
- let m = null;
84
- args.type = type;
85
- switch (type) {
86
- case ItemType.Rect: {
87
- if (!("top" in args))
88
- args.top = 0;
89
- if (!("left" in args))
90
- args.left = 0;
91
- if (!("width" in args))
92
- args.width = 100;
93
- if (!("height" in args))
94
- args.height = 100;
95
- let top = args["top"], left = args["left"], width = args["width"], height = args["height"];
96
- args.vertices = [[left, top], [left + width, top], [left + width, top + height], [left, top + height]];
97
- delete args["top"];
98
- delete args["left"];
99
- delete args["width"];
100
- delete args["height"];
101
- if (!("fillColor" in args)) {
102
- args.fillColor = "none";
103
- }
104
- m = new RectPath(args);
105
- break;
106
- }
107
- case ItemType.Area:
108
- if (args !== undefined && "x1" in args && "y1" in args && "x2" in args && "y2" in args) {
109
- let x1 = args["x1"], y1 = args["y1"], x2 = args["x2"], y2 = args["y2"];
110
- // args.vertices contains all the vertices on two boundary lines
111
- args.vertices = [[x1, y1], [x2, y1], [x2, y2], [x1, y2]];
112
- delete args["x1"];
113
- delete args["y1"];
114
- delete args["x2"];
115
- delete args["y2"];
116
- }
117
- m = new AreaPath(args);
118
- break;
119
- case ItemType.Line: {
120
- //it is possible to create a skeleton line without x1, y1, x2, y2 args, e.g. when duplicating
121
- if (args !== undefined && "x1" in args && "y1" in args && "x2" in args && "y2" in args) {
122
- let x1 = args["x1"], y1 = args["y1"], x2 = args["x2"], y2 = args["y2"];
123
- args.vertices = [[x1, y1], [x2, y2]];
124
- //remove x1, y1, x2, y2 and compute these values at rendering time
125
- //so that we don't have to keep track of them when the line is transformed
126
- delete args["x1"];
127
- delete args["y1"];
128
- delete args["x2"];
129
- delete args["y2"];
130
- }
131
- m = new Path(args);
132
- m.type = ItemType.Line;
133
- break;
134
- }
135
- case ItemType.Path:
136
- m = new Path(args);
137
- break;
138
- case ItemType.Circle:
139
- m = new CirclePath(args);
140
- break;
141
- case ItemType.Ring:
142
- m = new RingPath(args);
143
- break;
144
- case ItemType.Arc:
145
- case ItemType.Pie:
146
- m = new ArcPath(args);
147
- break;
148
- case ItemType.Polygon:
149
- m = new PolygonPath(args);
150
- break;
151
- // case ItemType.Pie:
152
- // args.innerRadius = 0;
153
- // if ("radius" in args) {
154
- // args.outerRadius = args.radius;
155
- // }
156
- // m = new ArcPath(args);
157
- // break;
158
- case "text":
159
- case ItemType.PointText:
160
- if (!("anchor" in args))
161
- args["anchor"] = ["center", "middle"];
162
- m = new PointText(args);
163
- break;
164
- case ItemType.Image:
165
- m = new Image(args);
166
- break;
167
- case ItemType.Link:
168
- m = new LinkPath(args);
169
- break;
170
- default:
171
- break;
172
- }
173
- if (m !== null) {
174
- if ("id" in args)
175
- m.id = args.id;
176
- else
177
- m.id = m.type + ItemCounter[m.type]++;
178
- m.classId = m.id;
179
- this.addChild(m);
180
- this._itemMap[m.id] = m;
181
- }
182
- return m;
183
- }
184
-
185
- glyph(...args) {
186
- let g = new Glyph(args);
187
- g.classId = g.id;
188
- this.addChild(g);
189
- this._itemMap[g.id] = g;
190
- return g;
191
- }
192
-
193
- collection() {
194
- let c = new Collection();
195
- this.addChild(c);
196
- this._itemMap[c.id] = c;
197
- return c;
198
- }
199
-
200
- attach(item, table) {
201
- item.dataScope = new DataScope(table);
202
- }
203
-
204
- repeat(item, data, param) {
205
- if (!item || data === undefined) {
206
- throw Errors.INCOMPLETE_REPEAT_INFO;
207
- }
208
-
209
- if (data.nodeTable && data.linkTable) {
210
- if (!Array.isArray(item) || item.length !== 2)
211
- throw Errors.REPEAT_NODE_LINK;
212
- return repeatNodeLink(this, item[0], item[1], data);
213
- } else {
214
- let args = param ? param : {},
215
- field = args["field"] ? args["field"] : DataTable.RowID,
216
- callback = args["callback"];
217
-
218
- validateField(field, data);
219
-
220
- let collection = repeatItem(this, item, field, data, callback);
221
- if (args.layout)
222
- collection.layout = args.layout;
223
- return collection;
224
- }
225
- }
226
-
227
- repopulate(item, table, param) {
228
- if (!item || table === undefined) {
229
- throw Errors.INCOMPLETE_REPEAT_INFO;
230
- }
231
-
232
- let args = param ? param : {},
233
- field = args["field"] ? args["field"] : DataTable.RowID;
234
-
235
- validateField(field, table);
236
- repopulateItem(this, item, field, table);
237
- }
238
-
239
- densify(item, table, param) {
240
- if (!item || table === undefined) {
241
- throw Errors.INCOMPLETE_PARTITION_INFO;
242
- }
243
-
244
- let args = param ? param : {},
245
- orientation = args["orientation"],
246
- field = args["field"] ? args["field"] : DataTable.RowID,
247
- //following two are for circle densification
248
- startAngle = "startAngle" in args ? args["startAngle"] : 90,
249
- direction = 'direction' in args ? args["direction"] : "clockwise",
250
- callback = args["callback"];
251
-
252
- validateField(field, table);
253
-
254
- let newItem = densifyItem(this, item, orientation, field, table, callback, startAngle, direction);
255
- SceneValidator.markDensified(item, newItem);
256
- return newItem;
257
- }
258
-
259
- stratify(item, data, param) {
260
- if (!(data instanceof Tree)) {
261
- throw Errors.STRATIFY_WITHOUT_TREE;
262
- }
263
-
264
- if (item.type !== ItemType.Circle && item.type !== ItemType.Rect) {
265
- throw Errors.STRATIFY_WRONG_ITEM;
266
- }
267
-
268
- let args = param ? param : {},
269
- direction = args["direction"],
270
- size = args["size"];
271
-
272
- let collection = stratifyItem(this, item, direction, size, data);
273
- //SceneValidator.markDivided(item, collection);
274
- return collection;
275
- }
276
-
277
- divide(item, data, param) {
278
- if (!item || data == undefined) {
279
- throw Errors.INCOMPLETE_PARTITION_INFO;
280
- }
281
-
282
- let args = param ? param : {},
283
- orientation = args["orientation"],
284
- field = args["field"] ? args["field"] : DataTable.RowID,
285
- callback = args["callback"];
286
-
287
- validateField(field, data);
288
-
289
- let collection = divideItem(this, item, orientation, field, data, callback);
290
- if (args.layout)
291
- collection.layout = args.layout;
292
-
293
- SceneValidator.markDivided(item, collection);
294
- return collection;
295
- }
296
-
297
- classify(item, param) {
298
- if (!classifiable(item)) {
299
- throw Errors.CANNOT_CLASSIFY + item.type;
300
- }
301
-
302
- let args = param ? param : {},
303
- field = args["field"] ? args["field"] : DataTable.RowID,
304
- dt = item.firstChild.dataScope.dataTable,
305
- layout = args.layout;
306
- validateField(field, dt);
307
-
308
- classifyCollectionChildren(this, item, field, layout);
309
-
310
- //SceneValidator.markDivided(item, collection);
311
- return item;
312
- }
313
-
314
- _validateEncodeArgs(item, args) {
315
- if (!item || !("channel" in args) || !("field" in args)) {
316
- throw Errors.INCOMPLETE_BINDING_INFO;
317
- }
318
-
319
- let field = args["field"];
320
-
321
- //check if can apply encoding
322
- if (item.type == "vertex" || item.type == "segment") {
323
- if (!item.parent.dataScope && !item.dataScope) {
324
- throw Errors.BIND_WITHOUT_DATASCOPE;
325
- }
326
- } else if (!item.dataScope) {
327
- throw Errors.BIND_WITHOUT_DATASCOPE;
328
- }
329
-
330
-
331
- let datatable = args.table ? args.table : item.dataScope ? item.dataScope._dt : item.parent.dataScope._dt;
332
-
333
- let ft = datatable.getFieldType(field);
334
- if (args.channel === "fillGradient" && [DataType.String, DataType.Boolean, DataType.Date].indexOf(ft) >= 0)
335
- throw Errors.UNSUPPORTED_FIELDTYPE + args.channel + ": " + ft;
336
-
337
- validateField(field, datatable);
338
- //todo: validate channel
339
- }
340
-
341
- //supports encoding one single item or an array of items (which will use the same scale)
342
- encode(itm, args) {
343
- let arr = Array.isArray(itm) ? itm : [itm];
344
- let encs = [], scale;
345
- for (let item of arr) {
346
- let items;
347
- if ([ItemType.Pie, ItemType.Arc].indexOf(itm.type) >= 0 && args.channel === "angle") {
348
- let parent = itm.parent;
349
- if (parent.type === ItemType.Collection && parent.layout && parent.layout.orientation === Orientation.Angular) {
350
- encs.push(this._encodeWithinCollection(item, args));
351
- continue;
352
- }
353
- }
354
- this._validateEncodeArgs(item, args);
355
- if (item.type == "vertex" && item.parent.type == ItemType.Area) {
356
- let areas = getPeers(item.parent, this);
357
- items = [];
358
- let firstHalf = item.parent.vertices.indexOf(item) < item.parent.vertices.length / 2;
359
- for (let area of areas) {
360
- items = firstHalf ? items.concat(area.vertices.slice(0, area.vertices.length / 2)) : items.concat(area.vertices.slice(area.vertices.length / 2));
361
- }
362
- } else {
363
- items = getPeers(item, this);
364
- }
365
- if (items.length === 1 && items[0].type === ItemType.Area && (args.channel === "x" || args.channel === "y")) {
366
- console.warn("Only 1 " + item.type + " found, cannot encode " + args.field);
367
- return;
368
- }
369
- if (!args.scale && scale) {
370
- args.scale = scale;
371
- }
372
- let enc = this._doEncode(items, args);
373
- if (!scale)
374
- scale = enc.scale;
375
- encs.push(enc);
376
- }
377
-
378
- return encs.length > 1 ? encs : encs[0];
379
- }
380
-
381
- _doEncode(items, args) {
382
- let item = items[0],
383
- channel = args["channel"],
384
- field = args["field"];
385
-
386
- if (!("datatable" in args))
387
- args.datatable = item.dataScope ? item.dataScope.dataTable : item.parent.dataScope.dataTable;
388
- if (!("aggregator" in args))
389
- args.aggregator = "mean";
390
- if (!("flipScale" in args))
391
- args.flipScale = false;
392
- if (!("includeZero" in args))
393
- args.includeZero = false;
394
- if (!("scaleType" in args))
395
- args.scaleType = "linear";
396
-
397
- let encoding = new Encoding(items, this, channel, field, args);
398
- switch (channel) {
399
- case "width":
400
- case "height":
401
- case "radius":
402
- case "outerRadius":
403
- case "innerRadius":
404
- case "area":
405
- case "fontSize":
406
- if (item.type == ItemType.Area)
407
- bindToAreaMark(encoding);
408
- else
409
- bindToSize(encoding);
410
- break;
411
- case "strokeWidth":
412
- if (item.type == ItemType.Link)
413
- bindToLink(encoding);
414
- else
415
- bindToSize(encoding);
416
- break;
417
- case "x":
418
- case "y":
419
- bindToPosition(encoding);
420
- // if (item.type == ItemType.Area)
421
- // bindToAreaMark(encoding);
422
- // else
423
- // bindToPosition(encoding);
424
- break;
425
- case "fillColor":
426
- case "strokeColor":
427
- bindToColor(encoding);
428
- break;
429
- case "fillGradient":
430
- if (item.type === ItemType.Area)
431
- bindToAreaMark(encoding);
432
- break;
433
- case "angle":
434
- bindToAngle(encoding);
435
- break;
436
- case "text":
437
- bindToText(encoding);
438
- break;
439
- case "radialDistance":
440
- // encoding.x = item.parent.x;
441
- // encoding.y = item.parent.y;
442
- // encoding.radius = item.parent.radius;
443
- bindToRadialDistance(encoding);
444
- break;
445
- case "thickness":
446
- bindToThickness(encoding);
447
- break;
448
- default:
449
- break;
450
- }
451
-
452
- if (!("_remember" in args) || args._remember == true)
453
- this._registerBinding(encoding);
454
-
455
- if (channel.indexOf("Color") < 0)
456
- this._updateAncestorBounds(item, encoding.items);
457
-
458
- return encoding;
459
- }
460
-
461
- _encodeWithinCollection(item, args) {
462
- this._validateEncodeArgs(item, args);
463
- let peersByGroup = getPeersGroupedByParent(item, this);
464
- let encs = [];
465
- for (let g of peersByGroup) {
466
- let enc = this._doEncode(g, args);
467
- encs.push(enc);
468
- }
469
- return encs;
470
- }
471
-
472
- getPeers(item) {
473
- return getPeers(item, this);
474
- }
475
-
476
- find(predicates) {
477
- return findItems(this, predicates);
478
- }
479
-
480
- align(items, direction) {
481
- //TODO: check the existing constraints and encodings and see if there's any conflict
482
- //if so, do nothing and return false
483
- if (!canAlign(items, direction, this)) return false;
484
- let c = new AlignConstraint(items, direction);
485
- if (c.id in this.constraints) {
486
- console.warn('constraint has been added');
487
- return false;
488
- }
489
- this.constraints[c.id] = c;
490
- c.apply();
491
- this._updateAncestorBounds(items[0]);
492
- }
493
-
494
- removeAllConstraints() {
495
- this.constraints = {};
496
- }
497
-
498
- removeConstraint(c) {
499
- delete this.constraints[c.id];
500
- }
501
-
502
- getRelatedConstraints(items) {
503
- let cstrs = [];
504
- for (let cid in this.constraints) {
505
- let c = this.constraints[cid];
506
- switch (c.type) {
507
- case ConstraintType.Align:
508
- if (c._itemIds === items.map(d => d.classId).sort().join("_"))
509
- cstrs.push(c);
510
- break;
511
- case ConstraintType.Affix:
512
- break;
513
- default:
514
- break;
515
- }
516
- }
517
- return cstrs;
518
- }
519
-
520
- // alignInCell(item, direction) {
521
- // //TODO replace grid.vertCellAlignment and grid.horzCellAlignment
522
- // }
523
-
524
- affix(item, baseItem, channel, param) {
525
- let args = param ? param : {},
526
- offset = "offset" in args ? args.offset : 0,
527
- itemAnchor = "itemAnchor" in args ? args.itemAnchor : (channel == "x" || channel == "angle") ? "center" : "middle",
528
- baseAnchor = "baseAnchor" in args ? args.baseAnchor : (channel == "x" || channel == "angle") ? "center" : "middle";
529
- let c = new AffixConstraint(item, baseItem, this, channel, itemAnchor, baseAnchor, offset);
530
- if (c.id in this.constraints) {
531
- //TODO: throw warning the constraint has been added, return false;
532
- }
533
- this.constraints[c.id] = c;
534
- c.apply();
535
- }
536
-
537
- //arguments include a channel (x, y, width, height for now)
538
- //optional arguments include orientation, x-coordinate, y-coordinate, tickFormat, strokeColor,
539
- axis(channel, field, params) {
540
- //need to figure out if item has the corresponding encoding, or if item position is determined by layout
541
- let args = params ? params : {}, enc = args.item ? this.getEncodingByItem(args.item, channel) : this.getEncodingByField(field, channel);
542
- if (enc && enc.field === field) {
543
- if (enc.datatable.getFieldType(field) === DataType.Date && !("labelFormat" in args)) {
544
- args.labelFormat = "%m/%d/%y";
545
- }
546
- if (enc.channel === "width") {
547
- let existingChannels = this.children.filter(d => d.type === ItemType.Axis).map(d => d.channel);
548
- if (!("orientation" in args))
549
- args.orientation = existingChannels.indexOf("x") >= 0 ? "top" : "bottom";
550
- } else if (enc.channel === "height") {
551
- let existingChannels = this.children.filter(d => d.type === ItemType.Axis).map(d => d.channel);
552
- if (!("orientation" in args))
553
- args.orientation = existingChannels.indexOf("y") >= 0 ? "right" : "left";
554
- }
555
- let axis = new EncodingAxis(enc, args.item ? args.item : enc.anyItem, args);
556
- if ("tickValues" in args) {
557
- axis.tickValues = args["tickValues"];
558
- axis.labelValues = args["tickValues"];
559
- } else {
560
- axis.tickValues = enc._inferTickValues();
561
- axis.labelValues = enc._inferTickValues();
562
- }
563
- //TODO: need to remove axis when encoding changes or axis is removed
564
- enc._axes.push(axis);
565
-
566
- this.addChildAt(axis, 0);
567
- this._itemMap[axis.id] = axis;
568
- this._updateBounds();
569
- return axis;
570
- }
571
-
572
- //TODO: find out item from the field
573
- let item = args.item ? args.item : findItems(this, [{ "field": field }])[0];
574
- if (item === undefined) {
575
- console.warn(Warnings.INCORRECT_AXIS_INFO + field);
576
- return;
577
- }
578
- let layout = getClosestLayout(item);
579
- if (!layout || (layout.type !== LayoutType.Grid && layout.type !== LayoutType.Stack)) return;
580
-
581
- if (layout && (channel == "x" || channel == "y")) {
582
- let group = layout.group,
583
- groups = getPeers(group, this);
584
- let axis, classId;
585
- //TODO: think about how to specify if mutliple axes need to be created properly
586
- // if (args.item)
587
- // groups = [args.item.parent];
588
- for (let c of groups) {
589
- let itm = findItems(c, [{ "field": field }])[0];
590
- let items = getPeers(itm, c);
591
- if (itm.dataScope.dataTable.getFieldType(field) === DataType.Date && !("labelFormat" in args)) {
592
- args.labelFormat = "%m/%d/%y";
593
- }
594
- axis = new LayoutAxis(items, c.layout, channel, field, args);
595
- if (classId == undefined)
596
- classId = axis.id;
597
- axis.classId = classId;
598
- this.addChildAt(axis, 0);
599
- this._itemMap[axis.id] = axis;
600
- // break;
601
- }
602
- this._updateBounds();
603
- return axis;
604
- } else {
605
- console.warn(Warnings.INCORRECT_AXIS_INFO + field);
606
- }
607
- }
608
-
609
- getRelatedAxes(item) {
610
- let axes = [];
611
- if (isGuide(item))
612
- return axes;
613
- for (let c of this.children) {
614
- if (c.type !== ItemType.Axis) continue;
615
- if (c.matches(item)) {
616
- axes.push(c);
617
- continue;
618
- }
619
- //handle layout axis for small multiples
620
- let p = c._item, found = false;
621
- while (p.children && p.children.length > 0) {
622
- for (let ic of p.children) {
623
- if (ic.classId === getEncodingKey(item).split("_")[0]) {
624
- found = true;
625
- axes.push(c);
626
- break;
627
- }
628
- }
629
- if (found) break;
630
- else p = p.children[0];
631
- }
632
-
633
- //handle axis if the updated item is a group/collection
634
- let allChildren = getAllChildren(item);
635
- let map = {};
636
- for (let i of allChildren) {
637
- if (i.classId in map) continue;
638
- map[i.classId] = i;
639
- }
640
- let toCheck = Object.values(map);
641
- for (let i of toCheck) {
642
- if (c.matches(i)) {
643
- axes.push(c);
644
- break;
645
- }
646
- }
647
- // while (p.children && p.children.length > 0) {
648
- // for (let ic of p.children) {
649
- // if (c.matches(ic)) {
650
- // found = true;
651
- // axes.push(c);
652
- // break;
653
- // }
654
- // }
655
- // if (found) break;
656
- // else p = p.children[0];
657
- // }
658
- }
659
- return axes;
660
- }
661
-
662
- removeItem(itm) {
663
- if (!isGuide(itm)) {
664
- let encodings = this.getRelatedEncodings(itm);
665
- for (let enc of encodings) {
666
- this.removeEncoding(enc);
667
- }
668
- //TODO: remove relevant graphical constraints
669
- let axes = this.getRelatedAxes(itm);
670
- for (let a of axes)
671
- this.removeItem(a);
672
- for (let g of this.getRelatedGridlines(itm))
673
- this.removeItem(g);
674
- }
675
- delete this._itemMap[itm.id];
676
- this.removeChild(itm);
677
- this._updateBounds();
678
- }
679
-
680
- //this is used to handle item deletion, assuming that item's parent is scene
681
- getRelatedEncodings(item) {
682
- let encodingKeys = [];
683
- let itm = item;
684
- while (itm) {
685
- encodingKeys.push(getEncodingKey(itm));
686
- if (itm.type == ItemType.Collection) {
687
- itm = itm.firstChild;
688
- } else if (itm.type == ItemType.Glyph) {
689
- for (let c of itm.children) {
690
- encodingKeys.push(getEncodingKey(c));
691
- }
692
- itm = undefined;
693
- } else {
694
- itm = undefined;
695
- }
696
- }
697
- let keys = Object.keys(this._encodings), encodings = [];
698
- for (let k of keys) {
699
- let itemKey = k.split("_")[0];
700
- if (encodingKeys.indexOf(itemKey) >= 0) {
701
- for (let channel in this._encodings[k])
702
- encodings.push(this._encodings[k][channel]);
703
- }
704
- }
705
- return encodings;
706
- }
707
-
708
- removeAllEncodings() {
709
- this._encodings = {};
710
- this.removeAllItemsByType(ItemType.Axis);
711
- this.removeAllItemsByType(ItemType.Legend);
712
- this.removeAllItemsByType(ItemType.Gridlines);
713
- }
714
-
715
- removeEncoding(enc) {
716
- let key = getEncodingKey(enc.anyItem);
717
- delete this._encodings[key][enc.channel];
718
- if (Object.keys(this._encodings[key]).length === 0)
719
- delete this._encodings[key];
720
- let toRemove = [];
721
- for (let c of this.children) {
722
- if (isGuide(c) && c.encoding && c.encoding === enc) {
723
- toRemove.push(c);
724
- }
725
- }
726
- for (let a of toRemove) {
727
- this.removeItem(a);
728
- }
729
- this._updateBounds();
730
- }
731
-
732
- removeAllItemsByType(type) {
733
- let toRemove = [];
734
- for (let a of this.children) {
735
- if (a.type === type) {
736
- toRemove.push(a);
737
- }
738
- }
739
- for (let i of toRemove)
740
- this.removeItem(i);
741
- this._updateBounds();
742
- }
743
-
744
- reCreateRelatedAxes(item) {
745
- let axes = this.getRelatedAxes(item);
746
- let layoutAxisClassIds = [];
747
- axes.forEach(a => {
748
- let args = a.toJSON().args;
749
- if (args.item)
750
- args.item = this.getItem(args.item);
751
- delete args["tickValues"];
752
- delete args["labelValues"];
753
- this.removeItem(a);
754
- if (a instanceof LayoutAxis) {
755
- if (layoutAxisClassIds.indexOf(a.classId) < 0) {
756
- this.axis(a.channel, a.field, args);
757
- layoutAxisClassIds.push(a.classId);
758
- }
759
- } else {
760
- this.axis(a.channel, a.field, args);
761
- }
762
- //toCreate.push({channel: a.channel, field: a.field, args: a.args});
763
- });
764
- this._updateBounds();
765
- }
766
-
767
- reCreateRelatedLegends(item) {
768
- let lgds = this.getRelatedLegends(item);
769
- lgds.forEach(a => {
770
- let args = a.toJSON().args;
771
- if (args.item)
772
- args.item = this.getItem(args.item);
773
- this.removeItem(a);
774
- this.legend(a.channel, a.field, args);
775
- });
776
- this._updateBounds();
777
- }
778
-
779
- legend(channel, field, param) {
780
- let args = param ? param : {};
781
- let enc = this.getEncodingByField(field, channel);
782
- if (!enc)
783
- throw Errors.INCORRECT_LEGEND_INFO + field;
784
-
785
- if (!("x" in args))
786
- args["x"] = 100;
787
- if (!("y" in args))
788
- args["y"] = 100;
789
- let legend = new Legend(enc, args);
790
- this.addChild(legend);
791
- this._itemMap[legend.id] = legend;
792
- this._updateBounds();
793
- return legend;
794
- }
795
-
796
- gridlines(channel, field, params) {
797
- let enc = this.getEncodingByField(field, channel), args = params ? params : {};
798
- if (!enc) return false;
799
- let gl = new Gridlines(enc, args.item ? args.item : enc.anyItem, args);
800
-
801
- if ("values" in args) {
802
- gl.values = args["values"];
803
- } else {
804
- gl.values = enc._inferTickValues();
805
- }
806
-
807
- this.addChildAt(gl, 0);
808
- this._itemMap[gl.id] = gl;
809
- this._updateBounds();
810
- return gl;
811
- }
812
-
813
- getRelatedLegends(item) {
814
- let lg = [];
815
- if (isGuide(item)) return lg;
816
- for (let c of this.children) {
817
- if (c.type !== ItemType.Legend) continue;
818
- if (c.matches(item)) {
819
- lg.push(c);
820
- continue;
821
- }
822
- }
823
- return lg;
824
- }
825
-
826
- getRelatedGridlines(item) {
827
- let gl = [];
828
- if (isGuide(item))
829
- return gl;
830
- for (let c of this.children) {
831
- if (c.type !== ItemType.Gridlines) continue;
832
- if (c.matches(item)) {
833
- gl.push(c);
834
- continue;
835
- }
836
- //handle layout axis for small multiples
837
- let p = c._item, found = false;
838
- while (p.children && p.children.length > 0) {
839
- for (let ic of p.children) {
840
- if (ic.classId === item.classId) {
841
- found = true;
842
- gl.push(c);
843
- break;
844
- }
845
- }
846
- if (found) break;
847
- else p = p.children[0];
848
- }
849
-
850
- //handle axis if the updated item is a group/collection
851
- let allChildren = getAllChildren(item);
852
- let map = {};
853
- for (let i of allChildren) {
854
- if (i.classId in map) continue;
855
- map[i.classId] = i;
856
- }
857
- let toCheck = Object.values(map);
858
- for (let i of toCheck) {
859
- if (c.matches(i)) {
860
- gl.push(c);
861
- break;
862
- }
863
- }
864
- // p = item, found = false;
865
- // while (p.children && p.children.length > 0) {
866
- // for (let ic of p.children) {
867
- // if (c.matches(ic)) {
868
- // found = true;
869
- // gl.push(c);
870
- // break;
871
- // }
872
- // }
873
- // if (found) break;
874
- // else p = p.children[0];
875
- // }
876
- }
877
- return gl;
878
- }
879
-
880
- propagate(item, method, ...args) {
881
- let peers = getPeers(item, this);
882
- for (let p of peers)
883
- p[method](...args);
884
- }
885
-
886
- getEncodingByItem(item, channel) {
887
- let enc = this._encodings[getEncodingKey(item)];
888
- if (enc && enc[channel]) {
889
- return enc[channel];
890
- } else
891
- return null;
892
- }
893
-
894
- getEncodingByField(field, channel) {
895
- for (let itmKey in this._encodings) {
896
- let enc = this._encodings[itmKey];
897
- if (enc[channel] && enc[channel].field == field)
898
- return enc[channel];
899
- }
900
- return null;
901
- }
902
-
903
- //item can be a mark, a group, a vertex or a segment
904
- positionBound(item, channel) {
905
- let enc = this.getEncodingByItem(item, channel);
906
- if (enc)
907
- return enc;
908
- else if (isPath(item)) {
909
- for (let key in this._encodings) {
910
- let classId = key.split("_")[0];
911
- if (classId === item.classId && channel in this._encodings[key])
912
- return this._encodings[key][channel];
913
- }
914
- }
915
- else
916
- return null;
917
- }
918
-
919
- sizeBound(mark, channel) {
920
- let enc = this.getEncodingByItem(mark, channel);
921
- if (enc)
922
- return enc;
923
- if (isPath(mark)) {
924
- let dep = channel === "width" ? ["area"] : channel === "height" ? ["area"] : channel === "radius" ? ["area"] : ["width", "height"],
925
- dep2 = channel === "width" ? ["x"] : channel === "height" ? ["y"] : ["x", "y"];
926
- for (let key in this._encodings) {
927
- let classId = key.split("_")[0];
928
- if (key.indexOf("_") < 0) {
929
- for (let c of dep) {
930
- if (classId === mark.classId && c in this._encodings[key])
931
- return this._encodings[key][c];
932
- }
933
- } else {
934
- for (let c of dep2) {
935
- if (classId === mark.classId && c in this._encodings[key])
936
- return this._encodings[key][c];
937
- }
938
- }
939
- }
940
- }
941
- return null;
942
- }
943
-
944
- setProperties(item, args) {
945
- let result = {}, peers;
946
- for (let p in args)
947
- result[p] = true;
948
-
949
- if (Object.values(LayoutType).indexOf(item.type) > -1 && item.group) {
950
- peers = getPeers(item.group, this);
951
- for (let coll of peers) {
952
- for (let p in args) {
953
- coll.layout[p] = args[p];
954
- }
955
- }
956
- } else {
957
- peers = getPeers(item, this);
958
- if (item.type === "vertex") {
959
- //TODO: validate the property names in args
960
- for (let vertex of peers) {
961
- for (let p in args) {
962
- vertex[p] = args[p];
963
- }
964
- }
965
- } else if (item instanceof Mark) {
966
- for (let p in args) {
967
- //TODO: validate p is a legit property, check if p is bound by data
968
- if ((p === "x" || p === "y") && this.positionBound(item, p)) {
969
- result[p] = false;
970
- continue;
971
- }
972
- if ((p === "width" || p === "height" || p === "radius") && this.sizeBound(item, p)) {
973
- //result[p] = false;
974
- let enc = this.getEncodingByItem(item, p);
975
- if (!enc && p == "radius") enc = this.getEncodingByItem(item, "area");
976
- let re = enc.scale.rangeExtent * args[p] / item[p];
977
- enc.scale.rangeExtent = re;
978
- continue;
979
- }
980
- if ((item.type === ItemType.Rect || item.type === ItemType.Line) && (p === "width" || p === "height")) {
981
- if (p === "width")
982
- peers.forEach(d => d.resize(args[p], d.bounds.height, args["xRef"]));
983
- else
984
- peers.forEach(d => d.resize(d.bounds.width, args[p], undefined, args["yRef"]));
985
- } else if (item.type == ItemType.Circle && p == "radius") {
986
- peers.forEach(d => d.resize(args[p] * 2, args[p] * 2, args["xRef"], args["yRef"]));
987
- } else {
988
- peers.forEach(d => d[p] = args[p]);
989
- }
990
- }
991
-
992
- } else if (item.type == "collection" || item.type == "group") {
993
- for (let c of peers) {
994
- for (let p in args) {
995
- c[p] = (p === "layout" && args[p] !== undefined) ? args[p].clone() : args[p];
996
- }
997
- //c._updateBounds();
998
- }
999
- }
1000
- }
1001
-
1002
- //invoke SceneValidator accordingly
1003
- let props = Object.keys(result).filter(d => result[d]);
1004
- let sizeProps = ["width", "height", "fontSize", "area", "radius"];
1005
- for (let s of sizeProps) {
1006
- if (props.indexOf(s) >= 0 && isMark(item)) {
1007
- SceneValidator.itemResized(item, peers);
1008
- break;
1009
- }
1010
- }
1011
-
1012
- if (props.indexOf("baseline") >= 0 && item.type === ItemType.Area)
1013
- SceneValidator.areaRebased(item, peers);
1014
-
1015
- let layoutProps = ["layout", "rowGap", "colGap", "numRows", "numCols", "orientation", "vertCellAlignment", "horzCellAlignment", "direction", "childrenOrder"];
1016
- let changed = props.filter(d => layoutProps.indexOf(d) >= 0);
1017
- if (changed.length > 0)
1018
- SceneValidator.layoutChanged(peers[0], peers, changed);
1019
-
1020
- return result;
1021
- //TODO: relayout if needed (typically Layout or setProperty should happen before encoding)
1022
- }
1023
-
1024
- _canTranslate(item) {
1025
- let r = { x: true, y: true };
1026
- if (item.type == ItemType.Axis) {
1027
- if (item.channel === "x" || item.channel === "width")
1028
- r.x = false;
1029
- else if (item.channel === "y" || item.channel === "height")
1030
- r.y = false;
1031
- return r;
1032
- }
1033
- if (item.parent.type === ItemType.Collection && item.parent.layout) {
1034
- r.x = false;
1035
- r.y = false;
1036
- }
1037
- if (this.positionBound(item, "x"))
1038
- r.x = false;
1039
- if (this.positionBound(item, "y"))
1040
- r.y = false;
1041
- //TODO: check constraints, handle vertices and
1042
- return r;
1043
- }
1044
-
1045
- //always check canTranslate before calling this method
1046
- translate(item, dx, dy) {
1047
- let ct = this._canTranslate(item);
1048
- if (!ct.x && !ct.y) return ct;
1049
- const adx = ct.x ? dx : 0, ady = ct.y ? dy : 0;
1050
- item._doTranslate(adx, ady);
1051
- this._updateAncestorBounds(item);
1052
- SceneValidator.itemTranslated(item, adx, ady);
1053
- return ct;
1054
- }
1055
-
1056
- _updateAncestorBounds(cpnt, cpntPeers) {
1057
- let peers = cpntPeers ? cpntPeers : getPeers(cpnt, this);
1058
- let parents = getParents(peers);
1059
-
1060
- while (parents.length > 0) {
1061
- for (let p of parents) {
1062
- if (p.children && p.children.length > 0) {
1063
- p._updateBounds();
1064
- } else if (p.vertices) {
1065
- p._updateBounds();
1066
- }
1067
- }
1068
- parents = getParents(parents);
1069
- }
1070
- }
1071
-
1072
- /**
1073
- ** should only be used in Scene methods
1074
- **/
1075
-
1076
- _reapplyConstraints(item) {
1077
- let itm = item, itms = [item];
1078
- while (itm.children) {
1079
- if (itm.type == ItemType.Collection) {
1080
- itms.push(itm.firstChild);
1081
- } else { //glyph or group
1082
- itms = itms.concat(itm.children);
1083
- }
1084
- itm = itm.firstChild;
1085
- }
1086
-
1087
- itm = item.parent;
1088
- while (itm && itm.type !== ItemType.Scene) {
1089
- itms.push(itm);
1090
- itm = itm.parent;
1091
- }
1092
-
1093
- const classIds = itms.map(d => d.classId);
1094
-
1095
- for (let c in this.constraints) {
1096
- const cstr = this.constraints[c];
1097
- switch (cstr.type) {
1098
- case ConstraintType.Affix:
1099
- if (classIds.indexOf(cstr.item.classId) >= 0 || classIds.indexOf(cstr.baseItem.classId) >= 0)
1100
- cstr.apply();
1101
- break;
1102
- case ConstraintType.Align:
1103
- for (let itm of cstr.items) {
1104
- if (classIds.indexOf(itm.classId) >= 0) {
1105
- cstr.apply();
1106
- break;
1107
- }
1108
- }
1109
- break;
1110
- default:
1111
- break;
1112
- }
1113
- }
1114
- }
1115
-
1116
- _relayoutAncestors(cpnt, cpntPeers) {
1117
- let peers = cpntPeers ? cpntPeers : getPeers(cpnt, this);
1118
- let parents = getParents(peers);
1119
- while (parents.length > 0) {
1120
- for (let p of parents) {
1121
- if (p.layout) {
1122
- p.layout.run();
1123
- }
1124
- if (p.children && p.children.length > 0) {
1125
- p._updateBounds();
1126
- }
1127
- if (p.vertices) {
1128
- p._updateBounds();
1129
- }
1130
- }
1131
- parents = getParents(parents);
1132
- }
1133
- }
1134
-
1135
- _reapplySizeBindings(compnt) {
1136
- let sizeChannels = ["width", "height"];
1137
- for (let classId in this._encodings) {
1138
- if (compnt.classId != classId) continue;
1139
- let encodings = this._encodings[classId];
1140
- //TODO: re-use bindSpec and adjust scale accordingly
1141
- let peers = findItems(this, [{ "classId": classId }]);
1142
- for (let channel of sizeChannels) {
1143
- let encoding = encodings[channel];
1144
- if (!encoding) continue;
1145
- encoding.run();
1146
- }
1147
- this._relayoutAncestors(peers[0], peers);
1148
- }
1149
- }
1150
-
1151
- _registerBinding(enc) {
1152
- let encodings = this._encodings;
1153
- let key = getEncodingKey(enc.anyItem);
1154
- if (!(key in encodings))
1155
- encodings[key] = {};
1156
- encodings[key][enc.channel] = enc;
1157
- return true;
1158
- }
1159
-
1160
- toJSON() {
1161
- let json = super.toJSON();
1162
- if (this.fillColor)
1163
- json.fillColor = this.fillColor;
1164
- let scales = {};
1165
- json.encodings = [];
1166
- json.itemCounter = ItemCounter;
1167
- for (let classId in this._encodings) {
1168
- for (let channel in this._encodings[classId]) {
1169
- let e = this._encodings[classId][channel];
1170
- json.encodings.push(e.toJSON());
1171
- if (e.scale && !(e.scale.id in scales)) {
1172
- scales[e.scale.id] = e.scale.toJSON();
1173
- }
1174
- }
1175
- }
1176
- json.scales = scales;
1177
- json.constraints = {};
1178
- for (let c in this.constraints)
1179
- json.constraints[c] = this.constraints[c].toJSON();
1180
- json.tables = {};
1181
- let tables = this.getDataTables();
1182
- for (let t in tables) {
1183
- json.tables[t] = tables[t].toJSON();
1184
- }
1185
- return json;
1186
- }
1187
-
1188
- //get data tables used in this scene's encodings
1189
- getDataTables() {
1190
- let tables = {};
1191
- for (let classId in this._encodings) {
1192
- for (let channel in this._encodings[classId]) {
1193
- let e = this._encodings[classId][channel];
1194
- if (!(e.datatable.id in tables)) {
1195
- tables[e.datatable.id] = e.datatable;
1196
- }
1197
- }
1198
- }
1199
- for (let c of this.children) {
1200
- if (isGuide(c)) continue;
1201
- if (c.dataScope) {
1202
- tables[c.dataScope.dataTable.id] = c.dataScope.dataTable;
1203
- break;
1204
- } else if (c.children && c.children.length > 0) {
1205
- let itm = c.firstChild;
1206
- while (itm) {
1207
- if (itm.dataScope) {
1208
- tables[itm.dataScope.dataTable.id] = itm.dataScope.dataTable;
1209
- break;
1210
- } else if (itm.children && itm.children.length > 0) {
1211
- itm = itm.firstChild
1212
- } else {
1213
- itm = undefined;
1214
- }
1215
- }
1216
- }
1217
- }
1218
- return tables;
1219
- }
1220
-
1221
- //handles marks, groups, vertices and segments
1222
- getItem(id) {
1223
- let markId = id.split("_")[0];
1224
- if (id.indexOf("_v_") > 0) {
1225
- let idx = parseInt(id.split("_v_")[1]);
1226
- return this._itemMap[markId].vertices.find(d => d._id === idx);
1227
- } else if (id.indexOf("_s_") > 0) {
1228
- let idx = parseInt(id.split("_s_")[1]);
1229
- return this._itemMap[markId].segments.find(d => d._id === idx);
1230
- } else {
1231
- return this._itemMap[id];
1232
- }
1233
- }
1234
-
1235
- addInteraction(obj) {
1236
- // let i = new Interaction(listener, eventType, selDef, targetDef);
1237
- this._interactions.push(obj);
1238
- this._interactionsObj[obj['event']] = obj;
1239
- }
1240
-
1241
- get encodings() {
1242
- let r = [];
1243
- for (let itmKey in this._encodings) {
1244
- let enc = this._encodings[itmKey];
1245
- for (let channel in enc) {
1246
- r.push(enc[channel]);
1247
- }
1248
- }
1249
- return r;
1250
- }
1251
- }