mascot-vis 1.10.0 → 1.11.0

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.
package/dist/mascot.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable */
2
- // version: 1.10.0
2
+ // version: 1.11.0
3
3
  (function (global, factory) {
4
4
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3'), require('pixi.js')) :
5
5
  typeof define === 'function' && define.amd ? define(['exports', 'd3', 'pixi.js'], factory) :
@@ -256,7 +256,8 @@
256
256
  INCORRECT_CONSTRAINT_INFO: "Constrain information is incorreclty passed",
257
257
  FEATURE_NOT_IMPLEMENTED: "This feature has not been implemented yet",
258
258
  LAYOUT_WITHOUT_TREE: "The layout can only be applied to a tree",
259
- UNSUPPORTED_FIELDTYPE: "Unsupported field type for encoding "
259
+ UNSUPPORTED_FIELDTYPE: "Unsupported field type for encoding ",
260
+ CANNOT_CLASSIFY: "Cannot classify items in "
260
261
  };
261
262
 
262
263
  class Layout {
@@ -284,6 +285,8 @@
284
285
  this._colGap = "colGap" in args && args["colGap"] !== undefined ? args["colGap"] : 5;
285
286
  this._cellHorzAlignment = "horzCellAlignment" in args && this._validateCellAlignment("h", args["horzCellAlignment"]) ? args["horzCellAlignment"] : Alignment.Left;
286
287
  this._cellVertAlignment = "vertCellAlignment" in args && this._validateCellAlignment("v", args["vertCellAlignment"]) ? args["vertCellAlignment"] : Alignment.Bottom;
288
+ if (!this._numCols && !this._numRows)
289
+ this._numRows = 1;
287
290
  }
288
291
 
289
292
  _validateCellAlignment(orientation, v) {
@@ -651,6 +654,20 @@
651
654
  get horzCellAlignment() {
652
655
  return this._cellHorzAlignment;
653
656
  }
657
+
658
+ //accepts two formats: a two-element array, or a string
659
+ set direction(d) {
660
+ if (Array.isArray(d) && d.length === 2) {
661
+ this._dir = d;
662
+ } else {
663
+ this._dir = d.split("_");
664
+ }
665
+ this.run();
666
+ }
667
+
668
+ get direction() {
669
+ return this._dir.join("_");
670
+ }
654
671
  }
655
672
 
656
673
  GridLayout.direction = {
@@ -3520,6 +3537,11 @@
3520
3537
  this._updateBounds();
3521
3538
  }
3522
3539
 
3540
+ set area(a) {
3541
+ this.attrs["radius"] = Math.sqrt(a);
3542
+ this._updateBounds();
3543
+ }
3544
+
3523
3545
  // set width(w) {
3524
3546
  // this.attrs["radius"] = w/2;
3525
3547
  // this._updateBounds();
@@ -3606,7 +3628,7 @@
3606
3628
 
3607
3629
  //TODO: check if item width has already been encoded with a different field
3608
3630
  //the code below assumes width hasn't been bound to data
3609
- scale._setRange([0, Math.max(...(items.map(d => d.width)))]);
3631
+ scale._setRange([0, this.rangeExtent ? this.rangeExtent : Math.max(...(items.map(d => d.width)))]);
3610
3632
  } else {
3611
3633
  // let top = Math.min(...(items.map(d => d.bounds.top))),
3612
3634
  // bottom = Math.max(...(items.map(d => d.bounds.bottom)));
@@ -3614,7 +3636,7 @@
3614
3636
 
3615
3637
  //TODO: check if item height has already been encoded with a different field
3616
3638
  //the code below assumes height hasn't been bound to data
3617
- scale._setRange([0, Math.max(...(items.map(d => d.height)))]);
3639
+ scale._setRange([0, this.rangeExtent ? this.rangeExtent : Math.max(...(items.map(d => d.height)))]);
3618
3640
  }
3619
3641
  } else {
3620
3642
  scale.domain = [0, Math.max(...data)];
@@ -4389,6 +4411,9 @@
4389
4411
  extent = Math.max(...this.areas.map(d => d.bounds.height));
4390
4412
  }
4391
4413
  }
4414
+
4415
+ if (this.rangeExtent)
4416
+ extent = this.rangeExtent;
4392
4417
 
4393
4418
  if (min < 0) {
4394
4419
  scale._scale.domain([min, max]);
@@ -4955,7 +4980,7 @@
4955
4980
  } else {
4956
4981
  let items = getPeers(item, this.scene);
4957
4982
  //TODO: handle cases where items are aligned top
4958
- let offset = Math.min(...items.map(d => d.refBounds.bottom));
4983
+ let offset = Math.max(...items.map(d => d.refBounds.bottom));
4959
4984
  return [offset, offset - this.scale.rangeExtent];
4960
4985
  }
4961
4986
  } else if (this.channel == "radialDistance") {
@@ -5303,6 +5328,7 @@
5303
5328
  r.push(f);
5304
5329
  }
5305
5330
  }
5331
+ r.sort((a,b) => this.getUniqueFieldValues(a).length - this.getUniqueFieldValues(b).length);
5306
5332
  return r;
