survey-analytics 2.2.2 → 2.2.4

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 (55) hide show
  1. package/fesm/shared.mjs +10 -2
  2. package/fesm/shared.mjs.map +1 -1
  3. package/fesm/shared2.mjs +748 -262
  4. package/fesm/shared2.mjs.map +1 -1
  5. package/fesm/survey.analytics.core.mjs +2 -2
  6. package/fesm/survey.analytics.mjs +315 -538
  7. package/fesm/survey.analytics.mjs.map +1 -1
  8. package/fesm/survey.analytics.tabulator.mjs +1 -1
  9. package/package.json +8 -8
  10. package/survey-analytics-tabulator.types/analytics-localization/english.d.ts +2 -0
  11. package/survey-analytics-tabulator.types/localizationManager.d.ts +2 -0
  12. package/survey-analytics-tabulator.types/utils/index.d.ts +1 -1
  13. package/survey-analytics.types/alternativeVizualizersWrapper.d.ts +2 -0
  14. package/survey-analytics.types/analytics-localization/english.d.ts +2 -0
  15. package/survey-analytics.types/boolean.d.ts +0 -1
  16. package/survey-analytics.types/entries/summary.core.d.ts +3 -1
  17. package/survey-analytics.types/histogram.d.ts +1 -1
  18. package/survey-analytics.types/localizationManager.d.ts +2 -0
  19. package/survey-analytics.types/matrix.d.ts +0 -1
  20. package/survey-analytics.types/pivot.d.ts +64 -0
  21. package/survey-analytics.types/plotly/chart-adapter.d.ts +13 -0
  22. package/survey-analytics.types/plotly/index.d.ts +2 -7
  23. package/survey-analytics.types/plotly/legacy.d.ts +33 -0
  24. package/survey-analytics.types/plotly/setup.d.ts +5 -3
  25. package/survey-analytics.types/{plotly/ranking.d.ts → ranking.d.ts} +2 -2
  26. package/survey-analytics.types/selectBase.d.ts +3 -1
  27. package/survey-analytics.types/utils/index.d.ts +1 -1
  28. package/survey-analytics.types/visualizationManager.d.ts +3 -0
  29. package/survey-analytics.types/visualizerBase.d.ts +13 -1
  30. package/survey.analytics.core.css +7 -1
  31. package/survey.analytics.core.css.map +1 -1
  32. package/survey.analytics.core.js +659 -51
  33. package/survey.analytics.core.js.map +1 -1
  34. package/survey.analytics.core.min.css +2 -2
  35. package/survey.analytics.core.min.js +1 -1
  36. package/survey.analytics.core.min.js.LICENSE.txt +1 -1
  37. package/survey.analytics.css +7 -1
  38. package/survey.analytics.css.map +1 -1
  39. package/survey.analytics.js +1048 -817
  40. package/survey.analytics.js.map +1 -1
  41. package/survey.analytics.min.css +2 -2
  42. package/survey.analytics.min.js +1 -1
  43. package/survey.analytics.min.js.LICENSE.txt +1 -1
  44. package/survey.analytics.tabulator.css +1 -1
  45. package/survey.analytics.tabulator.js +10 -2
  46. package/survey.analytics.tabulator.js.map +1 -1
  47. package/survey.analytics.tabulator.min.css +1 -1
  48. package/survey.analytics.tabulator.min.js +1 -1
  49. package/survey.analytics.tabulator.min.js.LICENSE.txt +1 -1
  50. package/survey-analytics.types/plotly/boolean.d.ts +0 -16
  51. package/survey-analytics.types/plotly/histogram.d.ts +0 -13
  52. package/survey-analytics.types/plotly/matrix.d.ts +0 -11
  53. package/survey-analytics.types/plotly/matrixdropdown-grouped.d.ts +0 -11
  54. package/survey-analytics.types/plotly/rating.d.ts +0 -20
  55. package/survey-analytics.types/plotly/selectBase.d.ts +0 -26
@@ -1,14 +1,14 @@
1
1
  /*!
2
- * surveyjs - SurveyJS Dashboard library v2.2.2
2
+ * surveyjs - SurveyJS Dashboard library v2.2.4
3
3
  * Copyright (c) 2015-2025 Devsoft Baltic OÜ - http://surveyjs.io/
4
4
  * License: MIT (http://www.opensource.org/licenses/mit-license.php)
5
5
  */
6
6
 
7
7
  import { Event, ItemValue } from 'survey-core';
8
- import { l as localization, D as DocumentHelper, a as DataHelper } from './shared.mjs';
9
- export { s as surveyStrings } from './shared.mjs';
10
- import { b as VisualizationManager, S as SelectBase, _ as __awaiter, M as Matrix, B as BooleanModel, d as defaultStatisticsCalculator, H as HistogramModel, N as NumberModel } from './shared2.mjs';
11
- export { A as AlternativeVisualizersWrapper, D as DataProvider, n as NpsAdapter, o as NpsVisualizer, m as NpsVisualizerWidget, P as PostponeHelper, l as StatisticsTable, k as StatisticsTableAdapter, j as Text, T as TextTableAdapter, g as VisualizationMatrixDropdown, f as VisualizationMatrixDynamic, c as VisualizationPanel, e as VisualizationPanelDynamic, a as VisualizerBase, V as VisualizerFactory, i as WordCloud, W as WordCloudAdapter, h as hideEmptyAnswersInData, t as textHelper } from './shared2.mjs';
8
+ import { l as localization, a as DataHelper } from './shared.mjs';
9
+ export { D as DocumentHelper, s as surveyStrings } from './shared.mjs';
10
+ import { N as NumberModel, b as VisualizationManager, S as SelectBase, d as defaultStatisticsCalculator, B as BooleanModel, H as HistogramModel, M as Matrix, p as PivotModel, R as RankingModel, a as VisualizerBase, _ as __awaiter } from './shared2.mjs';
11
+ export { A as AlternativeVisualizersWrapper, D as DataProvider, n as NpsAdapter, o as NpsVisualizer, m as NpsVisualizerWidget, P as PostponeHelper, l as StatisticsTable, k as StatisticsTableAdapter, j as Text, T as TextTableAdapter, g as VisualizationMatrixDropdown, f as VisualizationMatrixDynamic, c as VisualizationPanel, e as VisualizationPanelDynamic, V as VisualizerFactory, i as WordCloud, W as WordCloudAdapter, h as hideEmptyAnswersInData, t as textHelper } from './shared2.mjs';
12
12
  import Plotly from 'plotly.js-dist-min';
