@vizabi/bubblechart 3.17.0 → 3.17.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.
@@ -1,4 +1,4 @@
1
- // https://github.com/vizabi/bubblechart#readme v3.17.0 build 1684329878518 Copyright 2023 Gapminder Foundation and contributors
1
+ // https://github.com/vizabi/bubblechart#readme v3.17.2 build 1685443324638 Copyright 2023 Gapminder Foundation and contributors
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@vizabi/shared-components'), require('d3'), require('mobx')) :
4
4
  typeof define === 'function' && define.amd ? define(['@vizabi/shared-components', 'd3', 'mobx'], factory) :
@@ -700,6 +700,381 @@
700
700
 
701
701
  }
702
702
 
703
+ const {ICON_QUESTION} = sharedComponents.Icons;
704
+
705
+ class BCAxisTitles extends sharedComponents.BaseComponent {
706
+
707
+ constructor(config) {
708
+ config.template = `
709
+ <g class="vzb-bc-axis-x-title"><text></text></g>
710
+ <g class="vzb-bc-axis-y-title"><text></text></g>
711
+ <g class="vzb-bc-axis-s-title"><text></text></g>
712
+ <g class="vzb-bc-axis-x-subtitle"><text></text></g>
713
+ <g class="vzb-bc-axis-y-subtitle"><text></text></g>
714
+ <g class="vzb-bc-axis-x-info vzb-noexport"></g>
715
+ <g class="vzb-bc-axis-y-info vzb-noexport"></g>
716
+ `;
717
+ super(config);
718
+ }
719
+
720
+ setup(){
721
+ this.DOM = {
722
+ xTitle: this.element.select(".vzb-bc-axis-x-title"),
723
+ yTitle: this.element.select(".vzb-bc-axis-y-title"),
724
+ sTitle: this.element.select(".vzb-bc-axis-s-title"),
725
+ xSubTitle: this.element.select(".vzb-bc-axis-x-subtitle"),
726
+ ySubTitle: this.element.select(".vzb-bc-axis-y-subtitle"),
727
+ xInfo: this.element.select(".vzb-bc-axis-x-info"),
728
+ yInfo: this.element.select(".vzb-bc-axis-y-info")
729
+ };
730
+
731
+ this.axisTitleComplimentStrings = {Y: "", X: "", S: "", C: ""};
732
+
733
+ this._initInfoElements();
734
+ }
735
+
736
+ draw(){
737
+ this.localise = this.services.locale.auto();
738
+
739
+ this.addReaction(this.updateUIStrings);
740
+ this.addReaction(this.updateTreemenu);
741
+ this.addReaction(this.updateSize);
742
+ this.addReaction(this.updateInfoElements);
743
+ }
744
+
745
+ get MDL(){
746
+ return {
747
+ y: this.model.encoding[this.state.alias?.y || "y"],
748
+ x: this.model.encoding[this.state.alias?.x || "x"],
749
+ size: this.model.encoding.size,
750
+ color: this.model.encoding.color
751
+ };
752
+ }
753
+
754
+ updateTreemenu(){
755
+ const treemenu = this.root.findChild({type: "TreeMenu"});
756
+
757
+ this.DOM.yTitle
758
+ .classed("vzb-disabled", treemenu.state.ownReadiness !== sharedComponents.Utils.STATUS.READY)
759
+ .on("click", () => {
760
+ treemenu
761
+ .encoding(this.parent._alias("y"))
762
+ .alignX(this.services.locale.isRTL() ? "right" : "left")
763
+ .alignY("top")
764
+ .updateView()
765
+ .toggle();
766
+ });
767
+
768
+ this.DOM.xTitle
769
+ .classed("vzb-disabled", treemenu.state.ownReadiness !== sharedComponents.Utils.STATUS.READY)
770
+ .on("click", () => {
771
+ treemenu
772
+ .encoding(this.parent._alias("x"))
773
+ .alignX(this.services.locale.isRTL() ? "right" : "left")
774
+ .alignY("bottom")
775
+ .updateView()
776
+ .toggle();
777
+ });
778
+ }
779
+
780
+ updateUIStrings() {
781
+ const {
782
+ y, x, size, color
783
+ } = this.MDL;
784
+
785
+ this.strings = {
786
+ title: {
787
+ Y: sharedComponents.Utils.getConceptName(y, this.localise),
788
+ X: sharedComponents.Utils.getConceptName(x, this.localise),
789
+ S: sharedComponents.Utils.getConceptName(size, this.localise),
790
+ C: sharedComponents.Utils.getConceptName(color, this.localise)
791
+ },
792
+ title_short: {
793
+ Y: sharedComponents.Utils.getConceptShortName(y, this.localise),
794
+ X: sharedComponents.Utils.getConceptShortName(x, this.localise),
795
+ S: sharedComponents.Utils.getConceptShortName(size, this.localise),
796
+ C: sharedComponents.Utils.getConceptShortName(color, this.localise)
797
+ },
798
+ subtitle: {
799
+ Y: sharedComponents.Utils.getConceptNameMinusShortName(y, this.localise),
800
+ X: sharedComponents.Utils.getConceptNameMinusShortName(x, this.localise)
801
+ },
802
+ unit: {
803
+ Y: sharedComponents.Utils.getConceptUnit(y),
804
+ X: sharedComponents.Utils.getConceptUnit(x),
805
+ S: sharedComponents.Utils.getConceptUnit(size),
806
+ C: sharedComponents.Utils.getConceptUnit(color)
807
+ }
808
+ };
809
+
810
+ Promise.all([
811
+ sharedComponents.Utils.getConceptNameCompliment(y),
812
+ sharedComponents.Utils.getConceptNameCompliment(x),
813
+ sharedComponents.Utils.getConceptNameCompliment(size),
814
+ sharedComponents.Utils.getConceptNameCompliment(color)
815
+ ]).then(mobx.action(response => {
816
+ [
817
+ this.axisTitleComplimentStrings.Y,
818
+ this.axisTitleComplimentStrings.X,
819
+ this.axisTitleComplimentStrings.S,
820
+ this.axisTitleComplimentStrings.C
821
+ ] = response;
822
+ }));
823
+ }
824
+
825
+
826
+ _initInfoElements() {
827
+ const _this = this;
828
+ const dataNotesDialog = () => this.root.findChild({type: "DataNotes"});
829
+ const timeSlider = () => this.root.findChild({type: "TimeSlider"});
830
+
831
+ sharedComponents.LegacyUtils.setIcon(this.DOM.yInfo, ICON_QUESTION)
832
+ .on("click", () => {
833
+ dataNotesDialog().pin();
834
+ })
835
+ .on("mouseover", function() {
836
+ if (timeSlider().ui.dragging) return;
837
+ const rect = this.getBBox();
838
+ const coord = sharedComponents.LegacyUtils.makeAbsoluteContext(this, this.farthestViewportElement)(rect.x - 10, rect.y + rect.height + 10);
839
+ const toolRect = _this.root.element.node().getBoundingClientRect();
840
+ const chartRect = _this.element.node().getBoundingClientRect();
841
+ dataNotesDialog()
842
+ .setEncoding(_this.MDL.y)
843
+ .show()
844
+ .setPos(coord.x + chartRect.left - toolRect.left, coord.y);
845
+ })
846
+ .on("mouseout", () => {
847
+ if (timeSlider().ui.dragging) return;
848
+ dataNotesDialog().hide();
849
+ });
850
+
851
+ sharedComponents.LegacyUtils.setIcon(this.DOM.xInfo, ICON_QUESTION)
852
+ .on("click", () => {
853
+ dataNotesDialog().pin();
854
+ })
855
+ .on("mouseover", function() {
856
+ if (timeSlider().ui.dragging) return;
857
+ const rect = this.getBBox();
858
+ const coord = sharedComponents.LegacyUtils.makeAbsoluteContext(this, this.farthestViewportElement)(rect.x - 10, rect.y + rect.height + 10);
859
+ const toolRect = _this.root.element.node().getBoundingClientRect();
860
+ const chartRect = _this.element.node().getBoundingClientRect();
861
+ dataNotesDialog()
862
+ .setEncoding(_this.MDL.x)
863
+ .show()
864
+ .setPos(coord.x + chartRect.left - toolRect.left, coord.y);
865
+ })
866
+ .on("mouseout", () => {
867
+ if (timeSlider().ui.dragging) return;
868
+ dataNotesDialog().hide();
869
+ });
870
+ }
871
+
872
+ updateInfoElements() {
873
+ this.services.layout.size;
874
+ this.axisTitleComplimentStrings.X;
875
+ this.axisTitleComplimentStrings.Y;
876
+
877
+ const {xInfo, yInfo, xTitle, yTitle} = this.DOM;
878
+ const {x, y} = this.MDL;
879
+ const isRTL = this.services.locale.isRTL();
880
+ const infoElHeight = this.parent.profileConstants.infoElHeight;
881
+ const layoutProfile = this.services.layout.profile;
882
+
883
+ if (yInfo.select("svg").node()) {
884
+ const titleBBox = yTitle.node().getBBox();
885
+ const t = sharedComponents.LegacyUtils.transform(yTitle.node());
886
+ const hTranslate = isRTL ? (titleBBox.x + t.translateX - infoElHeight * 1.4) : (titleBBox.x + t.translateX + titleBBox.width + infoElHeight * 0.4);
887
+ const vTranslate = isRTL ? (t.translateY + infoElHeight * 1.4 + titleBBox.width * 0.5) : (t.translateY - infoElHeight * 0.4 - titleBBox.width * 0.5);
888
+ const conceptPropsY = y.data.conceptProps;
889
+
890
+ yInfo
891
+ .classed("vzb-hidden", !conceptPropsY.description && !conceptPropsY.sourceLink || this.services.layout.projector)
892
+ .attr("transform", layoutProfile !== "SMALL" ?
893
+ `translate(${ t.translateX - infoElHeight * 0.8 }, ${ vTranslate }) rotate(-90)` :
894
+ `translate(${ hTranslate },${ t.translateY - infoElHeight * 0.8 })`)
895
+ .select("svg")
896
+ .attr("width", infoElHeight + "px")
897
+ .attr("height", infoElHeight + "px");
898
+ }
899
+
900
+ if (xInfo.select("svg").node()) {
901
+ const titleBBox = xTitle.node().getBBox();
902
+ const t = sharedComponents.LegacyUtils.transform(xTitle.node());
903
+ const hTranslate = isRTL ? (titleBBox.x + t.translateX - infoElHeight * 1.4) : (titleBBox.x + t.translateX + titleBBox.width + infoElHeight * 0.4);
904
+ const conceptPropsX = x.data.conceptProps;
905
+
906
+ xInfo
907
+ .classed("vzb-hidden", !conceptPropsX.description && !conceptPropsX.sourceLink || this.services.layout.projector)
908
+ .attr("transform", `translate(${ hTranslate }, ${ t.translateY - infoElHeight * 0.8 })`)
909
+ .select("svg")
910
+ .attr("width", infoElHeight + "px")
911
+ .attr("height", infoElHeight + "px");
912
+ }
913
+ }
914
+
915
+
916
+ _updateSTitle(width = this.parent.width, height = this.parent.height) {
917
+ const { sTitle } = this.DOM;
918
+ const { size, color } = this.MDL;
919
+ const compl = this.axisTitleComplimentStrings;
920
+
921
+ // vertical text about size and color
922
+ const invisible = this.parent.profileConstants.hideSTitle
923
+ && this.root.ui.dialogs.dialogs.sidebar.includes("colors")
924
+ && this.root.ui.dialogs.dialogs.sidebar.includes("size");
925
+
926
+ sTitle.classed("vzb-invisible", invisible);
927
+ if (invisible) return;
928
+
929
+ const sTitleContent = !size.data.constant
930
+ ? this.localise("buttons/size") + ": " + this.strings.title.S + (compl.S ? " · " + compl.S : "")
931
+ : "";
932
+ const cTitleContent = !color.data.constant
933
+ ? this.localise("buttons/colors") + ": " + this.strings.title.C + (compl.C ? " · " + compl.C : "")
934
+ : "";
935
+
936
+ const sTitleText = sTitle
937
+ .attr("text-anchor", "end")
938
+ .attr("transform", "translate(" + width + "," + 20 + ") rotate(-90)")
939
+ .select("text")
940
+ .style("font-size", null) // reset font size to remove jumpy measurement
941
+ .text(sTitleContent + (sTitleContent && cTitleContent ? ", " : "") + cTitleContent);
942
+
943
+ // reduce font size if the caption doesn't fit
944
+ const sTitleWidth = sTitleText.node().getBBox().width;
945
+ const padding = 30;
946
+ const font = parseInt(sTitleText.style("font-size")) * (height - padding) / sTitleWidth;
947
+ sTitleText.style("font-size", sTitleWidth > (height - padding) ? font + "px" : null);
948
+ }
949
+
950
+
951
+ _updateYTitle(width = this.parent.width, height = this.parent.height) {
952
+ const { yTitle, ySubTitle } = this.DOM;
953
+
954
+ const {
955
+ margin,
956
+ infoElHeight,
957
+ yAxisTitleBottomMargin,
958
+ } = this.parent.profileConstants;
959
+
960
+ const layoutProfile = this.services.layout.profile;
961
+
962
+ const compl = this.axisTitleComplimentStrings;
963
+ const isRTL = this.services.locale.isRTL();
964
+
965
+ if (layoutProfile !== "SMALL") {
966
+ ySubTitle
967
+ .attr("transform", "translate(" + 0 + "," + 0 + ") rotate(-90)")
968
+ .select("text")
969
+ .attr("dy", infoElHeight * 0.6)
970
+ .style("font-size", (infoElHeight * 0.8) + "px")
971
+ .text(this.strings.subtitle.Y);
972
+
973
+ const yTitleText = yTitle.select("text")
974
+ .style("font-size", infoElHeight + "px")
975
+ .text(this.strings.title_short.Y + (compl.Y ? " · " + compl.Y : ""));
976
+
977
+ yTitleText.append("tspan")
978
+ .classed("vzb-noexport", true)
979
+ .style("font-size", (infoElHeight * 0.7) + "px")
980
+ .attr("dx", ( (isRTL ? -1 : 1) * infoElHeight * 0.25) + "px")
981
+ .text("▼");
982
+
983
+ const doesntFit = yTitle.node().getBBox().width > height;
984
+
985
+ yTitle
986
+ .attr("text-anchor", doesntFit ? "start" : "middle")
987
+ .attr("transform", "translate(" + (-margin.left - yAxisTitleBottomMargin) + "," + (doesntFit ? (isRTL ? 0 : height) : height / 2 ) + ") rotate(-90)");
988
+
989
+ } else {
990
+ ySubTitle.select("text").text("");
991
+
992
+ const yTitleText = yTitle
993
+ .select("text")
994
+ .text(this.strings.title.Y + (compl.Y ? " · " + compl.Y : ""));
995
+
996
+ const doesntFit = yTitleText.node().getBBox().width > width;
997
+ if (doesntFit) yTitleText.text(this.strings.title_short.Y + (compl.Y ? " · " + compl.Y : ""));
998
+
999
+ yTitle
1000
+ .attr("text-anchor", "start")
1001
+ .attr("transform", "translate(" + (isRTL ? width : 10 - margin.left) + ", -" + yAxisTitleBottomMargin + ")");
1002
+ }
1003
+ }
1004
+
1005
+
1006
+ _updateXTitle(width = this.parent.width, height = this.parent.height) {
1007
+ const { xTitle, xSubTitle } = this.DOM;
1008
+
1009
+ const {
1010
+ margin,
1011
+ infoElHeight,
1012
+ xAxisTitleBottomMargin,
1013
+ } = this.parent.profileConstants;
1014
+
1015
+ const layoutProfile = this.services.layout.profile;
1016
+
1017
+ const compl = this.axisTitleComplimentStrings;
1018
+ const isRTL = this.services.locale.isRTL();
1019
+
1020
+ if (layoutProfile !== "SMALL") {
1021
+ xSubTitle
1022
+ .attr("transform", "translate(" + width + "," + height + ")")
1023
+ .select("text")
1024
+ .attr("dy", -infoElHeight * 0.3)
1025
+ .style("font-size", (infoElHeight * 0.8) + "px")
1026
+ .text(this.strings.subtitle.X);
1027
+
1028
+ const xTitleText = xTitle.select("text")
1029
+ .style("font-size", infoElHeight + "px")
1030
+ .text(this.strings.title_short.X + (compl.X ? " · " + compl.X : ""));
1031
+
1032
+ xTitleText
1033
+ .append("tspan")
1034
+ .classed("vzb-noexport", true)
1035
+ .style("font-size", (infoElHeight * 0.7) + "px")
1036
+ .attr("dx", ( (isRTL ? -1 : 1) * infoElHeight * 0.25) + "px")
1037
+ .text("▼");
1038
+
1039
+ } else {
1040
+ xSubTitle.select("text").text("");
1041
+
1042
+ xTitle.select("text")
1043
+ .text(this.strings.title.X + (compl.X ? " · " + compl.X : ""));
1044
+ }
1045
+
1046
+ const doesntFit = xTitle.node().getBBox().width > width - 100;
1047
+ xTitle
1048
+ .attr("text-anchor", doesntFit ? "start" : "middle")
1049
+ .attr("transform", "translate(" + (doesntFit ? (isRTL ? width : 0) : width / 2) + "," + (height + margin.bottom - xAxisTitleBottomMargin) + ")");
1050
+
1051
+ if (doesntFit && layoutProfile === "SMALL") xTitle.select("text").text(this.strings.title_short.X) + (compl.X ? " · " + compl.X : "");
1052
+ }
1053
+
1054
+
1055
+ updateSize() {
1056
+ this.services.layout.size;
1057
+
1058
+ const {
1059
+ margin,
1060
+ leftMarginRatio
1061
+ } = this.parent.profileConstants;
1062
+
1063
+ const height = (this.parent.elementHeight - margin.top - margin.bottom) || 0;
1064
+ const width = (this.parent.elementWidth - margin.left * leftMarginRatio - margin.right) || 0;
1065
+
1066
+ this._updateSTitle(width, height);
1067
+ this._updateYTitle(width, height);
1068
+ this._updateXTitle(width, height);
1069
+
1070
+ }
1071
+ }
1072
+
1073
+ const decorated = mobx.decorate(BCAxisTitles, {
1074
+ "MDL": mobx.computed,
1075
+ "axisTitleComplimentStrings": mobx.observable
1076
+ });
1077
+
703
1078
  class BCDecorations{
704
1079
  constructor(){
705
1080
  }
@@ -843,22 +1218,31 @@
843
1218
  && layoutProfile !== "SMALL";
844
1219
 
845
1220
  this.DOM.lineEqualXY.classed("vzb-invisible", !showLineEqualXY);
1221
+
846
1222
  if (showLineEqualXY) {
847
- const min = d3.min(this.yScale.domain().concat(this.xScale.domain()));
848
- const max = d3.max(this.yScale.domain().concat(this.xScale.domain()));
1223
+ this.MDL.x.scale.type; //watch
1224
+ this.MDL.y.scale.type; //watch
1225
+
1226
+ const domains = this.yScale.domain().concat(this.xScale.domain()),
1227
+ min = d3.min(domains),
1228
+ max = d3.max(domains),
1229
+ step = (max-min)/100;
1230
+
1231
+ const sequence = d3.range(min, max, step).concat(max);
1232
+
1233
+ const line = d3.line()
1234
+ .curve(d3.curveBasis)
1235
+ .x(d => this.xScale(d))
1236
+ .y(d => this.yScale(d));
849
1237
 
850
1238
  this.DOM.lineEqualXY
851
1239
  .transition()
852
1240
  .duration(duration || 0)
853
- .attr("y1", this.yScale(min) || 0)
854
- .attr("y2", this.yScale(max) || 0)
855
- .attr("x1", this.xScale(min) || 0)
856
- .attr("x2", this.xScale(max) || 0);
1241
+ .attr("d", line(sequence));
857
1242
  }
858
1243
  }