5307
5333
  }
5308
5334
 
@@ -8183,7 +8209,7 @@
8183
8209
  gl.forEach(l => l.updateLinePositions());
8184
8210
  },
8185
8211
 
8186
- layoutChanged: function(item, peers, reGenerateAxes) {
8212
+ layoutChanged: function(item, peers, props) {
8187
8213
  let scene = item.getScene();
8188
8214
  scene._relayoutAncestors(item, peers);
8189
8215
 
@@ -8195,6 +8221,36 @@
8195
8221
  for (let i of items)
8196
8222
  i.getScene()._reapplyConstraints(i);
8197
8223
 
8224
+ let reGenerateAxes = false;
8225
+ for (let p of props) {
8226
+ if (["numRows", "numCols", "layout", "childrenOrder"].indexOf(p) >= 0) {
8227
+ reGenerateAxes = true;
8228
+ break;
8229
+ }
8230
+ }
8231
+
8232
+ //if grid layout changes to a single column or row, or stack layout's orientation changes, update axis channel
8233
+ let updateChannel = false, channel;
8234
+ if (item.layout) {
8235
+ if (item.layout.type === LayoutType.Grid && (item.layout.numRows === 1 || item.layout.numCols === 1)) {
8236
+ updateChannel = true;
8237
+ channel = item.layout.numRows === 1 ? "x" : "y";
8238
+ } else if (item.layout.type === LayoutType.Stack && props.indexOf("orientation") >= 0) {
8239
+ updateChannel = true;
8240
+ channel = item.layout.orientation === Orientation.Horizontal ? "x" : "y";
8241
+ }
8242
+ }
8243
+ if (updateChannel) {
8244
+ let axes = scene.getRelatedAxes(item).filter(d => d instanceof LayoutAxis && d._item.parent.classId === item.classId);
8245
+ for (let a of axes) {
8246
+ scene.removeItem(a);
8247
+ let args = a.toJSON().args;
8248
+ delete args["orientation"];
8249
+ args.item = item.firstChild;
8250
+ scene.axis(channel, a.field, args);
8251
+ }
8252
+ }
8253
+
8198
8254
  if (reGenerateAxes) {
8199
8255
  scene.reCreateRelatedAxes(item);
8200
8256
  } else {
@@ -8231,8 +8287,8 @@
8231
8287
  let axes = enc.scene.getRelatedAxes(item);
8232
8288
  for (let a of axes) {
8233
8289
  if (a.encoding && a.encoding.scale === scale) {
8234
- a.tickValues = enc.scene._inferTickValues(enc);
8235
- a.labelValues = enc.scene._inferTickValues(enc);
8290
+ a.tickValues = enc._inferTickValues(enc);
8291
+ a.labelValues = enc._inferTickValues(enc);
8236
8292
  a._positionPath();
8237
8293
  if (a._showTitle)
8238
8294
  a._positionTitle();
@@ -8985,6 +9041,42 @@
8985
9041
  }
8986
9042
  }
8987
9043
 
9044
+ function classifyCollectionChildren(scene, c, field, layout) {
9045
+ let peers = getPeers(c, scene);
9046
+ for (let p of peers) {
9047
+ let collections = {}, cid, items = p.children;
9048
+ for (let item of items) {
9049
+ let v = item.dataScope.getFieldValue(field);
9050
+ if (!(v in collections)) {
9051
+ collections[v] = [];
9052
+ }
9053
+ collections[v].push(item);
9054
+ }
9055
+ let tbl = items[0].dataScope._dt; //results = []; //,
9056
+ for (let v in collections) {
9057
+ let coll = scene.collection();
9058
+ p.addChild(coll);
9059
+ if (cid === undefined)
9060
+ cid = coll.id;
9061
+ coll.classId = cid;
9062
+ coll.dataScope = p.dataScope ? p.dataScope.cross(field, v) : new DataScope(tbl).cross(field, v);
9063
+ for (let c of collections[v]) {
9064
+ coll.addChild(c);
9065
+ }
9066
+ // if (layout)
9067
+ // coll.layout = layout;
9068
+ //results.push(coll);
9069
+ }
9070
+ // if (oldParent.children.length === 0) {
9071
+ // oldParent.parent.removeChild(oldParent);
9072
+ // }
9073
+ }
9074
+
9075
+ if (layout)
9076
+ scene.setProperties(c.firstChild, {layout: layout});
9077
+ //return results;
9078
+ }
9079
+
8988
9080
  class Scene extends Group{
8989
9081
 
8990
9082
  constructor(args){
@@ -9233,6 +9325,23 @@
9233
9325
  return collection;
9234
9326
  }
9235
9327
 
9328
+ classify(item, param){
9329
+ if (!canClassify(item)){
9330
+ throw Errors.CANNOT_CLASSIFY + item.type;
9331
+ }
9332
+
9333
+ let args = param ? param : {},
9334
+ field = args["field"] ? args["field"] : DataTable.RowID,
9335
+ dt = item.firstChild.dataScope.dataTable,
9336
+ layout = args.layout;
9337
+ validateField(field, dt);
9338
+
9339
+ classifyCollectionChildren(this, item, field, layout);
9340
+
9341
+ //SceneValidator.markDivided(item, collection);
9342
+ return item;
9343
+ }
9344
+
9236
9345
  _validateEncodeArgs(item, args) {
9237
9346
  if (!item || !("channel" in args) || !("field" in args)) {
9238
9347
  throw Errors.INCOMPLETE_BINDING_INFO;
@@ -9777,36 +9886,6 @@
9777
9886
  p[method](...args);
9778
9887
  }
9779
9888
 
9780
- classify(items, field, parent){
9781
- let collections = {}, cid, oldParent = items[0].parent;
9782
- for (let item of items) {
9783
- let v = item.dataScope.getFieldValue(field);
9784
- if (!(v in collections)) {
9785
- collections[v] = [];
9786
- }
9787
- collections[v].push(item);
9788
- }
9789
- let results = [], tbl = items[0].dataScope._dt;
9790
- for (let v in collections) {
9791
- let coll = this.collection();
9792
- parent.addChild(coll);
9793
- if (cid === undefined)
9794
- cid = coll.id;
9795
- coll.classId = cid;
9796
- coll.dataScope = new DataScope(tbl).cross(field, v);
9797
- for (let c of collections[v]) {
9798
- coll.addChild(c);
9799
- }
9800
- results.push(coll);
9801
- }
9802
-
9803
- if (oldParent.children.length === 0) {
9804
- oldParent.parent.removeChild(oldParent);
9805
- }
9806
-
9807
- return results;
9808
- }
9809
-
9810
9889
  getEncodingByItem(item, channel) {
9811
9890
  let enc = this.encodings[getEncodingKey(item)];
9812
9891
  if (enc && enc[channel]) {
@@ -9923,6 +10002,7 @@
9923
10002
  }
9924
10003
  }
9925
10004
 
10005
+ //invoke SceneValidator accordingly
9926
10006
  let props = Object.keys(result).filter(d => result[d]);
9927
10007
  let sizeProps = ["width", "height", "fontSize", "area", "radius"];
9928
10008
  for (let s of sizeProps) {
@@ -9931,17 +10011,15 @@
9931
10011
  break;
9932
10012
  }
9933
10013
  }
10014
+
9934
10015
  if (props.indexOf("baseline") >=0 && item.type === ItemType.Area)
9935
10016
  SceneValidator.areaRebased(item, peers);
9936
10017
 
9937
- let layoutProps = ["layout", "rowGap", "colGap", "numRows", "numCols", "vertCellAlignment", "horzCellAlignment"];
9938
- for (let l of layoutProps) {
9939
- if (props.indexOf(l) >= 0) {
9940
- let reGenerateAxes = (props.indexOf("numRows") >= 0 || props.indexOf("numCols") >= 0 || props.indexOf("layout") >= 0);
9941
- SceneValidator.layoutChanged(peers[0], peers, reGenerateAxes);
9942
- break;
9943
- }
9944
- }
10018
+ let layoutProps = ["layout", "rowGap", "colGap", "numRows", "numCols", "orientation", "vertCellAlignment", "horzCellAlignment", "direction", "childrenOrder"];
10019
+ let changed = props.filter(d => layoutProps.indexOf(d) >= 0);
10020
+ if (changed.length > 0)
10021
+ SceneValidator.layoutChanged(peers[0], peers, changed);
10022
+
9945
10023
  return result;
9946
10024
  //TODO: relayout if needed (typically Layout or setProperty should happen before encoding)
9947
10025
  }
@@ -24023,6 +24101,20 @@
24023
24101
  }
24024
24102
  }
24025
24103
 
24104
+ function canClassify(item) {
24105
+ if (item.type !== ItemType.Collection) return false;
24106
+ if (item.children.length < 2) return false;
24107
+ // if (!Array.isArray(items)) return false;
24108
+ // if (items.length < 1) return false;
24109
+ // for (let i of items) {
24110
+ // if (!i.dataScope)
24111
+ // return false;
24112
+ // }
24113
+ // let tbls = uniqueStrings(items.map(d => d.dataScope.dataTable.name));
24114
+ // if (tbls.length > 1) return false;
24115
+ return true;
24116
+ }
24117
+
24026
24118
  function getPeersInScene(item) {
24027
24119
  if (item.type == "vertex" || item.type == "segment") {
24028
24120
  return getPeers(item, item.parent.getScene());
@@ -24031,6 +24123,7 @@
24031
24123
  }
24032
24124
  }
24033
24125
 
24126
+ exports.canClassify = canClassify;
24034
24127
  exports.canDensify = canDensify;
24035
24128
  exports.canDivide = canDivide;
24036
24129
  exports.canRepeat = canRepeat;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mascot-vis",
3
- "version": "1.10.0",
3
+ "version": "1.11.0",
4
4
  "description": "Manipulable Semantic Components in Data Visualization",
5
5
  "scripts": {
6
6
  "build": "rollup --config",