13
13
 
14
14
  class PlotlySetup {
@@ -17,38 +17,44 @@ class PlotlySetup {
17
17
  }
18
18
  static setupPie(model, answersData) {
19
19
  let { datasets, labels, colors, texts, seriesLabels, } = answersData;
20
- let traces = [];
21
20
  const hasSeries = seriesLabels.length > 1 || model.question.getType() === "matrix";
21
+ const layoutColumns = 2;
22
+ let traces = [];
22
23
  const traceConfig = {
23
24
  type: model.chartType,
24
- y: hasSeries ? seriesLabels : labels,
25
- text: (hasSeries ? seriesLabels : labels).map((label) => {
25
+ labels: labels,
26
+ customdata: labels,
27
+ text: labels.map((label) => {
26
28
  return PlotlySetup.getTruncatedLabel(label, model.labelTruncateLength);
27
29
  }),
28
- hoverinfo: "x+y",
29
- mode: "markers",
30
- marker: {},
30
+ hoverinfo: "label+value+percent",
31
+ textposition: "inside",
31
32
  };
32
- traceConfig.hoverinfo = "label+value+percent";
33
- traceConfig.marker.colors = colors;
34
- traceConfig.textposition = "inside";
35
33
  if (model.chartType === "doughnut") {
36
34
  traceConfig.type = "pie";
37
35
  traceConfig.hole = 0.4;
38
36
  }
39
37
  if (!hasSeries) {
38
+ traceConfig.mode = "markers",
39
+ traceConfig.marker = { color: colors };
40
40
  traceConfig.marker.symbol = "circle";
41
41
  traceConfig.marker.size = 16;
42
42
  }
43
43
  datasets.forEach((dataset, index) => {
44
- traces.push(Object.assign({}, traceConfig, {
45
- values: dataset,
46
- labels: hasSeries ? seriesLabels : labels,
47
- customdata: hasSeries ? seriesLabels : labels,
48
- }));
44
+ const isNotEmpty = dataset.some((value) => value != 0);
45
+ if (isNotEmpty) {
46
+ traces.push(Object.assign({}, traceConfig, {
47
+ values: dataset,
48
+ domain: {
49
+ column: traces.length % layoutColumns,
50
+ row: Math.floor(traces.length / layoutColumns),
51
+ },
52
+ title: { position: "bottom center", text: seriesLabels[index] }
53
+ }));
54
+ }
49
55
  });
50
56
  const radius = labels.length < 10 ? labels.length * 50 + 100 : 550;
51
- const height = radius * Math.round(traces.length / 2) + 25;
57
+ const height = (radius + 25) * Math.ceil(traces.length / layoutColumns);
52
58
  const layout = {
53
59
  font: {
54
60
  family: "Segoe UI, sans-serif",
@@ -71,21 +77,7 @@ class PlotlySetup {
71
77
  };
72
78
  if (hasSeries) {
73
79
  layout.annotations = [];
74
- labels.forEach((label, index) => {
75
- traces[index].title = { position: "bottom center", text: label };
76
- });
77
- traces = traces.filter(t => !(t.values.length === 1 && t.values[0] === 0));
78
- traces.forEach((label, index) => {
79
- traces[index].domain = {
80
- column: index % 2,
81
- row: Math.floor(index / 2),
82
- };
83
- });
84
- layout.grid = {
85
- rows: Math.round(traces.length / 2),
86
- columns: 2,
87
- };
88
- layout.height = radius * Math.round(traces.length / 2) + 25;
80
+ layout.grid = { rows: Math.ceil(traces.length / layoutColumns), columns: layoutColumns };
89
81
  }
90
82
  return { traces, layout, hasSeries };
91
83
  }
@@ -94,36 +86,45 @@ class PlotlySetup {
94
86
  let topMargin = 30;
95
87
  let bottomMargin = 30;
96
88
  let { datasets, labels, colors, texts, seriesLabels, } = answersData;
97
- const traces = [];
98
89
  const hasSeries = seriesLabels.length > 1 || model.question.getType() === "matrix";
99
- const yFullTexts = hasSeries ? seriesLabels : labels;
90
+ const traces = [];
100
91
  const traceConfig = {
101
- type: model.chartType,
102
- y: yFullTexts,
103
- text: yFullTexts,
104
- customdata: hasSeries ? seriesLabels : labels,
92
+ type: model.chartType === "line" ? "line" : "bar",
93
+ y: labels,
94
+ customdata: labels,
105
95
  hoverinfo: "text",
106
96
  orientation: "h",
107
- mode: "markers",
108
97
  textposition: "none",
109
- width: 0.5,
110
- bargap: 0.5,
111
- marker: {},
112
98
  };
113
- traceConfig.marker.color = colors;
99
+ if (!hasSeries) {
100
+ traceConfig.width = 0.5;
101
+ traceConfig.bargap = 0.5;
102
+ traceConfig.mode = "markers",
103
+ traceConfig.marker = { color: colors };
104
+ }
114
105
  datasets.forEach((dataset, index) => {
115
- var trace = Object.assign({}, traceConfig, {
106
+ const traceName = hasSeries ? seriesLabels[index] : labels[index];
107
+ const percentString = model.showPercentages ? "%" : "";
108
+ const trace = Object.assign({}, traceConfig, {
116
109
  x: dataset,
110
+ name: traceName,
111
+ width: hasSeries && model.chartType !== "stackedbar" ? 0.5 / seriesLabels.length : 0.5,
117
112
  text: texts[index],
118
- hovertext: yFullTexts.map((label, labelIndex) => {
119
- return `${texts[index][labelIndex]}, ${label}`;
113
+ hovertext: labels.map((label, labelIndex) => {
114
+ if (model.showOnlyPercentages) {
115
+ return `${texts[index][labelIndex]}${percentString}`;
116
+ }
117
+ else {
118
+ return hasSeries ? `${traceName} : ${label}, ${texts[index][labelIndex]}${percentString}` : `${texts[index][labelIndex]}${percentString}, ${label}`;
119
+ }
120
120
  }),
121
121
  });
122
122
  if (model.showPercentages) {
123
123
  let texttemplate = model.showOnlyPercentages ? "%{text}%" : "%{value} (%{text}%)";
124
124
  trace.textposition = "inside";
125
125
  trace.texttemplate = texttemplate;
126
- trace.bargap = 0.1;
126
+ trace.width = hasSeries && model.chartType !== "stackedbar" ? 0.7 / seriesLabels.length : 0.9;
127
+ trace.bargap = hasSeries && model.chartType !== "stackedbar" ? 0.3 / seriesLabels.length : 0.1;
127
128
  }
128
129
  traces.push(trace);
129
130
  });
@@ -143,60 +144,49 @@ class PlotlySetup {
143
144
  },
144
145
  colorway: colors,
145
146
  hovermode: "closest",
147
+ plot_bgcolor: model.backgroundColor,
148
+ paper_bgcolor: model.backgroundColor,
149
+ showlegend: hasSeries,
150
+ barmode: hasSeries && model.chartType == "stackedbar" ? "stack" : "group",
151
+ xaxis: {
152
+ rangemode: "nonnegative",
153
+ automargin: true,
154
+ },
146
155
  yaxis: {
147
156
  automargin: true,
148
157
  type: "category",
149
158
  orientation: "h",
150
159
  tickmode: "array",
151
- tickvals: yFullTexts,
152
- ticktext: yFullTexts.map((label) => {
160
+ tickvals: labels,
161
+ ticktext: labels.map((label) => {
153
162
  return PlotlySetup.getTruncatedLabel(label, model.labelTruncateLength) + " ";
154
163
  }),
155
164
  },
156
- xaxis: {
157
- rangemode: "nonnegative",
158
- automargin: true,
159
- // dtick: 1
160
- },
161
- plot_bgcolor: model.backgroundColor,
162
- paper_bgcolor: model.backgroundColor,
163
- showlegend: false,
164
165
  };
165
- if (hasSeries) {
166
- layout.showlegend = true;
167
- if (model.chartType == "stackedbar") {
168
- layout.barmode = "stack";
169
- layout.height =
170
- (seriesLabels.length + 1) * lineHeight +
171
- topMargin +
172
- bottomMargin;
173
- }
174
- else {
175
- layout.height =
176
- (labels.length + 1) * lineHeight * seriesLabels.length +
177
- topMargin +
178
- bottomMargin;
179
- }
180
- labels.forEach((label, index) => {
181
- traces[index].marker.color = undefined;
182
- traces[index].name = label;
183
- if (model.chartType === "stackedbar") {
184
- traces[index].type = "bar";
185
- traces[index].width = 0.5;
186
- }
187
- else {
188
- traces[index].width =
189
- (model.showPercentages ? 0.7 : 0.5) / traces.length;
190
- }
191
- });
192
- traces.forEach((trace, traceIndex) => {
193
- const percentString = model.showPercentages ? "%" : "";
194
- traces[traceIndex].hovertext = [];
195
- yFullTexts.forEach((yFullText, yFullTextIndex) => {
196
- traces[traceIndex].hovertext.push(`${trace.y[yFullTextIndex]} : ${trace.name}, ${trace.text[yFullTextIndex]}${percentString}`);
197
- });
198
- });
166
+ if (hasSeries && model.chartType !== "stackedbar") {
167
+ layout.height =
168
+ (labels.length * seriesLabels.length + 1) * lineHeight +
169
+ topMargin +
170
+ bottomMargin;
199
171
  }
172
+ // labels.forEach((label, index) => {
173
+ // traces[index].marker.color = undefined;
174
+ // traces[index].name = label;
175
+ // if (model.chartType === "stackedbar") {
176
+ // traces[index].type = "bar";
177
+ // traces[index].width = 0.5;
178
+ // } else {
179
+ // traces[index].width =
180
+ // (model.showPercentages ? 0.7 : 0.5) / traces.length;
181
+ // }
182
+ // });
183
+ // traces.forEach((trace, traceIndex) => {
184
+ // const percentString = model.showPercentages ? "%" : "";
185
+ // traces[traceIndex].hovertext = [];
186
+ // yFullTexts.forEach((yFullText, yFullTextIndex) => {
187
+ // traces[traceIndex].hovertext.push(`${trace.y[yFullTextIndex]} : ${trace.name}, ${trace.text[yFullTextIndex]}${percentString}`);
188
+ // });
189
+ // });
200
190
  if (["ar", "fa"].indexOf(localization.currentLocale) !== -1) {
201
191
  layout.xaxis.autorange = "reversed";
202
192
  layout.yaxis.side = "right";
@@ -213,9 +203,11 @@ class PlotlySetup {
213
203
  let topMargin = 30;
214
204
  let bottomMargin = 30;
215
205
  let { datasets, labels, colors, texts, seriesLabels, } = answersData;
216
- if (model.type !== "histogram") {
206
+ const hasSeries = seriesLabels.length > 1 || model.question.getType() === "matrix";
207
+ if (model.type !== "histogram" && model.type !== "pivot") {
217
208
  labels = [].concat(labels).reverse();
218
- colors = [].concat(colors.slice(0, labels.length)).reverse();
209
+ seriesLabels = [].concat(seriesLabels).reverse();
210
+ colors = [].concat(colors.slice(0, hasSeries ? seriesLabels.length : labels.length)).reverse();
219
211
  const ts = [];
220
212
  texts.forEach(text => {
221
213
  ts.push([].concat(text).reverse());
@@ -228,7 +220,37 @@ class PlotlySetup {
228
220
  datasets = ds;
229
221
  }
230
222
  const traces = [];
231
- const hasSeries = seriesLabels.length > 1 || model.question.getType() === "matrix";
223
+ const traceConfig = {
224
+ type: model.chartType === "line" ? "line" : "bar",
225
+ x: labels,
226
+ customdata: hasSeries ? seriesLabels : labels,
227
+ hoverinfo: hasSeries ? undefined : "x+y",
228
+ orientation: "v",
229
+ textposition: "none",
230
+ };
231
+ if (model.type === "histogram" || !hasSeries) {
232
+ traceConfig.width = 0.5;
233
+ traceConfig.bargap = 0.5;
234
+ traceConfig.mode = "markers",
235
+ traceConfig.marker = { color: colors };
236
+ }
237
+ datasets.forEach((dataset, index) => {
238
+ var trace = Object.assign({}, traceConfig, {
239
+ y: dataset,
240
+ name: hasSeries ? seriesLabels[index] : labels[index],
241
+ text: texts[index],
242
+ });
243
+ if (model.showPercentages) {
244
+ let texttemplate = model.showOnlyPercentages ? "%{text}%" : "%{value} (%{text}%)";
245
+ trace.textposition = "inside";
246
+ trace.texttemplate = texttemplate;
247
+ if (!hasSeries) {
248
+ trace.width = 0.9;
249
+ trace.bargap = 0.1;
250
+ }
251
+ }
252
+ traces.push(trace);
253
+ });
232
254
  const layout = {
233
255
  font: {
234
256
  family: "Segoe UI, sans-serif",
@@ -245,34 +267,21 @@ class PlotlySetup {
245
267
  hovermode: "closest",
246
268
  plot_bgcolor: model.backgroundColor,
247
269
  paper_bgcolor: model.backgroundColor,
248
- showlegend: false,
249
- };
250
- const traceConfig = {
251
- type: model.chartType === "line" ? "line" : "bar",
252
- customdata: hasSeries ? seriesLabels : labels,
253
- hoverinfo: "x+y",
254
- mode: model.chartType === "line" ? "lines+markers" : "markers",
255
- textposition: "none",
256
- width: 0.5,
257
- bargap: 0.5,
258
- marker: {},
270
+ showlegend: hasSeries,
271
+ yaxis: {
272
+ rangemode: "nonnegative",
273
+ automargin: true,
274
+ },
275
+ xaxis: {
276
+ automargin: true,
277
+ type: "category",
278
+ tickmode: "array",
279
+ tickvals: labels,
280
+ ticktext: labels.map((label) => {
281
+ return PlotlySetup.getTruncatedLabel(label, model.labelTruncateLength) + " ";
282
+ }),
283
+ },
259
284
  };
260
- traceConfig.marker.color = colors;
261
- datasets.forEach((dataset, index) => {
262
- var trace = Object.assign({}, traceConfig, {
263
- x: labels,
264
- y: model.showPercentages ? texts[index].map(y => y / 100) : dataset,
265
- text: texts[index],
266
- });
267
- if (model.showPercentages) {
268
- let texttemplate = model.showOnlyPercentages ? "%{text}%" : "%{value} (%{text}%)";
269
- trace.textposition = "inside";
270
- trace.texttemplate = texttemplate;
271
- trace.width = 0.9;
272
- trace.bargap = 0.1;
273
- }
274
- traces.push(trace);
275
- });
276
285
  if (model.showPercentages && model.showOnlyPercentages) {
277
286
  layout.yaxis = {
278
287
  automargin: true,
@@ -363,6 +372,49 @@ class PlotlySetup {
363
372
  }
364
373
  return { traces, layout, hasSeries };
365
374
  }
375
+ static setupGauge(model, answersData) {
376
+ let [level, minValue, maxValue] = answersData;
377
+ if (model.question.getType() === "rating") {
378
+ const rateValues = model.question.visibleRateValues;
379
+ maxValue = rateValues[rateValues.length - 1].value;
380
+ minValue = rateValues[0].value;
381
+ }
382
+ const colors = model.generateColors(maxValue, minValue, NumberModel.stepsCount);
383
+ if (NumberModel.showAsPercentage) {
384
+ level = DataHelper.toPercentage(level, maxValue);
385
+ minValue = DataHelper.toPercentage(minValue, maxValue);
386
+ maxValue = DataHelper.toPercentage(maxValue, maxValue);
387
+ }
388
+ var traces = [
389
+ {
390
+ type: "indicator",
391
+ mode: "gauge+number",
392
+ gauge: {
393
+ axis: { range: [minValue, maxValue] },
394
+ shape: model.chartType,
395
+ bgcolor: "white",
396
+ bar: { color: colors[0] },
397
+ },
398
+ value: level,
399
+ text: model.name,
400
+ domain: { x: [0, 1], y: [0, 1] },
401
+ },
402
+ ];
403
+ const chartMargin = model.chartType === "bullet" ? 60 : 30;
404
+ var layout = {
405
+ height: 250,
406
+ margin: {
407
+ l: chartMargin,
408
+ r: chartMargin,
409
+ b: chartMargin,
410
+ t: chartMargin,
411
+ pad: 5
412
+ },
413
+ plot_bgcolor: model.backgroundColor,
414
+ paper_bgcolor: model.backgroundColor,
415
+ };
416
+ return { traces, layout, hasSeries: false };
417
+ }
366
418
  }
367
419
  PlotlySetup.imageExportFormat = "png";
368
420
  /**
@@ -382,6 +434,8 @@ PlotlySetup.setups = {
382
434
  doughnut: PlotlySetup.setupPie,
383
435
  pie: PlotlySetup.setupPie,
384
436
  scatter: PlotlySetup.setupScatter,
437
+ gauge: PlotlySetup.setupGauge,
438
+ bullet: PlotlySetup.setupGauge,
385
439
  };
386
440
  PlotlySetup.getTruncatedLabel = (label, labelTruncateLength) => {
387
441
  const truncateSymbols = "...";
@@ -395,276 +449,9 @@ PlotlySetup.getTruncatedLabel = (label, labelTruncateLength) => {
395
449
  return label.substring(0, labelTruncateLength) + truncateSymbols;
396
450
  };
397
451
 
398
- class PlotlyChartAdapter {
399
- constructor(model) {
400
- this.model = model;
401
- this._chart = undefined;
402
- }
403
- patchConfigParameters(chartNode, traces, layout, config) { }
404
- get chart() {
405
- return this._chart;
406
- }
407
- create(chartNode) {
408
- return __awaiter(this, void 0, void 0, function* () {
409
- const [plot, plotlyOptions] = yield this.update(chartNode);
410
- chartNode["on"]("plotly_click", (data) => {
411
- if (data.points.length > 0) {
412
- let itemText = "";
413
- if (!plotlyOptions.hasSeries) {
414
- itemText = Array.isArray(data.points[0].customdata)
415
- ? data.points[0].customdata[0]
416
- : data.points[0].customdata;
417
- const item = this.model.getSelectedItemByText(itemText);
418
- this.model.setSelection(item);
419
- }
420
- else {
421
- itemText = data.points[0].data.name;
422
- const propertyLabel = data.points[0].label;
423
- const seriesValues = this.model.getSeriesValues();
424
- const seriesLabels = this.model.getSeriesLabels();
425
- const propertyValue = seriesValues[seriesLabels.indexOf(propertyLabel)];
426
- const selectedItem = this.model.getSelectedItemByText(itemText);
427
- const item = new ItemValue({ [propertyValue]: selectedItem.value }, propertyLabel + ": " + selectedItem.text);
428
- this.model.setSelection(item);
429
- }
430
- // const itemText = plotlyOptions.hasSeries
431
- // ? data.points[0].data.name
432
- // : Array.isArray(data.points[0].customdata)
433
- // ? data.points[0].customdata[0]
434
- // : data.points[0].customdata;
435
- // const item: ItemValue = this.model.getSelectedItemByText(itemText);
436
- // this.model.setSelection(item);
437
- }
438
- });
439
- var getDragLayer = () => chartNode.getElementsByClassName("nsewdrag")[0];
440
- chartNode["on"]("plotly_hover", () => {
441
- const dragLayer = getDragLayer();
442
- dragLayer && (dragLayer.style.cursor = "pointer");
443
- });
444
- chartNode["on"]("plotly_unhover", () => {
445
- const dragLayer = getDragLayer();
446
- dragLayer && (dragLayer.style.cursor = "");
447
- });
448
- // setTimeout(() => Plotly.Plots.resize(chartNode), 10);
449
- this._chart = plot;
450
- return plot;
451
- });
452
- }
453
- update(chartNode) {
454
- return __awaiter(this, void 0, void 0, function* () {
455
- const answersData = yield this.model.getAnswersData();
456
- var plotlyOptions = PlotlySetup.setup(this.model.chartType, this.model, answersData);
457
- let config = {
458
- displaylogo: false,
459
- responsive: true,
460
- locale: localization.currentLocale,
461
- modeBarButtonsToRemove: ["toImage"],
462
- modeBarButtonsToAdd: [
463
- {
464
- name: "toImageSjs",
465
- title: localization.getString("saveDiagramAsPNG"),
466
- icon: Plotly.Icons.camera,
467
- click: (gd) => {
468
- let options = {
469
- format: PlotlySetup.imageExportFormat,
470
- // width: 800,
471
- // height: 600,
472
- filename: this.model.question.name,
473
- };
474
- PlotlySetup.onImageSaving.fire(this.model, options);
475
- Plotly.downloadImage(gd, options);
476
- },
477
- },
478
- ],
479
- };
480
- if (SelectBasePlotly.displayModeBar !== undefined) {
481
- config.displayModeBar = SelectBasePlotly.displayModeBar;
482
- }
483
- this.patchConfigParameters(chartNode, plotlyOptions.traces, plotlyOptions.layout, config);
484
- let options = {
485
- traces: plotlyOptions.traces,
486
- layout: plotlyOptions.layout,
487
- config: config,
488
- };
489
- PlotlySetup.onPlotCreating.fire(this.model, options);
490
- const plot = Plotly.react(chartNode, options.traces, options.layout, options.config);
491
- return [plot, plotlyOptions];
492
- });
493
- }
494
- destroy(node) {
495
- if (!!node) {
496
- Plotly.purge(node);
497
- }
498
- this._chart = undefined;
499
- }
500
- }
501
- class SelectBasePlotly extends SelectBase {
502
- constructor(question, data, options = {}, name) {
503
- super(question, data, options, name);
504
- this.chartTypes = [].concat(SelectBasePlotly.types);
505
- if (this.getSeriesValues().length > 0 && this.chartTypes.indexOf("stackedbar") === -1) {
506
- this.chartTypes.push("stackedbar");
507
- }
508
- if (options.allowExperimentalFeatures) ;
509
- this._chartType = this.chartTypes[0];
510
- if (this.chartTypes.indexOf(options.defaultChartType) !== -1) {
511
- this._chartType = options.defaultChartType;
512
- }
513
- this._chartAdapter = new PlotlyChartAdapter(this);
514
- }
515
- destroyContent(container) {
516
- this._chartAdapter.destroy(container.children[0]);
517
- super.destroyContent(container);
518
- }
519
- renderContentAsync(container) {
520
- return __awaiter(this, void 0, void 0, function* () {
521
- const chartNode = DocumentHelper.createElement("div");
522
- container.innerHTML = "";
523
- container.appendChild(chartNode);
524
- yield this._chartAdapter.create(chartNode);
525
- return container;
526
- });
527
- }
528
- updateContent() {
529
- var _a;
530
- const chartNode = (_a = this.contentContainer) === null || _a === void 0 ? void 0 : _a.children[0];
531
- if (chartNode) {
532
- this._chartAdapter.update(chartNode);
533
- }
534
- }
535
- getCalculatedValuesCore() {
536
- const statistics = super.getCalculatedValuesCore();
537
- const series = this.getSeriesValues();
538
- const values = this.getValues();
539
- if (series.length > 1) {
540
- const preparedData = [];
541
- values.forEach((val, valueIndex) => {
542
- const seriesData = series.map((seriesValue, seriesIndex) => statistics[seriesIndex][valueIndex]);
543
- preparedData.push(seriesData);
544
- });
545
- return preparedData;
546
- }
547
- return statistics;
548
- }
549
- }
550
- SelectBasePlotly.types = ["bar", "vbar", "pie", "doughnut"];
551
- SelectBasePlotly.displayModeBar = undefined;
552
- VisualizationManager.registerVisualizer("checkbox", SelectBasePlotly);
553
- VisualizationManager.registerVisualizer("radiogroup", SelectBasePlotly);
554
- VisualizationManager.registerVisualizer("dropdown", SelectBasePlotly);
555
- VisualizationManager.registerVisualizer("imagepicker", SelectBasePlotly);
556
- VisualizationManager.registerVisualizer("tagbox", SelectBasePlotly);
557
-
558
- class MatrixPlotly extends Matrix {
559
- constructor(question, data, options, name) {
560
- super(question, data, options, name);
561
- this.chartTypes = MatrixPlotly.types;
562
- this._chartType = this.chartTypes[0];
563
- this._chartAdapter = new PlotlyChartAdapter(this);
564
- }
565
- destroyContent(container) {
566
- this._chartAdapter.destroy(container.children[0]);
567
- super.destroyContent(container);
568
- }
569
- renderContentAsync(container) {
570
- return __awaiter(this, void 0, void 0, function* () {
571
- const chartNode = DocumentHelper.createElement("div");
572
- container.innerHTML = "";
573
- container.appendChild(chartNode);
574
- yield this._chartAdapter.create(chartNode);
575
- return container;
576
- });
577
- }
578
- }
579
- MatrixPlotly.types = ["bar", "stackedbar", "pie", "doughnut"];
580
- VisualizationManager.registerVisualizer("matrix", MatrixPlotly);
581
-
582
- class PlotlyBoolChartAdapter extends PlotlyChartAdapter {
583
- constructor(model) {
584
- super(model);
585
- }
586
- patchConfigParameters(chartNode, traces, layout, config) {
587
- const colors = this.model.getColors();
588
- const boolColors = [
589
- BooleanPlotly.trueColor || colors[0],
590
- BooleanPlotly.falseColor || colors[1],
591
- ];
592
- if (this.model.showMissingAnswers) {
593
- boolColors.push(colors[2]);
594
- }
595
- if (this.model.chartType === "pie" || this.model.chartType === "doughnut") {
596
- traces.forEach((trace) => {
597
- trace.marker.colors = boolColors;
598
- });
599
- }
600
- else if (this.model.chartType === "bar") {
601
- traces.forEach((trace) => {
602
- trace.marker.color = boolColors;
603
- });
604
- }
605
- }
606
- }
607
- class BooleanPlotly extends BooleanModel {
608
- constructor(question, data, options, name) {
609
- super(question, data, options, name);
610
- this.chartTypes = BooleanPlotly.types;
611
- this._chartType = this.chartTypes[0];
612
- this._chartAdapter = new PlotlyBoolChartAdapter(this);
613
- }
614
- destroyContent(container) {
615
- this._chartAdapter.destroy(container.children[0]);
616
- super.destroyContent(container);
617
- }
618
- renderContentAsync(container) {
619
- return __awaiter(this, void 0, void 0, function* () {
620
- const chartNode = DocumentHelper.createElement("div");
621
- yield this._chartAdapter.create(chartNode);
622
- container.innerHTML = "";
623
- container.appendChild(chartNode);
624
- return container;
625
- });
626
- }
627
- }
628
- BooleanPlotly.types = ["pie", "bar", "doughnut"];
629
- VisualizationManager.registerVisualizer("boolean", BooleanPlotly);
630
-
631
- class RankingPlotly extends SelectBasePlotly {
632
- getQuestionResults() {
633
- const name = this.question.name;
634
- return this.data.map((dataItem) => dataItem[name]);
635
- }
636
- getEmptyData() {
637
- const choices = this.getValues();
638
- let data = [];
639
- data.length = choices.length;
640
- data.fill(0);
641
- return data;
642
- }
643
- getCalculatedValuesCore() {
644
- const results = this.getQuestionResults();
645
- const choices = this.getValues();
646
- let plotlyData = this.getEmptyData();
647
- results.forEach((result) => {
648
- this.applyResultToPlotlyData(result, plotlyData, choices);
649
- });
650
- return [plotlyData];
651
- }
652
- applyResultToPlotlyData(result, plotlyData, choices) {
653
- if (!result || !plotlyData || !choices)
654
- return;
655
- result.forEach((resultValue, resultValueIndex, result) => {
656
- let index = choices.indexOf(resultValue);
657
- plotlyData[index] =
658
- +plotlyData[index] + (result.length - resultValueIndex);
659
- });
660
- }
661
- }
662
- VisualizationManager.registerVisualizer("ranking", RankingPlotly);
663
-
664
452
  class MatrixDropdownGrouped extends SelectBase {
665
453
  constructor(question, data, options, name) {
666
454
  super(question, data, options, name || "matrixDropdownGrouped");
667
- // this.getAnswersData();
668
455
  }
669
456
  get matrixQuestion() {
670
457
  return this.question;
@@ -701,138 +488,153 @@ class MatrixDropdownGrouped extends SelectBase {
701
488
  getSeriesValues: () => rows,
702
489
  getSeriesLabels: () => rows,
703
490
  });
704
- const preparedData = [];
705
- values.forEach((val, valueIndex) => {
706
- const seriesData = series.map((seriesName, seriesIndex) => statistics[seriesIndex][0][valueIndex]);
707
- preparedData.push(seriesData);
708
- });
709
- return preparedData;
491
+ return statistics.map(s => s[0]);
710
492
  }
711
493
  }
494
+ VisualizationManager.registerVisualizer("matrixdropdown-grouped", MatrixDropdownGrouped);
712
495
 
713
- class MatrixDropdownGroupedPlotly extends MatrixDropdownGrouped {
714
- constructor(question, data, options, name) {
715
- super(question, data, options, name);
716
- this.chartTypes = MatrixDropdownGroupedPlotly.types;
717
- this._chartType = this.chartTypes[0];
718
- this._chartAdapter = new PlotlyChartAdapter(this);
719
- }
720
- destroyContent(container) {
721
- this._chartAdapter.destroy(container.children[0]);
722
- super.destroyContent(container);
723
- }
724
- renderContentAsync(container) {
725
- return __awaiter(this, void 0, void 0, function* () {
726
- const chartNode = DocumentHelper.createElement("div");
727
- container.innerHTML = "";
728
- container.appendChild(chartNode);
729
- yield this._chartAdapter.create(chartNode);
730
- return container;
731
- });
732
- }
496
+ class SelectBasePlotly extends SelectBase {
733
497
  }
734
- MatrixDropdownGroupedPlotly.types = ["stackedbar", "bar", "pie", "doughnut"];
735
- VisualizationManager.registerVisualizer("matrixdropdown-grouped", MatrixDropdownGroupedPlotly);
736
-
498
+ SelectBasePlotly.types = ["bar", "vbar", "pie", "doughnut"];
499
+ SelectBasePlotly.displayModeBar = undefined;
500
+ class BooleanPlotly extends BooleanModel {
501
+ }
502
+ BooleanPlotly.types = ["pie", "bar", "doughnut"];
737
503
  class HistogramPlotly extends HistogramModel {
738
- constructor(question, data, options, name) {
739
- super(question, data, options, name);
740
- this.chartTypes = HistogramPlotly.types;
741
- this._chartType = this.chartTypes[0];
742
- this._chartAdapter = new PlotlyChartAdapter(this);
743
- }
744
- destroyContent(container) {
745
- this._chartAdapter.destroy(container.children[0]);
746
- super.destroyContent(container);
747
- }
748
- renderContentAsync(container) {
749
- return __awaiter(this, void 0, void 0, function* () {
750
- const chartNode = DocumentHelper.createElement("div");
751
- container.innerHTML = "";
752
- container.appendChild(chartNode);
753
- yield this._chartAdapter.create(chartNode);
754
- return container;
755
- });
756
- }
757
- getCalculatedValuesCore() {
758
- const statistics = super.getCalculatedValuesCore();
759
- const series = this.getSeriesValues();
760
- const values = this.getValues();
761
- if (series.length > 1) {
762
- const preparedData = [];
763
- values.forEach((val, valueIndex) => {
764
- const seriesData = series.map((seriesValue, seriesIndex) => statistics[seriesIndex][valueIndex]);
765
- preparedData.push(seriesData);
766
- });
767
- return preparedData;
768
- }
769
- return statistics;
770
- }
771
- getValueType() {
772
- return this.valueType;
773
- }
774
504
  }
775
505
  HistogramPlotly.types = ["vbar", "bar"];
776
- VisualizationManager.registerVisualizer("date", HistogramPlotly);
777
- VisualizationManager.registerVisualizer("number", HistogramPlotly);
778
- VisualizationManager.registerVisualizer("rating", HistogramPlotly);
506
+ class MatrixPlotly extends Matrix {
507
+ }
508
+ MatrixPlotly.types = ["bar", "stackedbar", "pie", "doughnut"];
509
+ class MatrixDropdownGroupedPlotly extends MatrixDropdownGrouped {
510
+ }
511
+ MatrixDropdownGroupedPlotly.types = ["stackedbar", "bar", "pie", "doughnut"];
512
+ class PivotPlotly extends PivotModel {
513
+ }
514
+ PivotPlotly.types = ["vbar", "bar", "line", "stackedbar", "pie", "doughnut"]; // ["vbar", "bar"];
515
+ class GaugePlotly extends NumberModel {
516
+ }
517
+ GaugePlotly.displayModeBar = undefined;
518
+ GaugePlotly.types = ["gauge", "bullet"];
519
+ class RankingPlotly extends RankingModel {
520
+ }
779
521
 
780
- class PlotlyGaugeAdapter {
522
+ class PlotlyChartAdapter {
781
523
  constructor(model) {
782
524
  this.model = model;
783
525
  this._chart = undefined;
784
526
  }
527
+ patchConfigParameters(chartNode, traces, layout, config) {
528
+ if (this.model.question.getType() === "boolean") {
529
+ const colors = this.model.getColors();
530
+ const boolColors = [
531
+ BooleanModel.trueColor || colors[0],
532
+ BooleanModel.falseColor || colors[1],
533
+ ];
534
+ if (this.model.showMissingAnswers) {
535
+ boolColors.push(colors[2]);
536
+ }
537
+ const chartType = this.model.chartType;
538
+ if (chartType === "pie" || chartType === "doughnut") {
539
+ traces.forEach((trace) => {
540
+ trace.marker.colors = boolColors;
541
+ });
542
+ }
543
+ else if (chartType === "bar") {
544
+ traces.forEach((trace) => {
545
+ trace.marker.color = boolColors;
546
+ });
547
+ }
548
+ }
549
+ if (this.model.type === "number") {
550
+ config.displayModeBar = true;
551
+ }
552
+ }
785
553
  get chart() {
786
554
  return this._chart;
787
555
  }
556
+ getChartTypes() {
557
+ const visualizerType = this.model.type;
558
+ if (visualizerType === "boolean") {
559
+ return BooleanPlotly.types;
560
+ }
561
+ else if (visualizerType === "number") {
562
+ return GaugePlotly.types;
563
+ }
564
+ else if (visualizerType === "selectBase") {
565
+ return SelectBasePlotly.types;
566
+ }
567
+ else if (visualizerType === "histogram") {
568
+ return HistogramPlotly.types;
569
+ }
570
+ else if (visualizerType === "matrix") {
571
+ return MatrixPlotly.types;
572
+ }
573
+ else if (visualizerType === "matrixDropdownGrouped") {
574
+ return MatrixDropdownGroupedPlotly.types;
575
+ }
576
+ else if (visualizerType === "pivot") {
577
+ return PivotPlotly.types;
578
+ }
579
+ return [];
580
+ }
788
581
  create(chartNode) {
789
582
  return __awaiter(this, void 0, void 0, function* () {
790
- const question = this.model.question;
791
- let [level, minValue, maxValue] = yield this.model.getCalculatedValues();
792
- if (question.getType() === "rating") {
793
- const rateValues = question.visibleRateValues;
794
- maxValue = rateValues[rateValues.length - 1].value;
795
- minValue = rateValues[0].value;
796
- }
797
- const colors = this.model.generateColors(maxValue, minValue, GaugePlotly.stepsCount);
798
- if (GaugePlotly.showAsPercentage) {
799
- level = DataHelper.toPercentage(level, maxValue);
800
- minValue = DataHelper.toPercentage(minValue, maxValue);
801
- maxValue = DataHelper.toPercentage(maxValue, maxValue);
583
+ const [plot, plotlyOptions] = yield this.update(chartNode);
584
+ if (this.model instanceof SelectBase) {
585
+ const _model = this.model;
586
+ chartNode["on"]("plotly_click", (data) => {
587
+ if (data.points.length > 0) {
588
+ let itemText = "";
589
+ if (!plotlyOptions.hasSeries) {
590
+ itemText = Array.isArray(data.points[0].customdata)
591
+ ? data.points[0].customdata[0]
592
+ : data.points[0].customdata;
593
+ const item = _model.getSelectedItemByText(itemText);
594
+ _model.setSelection(item);
595
+ }
596
+ else {
597
+ itemText = data.points[0].data.name;
598
+ const propertyLabel = data.points[0].label;
599
+ const seriesValues = this.model.getSeriesValues();
600
+ const seriesLabels = this.model.getSeriesLabels();
601
+ const propertyValue = seriesValues[seriesLabels.indexOf(propertyLabel)];
602
+ const selectedItem = _model.getSelectedItemByText(itemText);
603
+ const item = new ItemValue({ [propertyValue]: selectedItem.value }, propertyLabel + ": " + selectedItem.text);
604
+ _model.setSelection(item);
605
+ }
606
+ // const itemText = plotlyOptions.hasSeries
607
+ // ? data.points[0].data.name
608
+ // : Array.isArray(data.points[0].customdata)
609
+ // ? data.points[0].customdata[0]
610
+ // : data.points[0].customdata;
611
+ // const item: ItemValue = this.model.getSelectedItemByText(itemText);
612
+ // this.model.setSelection(item);
613
+ }
614
+ });
802
615
  }
803
- var data = [
804
- {
805
- type: "indicator",
806
- mode: "gauge+number",
807
- gauge: {
808
- axis: { range: [minValue, maxValue] },
809
- shape: this.model.chartType,
810
- bgcolor: "white",
811
- bar: { color: colors[0] },
812
- },
813
- value: level,
814
- text: question.name,
815
- domain: { x: [0, 1], y: [0, 1] },
816
- },
817
- ];
818
- const chartMargin = this.model.chartType === "bullet" ? 60 : 30;
819
- var layout = {
820
- height: 250,
821
- margin: {
822
- l: chartMargin,
823
- r: chartMargin,
824
- b: chartMargin,
825
- t: chartMargin,
826
- pad: 5
827
- },
828
- plot_bgcolor: this.model.backgroundColor,
829
- paper_bgcolor: this.model.backgroundColor,
830
- };
831
- const config = {
832
- displayModeBar: true,
833
- locale: localization.currentLocale,
834
- responsive: true,
616
+ var getDragLayer = () => chartNode.getElementsByClassName("nsewdrag")[0];
617
+ chartNode["on"]("plotly_hover", () => {
618
+ const dragLayer = getDragLayer();
619
+ dragLayer && (dragLayer.style.cursor = "pointer");
620
+ });
621
+ chartNode["on"]("plotly_unhover", () => {
622
+ const dragLayer = getDragLayer();
623
+ dragLayer && (dragLayer.style.cursor = "");
624
+ });
625
+ // setTimeout(() => Plotly.Plots.resize(chartNode), 10);
626
+ this._chart = plot;
627
+ return plot;
628
+ });
629
+ }
630
+ update(chartNode) {
631
+ return __awaiter(this, void 0, void 0, function* () {
632
+ const answersData = (this.model instanceof SelectBase) ? yield this.model.getAnswersData() : yield this.model.getCalculatedValues();
633
+ var plotlyOptions = PlotlySetup.setup(this.model.chartType, this.model, answersData);
634
+ let config = {
835
635
  displaylogo: false,
636
+ responsive: true,
637
+ locale: localization.currentLocale,
836
638
  modeBarButtonsToRemove: ["toImage"],
837
639
  modeBarButtonsToAdd: [
838
640
  {
@@ -852,18 +654,18 @@ class PlotlyGaugeAdapter {
852
654
  },
853
655
  ],
854
656
  };
855
- if (GaugePlotly.displayModeBar !== undefined) {
856
- config.displayModeBar = GaugePlotly.displayModeBar;
657
+ if (SelectBasePlotly.displayModeBar !== undefined) {
658
+ config.displayModeBar = SelectBasePlotly.displayModeBar;
857
659
  }
660
+ this.patchConfigParameters(chartNode, plotlyOptions.traces, plotlyOptions.layout, config);
858
661
  let options = {
859
- data: data,
860
- layout: layout,
662
+ traces: plotlyOptions.traces,
663
+ layout: plotlyOptions.layout,
861
664
  config: config,
862
665
  };
863
666
  PlotlySetup.onPlotCreating.fire(this.model, options);
864
- const plot = Plotly.newPlot(chartNode, options.data, options.layout, options.config);
865
- // setTimeout(() => Plotly.Plots.resize(chartNode), 10);
866
- return plot;
667
+ const plot = Plotly.react(chartNode, options.traces, options.layout, options.config);
668
+ return [plot, plotlyOptions];
867
669
  });
868
670
  }
869
671
  destroy(node) {
@@ -873,32 +675,7 @@ class PlotlyGaugeAdapter {
873
675
  this._chart = undefined;
874
676
  }
875
677
  }
876
- class GaugePlotly extends NumberModel {
877
- constructor(question, data, options, name) {
878
- super(question, data, options, name);
879
- this.chartTypes = GaugePlotly.types;
880
- this.chartType = this.chartTypes[0];
881
- this._chartAdapter = new PlotlyGaugeAdapter(this);
882
- }
883
- destroyContent(container) {
884
- this._chartAdapter.destroy(container.children[0]);
885
- super.destroyContent(container);
886
- }
887
- renderContentAsync(container) {
888
- return __awaiter(this, void 0, void 0, function* () {
889
- const chartNode = DocumentHelper.createElement("div");
890
- container.innerHTML = "";
891
- container.appendChild(chartNode);
892
- yield this._chartAdapter.create(chartNode);
893
- return container;
894
- });
895
- }
896
- }
897
- GaugePlotly.displayModeBar = undefined;
898
- GaugePlotly.types = ["gauge", "bullet"];
899
- VisualizationManager.registerVisualizer("number", GaugePlotly);
900
- VisualizationManager.registerVisualizer("rating", GaugePlotly);
901
- VisualizationManager.registerVisualizer("expression", GaugePlotly);
678
+ VisualizerBase.chartAdapterType = PlotlyChartAdapter;
902
679
 
903
- export { BooleanModel, BooleanPlotly, DocumentHelper, GaugePlotly, HistogramModel, HistogramPlotly, Matrix, MatrixDropdownGroupedPlotly, MatrixPlotly, NumberModel, PlotlyBoolChartAdapter, PlotlyChartAdapter, PlotlyGaugeAdapter, PlotlySetup, RankingPlotly, SelectBase, SelectBasePlotly, VisualizationManager, defaultStatisticsCalculator, localization };
680
+ export { BooleanModel, BooleanPlotly, GaugePlotly, HistogramModel, HistogramPlotly, Matrix, MatrixDropdownGroupedPlotly, MatrixPlotly, NumberModel, PivotModel, PivotPlotly, PlotlyChartAdapter, PlotlySetup, RankingModel, RankingPlotly, SelectBase, SelectBasePlotly, VisualizationManager, VisualizerBase, defaultStatisticsCalculator, localization };
904
681
  //# sourceMappingURL=survey.analytics.mjs.map