859
1244
  }
860
1245
 
861
- const {ICON_QUESTION} = sharedComponents.Icons;
862
1246
  const COLOR_WHITEISH = "rgb(253, 253, 253)";
863
1247
  const COLOR_BLACKISH = "rgb(51, 51, 51)";
864
1248
  const THICK_LINE_THRESHOLD_FOR_DARKER_COLOR = 3;
@@ -945,6 +1329,9 @@
945
1329
  },{
946
1330
  type: sharedComponents.DateTimeBackground,
947
1331
  placeholder: ".vzb-bc-date"
1332
+ },{
1333
+ type: decorated,
1334
+ placeholder: ".vzb-bc-axis-titles"
948
1335
  }];
949
1336
 
950
1337
  config.template = `
@@ -960,11 +1347,8 @@
960
1347
  </svg>
961
1348
  <svg class="vzb-bubblechart-svg-main">
962
1349
  <g class="vzb-bc-graph">
963
- <g class="vzb-bc-axis-x-title"><text></text></g>
964
- <g class="vzb-bc-axis-x-info vzb-noexport"></g>
1350
+ <g class="vzb-bc-axis-titles"></g>
965
1351
 
966
- <g class="vzb-bc-axis-y-title"><text></text></g>
967
- <g class="vzb-bc-axis-y-info vzb-noexport"></g>
968
1352
  <svg class="vzb-bc-bubbles-crop">
969
1353
  <g class="vzb-zoom-selection"></g>
970
1354
  <rect class="vzb-bc-eventarea"></rect>
@@ -973,11 +1357,6 @@
973
1357
  <rect class="vzb-bc-forecastoverlay vzb-hidden" x="0" y="0" width="100%" height="100%" fill="url(#vzb-bc-pattern-lines-${config.id})" pointer-events='none'></rect>
974
1358
  </svg>
975
1359
 
976
- <g class="vzb-bc-axis-y-subtitle"><text></text></g>
977
- <g class="vzb-bc-axis-x-subtitle"><text></text></g>
978
- <g class="vzb-bc-axis-s-title"><text></text></g>
979
- <g class="vzb-bc-axis-c-title"><text></text></g>
980
-
981
1360
  <rect class="vzb-bc-zoom-rect"></rect>
982
1361
  </g>
983
1362
  <g class="vzb-datawarning-button vzb-noexport"></g>
@@ -986,7 +1365,7 @@
986
1365
  <g class="vzb-bc-graph">
987
1366
  <svg class="vzb-bc-bubbles-crop">
988
1367
  <g class="vzb-bc-decorations">
989
- <line class="vzb-bc-line-equal-xy vzb-invisible"></line>
1368
+ <path class="vzb-bc-line-equal-xy vzb-invisible"></path>
990
1369
  <g class="vzb-bc-x-axis-groups"></g>
991
1370
  </g>
992
1371
  <g class="vzb-bc-lines"></g>
@@ -1036,14 +1415,6 @@
1036
1415
  this.DOM.chartSvg.select(".vzb-bc-graph").call(graph =>
1037
1416
  Object.assign(this.DOM, {
1038
1417
  graph: graph,
1039
- ySubTitleEl: graph.select(".vzb-bc-axis-y-subtitle"),
1040
- xSubTitleEl: graph.select(".vzb-bc-axis-x-subtitle"),
1041
- yTitleEl: graph.select(".vzb-bc-axis-y-title"),
1042
- xTitleEl: graph.select(".vzb-bc-axis-x-title"),
1043
- sTitleEl: graph.select(".vzb-bc-axis-s-title"),
1044
- cTitleEl: graph.select(".vzb-bc-axis-c-title"),
1045
- yInfoEl: graph.select(".vzb-bc-axis-y-info"),
1046
- xInfoEl: graph.select(".vzb-bc-axis-x-info"),
1047
1418
  trailsContainer: graph.select(".vzb-bc-trails"),
1048
1419
  bubbleContainer: graph.select(".vzb-bc-bubbles"),
1049
1420
  bubbleContainerCrop: graph.select(".vzb-bc-bubbles-crop"),
@@ -1082,12 +1453,10 @@
1082
1453
  this._labels = this.findChild({type: "Labels"});
1083
1454
  this._panZoom = new PanZoom(this);
1084
1455
  this.decorations = new BCDecorations(this);
1085
- this._initInfoElements();
1086
1456
 
1087
1457
  this.xAxis = sharedComponents.axisSmart("bottom");
1088
1458
  this.yAxis = sharedComponents.axisSmart("left");
1089
1459
 
1090
- this.axisTitleComplimentStrings = {Y: "", X: "", S: "", C: ""};
1091
1460
 
1092
1461
  this.isCanvasPreviouslyExpanded = false;
1093
1462
  this.draggingNow = null;
@@ -1134,51 +1503,6 @@
1134
1503
 
1135
1504
  }
1136
1505
 
1137
- _initInfoElements() {
1138
- const _this = this;
1139
- const dataNotesDialog = () => this.root.findChild({type: "DataNotes"});
1140
- const timeSlider = () => this.root.findChild({type: "TimeSlider"});
1141
-
1142
- sharedComponents.LegacyUtils.setIcon(this.DOM.yInfoEl, ICON_QUESTION)
1143
- .on("click", () => {
1144
- dataNotesDialog().pin();
1145
- })
1146
- .on("mouseover", function() {
1147
- if (timeSlider().ui.dragging) return;
1148
- const rect = this.getBBox();
1149
- const coord = sharedComponents.LegacyUtils.makeAbsoluteContext(this, this.farthestViewportElement)(rect.x - 10, rect.y + rect.height + 10);
1150
- const toolRect = _this.root.element.node().getBoundingClientRect();
1151
- const chartRect = _this.element.node().getBoundingClientRect();
1152
- dataNotesDialog()
1153
- .setEncoding(_this.MDL.y)
1154
- .show()
1155
- .setPos(coord.x + chartRect.left - toolRect.left, coord.y);
1156
- })
1157
- .on("mouseout", () => {
1158
- if (timeSlider().ui.dragging) return;
1159
- dataNotesDialog().hide();
1160
- });
1161
-
1162
- sharedComponents.LegacyUtils.setIcon(this.DOM.xInfoEl, ICON_QUESTION)
1163
- .on("click", () => {
1164
- dataNotesDialog().pin();
1165
- })
1166
- .on("mouseover", function() {
1167
- if (timeSlider().ui.dragging) return;
1168
- const rect = this.getBBox();
1169
- const coord = sharedComponents.LegacyUtils.makeAbsoluteContext(this, this.farthestViewportElement)(rect.x - 10, rect.y + rect.height + 10);
1170
- const toolRect = _this.root.element.node().getBoundingClientRect();
1171
- const chartRect = _this.element.node().getBoundingClientRect();
1172
- dataNotesDialog()
1173
- .setEncoding(_this.MDL.x)
1174
- .show()
1175
- .setPos(coord.x + chartRect.left - toolRect.left, coord.y);
1176
- })
1177
- .on("mouseout", () => {
1178
- if (timeSlider().ui.dragging) return;
1179
- dataNotesDialog().hide();
1180
- });
1181
- }
1182
1506
 
1183
1507
  get MDL(){
1184
1508
  return {
@@ -1208,10 +1532,7 @@
1208
1532
 
1209
1533
  if (this._updateLayoutProfile()) return; //return if exists with error
1210
1534
  this.addReaction(this._updateScales);
1211
- this.addReaction(this.updateUIStrings);
1212
- this.addReaction(this.updateTreemenu);
1213
1535
  this.addReaction(this._updateSize);
1214
- this.addReaction(this.updateInfoElements);
1215
1536
  // this.addReaction(this._resetZoomMinMaxXReaction, this._resetZoomMinMaxX);
1216
1537
  // this.addReaction(this._resetZoomMinMaxYReaction, this._resetZoomMinMaxY);
1217
1538
  this.addReaction(this._updateOpacity);
@@ -1745,76 +2066,7 @@
1745
2066
  return this.MDL.color.scale.d3Scale;
1746
2067
  }
1747
2068
 
1748
- updateUIStrings() {
1749
- const {
1750
- y, x, size, color
1751
- } = this.MDL;
1752
-
1753
- this.strings = {
1754
- title: {
1755
- Y: sharedComponents.Utils.getConceptName(y, this.localise),
1756
- X: sharedComponents.Utils.getConceptName(x, this.localise),
1757
- S: sharedComponents.Utils.getConceptName(size, this.localise),
1758
- C: sharedComponents.Utils.getConceptName(color, this.localise)
1759
- },
1760
- title_short: {
1761
- Y: sharedComponents.Utils.getConceptShortName(y, this.localise),
1762
- X: sharedComponents.Utils.getConceptShortName(x, this.localise),
1763
- S: sharedComponents.Utils.getConceptShortName(size, this.localise),
1764
- C: sharedComponents.Utils.getConceptShortName(color, this.localise)
1765
- },
1766
- subtitle: {
1767
- Y: sharedComponents.Utils.getConceptNameMinusShortName(y, this.localise),
1768
- X: sharedComponents.Utils.getConceptNameMinusShortName(x, this.localise)
1769
- },
1770
- unit: {
1771
- Y: sharedComponents.Utils.getConceptUnit(y),
1772
- X: sharedComponents.Utils.getConceptUnit(x),
1773
- S: sharedComponents.Utils.getConceptUnit(size),
1774
- C: sharedComponents.Utils.getConceptUnit(color)
1775
- }
1776
- };
1777
-
1778
- Promise.all([
1779
- sharedComponents.Utils.getConceptNameCompliment(y),
1780
- sharedComponents.Utils.getConceptNameCompliment(x),
1781
- sharedComponents.Utils.getConceptNameCompliment(size),
1782
- sharedComponents.Utils.getConceptNameCompliment(color)
1783
- ]).then(mobx.action(response => {
1784
- [
1785
- this.axisTitleComplimentStrings.Y,
1786
- this.axisTitleComplimentStrings.X,
1787
- this.axisTitleComplimentStrings.S,
1788
- this.axisTitleComplimentStrings.C
1789
- ] = response;
1790
- }));
1791
- }
1792
-
1793
- updateTreemenu(){
1794
- const treemenu = this.root.findChild({type: "TreeMenu"});
1795
-
1796
- this.DOM.yTitleEl
1797
- .classed("vzb-disabled", treemenu.state.ownReadiness !== sharedComponents.Utils.STATUS.READY)
1798
- .on("click", () => {
1799
- treemenu
1800
- .encoding(this._alias("y"))
1801
- .alignX(this.services.locale.isRTL() ? "right" : "left")
1802
- .alignY("top")
1803
- .updateView()
1804
- .toggle();
1805
- });
1806
2069
 
1807
- this.DOM.xTitleEl
1808
- .classed("vzb-disabled", treemenu.state.ownReadiness !== sharedComponents.Utils.STATUS.READY)
1809
- .on("click", () => {
1810
- treemenu
1811
- .encoding(this._alias("x"))
1812
- .alignX(this.services.locale.isRTL() ? "right" : "left")
1813
- .alignY("bottom")
1814
- .updateView()
1815
- .toggle();
1816
- });
1817
- }
1818
2070
 
1819
2071
  _updateSize() {
1820
2072
  this.services.layout.size;
@@ -1835,11 +2087,6 @@
1835
2087
  yAxisEl,
1836
2088
  projectionX,
1837
2089
  projectionY,
1838
- sTitleEl,
1839
- xTitleEl,
1840
- yTitleEl,
1841
- xSubTitleEl,
1842
- ySubTitleEl,
1843
2090
  xAxisGroupsEl,
1844
2091
  } = this.DOM;
1845
2092
 
@@ -1871,17 +2118,6 @@
1871
2118
  .attr("width", width)
1872
2119
  .attr("height", Math.max(0, height));
1873
2120
 
1874
- //update scales to the new range
1875
- // // if (this.model.marker.y.scaleType !== "ordinal") {
1876
- // // this.yScale.range(this._rangeBump([height, 0]));
1877
- // // } else {
1878
- // // this.yScale.rangePoints([height, 0], _this.profileConstants.padding).range();
1879
- // // }
1880
- // // if (this.model.marker.x.scaleType !== "ordinal") {
1881
- // // this.xScale.range(this._rangeBump([0, width]));
1882
- // // } else {
1883
- // // this.xScale.rangePoints([0, width], _this.profileConstants.padding).range();
1884
- // // }
1885
2121
  this.yScale.range(this._rangeBump([height, 0]));
1886
2122
  this.xScale.range(this._rangeBump([0, width]));
1887
2123
 
@@ -1944,61 +2180,6 @@
1944
2180
  projectionX.attr("y1", _this.yScale.range()[0] + rangeBump);
1945
2181
  projectionY.attr("x2", _this.xScale.range()[0] - rangeBump);
1946
2182
 
1947
-
1948
- // reduce font size if the caption doesn't fit
1949
- this._updateSTitle();
1950
- sTitleEl
1951
- .attr("text-anchor", "end")
1952
- .attr("transform", "translate(" + width + "," + 20 + ") rotate(-90)");
1953
-
1954
- const compl = this.axisTitleComplimentStrings;
1955
- if (layoutProfile !== "SMALL") {
1956
- ySubTitleEl.select("text").attr("dy", infoElHeight * 0.6).text(this.strings.subtitle.Y);
1957
- xSubTitleEl.select("text").attr("dy", -infoElHeight * 0.3).text(this.strings.subtitle.X);
1958
-
1959
- yTitleEl.select("text").text(this.strings.title_short.Y + (compl.Y ? " · " + compl.Y : "") + " ")
1960
- .append("tspan")
1961
- .classed("vzb-noexport", true)
1962
- .style("font-size", (infoElHeight * 0.7) + "px")
1963
- .text("▼");
1964
- xTitleEl.select("text").text(this.strings.title_short.X + (compl.X ? " · " + compl.X : "") + " ")
1965
- .append("tspan")
1966
- .classed("vzb-noexport", true)
1967
- .style("font-size", (infoElHeight * 0.7) + "px")
1968
- .text("▼");
1969
- } else {
1970
- ySubTitleEl.select("text").text("");
1971
- xSubTitleEl.select("text").text("");
1972
-
1973
- const yTitleText = yTitleEl.select("text").text(this.strings.title.Y + (compl.Y ? " · " + compl.Y : ""));
1974
- if (yTitleText.node().getBBox().width > width) yTitleText.text(this.strings.title_short.Y + (compl.Y ? " · " + compl.Y : ""));
1975
-
1976
- const xTitleText = xTitleEl.select("text").text(this.strings.title.X + (compl.X ? " · " + compl.X : ""));
1977
- if (xTitleText.node().getBBox().width > width - 100) xTitleText.text(this.strings.title_short.X) + (compl.X ? " · " + compl.X : "");
1978
- }
1979
-
1980
- const isRTL = this.services.locale.isRTL();
1981
- ySubTitleEl
1982
- .style("font-size", (infoElHeight * 0.8) + "px")
1983
- .attr("transform", "translate(" + 0 + "," + 0 + ") rotate(-90)");
1984
- xSubTitleEl
1985
- .style("font-size", (infoElHeight * 0.8) + "px")
1986
- .attr("transform", "translate(" + width + "," + height + ")");
1987
-
1988
- yTitleEl
1989
- .style("font-size", infoElHeight + "px")
1990
- .attr("transform", layoutProfile !== "SMALL" ?
1991
- "translate(" + (-margin.left - this.profileConstants.yAxisTitleBottomMargin) + "," + (height * 0.5) + ") rotate(-90)"
1992
- :
1993
- "translate(" + (isRTL ? width : 10 - this.profileConstants.margin.left) + ", -" + this.profileConstants.yAxisTitleBottomMargin + ")");
1994
-
1995
- xTitleEl
1996
- .style("font-size", infoElHeight + "px")
1997
- .attr("transform", layoutProfile !== "SMALL" ?
1998
- "translate(" + (width * 0.5) + "," + (height + margin.bottom - xAxisTitleBottomMargin) + ")"
1999
- :
2000
- "translate(" + (isRTL ? width : 0) + "," + (height + margin.bottom - xAxisTitleBottomMargin) + ")");
2001
-
2002
2183
  xAxisGroupsEl
2003
2184
  .style("font-size", infoElHeight * 0.8 + "px");
2004
2185
 
@@ -2010,65 +2191,11 @@
2010
2191
  right: margin.right,
2011
2192
  bottom: xAxisTitleBottomMargin,
2012
2193
  wLimit: (layoutProfile !== "SMALL" ? 0.5 : 1) *
2013
- (this.elementWidth - xTitleEl.node().getBBox().width - infoElHeight * 3)
2194
+ (this.elementWidth - this.DOM.graph.select(".vzb-bc-axis-x-title").node().getBBox().width - infoElHeight * 3)
2014
2195
  });
2015
2196
 
2016
- //this.services.layout.setHGrid([this.elementWidth - marginRightAdjusted]);
2017
- //this.ui.margin.set("left", margin.left * this.profileConstants.leftMarginRatio, false, false);
2018
-
2019
- // (function(xMin, xMax, yMin, yMax) {
2020
- // if ((xMin && xMax && yMin && yMax) === null) return;
2021
- // _this._panZoom.zoomer.dontFeedToState = true;
2022
- // _this._panZoom.rerun(); // includes redraw data points and trail resize
2023
- // _this._panZoom.zoomToMaxMin(xMin, xMax, yMin, yMax, 0, true);
2024
- // })(_this._zoomedXYMinMax.x.zoomedMin,
2025
- // _this._zoomedXYMinMax.x.zoomedMax,
2026
- // _this._zoomedXYMinMax.y.zoomedMin,
2027
- // _this._zoomedXYMinMax.y.zoomedMax);
2028
2197
  }
2029
2198
 
2030
- updateInfoElements() {
2031
- this.services.layout.size;
2032
- this.axisTitleComplimentStrings.X;
2033
- this.axisTitleComplimentStrings.Y;
2034
-
2035
- const {xInfoEl, yInfoEl, xTitleEl, yTitleEl} = this.DOM;
2036
- const {x, y} = this.MDL;
2037
- const isRTL = this.services.locale.isRTL();
2038
- const infoElHeight = this.profileConstants.infoElHeight;
2039
- const layoutProfile = this.services.layout.profile;
2040
-
2041
- if (yInfoEl.select("svg").node()) {
2042
- const titleBBox = yTitleEl.node().getBBox();
2043
- const t = sharedComponents.LegacyUtils.transform(yTitleEl.node());
2044
- const hTranslate = isRTL ? (titleBBox.x + t.translateX - infoElHeight * 1.4) : (titleBBox.x + t.translateX + titleBBox.width + infoElHeight * 0.4);
2045
- const vTranslate = isRTL ? (t.translateY + infoElHeight * 1.4 + titleBBox.width * 0.5) : (t.translateY - infoElHeight * 0.4 - titleBBox.width * 0.5);
2046
- const conceptPropsY = y.data.conceptProps;
2047
-
2048
- yInfoEl
2049
- .classed("vzb-hidden", !conceptPropsY.description && !conceptPropsY.sourceLink || this.services.layout.projector)
2050
- .attr("transform", layoutProfile !== "SMALL" ?
2051
- `translate(${ t.translateX - infoElHeight * 0.8 }, ${ vTranslate }) rotate(-90)` :
2052
- `translate(${ hTranslate },${ t.translateY - infoElHeight * 0.8 })`)
2053
- .select("svg")
2054
- .attr("width", infoElHeight + "px")
2055
- .attr("height", infoElHeight + "px");
2056
- }
2057
-
2058
- if (xInfoEl.select("svg").node()) {
2059
- const titleBBox = xTitleEl.node().getBBox();
2060
- const t = sharedComponents.LegacyUtils.transform(xTitleEl.node());
2061
- const hTranslate = isRTL ? (titleBBox.x + t.translateX - infoElHeight * 1.4) : (titleBBox.x + t.translateX + titleBBox.width + infoElHeight * 0.4);
2062
- const conceptPropsX = x.data.conceptProps;
2063
-
2064
- xInfoEl
2065
- .classed("vzb-hidden", !conceptPropsX.description && !conceptPropsX.sourceLink || this.services.layout.projector)
2066
- .attr("transform", `translate(${ hTranslate }, ${ t.translateY - infoElHeight * 0.8 })`)
2067
- .select("svg")
2068
- .attr("width", infoElHeight + "px")
2069
- .attr("height", infoElHeight + "px");
2070
- }
2071
- }
2072
2199
 
2073
2200
  _rangeBump(arg, undo) {
2074
2201
  const bump = this.profileConstants.maxRadiusPx;
@@ -2094,40 +2221,6 @@
2094
2221
  sharedComponents.LegacyUtils.warn("rangeBump error: input is not an array or empty");
2095
2222
  }
2096
2223
 
2097
- _updateSTitle(titleS, titleC) {
2098
- const { sTitleEl } = this.DOM;
2099
- const {
2100
- size,
2101
- color
2102
- } = this.MDL;
2103
- const compl = this.axisTitleComplimentStrings;
2104
- // vertical text about size and color
2105
- if (this.profileConstants.hideSTitle
2106
- && this.root.ui.dialogs.dialogs.sidebar.indexOf("colors") > -1
2107
- && this.root.ui.dialogs.dialogs.sidebar.indexOf("size") > -1) {
2108
- sTitleEl.classed("vzb-invisible", true);
2109
- return;
2110
- }
2111
- if (sTitleEl.classed("vzb-invisible")) {
2112
- sTitleEl.classed("vzb-invisible", false);
2113
- }
2114
- const sTitleContentON = !size.data.constant;
2115
- const cTitleContentON = !color.data.constant;
2116
- const sTitleText = sTitleEl.select("text")
2117
- // reset font size to remove jumpy measurement
2118
- .style("font-size", null)
2119
- .text(
2120
- (sTitleContentON ? this.localise("buttons/size") + ": " + (titleS ? titleS : this.strings.title.S) : "") +
2121
- (compl.S ? " · " + compl.S : "") +
2122
- (sTitleContentON && cTitleContentON ? ", " : "") +
2123
- (cTitleContentON ? this.localise("buttons/colors") + ": " + (titleC ? titleC : this.strings.title.C) : "") +
2124
- (compl.C ? " · " + compl.C : "")
2125
- );
2126
- const sTitleWidth = sTitleText.node().getBBox().width;
2127
- const remainigHeight = this.height - 30;
2128
- const font = parseInt(sTitleText.style("font-size")) * remainigHeight / sTitleWidth;
2129
- sTitleText.style("font-size", sTitleWidth > remainigHeight ? font + "px" : null);
2130
- }
2131
2224
 
2132
2225
  processFrameData() {
2133
2226
  return this.__dataProcessed = this.model.dataArray;
@@ -2362,8 +2455,6 @@
2362
2455
  const c = _this.__getColor(selectedKey, d.color);
2363
2456
  let entityOutOfView = false;
2364
2457
 
2365
- ////const titles = _this._formatSTitleValues(values.size[utils.getKey(d, dataKeys.size)], values.color[utils.getKey(d, dataKeys.color)]);
2366
- ////_this._updateSTitle(titles[0], titles[1]);
2367
2458
  if (x + s < 0 || x - s > this.width || y + s < 0 || y - s > this.height) {
2368
2459
  entityOutOfView = true;
2369
2460
  }
@@ -2411,7 +2502,6 @@
2411
2502
  this._axisProjections();
2412
2503
  ////this._trails.run(["opacityHandler"]);
2413
2504
  //hide tooltip
2414
- //this._updateSTitle();
2415
2505
  this._setTooltip();
2416
2506
  this._setBubbleCrown();
2417
2507
  this._labels.highlight(null, false);
@@ -2614,7 +2704,6 @@
2614
2704
  //export default BubbleChart;
2615
2705
  const VizabiBubbleChart = mobx.decorate(_VizabiBubbleChart, {
2616
2706
  "MDL": mobx.computed,
2617
- "axisTitleComplimentStrings": mobx.observable,
2618
2707
  "cScale": mobx.computed
2619
2708
  });
2620
2709
 
@@ -2776,7 +2865,7 @@
2776
2865
  }
2777
2866
  });
2778
2867
 
2779
- BubbleChart.versionInfo = { version: "3.17.0", build: 1684329878518, package: {"homepage":"https://github.com/vizabi/bubblechart#readme","name":"@vizabi/bubblechart","description":"Vizabi bubble chart"}, sharedComponents: sharedComponents.versionInfo};
2868
+ BubbleChart.versionInfo = { version: "3.17.2", build: 1685443324638, package: {"homepage":"https://github.com/vizabi/bubblechart#readme","name":"@vizabi/bubblechart","description":"Vizabi bubble chart"}, sharedComponents: sharedComponents.versionInfo};
2780
2869
 
2781
2870
  return BubbleChart;
2782
2871