survey-analytics 2.5.29 → 2.5.31
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/fesm/shared.mjs +211 -211
- package/fesm/shared.mjs.map +1 -1
- package/fesm/shared2.mjs +1160 -1160
- package/fesm/shared2.mjs.map +1 -1
- package/fesm/survey.analytics.core.mjs +1 -1
- package/fesm/survey.analytics.mjs +1 -1
- package/fesm/survey.analytics.mongo.mjs +1 -1
- package/fesm/survey.analytics.tabulator.mjs +1 -1
- package/package.json +2 -2
- package/survey-analytics.types/plotly/chart-adapter.d.ts +1 -0
- package/survey.analytics.core.css.map +1 -1
- package/survey.analytics.core.js +1 -1
- package/survey.analytics.core.min.js +1 -1
- package/survey.analytics.css.map +1 -1
- package/survey.analytics.d.ts +0 -1
- package/survey.analytics.js +1 -1
- package/survey.analytics.min.js +1 -1
- package/survey.analytics.mongo.js +1 -1
- package/survey.analytics.mongo.min.js +1 -1
- package/survey.analytics.tabulator.css.map +1 -1
- package/survey.analytics.tabulator.d.ts +0 -1
- package/survey.analytics.tabulator.js +1 -1
- package/survey.analytics.tabulator.min.js +1 -1
package/fesm/shared2.mjs
CHANGED
|
@@ -1,43 +1,11 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* surveyjs - SurveyJS Dashboard library v2.5.
|
|
2
|
+
* surveyjs - SurveyJS Dashboard library v2.5.31
|
|
3
3
|
* Copyright (c) 2015-2026 Devsoft Baltic OÜ - http://surveyjs.io/
|
|
4
4
|
* License: MIT (http://www.opensource.org/licenses/mit-license.php)
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { D as DocumentHelper, l as localization, g as createLoadingIndicator, b as DataHelper, e as createCommercialLicenseLink, f as svgTemplate, t as toPrecision } from './shared.mjs';
|
|
8
7
|
import { Event, QuestionCustomModel, QuestionCompositeModel, QuestionCommentModel, settings, hasLicense, ItemValue, QuestionRatingModel, surveyLocalization, IsTouch } from 'survey-core';
|
|
9
|
-
|
|
10
|
-
/******************************************************************************
|
|
11
|
-
Copyright (c) Microsoft Corporation.
|
|
12
|
-
|
|
13
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
14
|
-
purpose with or without fee is hereby granted.
|
|
15
|
-
|
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
17
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
18
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
19
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
20
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
21
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
22
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
23
|
-
***************************************************************************** */
|
|
24
|
-
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
28
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
29
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
30
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
31
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
32
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
33
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
38
|
-
var e = new Error(message);
|
|
39
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
40
|
-
};
|
|
8
|
+
import { D as DocumentHelper, l as localization, g as createLoadingIndicator, b as DataHelper, e as createCommercialLicenseLink, f as svgTemplate, t as toPrecision } from './shared.mjs';
|
|
41
9
|
|
|
42
10
|
class DataProvider {
|
|
43
11
|
constructor(_data = []) {
|
|
@@ -357,6 +325,38 @@ class VisualizerFactory {
|
|
|
357
325
|
}
|
|
358
326
|
}
|
|
359
327
|
|
|
328
|
+
/******************************************************************************
|
|
329
|
+
Copyright (c) Microsoft Corporation.
|
|
330
|
+
|
|
331
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
332
|
+
purpose with or without fee is hereby granted.
|
|
333
|
+
|
|
334
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
335
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
336
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
337
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
338
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
339
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
340
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
341
|
+
***************************************************************************** */
|
|
342
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
346
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
347
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
348
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
349
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
350
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
351
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
356
|
+
var e = new Error(message);
|
|
357
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
358
|
+
};
|
|
359
|
+
|
|
360
360
|
function defaultStatisticsCalculator(data, dataInfo) {
|
|
361
361
|
const dataNames = dataInfo.dataNames;
|
|
362
362
|
const statistics = [];
|
|
@@ -1277,113 +1277,6 @@ VisualizerBase.colors = [
|
|
|
1277
1277
|
];
|
|
1278
1278
|
VisualizationManager.defaultVisualizer = VisualizerBase;
|
|
1279
1279
|
|
|
1280
|
-
class NumberModel extends VisualizerBase {
|
|
1281
|
-
constructor(question, data, options = {}, name) {
|
|
1282
|
-
super(question, data, options, name || "number");
|
|
1283
|
-
if (VisualizerBase.chartAdapterType) {
|
|
1284
|
-
this._chartAdapter = new VisualizerBase.chartAdapterType(this);
|
|
1285
|
-
this.chartTypes = this._chartAdapter.getChartTypes();
|
|
1286
|
-
this.chartType = this.chartTypes[0];
|
|
1287
|
-
}
|
|
1288
|
-
if (this.options.allowChangeVisualizerType !== false) {
|
|
1289
|
-
this.registerToolbarItem("changeChartType", () => {
|
|
1290
|
-
if (this.chartTypes.length > 1) {
|
|
1291
|
-
return DocumentHelper.createSelector(this.chartTypes.map((chartType) => {
|
|
1292
|
-
return {
|
|
1293
|
-
value: chartType,
|
|
1294
|
-
text: localization.getString("chartType_" + chartType),
|
|
1295
|
-
};
|
|
1296
|
-
}), (option) => this.chartType === option.value, (e) => {
|
|
1297
|
-
this.setChartType(e.target.value);
|
|
1298
|
-
});
|
|
1299
|
-
}
|
|
1300
|
-
return null;
|
|
1301
|
-
});
|
|
1302
|
-
}
|
|
1303
|
-
}
|
|
1304
|
-
onDataChanged() {
|
|
1305
|
-
this._resultAverage = undefined;
|
|
1306
|
-
this._resultMin = undefined;
|
|
1307
|
-
this._resultMax = undefined;
|
|
1308
|
-
super.onDataChanged();
|
|
1309
|
-
}
|
|
1310
|
-
onChartTypeChanged() { }
|
|
1311
|
-
setChartType(chartType) {
|
|
1312
|
-
if (this.chartTypes.indexOf(chartType) !== -1 &&
|
|
1313
|
-
this.chartType !== chartType) {
|
|
1314
|
-
this.chartType = chartType;
|
|
1315
|
-
this.onChartTypeChanged();
|
|
1316
|
-
if (!!this.contentContainer) {
|
|
1317
|
-
this.destroyContent(this.contentContainer);
|
|
1318
|
-
this.renderContent(this.contentContainer);
|
|
1319
|
-
}
|
|
1320
|
-
this.invokeOnUpdate();
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
destroy() {
|
|
1324
|
-
this._resultAverage = undefined;
|
|
1325
|
-
this._resultMin = undefined;
|
|
1326
|
-
this._resultMax = undefined;
|
|
1327
|
-
super.destroy();
|
|
1328
|
-
}
|
|
1329
|
-
generateText(maxValue, minValue, stepsCount) {
|
|
1330
|
-
let texts = [];
|
|
1331
|
-
if (stepsCount === 5) {
|
|
1332
|
-
texts = [
|
|
1333
|
-
"very high (" + maxValue + ")",
|
|
1334
|
-
"high",
|
|
1335
|
-
"medium",
|
|
1336
|
-
"low",
|
|
1337
|
-
"very low (" + minValue + ")",
|
|
1338
|
-
];
|
|
1339
|
-
}
|
|
1340
|
-
else {
|
|
1341
|
-
texts.push(maxValue);
|
|
1342
|
-
for (let i = 0; i < stepsCount - 2; i++) {
|
|
1343
|
-
texts.push("");
|
|
1344
|
-
}
|
|
1345
|
-
texts.push(minValue);
|
|
1346
|
-
}
|
|
1347
|
-
if (!!NumberModel.generateTextsCallback) {
|
|
1348
|
-
return NumberModel.generateTextsCallback(this.question, maxValue, minValue, stepsCount, texts);
|
|
1349
|
-
}
|
|
1350
|
-
return texts;
|
|
1351
|
-
}
|
|
1352
|
-
generateValues(maxValue, stepsCount) {
|
|
1353
|
-
const values = [];
|
|
1354
|
-
for (let i = 0; i < stepsCount; i++) {
|
|
1355
|
-
values.push(maxValue / stepsCount);
|
|
1356
|
-
}
|
|
1357
|
-
values.push(maxValue);
|
|
1358
|
-
return values;
|
|
1359
|
-
}
|
|
1360
|
-
generateColors(maxValue, minValue, stepsCount) {
|
|
1361
|
-
const palette = this.getColors();
|
|
1362
|
-
const colors = [];
|
|
1363
|
-
for (let i = 0; i < stepsCount; i++) {
|
|
1364
|
-
colors.push(palette[i]);
|
|
1365
|
-
}
|
|
1366
|
-
colors.push("rgba(255, 255, 255, 0)");
|
|
1367
|
-
return colors;
|
|
1368
|
-
}
|
|
1369
|
-
convertFromExternalData(externalCalculatedData) {
|
|
1370
|
-
return [externalCalculatedData.value || 0, externalCalculatedData.minValue || 0, externalCalculatedData.maxValue || 0];
|
|
1371
|
-
}
|
|
1372
|
-
getCalculatedValuesCore() {
|
|
1373
|
-
if (this._resultAverage === undefined ||
|
|
1374
|
-
this._resultMin === undefined ||
|
|
1375
|
-
this._resultMax === undefined) {
|
|
1376
|
-
[this._resultAverage, this._resultMin, this._resultMax] = mathStatisticsCalculator(this.surveyData, this);
|
|
1377
|
-
}
|
|
1378
|
-
return [this._resultAverage, this._resultMin, this._resultMax];
|
|
1379
|
-
}
|
|
1380
|
-
}
|
|
1381
|
-
NumberModel.stepsCount = 5;
|
|
1382
|
-
NumberModel.showAsPercentage = false;
|
|
1383
|
-
VisualizationManager.registerVisualizer("number", NumberModel, 200);
|
|
1384
|
-
VisualizationManager.registerVisualizer("rating", NumberModel, 200);
|
|
1385
|
-
VisualizationManager.registerVisualizer("expression", NumberModel);
|
|
1386
|
-
|
|
1387
1280
|
class FilterInfo {
|
|
1388
1281
|
constructor(visualizer) {
|
|
1389
1282
|
this._htmlElement = undefined;
|
|
@@ -2087,6 +1980,88 @@ VisualizationManager.registerVisualizer("imagepicker", SelectBase);
|
|
|
2087
1980
|
VisualizationManager.registerVisualizer("tagbox", SelectBase);
|
|
2088
1981
|
VisualizationManager.registerVisualizer("rating", SelectBase, 100);
|
|
2089
1982
|
|
|
1983
|
+
class Matrix extends SelectBase {
|
|
1984
|
+
constructor(question, data, options, name) {
|
|
1985
|
+
super(question, data, options, name || "matrix");
|
|
1986
|
+
this._transposeData = true;
|
|
1987
|
+
// this.getAnswersData();
|
|
1988
|
+
}
|
|
1989
|
+
get matrixQuestion() {
|
|
1990
|
+
return this.question;
|
|
1991
|
+
}
|
|
1992
|
+
isSupportMissingAnswers() {
|
|
1993
|
+
return false;
|
|
1994
|
+
}
|
|
1995
|
+
getSeriesValues() {
|
|
1996
|
+
return this.matrixQuestion.rows.map((row) => "" + row.value);
|
|
1997
|
+
}
|
|
1998
|
+
getSeriesLabels() {
|
|
1999
|
+
return this.matrixQuestion.rows.map((row) => ItemValue.getTextOrHtmlByValue(this.matrixQuestion.rows, row.value));
|
|
2000
|
+
}
|
|
2001
|
+
getSelectedItemByText(itemText) {
|
|
2002
|
+
return this.matrixQuestion.columns.filter((column) => column.text === itemText)[0];
|
|
2003
|
+
}
|
|
2004
|
+
valuesSource() {
|
|
2005
|
+
return this.matrixQuestion.columns;
|
|
2006
|
+
}
|
|
2007
|
+
getHasAnswersInAllSeriesArray(datasets) {
|
|
2008
|
+
let result = Array();
|
|
2009
|
+
for (let i = 0; i < datasets[0].length; i++) {
|
|
2010
|
+
for (let j = 0; j < datasets.length; j++) {
|
|
2011
|
+
if (datasets[j][i] != 0) {
|
|
2012
|
+
result[i] = true;
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
return result;
|
|
2017
|
+
}
|
|
2018
|
+
getHasAnswersInSeries(dataset) {
|
|
2019
|
+
for (let i = 0; i < dataset.length; i++) {
|
|
2020
|
+
if (dataset[i] != 0) {
|
|
2021
|
+
return true;
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
return false;
|
|
2025
|
+
}
|
|
2026
|
+
hideEmptyAnswersInData(answersData) {
|
|
2027
|
+
const result = {
|
|
2028
|
+
datasets: [],
|
|
2029
|
+
labels: [],
|
|
2030
|
+
colors: [],
|
|
2031
|
+
texts: [],
|
|
2032
|
+
seriesLabels: [],
|
|
2033
|
+
};
|
|
2034
|
+
const hasAnswersInAllSeriesArr = this.getHasAnswersInAllSeriesArray(answersData.datasets);
|
|
2035
|
+
for (let i = 0; i < answersData.datasets.length; i++) {
|
|
2036
|
+
const hasAnswersInSeries = this.getHasAnswersInSeries(answersData.datasets[i]);
|
|
2037
|
+
if (hasAnswersInSeries) {
|
|
2038
|
+
result.labels.push(answersData.labels[i]);
|
|
2039
|
+
result.colors.push(answersData.colors[i]);
|
|
2040
|
+
}
|
|
2041
|
+
else {
|
|
2042
|
+
continue;
|
|
2043
|
+
}
|
|
2044
|
+
const datasets = [];
|
|
2045
|
+
const texts = [];
|
|
2046
|
+
for (let j = 0; j < answersData.datasets[0].length; j++) {
|
|
2047
|
+
if (hasAnswersInAllSeriesArr[j]) {
|
|
2048
|
+
datasets.push(answersData.datasets[i][j]);
|
|
2049
|
+
texts.push(answersData.texts[i][j]);
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
result.datasets.push(datasets);
|
|
2053
|
+
result.texts.push(texts);
|
|
2054
|
+
}
|
|
2055
|
+
for (let i = 0; i < answersData.datasets[0].length; i++) {
|
|
2056
|
+
if (hasAnswersInAllSeriesArr[i]) {
|
|
2057
|
+
result.seriesLabels.push(answersData.seriesLabels[i]);
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
return result;
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
VisualizationManager.registerVisualizer("matrix", Matrix);
|
|
2064
|
+
|
|
2090
2065
|
class BooleanModel extends SelectBase {
|
|
2091
2066
|
constructor(question, data, options, name) {
|
|
2092
2067
|
super(question, data, options, name || "boolean");
|
|
@@ -2720,707 +2695,283 @@ VisualizationManager.registerVisualizer("date", HistogramModel);
|
|
|
2720
2695
|
VisualizationManager.registerVisualizer("number", HistogramModel, 100);
|
|
2721
2696
|
VisualizationManager.registerVisualizer("rating", HistogramModel, 300);
|
|
2722
2697
|
|
|
2723
|
-
class
|
|
2724
|
-
constructor(question, data, options, name) {
|
|
2725
|
-
super(question, data, options, name || "
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2698
|
+
class NumberModel extends VisualizerBase {
|
|
2699
|
+
constructor(question, data, options = {}, name) {
|
|
2700
|
+
super(question, data, options, name || "number");
|
|
2701
|
+
if (VisualizerBase.chartAdapterType) {
|
|
2702
|
+
this._chartAdapter = new VisualizerBase.chartAdapterType(this);
|
|
2703
|
+
this.chartTypes = this._chartAdapter.getChartTypes();
|
|
2704
|
+
this.chartType = this.chartTypes[0];
|
|
2705
|
+
}
|
|
2706
|
+
if (this.options.allowChangeVisualizerType !== false) {
|
|
2707
|
+
this.registerToolbarItem("changeChartType", () => {
|
|
2708
|
+
if (this.chartTypes.length > 1) {
|
|
2709
|
+
return DocumentHelper.createSelector(this.chartTypes.map((chartType) => {
|
|
2710
|
+
return {
|
|
2711
|
+
value: chartType,
|
|
2712
|
+
text: localization.getString("chartType_" + chartType),
|
|
2713
|
+
};
|
|
2714
|
+
}), (option) => this.chartType === option.value, (e) => {
|
|
2715
|
+
this.setChartType(e.target.value);
|
|
2716
|
+
});
|
|
2717
|
+
}
|
|
2718
|
+
return null;
|
|
2719
|
+
});
|
|
2720
|
+
}
|
|
2737
2721
|
}
|
|
2738
|
-
|
|
2739
|
-
|
|
2722
|
+
onDataChanged() {
|
|
2723
|
+
this._resultAverage = undefined;
|
|
2724
|
+
this._resultMin = undefined;
|
|
2725
|
+
this._resultMax = undefined;
|
|
2726
|
+
super.onDataChanged();
|
|
2740
2727
|
}
|
|
2741
|
-
|
|
2742
|
-
|
|
2728
|
+
onChartTypeChanged() { }
|
|
2729
|
+
setChartType(chartType) {
|
|
2730
|
+
if (this.chartTypes.indexOf(chartType) !== -1 &&
|
|
2731
|
+
this.chartType !== chartType) {
|
|
2732
|
+
this.chartType = chartType;
|
|
2733
|
+
this.onChartTypeChanged();
|
|
2734
|
+
if (!!this.contentContainer) {
|
|
2735
|
+
this.destroyContent(this.contentContainer);
|
|
2736
|
+
this.renderContent(this.contentContainer);
|
|
2737
|
+
}
|
|
2738
|
+
this.invokeOnUpdate();
|
|
2739
|
+
}
|
|
2743
2740
|
}
|
|
2744
|
-
|
|
2745
|
-
|
|
2741
|
+
destroy() {
|
|
2742
|
+
this._resultAverage = undefined;
|
|
2743
|
+
this._resultMin = undefined;
|
|
2744
|
+
this._resultMax = undefined;
|
|
2745
|
+
super.destroy();
|
|
2746
2746
|
}
|
|
2747
|
-
|
|
2748
|
-
let
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2747
|
+
generateText(maxValue, minValue, stepsCount) {
|
|
2748
|
+
let texts = [];
|
|
2749
|
+
if (stepsCount === 5) {
|
|
2750
|
+
texts = [
|
|
2751
|
+
"very high (" + maxValue + ")",
|
|
2752
|
+
"high",
|
|
2753
|
+
"medium",
|
|
2754
|
+
"low",
|
|
2755
|
+
"very low (" + minValue + ")",
|
|
2756
|
+
];
|
|
2757
|
+
}
|
|
2758
|
+
else {
|
|
2759
|
+
texts.push(maxValue);
|
|
2760
|
+
for (let i = 0; i < stepsCount - 2; i++) {
|
|
2761
|
+
texts.push("");
|
|
2754
2762
|
}
|
|
2763
|
+
texts.push(minValue);
|
|
2755
2764
|
}
|
|
2756
|
-
|
|
2765
|
+
if (!!NumberModel.generateTextsCallback) {
|
|
2766
|
+
return NumberModel.generateTextsCallback(this.question, maxValue, minValue, stepsCount, texts);
|
|
2767
|
+
}
|
|
2768
|
+
return texts;
|
|
2757
2769
|
}
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
}
|
|
2770
|
+
generateValues(maxValue, stepsCount) {
|
|
2771
|
+
const values = [];
|
|
2772
|
+
for (let i = 0; i < stepsCount; i++) {
|
|
2773
|
+
values.push(maxValue / stepsCount);
|
|
2763
2774
|
}
|
|
2764
|
-
|
|
2775
|
+
values.push(maxValue);
|
|
2776
|
+
return values;
|
|
2765
2777
|
}
|
|
2766
|
-
|
|
2767
|
-
const
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
colors
|
|
2771
|
-
texts: [],
|
|
2772
|
-
seriesLabels: [],
|
|
2773
|
-
};
|
|
2774
|
-
const hasAnswersInAllSeriesArr = this.getHasAnswersInAllSeriesArray(answersData.datasets);
|
|
2775
|
-
for (let i = 0; i < answersData.datasets.length; i++) {
|
|
2776
|
-
const hasAnswersInSeries = this.getHasAnswersInSeries(answersData.datasets[i]);
|
|
2777
|
-
if (hasAnswersInSeries) {
|
|
2778
|
-
result.labels.push(answersData.labels[i]);
|
|
2779
|
-
result.colors.push(answersData.colors[i]);
|
|
2780
|
-
}
|
|
2781
|
-
else {
|
|
2782
|
-
continue;
|
|
2783
|
-
}
|
|
2784
|
-
const datasets = [];
|
|
2785
|
-
const texts = [];
|
|
2786
|
-
for (let j = 0; j < answersData.datasets[0].length; j++) {
|
|
2787
|
-
if (hasAnswersInAllSeriesArr[j]) {
|
|
2788
|
-
datasets.push(answersData.datasets[i][j]);
|
|
2789
|
-
texts.push(answersData.texts[i][j]);
|
|
2790
|
-
}
|
|
2791
|
-
}
|
|
2792
|
-
result.datasets.push(datasets);
|
|
2793
|
-
result.texts.push(texts);
|
|
2778
|
+
generateColors(maxValue, minValue, stepsCount) {
|
|
2779
|
+
const palette = this.getColors();
|
|
2780
|
+
const colors = [];
|
|
2781
|
+
for (let i = 0; i < stepsCount; i++) {
|
|
2782
|
+
colors.push(palette[i]);
|
|
2794
2783
|
}
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2784
|
+
colors.push("rgba(255, 255, 255, 0)");
|
|
2785
|
+
return colors;
|
|
2786
|
+
}
|
|
2787
|
+
convertFromExternalData(externalCalculatedData) {
|
|
2788
|
+
return [externalCalculatedData.value || 0, externalCalculatedData.minValue || 0, externalCalculatedData.maxValue || 0];
|
|
2789
|
+
}
|
|
2790
|
+
getCalculatedValuesCore() {
|
|
2791
|
+
if (this._resultAverage === undefined ||
|
|
2792
|
+
this._resultMin === undefined ||
|
|
2793
|
+
this._resultMax === undefined) {
|
|
2794
|
+
[this._resultAverage, this._resultMin, this._resultMax] = mathStatisticsCalculator(this.surveyData, this);
|
|
2799
2795
|
}
|
|
2800
|
-
return
|
|
2796
|
+
return [this._resultAverage, this._resultMin, this._resultMax];
|
|
2801
2797
|
}
|
|
2802
2798
|
}
|
|
2803
|
-
|
|
2799
|
+
NumberModel.stepsCount = 5;
|
|
2800
|
+
NumberModel.showAsPercentage = false;
|
|
2801
|
+
VisualizationManager.registerVisualizer("number", NumberModel, 200);
|
|
2802
|
+
VisualizationManager.registerVisualizer("rating", NumberModel, 200);
|
|
2803
|
+
VisualizationManager.registerVisualizer("expression", NumberModel);
|
|
2804
2804
|
|
|
2805
|
-
class
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
this.isRoot = isRoot;
|
|
2810
|
-
this.valueType = "enum";
|
|
2811
|
-
this._cachedValues = undefined;
|
|
2812
|
-
this._continuousData = undefined;
|
|
2813
|
-
this._cachedIntervals = undefined;
|
|
2814
|
-
this._intervalPrecision = 2;
|
|
2815
|
-
this.axisYSelectors = [];
|
|
2816
|
-
this.axisYQuestionNames = [];
|
|
2817
|
-
this.questionsY = [];
|
|
2818
|
-
this.questions = this.questions.filter((question) => ["matrixdropdown", "matrixdynamic", "matrix", "file", "signature", "multipletext", "comment", "html", "image"].indexOf(question.getType()) === -1);
|
|
2819
|
-
if (this.options.intervalPrecision !== undefined) {
|
|
2820
|
-
this._intervalPrecision = this.options.intervalPrecision;
|
|
2805
|
+
class AlternativeVisualizersWrapper extends VisualizerBase {
|
|
2806
|
+
updateVisualizerSelector() {
|
|
2807
|
+
if (!!this.visualizerSelector) {
|
|
2808
|
+
this.visualizerSelector.getElementsByTagName("select")[0].value = this.visualizer.type;
|
|
2821
2809
|
}
|
|
2822
|
-
this.axisXQuestionName = this.questions.length > 0 ? this.questions[0].name : undefined;
|
|
2823
|
-
this.registerToolbarItem("axisXSelector", () => this.axisXSelector = DocumentHelper.createSelector(this.questions.map((question) => {
|
|
2824
|
-
return {
|
|
2825
|
-
value: question.name,
|
|
2826
|
-
text: question.title || question.name,
|
|
2827
|
-
};
|
|
2828
|
-
}), (option) => this.axisXQuestionName === option.value, (e) => {
|
|
2829
|
-
this.axisXQuestionName = e.target.value;
|
|
2830
|
-
this.updateQuestionsSelection();
|
|
2831
|
-
this.updateToolbar();
|
|
2832
|
-
this.setupPivot();
|
|
2833
|
-
}, () => this.isXYChart() ? localization.getString("axisXSelectorTitle") : localization.getString("axisXAlternativeSelectorTitle")));
|
|
2834
|
-
this.registerToolbarItem("axisYSelector0", this.createYSelecterGenerator());
|
|
2835
|
-
this.setupPivot();
|
|
2836
2810
|
}
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
this.axisYSelectors.push(selector);
|
|
2844
|
-
}
|
|
2845
|
-
else {
|
|
2846
|
-
selector["__updateSelect"] && selector["__updateSelect"]();
|
|
2847
|
-
}
|
|
2848
|
-
return selector;
|
|
2811
|
+
constructor(visualizers, question, data, options) {
|
|
2812
|
+
super(question, data, options, "alternative");
|
|
2813
|
+
this.visualizers = visualizers;
|
|
2814
|
+
this.visualizersWithSelection = [];
|
|
2815
|
+
this.onAfterVisualizerRenderCallback = () => {
|
|
2816
|
+
this.afterRender(this.contentContainer);
|
|
2849
2817
|
};
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2818
|
+
this.onVisualizerStateChangedCallback = (s, options) => {
|
|
2819
|
+
this.stateChanged("visualizer", options);
|
|
2820
|
+
};
|
|
2821
|
+
/**
|
|
2822
|
+
* The event is fired right after AlternativeVisualizersWrapper content type has been changed.
|
|
2823
|
+
**/
|
|
2824
|
+
this.onVisualizerChanged = new Event();
|
|
2825
|
+
this.showToolbar = false;
|
|
2826
|
+
this.loadingData = false;
|
|
2827
|
+
if (!visualizers || visualizers.length < 2) {
|
|
2828
|
+
throw new Error("VisualizerArrayWrapper works with visualizers collection only.");
|
|
2854
2829
|
}
|
|
2855
|
-
this.
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
if (index < this.axisYSelectors.length - 1) {
|
|
2862
|
-
if (!value) {
|
|
2863
|
-
for (let i = index + 1; i < this.axisYSelectors.length; ++i) {
|
|
2864
|
-
this.unregisterToolbarItem("axisYSelector" + i);
|
|
2865
|
-
}
|
|
2866
|
-
this.axisYSelectors = this.axisYSelectors.slice(0, index + 1);
|
|
2867
|
-
this.axisYQuestionNames = this.axisYQuestionNames.slice(0, index + 1);
|
|
2830
|
+
this.visualizers.forEach((visualizer) => {
|
|
2831
|
+
visualizer.onUpdate = () => this.invokeOnUpdate();
|
|
2832
|
+
visualizer.onGetToolbarItemCreators = () => this.toolbarItemCreators;
|
|
2833
|
+
if (visualizer.supportSelection) {
|
|
2834
|
+
this._supportSelection = true;
|
|
2835
|
+
this.visualizersWithSelection.push(visualizer);
|
|
2868
2836
|
}
|
|
2837
|
+
});
|
|
2838
|
+
if (this.options.allowChangeVisualizerType !== false) {
|
|
2839
|
+
this.registerToolbarItem("changeVisualizer", () => this.visualizerSelector = DocumentHelper.createSelector(this.visualizers.map((visualizer) => {
|
|
2840
|
+
return {
|
|
2841
|
+
value: visualizer.type,
|
|
2842
|
+
text: localization.getString("visualizer_" + visualizer.type),
|
|
2843
|
+
};
|
|
2844
|
+
}), (option) => this.visualizer.type === option.value, (e) => this.setVisualizer(e.target.value)), 0);
|
|
2869
2845
|
}
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
}
|
|
2874
|
-
}
|
|
2875
|
-
this.updateQuestionsSelection();
|
|
2876
|
-
this.updateToolbar();
|
|
2877
|
-
this.setupPivot();
|
|
2846
|
+
this.visualizer = visualizers[0];
|
|
2847
|
+
this.visualizer.onAfterRender.add(this.onAfterVisualizerRenderCallback);
|
|
2848
|
+
this.visualizer.onStateChanged.add(this.onVisualizerStateChangedCallback);
|
|
2878
2849
|
}
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2850
|
+
get hasFooter() {
|
|
2851
|
+
return false;
|
|
2852
|
+
}
|
|
2853
|
+
getVisualizers() {
|
|
2854
|
+
return this.visualizers;
|
|
2855
|
+
}
|
|
2856
|
+
/**
|
|
2857
|
+
* This method selects visualizer to show by it name.
|
|
2858
|
+
*
|
|
2859
|
+
* parameters:
|
|
2860
|
+
* name - the name of visualizer to show,
|
|
2861
|
+
* quiet - set it to true if you don't want to rise a notification event
|
|
2862
|
+
*
|
|
2863
|
+
**/
|
|
2864
|
+
setVisualizer(type, quiet = false) {
|
|
2865
|
+
const visualizerCandidate = this.visualizers.filter((v) => v.type === type)[0];
|
|
2866
|
+
if (!!visualizerCandidate && visualizerCandidate !== this.visualizer) {
|
|
2867
|
+
let isFooterCollapsed;
|
|
2868
|
+
if (!!this.visualizer) {
|
|
2869
|
+
isFooterCollapsed = this.visualizer.isFooterCollapsed;
|
|
2870
|
+
this.visualizer.onStateChanged.remove(this.onVisualizerStateChangedCallback);
|
|
2871
|
+
this.visualizer.onAfterRender.remove(this.onAfterVisualizerRenderCallback);
|
|
2872
|
+
this.visualizer.destroy();
|
|
2886
2873
|
}
|
|
2887
|
-
|
|
2888
|
-
|
|
2874
|
+
this.visualizer = visualizerCandidate;
|
|
2875
|
+
this.visualizer.isFooterCollapsed = isFooterCollapsed;
|
|
2876
|
+
this.refresh();
|
|
2877
|
+
this.visualizer.onAfterRender.add(this.onAfterVisualizerRenderCallback);
|
|
2878
|
+
this.visualizer.onStateChanged.add(this.onVisualizerStateChangedCallback);
|
|
2879
|
+
if (!quiet) {
|
|
2880
|
+
this.onVisualizerChanged.fire(this, { visualizer: this.visualizer });
|
|
2881
|
+
this.stateChanged("visualizer", type);
|
|
2889
2882
|
}
|
|
2883
|
+
this.updateVisualizerSelector();
|
|
2890
2884
|
}
|
|
2891
2885
|
}
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
const choices = this.questions.filter(q => {
|
|
2895
|
-
if (q.name === this.axisXQuestionName) {
|
|
2896
|
-
return false;
|
|
2897
|
-
}
|
|
2898
|
-
const usedIndex = this.axisYQuestionNames.indexOf(q.name);
|
|
2899
|
-
return usedIndex == -1 || usedIndex >= selectorIndex;
|
|
2900
|
-
}).map((question) => {
|
|
2901
|
-
return {
|
|
2902
|
-
value: question.name,
|
|
2903
|
-
text: question.title || question.name,
|
|
2904
|
-
};
|
|
2905
|
-
});
|
|
2906
|
-
return [{ value: "", text: localization.getString("notSelected") }].concat(choices);
|
|
2907
|
-
};
|
|
2908
|
-
if (getChoices().length == 1) {
|
|
2909
|
-
return undefined;
|
|
2910
|
-
}
|
|
2911
|
-
const selector = DocumentHelper.createSelector(getChoices, (option) => this.axisYQuestionNames[selectorIndex] === option.value, (e) => { this.onAxisYSelectorChanged(selectorIndex, e.target.value); }, () => selectorIndex ? undefined : (this.isXYChart() ? localization.getString("axisYSelectorTitle") : localization.getString("axisYAlternativeSelectorTitle")));
|
|
2912
|
-
return selector;
|
|
2886
|
+
getVisualizer() {
|
|
2887
|
+
return this.visualizer;
|
|
2913
2888
|
}
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
}
|
|
2889
|
+
updateData(data) {
|
|
2890
|
+
super.updateData(data);
|
|
2891
|
+
this.visualizers.forEach((visualizer) => {
|
|
2892
|
+
visualizer.updateData(data);
|
|
2893
|
+
});
|
|
2920
2894
|
}
|
|
2921
|
-
|
|
2922
|
-
|
|
2895
|
+
set onDataItemSelected(val) {
|
|
2896
|
+
this.visualizersWithSelection.forEach((visualizer) => {
|
|
2897
|
+
visualizer.onDataItemSelected = val;
|
|
2898
|
+
});
|
|
2923
2899
|
}
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
}
|
|
2929
|
-
else if (questionType === "text" || questionType === "rating" || questionType === "expression" || questionType === "range") {
|
|
2930
|
-
return "number";
|
|
2931
|
-
}
|
|
2932
|
-
return "enum";
|
|
2900
|
+
setSelection(item) {
|
|
2901
|
+
this.visualizersWithSelection.forEach((visualizer) => {
|
|
2902
|
+
visualizer.setSelection(item);
|
|
2903
|
+
});
|
|
2933
2904
|
}
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
if (!questionX) {
|
|
2937
|
-
return;
|
|
2938
|
-
}
|
|
2939
|
-
this.question = questionX;
|
|
2940
|
-
this.valueType = this.getQuestionValueType(questionX);
|
|
2941
|
-
this.questionsY = this.axisYQuestionNames.map((name) => {
|
|
2942
|
-
const questionY = this.questions.filter((q) => q.name === name)[0];
|
|
2943
|
-
if (!!questionY) {
|
|
2944
|
-
return this.getQuestionValueType(questionY) === "enum" ? new SelectBase(questionY, []) : new VisualizerBase(questionY, []);
|
|
2945
|
-
}
|
|
2946
|
-
}).filter((q) => !!q);
|
|
2947
|
-
this.onDataChanged();
|
|
2905
|
+
get selection() {
|
|
2906
|
+
return this.visualizer.selection || this.selectedItem;
|
|
2948
2907
|
}
|
|
2949
|
-
|
|
2950
|
-
this.
|
|
2951
|
-
this.
|
|
2952
|
-
this._cachedIntervals = undefined;
|
|
2908
|
+
renderContent(container) {
|
|
2909
|
+
this.visualizerContainer = container;
|
|
2910
|
+
this.visualizer.render(this.visualizerContainer);
|
|
2953
2911
|
}
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
}
|
|
2958
|
-
return parseFloat(value);
|
|
2912
|
+
setBackgroundColorCore(color) {
|
|
2913
|
+
super.setBackgroundColorCore(color);
|
|
2914
|
+
this.visualizers.forEach(visualizer => visualizer.backgroundColor = color);
|
|
2959
2915
|
}
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2916
|
+
/**
|
|
2917
|
+
* Returns an object with properties that describe a current visualizer state. The properties are different for each individual visualizer.
|
|
2918
|
+
*
|
|
2919
|
+
* > This method is overriden in descendant classes.
|
|
2920
|
+
* @see setState
|
|
2921
|
+
* @see resetState
|
|
2922
|
+
*/
|
|
2923
|
+
getState() {
|
|
2924
|
+
const currentVisualizerState = this.visualizer.getState();
|
|
2925
|
+
const state = {
|
|
2926
|
+
visualizer: this.visualizer.type,
|
|
2927
|
+
};
|
|
2928
|
+
if (Object.keys(currentVisualizerState).length > 0) {
|
|
2929
|
+
state.state = currentVisualizerState;
|
|
2963
2930
|
}
|
|
2964
|
-
return
|
|
2965
|
-
}
|
|
2966
|
-
toPrecision(value) {
|
|
2967
|
-
const base = Math.pow(10, this._intervalPrecision);
|
|
2968
|
-
return Math.round(base * value) / base;
|
|
2931
|
+
return state;
|
|
2969
2932
|
}
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2933
|
+
/**
|
|
2934
|
+
* Sets the visualizer's state.
|
|
2935
|
+
*
|
|
2936
|
+
* @see getState
|
|
2937
|
+
* @see resetState
|
|
2938
|
+
*/
|
|
2939
|
+
setState(state) {
|
|
2940
|
+
if (!!state.visualizer) {
|
|
2941
|
+
this.setVisualizer(state.visualizer, true);
|
|
2942
|
+
}
|
|
2943
|
+
if (!!state.state) {
|
|
2944
|
+
this.visualizer.setState(state.state);
|
|
2974
2945
|
}
|
|
2975
|
-
const labels = this.getLabels();
|
|
2976
|
-
const labelIndex = labels.indexOf(itemText);
|
|
2977
|
-
return new ItemValue(this.getValues()[labelIndex], labels[labelIndex]);
|
|
2978
2946
|
}
|
|
2979
2947
|
/**
|
|
2980
|
-
*
|
|
2948
|
+
* Resets the visualizer's state.
|
|
2949
|
+
*
|
|
2950
|
+
* @see getState
|
|
2951
|
+
* @see setState
|
|
2981
2952
|
*/
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
onDataChanged() {
|
|
2987
|
-
this.reset();
|
|
2988
|
-
super.onDataChanged();
|
|
2989
|
-
}
|
|
2990
|
-
getContinuousValues() {
|
|
2991
|
-
if (this._cachedValues === undefined) {
|
|
2992
|
-
this._continuousData = [];
|
|
2993
|
-
if (this.valueType === "enum") {
|
|
2994
|
-
this._cachedValues = [];
|
|
2995
|
-
return this._cachedValues;
|
|
2996
|
-
}
|
|
2997
|
-
const hash = {};
|
|
2998
|
-
this.data.forEach(dataItem => {
|
|
2999
|
-
const answerData = dataItem[this.name];
|
|
3000
|
-
if (answerData !== undefined) {
|
|
3001
|
-
// TODO: _continuousData should be sorted in order to speed-up statistics calculation in the getData function
|
|
3002
|
-
this._continuousData.push({ continuous: this.getContinuousValue(answerData), row: dataItem });
|
|
3003
|
-
hash[answerData] = { value: answerData, row: dataItem };
|
|
3004
|
-
}
|
|
3005
|
-
});
|
|
3006
|
-
this._cachedValues = Object.keys(hash).map(key => ({ original: hash[key].value, continuous: this.getContinuousValue(key), row: hash[key].row }));
|
|
3007
|
-
this._cachedValues.sort((a, b) => a.continuous - b.continuous);
|
|
3008
|
-
}
|
|
3009
|
-
return this._cachedValues;
|
|
2953
|
+
resetState() {
|
|
2954
|
+
super.resetState();
|
|
2955
|
+
this.visualizers.forEach(visualizer => visualizer.resetState());
|
|
2956
|
+
this.setVisualizer(this.visualizers[0].type, true);
|
|
3010
2957
|
}
|
|
3011
|
-
|
|
3012
|
-
return
|
|
2958
|
+
getValues() {
|
|
2959
|
+
return this.visualizer.getValues();
|
|
3013
2960
|
}
|
|
3014
|
-
|
|
3015
|
-
return
|
|
2961
|
+
getLabels() {
|
|
2962
|
+
return this.visualizer.getLabels();
|
|
3016
2963
|
}
|
|
3017
|
-
|
|
3018
|
-
return this.
|
|
2964
|
+
getCalculatedValues() {
|
|
2965
|
+
return this.visualizer.getCalculatedValues();
|
|
3019
2966
|
}
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
this.questionsY.forEach(q => {
|
|
3026
|
-
if (this.getQuestionValueType(q.question) === "enum") {
|
|
3027
|
-
seriesValues.push.apply(seriesValues, q.getValues().reverse());
|
|
3028
|
-
}
|
|
3029
|
-
else {
|
|
3030
|
-
seriesValues.push(q.question.name);
|
|
3031
|
-
}
|
|
2967
|
+
destroy() {
|
|
2968
|
+
this.visualizers.forEach((visualizer) => {
|
|
2969
|
+
visualizer.onAfterRender.remove(this.onAfterVisualizerRenderCallback);
|
|
2970
|
+
visualizer.onStateChanged.remove(this.onVisualizerStateChangedCallback);
|
|
2971
|
+
visualizer.onUpdate = undefined;
|
|
3032
2972
|
});
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
getSeriesLabels() {
|
|
3036
|
-
if (this.questionsY.length === 0) {
|
|
3037
|
-
return this.getSeriesValues();
|
|
3038
|
-
}
|
|
3039
|
-
const seriesLabels = [];
|
|
3040
|
-
this.questionsY.forEach(q => {
|
|
3041
|
-
if (this.getQuestionValueType(q.question) === "enum") {
|
|
3042
|
-
seriesLabels.push.apply(seriesLabels, q.getLabels().reverse());
|
|
3043
|
-
}
|
|
3044
|
-
else {
|
|
3045
|
-
seriesLabels.push(q.question.title || q.question.name);
|
|
3046
|
-
}
|
|
3047
|
-
});
|
|
3048
|
-
return seriesLabels;
|
|
3049
|
-
}
|
|
3050
|
-
getValues() {
|
|
3051
|
-
if (this.valueType === "enum") {
|
|
3052
|
-
return super.getValues().reverse();
|
|
3053
|
-
}
|
|
3054
|
-
return this.intervals.map(interval => interval.start);
|
|
3055
|
-
}
|
|
3056
|
-
getLabels() {
|
|
3057
|
-
if (this.valueType === "enum") {
|
|
3058
|
-
return super.getLabels().reverse();
|
|
3059
|
-
}
|
|
3060
|
-
return this.intervals.map(interval => interval.label);
|
|
3061
|
-
}
|
|
3062
|
-
get hasCustomIntervals() {
|
|
3063
|
-
return !!this.questionOptions && Array.isArray(this.questionOptions.intervals);
|
|
3064
|
-
}
|
|
3065
|
-
get intervals() {
|
|
3066
|
-
if (this.hasCustomIntervals) {
|
|
3067
|
-
return this.questionOptions.intervals;
|
|
3068
|
-
}
|
|
3069
|
-
if (this.question.getType() == "rating") {
|
|
3070
|
-
if (this.needUseRateValues) {
|
|
3071
|
-
const rateValues = this.question["rateValues"];
|
|
3072
|
-
rateValues.sort((iv1, iv2) => iv1.value - iv2.value);
|
|
3073
|
-
return rateValues.map((rateValue, i) => ({
|
|
3074
|
-
start: rateValue.value,
|
|
3075
|
-
end: i < rateValues.length - 1 ? rateValues[i + 1].value : rateValue.value + 1,
|
|
3076
|
-
label: rateValue.text
|
|
3077
|
-
}));
|
|
3078
|
-
}
|
|
3079
|
-
else {
|
|
3080
|
-
const rateIntervals = [];
|
|
3081
|
-
for (let i = (this.question["rateMin"] || 0); i <= (this.question["rateMax"] || (PivotModel.IntervalsCount - 1)); i += (this.question["rateStep"] || 1)) {
|
|
3082
|
-
rateIntervals.push({
|
|
3083
|
-
start: i,
|
|
3084
|
-
end: i + 1,
|
|
3085
|
-
label: "" + (!!this.question["rateMin"] && !!this.question["rateMax"] ? i : (i + "-" + (i + 1)))
|
|
3086
|
-
});
|
|
3087
|
-
}
|
|
3088
|
-
return rateIntervals;
|
|
3089
|
-
}
|
|
3090
|
-
}
|
|
3091
|
-
if (this._cachedIntervals === undefined) {
|
|
3092
|
-
const continuousValues = this.getContinuousValues();
|
|
3093
|
-
this._cachedIntervals = [];
|
|
3094
|
-
if (continuousValues.length) {
|
|
3095
|
-
let start = continuousValues[0].continuous;
|
|
3096
|
-
const end = continuousValues[continuousValues.length - 1].continuous;
|
|
3097
|
-
const intervalsCount = PivotModel.IntervalsCount;
|
|
3098
|
-
const delta = (end - start) / intervalsCount;
|
|
3099
|
-
for (let i = 0; i < intervalsCount; ++i) {
|
|
3100
|
-
const next = start + delta;
|
|
3101
|
-
const istart = this.toPrecision(start);
|
|
3102
|
-
const inext = this.toPrecision(next);
|
|
3103
|
-
this._cachedIntervals.push({
|
|
3104
|
-
start: istart,
|
|
3105
|
-
end: i < intervalsCount - 1 ? inext : inext + delta / 100,
|
|
3106
|
-
label: "" + this.getString(istart) + "-" + this.getString(inext)
|
|
3107
|
-
});
|
|
3108
|
-
start = next;
|
|
3109
|
-
}
|
|
3110
|
-
}
|
|
3111
|
-
}
|
|
3112
|
-
return this._cachedIntervals;
|
|
3113
|
-
}
|
|
3114
|
-
convertFromExternalData(externalCalculatedData) {
|
|
3115
|
-
return [externalCalculatedData];
|
|
3116
|
-
}
|
|
3117
|
-
getSeriesValueIndexes() {
|
|
3118
|
-
const seriesValueIndexes = {};
|
|
3119
|
-
let valueIndex = 0;
|
|
3120
|
-
for (var i = 0; i < this.questionsY.length; ++i) {
|
|
3121
|
-
const questionValueType = this.getQuestionValueType(this.questionsY[i].question);
|
|
3122
|
-
if (questionValueType === "enum") {
|
|
3123
|
-
this.questionsY[i].getValues().reverse().forEach((value) => {
|
|
3124
|
-
seriesValueIndexes[this.questionsY[i].name + "_" + value] = valueIndex++;
|
|
3125
|
-
});
|
|
3126
|
-
}
|
|
3127
|
-
else {
|
|
3128
|
-
seriesValueIndexes[this.questionsY[i].name] = valueIndex++;
|
|
3129
|
-
}
|
|
3130
|
-
}
|
|
3131
|
-
return seriesValueIndexes;
|
|
3132
|
-
}
|
|
3133
|
-
updateStatisticsSeriesValue(statistics, dataRow, valueIndex, seriesValueIndexes) {
|
|
3134
|
-
for (let j = 0; j < this.questionsY.length; ++j) {
|
|
3135
|
-
if (dataRow[this.questionsY[j].name] !== undefined) {
|
|
3136
|
-
const questionValueType = this.getQuestionValueType(this.questionsY[j].question);
|
|
3137
|
-
if (questionValueType === "enum" || questionValueType === "date") {
|
|
3138
|
-
const seriesValueIndex = seriesValueIndexes[this.questionsY[j].name + "_" + dataRow[this.questionsY[j].name]];
|
|
3139
|
-
statistics[seriesValueIndex][valueIndex]++;
|
|
3140
|
-
}
|
|
3141
|
-
else {
|
|
3142
|
-
const seriesValueIndex = seriesValueIndexes[this.questionsY[j].name];
|
|
3143
|
-
statistics[seriesValueIndex][valueIndex] += parseFloat(dataRow[this.questionsY[j].name]);
|
|
3144
|
-
}
|
|
3145
|
-
}
|
|
3146
|
-
}
|
|
3147
|
-
}
|
|
3148
|
-
getCalculatedValuesCore() {
|
|
3149
|
-
const statistics = [];
|
|
3150
|
-
const series = this.getSeriesValues();
|
|
3151
|
-
if (series.length === 0) {
|
|
3152
|
-
series.push("");
|
|
3153
|
-
}
|
|
3154
|
-
const seriesValueIndexes = this.getSeriesValueIndexes();
|
|
3155
|
-
if (this.valueType === "enum") {
|
|
3156
|
-
const values = this.getValues();
|
|
3157
|
-
const valueIndexes = {};
|
|
3158
|
-
values.forEach((value, index) => {
|
|
3159
|
-
valueIndexes[value] = index;
|
|
3160
|
-
});
|
|
3161
|
-
for (var i = 0; i < series.length; ++i) {
|
|
3162
|
-
statistics.push(values.map(i => 0));
|
|
3163
|
-
}
|
|
3164
|
-
this.data.forEach(dataRow => {
|
|
3165
|
-
const answerData = dataRow[this.name];
|
|
3166
|
-
if (answerData !== undefined && valueIndexes[answerData] !== undefined) {
|
|
3167
|
-
const valueIndex = valueIndexes[answerData];
|
|
3168
|
-
if (this.questionsY.length === 0) {
|
|
3169
|
-
statistics[0][valueIndex]++;
|
|
3170
|
-
}
|
|
3171
|
-
else {
|
|
3172
|
-
this.updateStatisticsSeriesValue(statistics, dataRow, valueIndex, seriesValueIndexes);
|
|
3173
|
-
}
|
|
3174
|
-
}
|
|
3175
|
-
});
|
|
3176
|
-
}
|
|
3177
|
-
else {
|
|
3178
|
-
this.getContinuousValues();
|
|
3179
|
-
const intervals = this.intervals;
|
|
3180
|
-
for (var i = 0; i < series.length; ++i) {
|
|
3181
|
-
statistics.push(intervals.map(i => 0));
|
|
3182
|
-
}
|
|
3183
|
-
this._continuousData.forEach(dataValue => {
|
|
3184
|
-
for (let valueIndex = 0; valueIndex < intervals.length; ++valueIndex) {
|
|
3185
|
-
if (intervals[valueIndex].start <= dataValue.continuous && (dataValue.continuous < intervals[valueIndex].end || valueIndex == intervals.length - 1)) {
|
|
3186
|
-
if (this.questionsY.length === 0) {
|
|
3187
|
-
statistics[0][valueIndex]++;
|
|
3188
|
-
}
|
|
3189
|
-
else {
|
|
3190
|
-
this.updateStatisticsSeriesValue(statistics, dataValue.row, valueIndex, seriesValueIndexes);
|
|
3191
|
-
}
|
|
3192
|
-
break;
|
|
3193
|
-
}
|
|
3194
|
-
}
|
|
3195
|
-
});
|
|
3196
|
-
}
|
|
3197
|
-
return statistics;
|
|
3198
|
-
}
|
|
3199
|
-
getValueType() {
|
|
3200
|
-
return this.valueType;
|
|
3201
|
-
}
|
|
3202
|
-
isSupportSoftUpdateContent() {
|
|
3203
|
-
return false;
|
|
3204
|
-
}
|
|
3205
|
-
renderToolbar(container) {
|
|
3206
|
-
if (!this.haveCommercialLicense && this.isRoot) {
|
|
3207
|
-
const banner = createCommercialLicenseLink();
|
|
3208
|
-
container.appendChild(banner);
|
|
3209
|
-
}
|
|
3210
|
-
container.className += " sa-pivot__header";
|
|
3211
|
-
super.renderToolbar(container);
|
|
3212
|
-
}
|
|
3213
|
-
}
|
|
3214
|
-
PivotModel.IntervalsCount = 10;
|
|
3215
|
-
PivotModel.UseIntervalsFrom = 10;
|
|
3216
|
-
VisualizationManager.registerPivotVisualizer(PivotModel);
|
|
3217
|
-
|
|
3218
|
-
class RankingModel extends SelectBase {
|
|
3219
|
-
constructor(question, data, options, name) {
|
|
3220
|
-
super(question, data, options, name || "ranking");
|
|
3221
|
-
}
|
|
3222
|
-
getQuestionResults() {
|
|
3223
|
-
const name = this.question.name;
|
|
3224
|
-
return this.data.map((dataItem) => dataItem[name]);
|
|
3225
|
-
}
|
|
3226
|
-
getEmptyData() {
|
|
3227
|
-
const choices = this.getValues();
|
|
3228
|
-
let data = [];
|
|
3229
|
-
data.length = choices.length;
|
|
3230
|
-
data.fill(0);
|
|
3231
|
-
return data;
|
|
3232
|
-
}
|
|
3233
|
-
getCalculatedValuesCore() {
|
|
3234
|
-
const results = this.getQuestionResults();
|
|
3235
|
-
const choices = this.getValues();
|
|
3236
|
-
let plotlyData = this.getEmptyData();
|
|
3237
|
-
results.forEach((result) => {
|
|
3238
|
-
this.applyResultToPlotlyData(result, plotlyData, choices);
|
|
3239
|
-
});
|
|
3240
|
-
return [plotlyData];
|
|
3241
|
-
}
|
|
3242
|
-
applyResultToPlotlyData(result, plotlyData, choices) {
|
|
3243
|
-
if (!result || !plotlyData || !choices)
|
|
3244
|
-
return;
|
|
3245
|
-
result.forEach((resultValue, resultValueIndex, result) => {
|
|
3246
|
-
let index = choices.indexOf(resultValue);
|
|
3247
|
-
plotlyData[index] =
|
|
3248
|
-
+plotlyData[index] + (result.length - resultValueIndex);
|
|
3249
|
-
});
|
|
3250
|
-
}
|
|
3251
|
-
}
|
|
3252
|
-
VisualizationManager.registerVisualizer("ranking", RankingModel);
|
|
3253
|
-
|
|
3254
|
-
class AlternativeVisualizersWrapper extends VisualizerBase {
|
|
3255
|
-
updateVisualizerSelector() {
|
|
3256
|
-
if (!!this.visualizerSelector) {
|
|
3257
|
-
this.visualizerSelector.getElementsByTagName("select")[0].value = this.visualizer.type;
|
|
3258
|
-
}
|
|
3259
|
-
}
|
|
3260
|
-
constructor(visualizers, question, data, options) {
|
|
3261
|
-
super(question, data, options, "alternative");
|
|
3262
|
-
this.visualizers = visualizers;
|
|
3263
|
-
this.visualizersWithSelection = [];
|
|
3264
|
-
this.onAfterVisualizerRenderCallback = () => {
|
|
3265
|
-
this.afterRender(this.contentContainer);
|
|
3266
|
-
};
|
|
3267
|
-
this.onVisualizerStateChangedCallback = (s, options) => {
|
|
3268
|
-
this.stateChanged("visualizer", options);
|
|
3269
|
-
};
|
|
3270
|
-
/**
|
|
3271
|
-
* The event is fired right after AlternativeVisualizersWrapper content type has been changed.
|
|
3272
|
-
**/
|
|
3273
|
-
this.onVisualizerChanged = new Event();
|
|
3274
|
-
this.showToolbar = false;
|
|
3275
|
-
this.loadingData = false;
|
|
3276
|
-
if (!visualizers || visualizers.length < 2) {
|
|
3277
|
-
throw new Error("VisualizerArrayWrapper works with visualizers collection only.");
|
|
3278
|
-
}
|
|
3279
|
-
this.visualizers.forEach((visualizer) => {
|
|
3280
|
-
visualizer.onUpdate = () => this.invokeOnUpdate();
|
|
3281
|
-
visualizer.onGetToolbarItemCreators = () => this.toolbarItemCreators;
|
|
3282
|
-
if (visualizer.supportSelection) {
|
|
3283
|
-
this._supportSelection = true;
|
|
3284
|
-
this.visualizersWithSelection.push(visualizer);
|
|
3285
|
-
}
|
|
3286
|
-
});
|
|
3287
|
-
if (this.options.allowChangeVisualizerType !== false) {
|
|
3288
|
-
this.registerToolbarItem("changeVisualizer", () => this.visualizerSelector = DocumentHelper.createSelector(this.visualizers.map((visualizer) => {
|
|
3289
|
-
return {
|
|
3290
|
-
value: visualizer.type,
|
|
3291
|
-
text: localization.getString("visualizer_" + visualizer.type),
|
|
3292
|
-
};
|
|
3293
|
-
}), (option) => this.visualizer.type === option.value, (e) => this.setVisualizer(e.target.value)), 0);
|
|
3294
|
-
}
|
|
3295
|
-
this.visualizer = visualizers[0];
|
|
3296
|
-
this.visualizer.onAfterRender.add(this.onAfterVisualizerRenderCallback);
|
|
3297
|
-
this.visualizer.onStateChanged.add(this.onVisualizerStateChangedCallback);
|
|
3298
|
-
}
|
|
3299
|
-
get hasFooter() {
|
|
3300
|
-
return false;
|
|
3301
|
-
}
|
|
3302
|
-
getVisualizers() {
|
|
3303
|
-
return this.visualizers;
|
|
3304
|
-
}
|
|
3305
|
-
/**
|
|
3306
|
-
* This method selects visualizer to show by it name.
|
|
3307
|
-
*
|
|
3308
|
-
* parameters:
|
|
3309
|
-
* name - the name of visualizer to show,
|
|
3310
|
-
* quiet - set it to true if you don't want to rise a notification event
|
|
3311
|
-
*
|
|
3312
|
-
**/
|
|
3313
|
-
setVisualizer(type, quiet = false) {
|
|
3314
|
-
const visualizerCandidate = this.visualizers.filter((v) => v.type === type)[0];
|
|
3315
|
-
if (!!visualizerCandidate && visualizerCandidate !== this.visualizer) {
|
|
3316
|
-
let isFooterCollapsed;
|
|
3317
|
-
if (!!this.visualizer) {
|
|
3318
|
-
isFooterCollapsed = this.visualizer.isFooterCollapsed;
|
|
3319
|
-
this.visualizer.onStateChanged.remove(this.onVisualizerStateChangedCallback);
|
|
3320
|
-
this.visualizer.onAfterRender.remove(this.onAfterVisualizerRenderCallback);
|
|
3321
|
-
this.visualizer.destroy();
|
|
3322
|
-
}
|
|
3323
|
-
this.visualizer = visualizerCandidate;
|
|
3324
|
-
this.visualizer.isFooterCollapsed = isFooterCollapsed;
|
|
3325
|
-
this.refresh();
|
|
3326
|
-
this.visualizer.onAfterRender.add(this.onAfterVisualizerRenderCallback);
|
|
3327
|
-
this.visualizer.onStateChanged.add(this.onVisualizerStateChangedCallback);
|
|
3328
|
-
if (!quiet) {
|
|
3329
|
-
this.onVisualizerChanged.fire(this, { visualizer: this.visualizer });
|
|
3330
|
-
this.stateChanged("visualizer", type);
|
|
3331
|
-
}
|
|
3332
|
-
this.updateVisualizerSelector();
|
|
3333
|
-
}
|
|
3334
|
-
}
|
|
3335
|
-
getVisualizer() {
|
|
3336
|
-
return this.visualizer;
|
|
3337
|
-
}
|
|
3338
|
-
updateData(data) {
|
|
3339
|
-
super.updateData(data);
|
|
3340
|
-
this.visualizers.forEach((visualizer) => {
|
|
3341
|
-
visualizer.updateData(data);
|
|
3342
|
-
});
|
|
3343
|
-
}
|
|
3344
|
-
set onDataItemSelected(val) {
|
|
3345
|
-
this.visualizersWithSelection.forEach((visualizer) => {
|
|
3346
|
-
visualizer.onDataItemSelected = val;
|
|
3347
|
-
});
|
|
3348
|
-
}
|
|
3349
|
-
setSelection(item) {
|
|
3350
|
-
this.visualizersWithSelection.forEach((visualizer) => {
|
|
3351
|
-
visualizer.setSelection(item);
|
|
3352
|
-
});
|
|
3353
|
-
}
|
|
3354
|
-
get selection() {
|
|
3355
|
-
return this.visualizer.selection || this.selectedItem;
|
|
3356
|
-
}
|
|
3357
|
-
renderContent(container) {
|
|
3358
|
-
this.visualizerContainer = container;
|
|
3359
|
-
this.visualizer.render(this.visualizerContainer);
|
|
3360
|
-
}
|
|
3361
|
-
setBackgroundColorCore(color) {
|
|
3362
|
-
super.setBackgroundColorCore(color);
|
|
3363
|
-
this.visualizers.forEach(visualizer => visualizer.backgroundColor = color);
|
|
3364
|
-
}
|
|
3365
|
-
/**
|
|
3366
|
-
* Returns an object with properties that describe a current visualizer state. The properties are different for each individual visualizer.
|
|
3367
|
-
*
|
|
3368
|
-
* > This method is overriden in descendant classes.
|
|
3369
|
-
* @see setState
|
|
3370
|
-
* @see resetState
|
|
3371
|
-
*/
|
|
3372
|
-
getState() {
|
|
3373
|
-
const currentVisualizerState = this.visualizer.getState();
|
|
3374
|
-
const state = {
|
|
3375
|
-
visualizer: this.visualizer.type,
|
|
3376
|
-
};
|
|
3377
|
-
if (Object.keys(currentVisualizerState).length > 0) {
|
|
3378
|
-
state.state = currentVisualizerState;
|
|
3379
|
-
}
|
|
3380
|
-
return state;
|
|
3381
|
-
}
|
|
3382
|
-
/**
|
|
3383
|
-
* Sets the visualizer's state.
|
|
3384
|
-
*
|
|
3385
|
-
* @see getState
|
|
3386
|
-
* @see resetState
|
|
3387
|
-
*/
|
|
3388
|
-
setState(state) {
|
|
3389
|
-
if (!!state.visualizer) {
|
|
3390
|
-
this.setVisualizer(state.visualizer, true);
|
|
3391
|
-
}
|
|
3392
|
-
if (!!state.state) {
|
|
3393
|
-
this.visualizer.setState(state.state);
|
|
3394
|
-
}
|
|
3395
|
-
}
|
|
3396
|
-
/**
|
|
3397
|
-
* Resets the visualizer's state.
|
|
3398
|
-
*
|
|
3399
|
-
* @see getState
|
|
3400
|
-
* @see setState
|
|
3401
|
-
*/
|
|
3402
|
-
resetState() {
|
|
3403
|
-
super.resetState();
|
|
3404
|
-
this.visualizers.forEach(visualizer => visualizer.resetState());
|
|
3405
|
-
this.setVisualizer(this.visualizers[0].type, true);
|
|
3406
|
-
}
|
|
3407
|
-
getValues() {
|
|
3408
|
-
return this.visualizer.getValues();
|
|
3409
|
-
}
|
|
3410
|
-
getLabels() {
|
|
3411
|
-
return this.visualizer.getLabels();
|
|
3412
|
-
}
|
|
3413
|
-
getCalculatedValues() {
|
|
3414
|
-
return this.visualizer.getCalculatedValues();
|
|
3415
|
-
}
|
|
3416
|
-
destroy() {
|
|
3417
|
-
this.visualizers.forEach((visualizer) => {
|
|
3418
|
-
visualizer.onAfterRender.remove(this.onAfterVisualizerRenderCallback);
|
|
3419
|
-
visualizer.onStateChanged.remove(this.onVisualizerStateChangedCallback);
|
|
3420
|
-
visualizer.onUpdate = undefined;
|
|
3421
|
-
});
|
|
3422
|
-
this.visualizer.destroy();
|
|
3423
|
-
super.destroy();
|
|
2973
|
+
this.visualizer.destroy();
|
|
2974
|
+
super.destroy();
|
|
3424
2975
|
}
|
|
3425
2976
|
}
|
|
3426
2977
|
VisualizationManager.registerAltVisualizerSelector(AlternativeVisualizersWrapper);
|
|
@@ -12740,469 +12291,918 @@ class WordCloudAdapter {
|
|
|
12740
12291
|
});
|
|
12741
12292
|
}
|
|
12742
12293
|
destroy(node) {
|
|
12743
|
-
if (this._wordcloud && typeof this._wordcloud.dispose === "function") {
|
|
12744
|
-
this._wordcloud.dispose();
|
|
12745
|
-
}
|
|
12746
|
-
this._wordcloud = undefined;
|
|
12294
|
+
if (this._wordcloud && typeof this._wordcloud.dispose === "function") {
|
|
12295
|
+
this._wordcloud.dispose();
|
|
12296
|
+
}
|
|
12297
|
+
this._wordcloud = undefined;
|
|
12298
|
+
}
|
|
12299
|
+
}
|
|
12300
|
+
WordCloudAdapter.drawOutOfBound = false;
|
|
12301
|
+
WordCloudAdapter.shrinkToFit = true;
|
|
12302
|
+
WordCloudAdapter.abortThreshold = undefined;
|
|
12303
|
+
WordCloudAdapter.weightFactor = 20;
|
|
12304
|
+
WordCloudAdapter.onWordcloudCreating = new Event();
|
|
12305
|
+
class WordCloud extends VisualizerBase {
|
|
12306
|
+
constructor(question, data, options, name) {
|
|
12307
|
+
super(question, data, options, name || "wordcloud");
|
|
12308
|
+
this._wordcloudAdapter = new WordCloudAdapter(this);
|
|
12309
|
+
}
|
|
12310
|
+
convertFromExternalData(externalCalculatedData) {
|
|
12311
|
+
const innerCalculatedData = [];
|
|
12312
|
+
Object.keys(externalCalculatedData || []).forEach(word => {
|
|
12313
|
+
innerCalculatedData.push([word, externalCalculatedData[word]]);
|
|
12314
|
+
});
|
|
12315
|
+
return innerCalculatedData;
|
|
12316
|
+
}
|
|
12317
|
+
getCalculatedValuesCore() {
|
|
12318
|
+
let result = {};
|
|
12319
|
+
let stopWords = [];
|
|
12320
|
+
const locale = localization.currentLocale;
|
|
12321
|
+
if (locale) {
|
|
12322
|
+
stopWords = textHelper.getStopWords(locale);
|
|
12323
|
+
}
|
|
12324
|
+
else {
|
|
12325
|
+
stopWords = textHelper.getStopWords();
|
|
12326
|
+
}
|
|
12327
|
+
const clearWordRegexp = new RegExp("[.,\/#!$%\^\*;:{}=\-_`~()]", "g");
|
|
12328
|
+
const stopTheWord = (word) => {
|
|
12329
|
+
if (stopWords.indexOf(word) !== -1) {
|
|
12330
|
+
return "";
|
|
12331
|
+
}
|
|
12332
|
+
return word;
|
|
12333
|
+
};
|
|
12334
|
+
const processString = (row) => {
|
|
12335
|
+
row = "" + row;
|
|
12336
|
+
// if (row.length > 15) row = row.substring(0, 14) + "...";
|
|
12337
|
+
if (!!row) {
|
|
12338
|
+
row.split(" ").forEach((word) => {
|
|
12339
|
+
let clearedWord = (word || "").toLowerCase().replace(clearWordRegexp, "");
|
|
12340
|
+
clearedWord = stopTheWord(clearedWord);
|
|
12341
|
+
if (!!clearedWord) {
|
|
12342
|
+
if (!result[clearedWord]) {
|
|
12343
|
+
result[clearedWord] = 1;
|
|
12344
|
+
}
|
|
12345
|
+
else {
|
|
12346
|
+
result[clearedWord]++;
|
|
12347
|
+
}
|
|
12348
|
+
}
|
|
12349
|
+
});
|
|
12350
|
+
}
|
|
12351
|
+
};
|
|
12352
|
+
this.surveyData.forEach((dataRow) => {
|
|
12353
|
+
const nestedDataRows = getNestedDataRows(dataRow, this);
|
|
12354
|
+
nestedDataRows.forEach(row => {
|
|
12355
|
+
const rowValue = row[this.question.name];
|
|
12356
|
+
if (!!rowValue) {
|
|
12357
|
+
if (Array.isArray(rowValue)) {
|
|
12358
|
+
rowValue.forEach(processString);
|
|
12359
|
+
}
|
|
12360
|
+
else {
|
|
12361
|
+
if (typeof rowValue === "object") {
|
|
12362
|
+
Object.keys(rowValue).forEach((key) => processString(rowValue[key]));
|
|
12363
|
+
}
|
|
12364
|
+
else {
|
|
12365
|
+
processString(rowValue);
|
|
12366
|
+
}
|
|
12367
|
+
}
|
|
12368
|
+
}
|
|
12369
|
+
});
|
|
12370
|
+
});
|
|
12371
|
+
return Object.keys(result).map((key) => {
|
|
12372
|
+
return [key, result[key]];
|
|
12373
|
+
});
|
|
12374
|
+
}
|
|
12375
|
+
destroyContent(container) {
|
|
12376
|
+
this._wordcloudAdapter.destroy(container);
|
|
12377
|
+
super.destroyContent(container);
|
|
12378
|
+
}
|
|
12379
|
+
renderContentAsync(container) {
|
|
12380
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
12381
|
+
const chartNode = DocumentHelper.createElement("div");
|
|
12382
|
+
container.appendChild(chartNode);
|
|
12383
|
+
yield this._wordcloudAdapter.create(chartNode);
|
|
12384
|
+
container.innerHTML = "";
|
|
12385
|
+
container.appendChild(chartNode);
|
|
12386
|
+
return container;
|
|
12387
|
+
});
|
|
12388
|
+
}
|
|
12389
|
+
destroy() {
|
|
12390
|
+
this._wordcloudAdapter.destroy(this.contentContainer);
|
|
12391
|
+
super.destroy();
|
|
12392
|
+
}
|
|
12393
|
+
}
|
|
12394
|
+
VisualizationManager.registerVisualizer("text", WordCloud);
|
|
12395
|
+
VisualizationManager.registerVisualizer("comment", WordCloud);
|
|
12396
|
+
VisualizationManager.registerVisualizer("multipletext", WordCloud);
|
|
12397
|
+
|
|
12398
|
+
class TextTableAdapter {
|
|
12399
|
+
constructor(model) {
|
|
12400
|
+
this.model = model;
|
|
12401
|
+
}
|
|
12402
|
+
create(container) {
|
|
12403
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
12404
|
+
const { columnCount, data } = (yield this.model.getCalculatedValues());
|
|
12405
|
+
const emptyTextNode = DocumentHelper.createElement("p", "", {
|
|
12406
|
+
innerText: localization.getString("noResults"),
|
|
12407
|
+
});
|
|
12408
|
+
if (data.length === 0) {
|
|
12409
|
+
container.appendChild(emptyTextNode);
|
|
12410
|
+
return;
|
|
12411
|
+
}
|
|
12412
|
+
const tableNode = (DocumentHelper.createElement("table", "sa-text-table"));
|
|
12413
|
+
tableNode.style.backgroundColor = this.model.backgroundColor;
|
|
12414
|
+
container.appendChild(tableNode);
|
|
12415
|
+
if (this.model.columns) {
|
|
12416
|
+
var row = DocumentHelper.createElement("tr");
|
|
12417
|
+
this.model.columns.forEach(column => {
|
|
12418
|
+
var td = DocumentHelper.createElement("th", "sa-text-table__cell", {
|
|
12419
|
+
textContent: column.title,
|
|
12420
|
+
});
|
|
12421
|
+
row.appendChild(td);
|
|
12422
|
+
});
|
|
12423
|
+
tableNode.appendChild(row);
|
|
12424
|
+
}
|
|
12425
|
+
data.forEach((rowData) => {
|
|
12426
|
+
var row = DocumentHelper.createElement("tr");
|
|
12427
|
+
for (var i = 0; i < columnCount; i++) {
|
|
12428
|
+
const column = this.model.columns[i];
|
|
12429
|
+
var td = DocumentHelper.createElement("td", "sa-text-table__cell" + ((column === null || column === void 0 ? void 0 : column.type) == "number" ? " sa-text-table__cell--number" : ""), {
|
|
12430
|
+
textContent: rowData[i],
|
|
12431
|
+
});
|
|
12432
|
+
row.appendChild(td);
|
|
12433
|
+
}
|
|
12434
|
+
tableNode.appendChild(row);
|
|
12435
|
+
});
|
|
12436
|
+
container.className = "sa-text-table__container";
|
|
12437
|
+
container.appendChild(tableNode);
|
|
12438
|
+
});
|
|
12439
|
+
}
|
|
12440
|
+
destroy(node) {
|
|
12441
|
+
node.innerHTML = "";
|
|
12747
12442
|
}
|
|
12748
12443
|
}
|
|
12749
|
-
|
|
12750
|
-
WordCloudAdapter.shrinkToFit = true;
|
|
12751
|
-
WordCloudAdapter.abortThreshold = undefined;
|
|
12752
|
-
WordCloudAdapter.weightFactor = 20;
|
|
12753
|
-
WordCloudAdapter.onWordcloudCreating = new Event();
|
|
12754
|
-
class WordCloud extends VisualizerBase {
|
|
12444
|
+
class Text extends VisualizerBase {
|
|
12755
12445
|
constructor(question, data, options, name) {
|
|
12756
|
-
super(question, data, options, name || "
|
|
12757
|
-
this.
|
|
12446
|
+
super(question, data, options, name || "text");
|
|
12447
|
+
this._textTableAdapter = new TextTableAdapter(this);
|
|
12758
12448
|
}
|
|
12759
|
-
|
|
12760
|
-
const
|
|
12761
|
-
|
|
12762
|
-
|
|
12763
|
-
|
|
12764
|
-
|
|
12449
|
+
get columns() {
|
|
12450
|
+
const columns = [];
|
|
12451
|
+
if (this.question.getType() == "multipletext") {
|
|
12452
|
+
this.question.items.forEach(item => {
|
|
12453
|
+
columns.push({ name: item.name, title: item.title, type: item.inputType });
|
|
12454
|
+
});
|
|
12455
|
+
}
|
|
12456
|
+
return columns;
|
|
12765
12457
|
}
|
|
12766
12458
|
getCalculatedValuesCore() {
|
|
12767
|
-
let result =
|
|
12768
|
-
let
|
|
12769
|
-
const locale = localization.currentLocale;
|
|
12770
|
-
if (locale) {
|
|
12771
|
-
stopWords = textHelper.getStopWords(locale);
|
|
12772
|
-
}
|
|
12773
|
-
else {
|
|
12774
|
-
stopWords = textHelper.getStopWords();
|
|
12775
|
-
}
|
|
12776
|
-
const clearWordRegexp = new RegExp("[.,\/#!$%\^\*;:{}=\-_`~()]", "g");
|
|
12777
|
-
const stopTheWord = (word) => {
|
|
12778
|
-
if (stopWords.indexOf(word) !== -1) {
|
|
12779
|
-
return "";
|
|
12780
|
-
}
|
|
12781
|
-
return word;
|
|
12782
|
-
};
|
|
12783
|
-
const processString = (row) => {
|
|
12784
|
-
row = "" + row;
|
|
12785
|
-
// if (row.length > 15) row = row.substring(0, 14) + "...";
|
|
12786
|
-
if (!!row) {
|
|
12787
|
-
row.split(" ").forEach((word) => {
|
|
12788
|
-
let clearedWord = (word || "").toLowerCase().replace(clearWordRegexp, "");
|
|
12789
|
-
clearedWord = stopTheWord(clearedWord);
|
|
12790
|
-
if (!!clearedWord) {
|
|
12791
|
-
if (!result[clearedWord]) {
|
|
12792
|
-
result[clearedWord] = 1;
|
|
12793
|
-
}
|
|
12794
|
-
else {
|
|
12795
|
-
result[clearedWord]++;
|
|
12796
|
-
}
|
|
12797
|
-
}
|
|
12798
|
-
});
|
|
12799
|
-
}
|
|
12800
|
-
};
|
|
12459
|
+
let result = [];
|
|
12460
|
+
let columnCount = 0;
|
|
12801
12461
|
this.surveyData.forEach((dataRow) => {
|
|
12802
12462
|
const nestedDataRows = getNestedDataRows(dataRow, this);
|
|
12803
12463
|
nestedDataRows.forEach(row => {
|
|
12804
12464
|
const rowValue = row[this.question.name];
|
|
12465
|
+
let dataStrings = [];
|
|
12805
12466
|
if (!!rowValue) {
|
|
12806
12467
|
if (Array.isArray(rowValue)) {
|
|
12807
|
-
|
|
12468
|
+
dataStrings = dataStrings.concat(rowValue);
|
|
12808
12469
|
}
|
|
12809
12470
|
else {
|
|
12810
12471
|
if (typeof rowValue === "object") {
|
|
12811
|
-
Object.keys(rowValue).forEach((key) =>
|
|
12472
|
+
Object.keys(rowValue).forEach((key) => dataStrings.push(rowValue[key]));
|
|
12812
12473
|
}
|
|
12813
12474
|
else {
|
|
12814
|
-
|
|
12475
|
+
dataStrings.push(rowValue);
|
|
12815
12476
|
}
|
|
12816
12477
|
}
|
|
12478
|
+
result.push(dataStrings);
|
|
12479
|
+
if (dataStrings.length > columnCount) {
|
|
12480
|
+
columnCount = dataStrings.length;
|
|
12481
|
+
}
|
|
12817
12482
|
}
|
|
12818
12483
|
});
|
|
12819
12484
|
});
|
|
12820
|
-
return
|
|
12821
|
-
|
|
12485
|
+
return { columnCount: columnCount, data: result };
|
|
12486
|
+
}
|
|
12487
|
+
destroyContent(container) {
|
|
12488
|
+
this._textTableAdapter.destroy(container);
|
|
12489
|
+
super.destroyContent(container);
|
|
12490
|
+
}
|
|
12491
|
+
renderContentAsync(container) {
|
|
12492
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
12493
|
+
const tableNode = DocumentHelper.createElement("div");
|
|
12494
|
+
yield this._textTableAdapter.create(tableNode);
|
|
12495
|
+
container.innerHTML = "";
|
|
12496
|
+
container.appendChild(tableNode);
|
|
12497
|
+
return container;
|
|
12498
|
+
});
|
|
12499
|
+
}
|
|
12500
|
+
destroy() {
|
|
12501
|
+
this._textTableAdapter.destroy(this.contentContainer);
|
|
12502
|
+
super.destroy();
|
|
12503
|
+
}
|
|
12504
|
+
}
|
|
12505
|
+
VisualizationManager.registerVisualizer("text", Text);
|
|
12506
|
+
VisualizationManager.registerVisualizer("comment", Text);
|
|
12507
|
+
VisualizationManager.registerVisualizer("multipletext", Text);
|
|
12508
|
+
|
|
12509
|
+
class StatisticsTableAdapter {
|
|
12510
|
+
constructor(model) {
|
|
12511
|
+
this.model = model;
|
|
12512
|
+
}
|
|
12513
|
+
create(container) {
|
|
12514
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
12515
|
+
let { datasets, labels, colors, texts, seriesLabels, } = yield this.model.getAnswersData();
|
|
12516
|
+
seriesLabels.length > 1;
|
|
12517
|
+
const emptyTextNode = DocumentHelper.createElement("p", "", {
|
|
12518
|
+
innerText: localization.getString("noResults"),
|
|
12519
|
+
});
|
|
12520
|
+
if (datasets.length === 0 || datasets[0].length === 0) {
|
|
12521
|
+
container.appendChild(emptyTextNode);
|
|
12522
|
+
return;
|
|
12523
|
+
}
|
|
12524
|
+
datasets.forEach((data, idx) => {
|
|
12525
|
+
const tableNode = (DocumentHelper.createElement("table", "sa-statistics-table"));
|
|
12526
|
+
tableNode.style.backgroundColor = this.model.backgroundColor;
|
|
12527
|
+
container.appendChild(tableNode);
|
|
12528
|
+
var headerRow = DocumentHelper.createElement("tr");
|
|
12529
|
+
var labelCell = DocumentHelper.createElement("th", "sa-statistics-table__cell-header", {
|
|
12530
|
+
textContent: localization.getString("answer"),
|
|
12531
|
+
});
|
|
12532
|
+
headerRow.appendChild(labelCell);
|
|
12533
|
+
var sparklineCell = DocumentHelper.createElement("th", "sa-statistics-table__cell-header", {
|
|
12534
|
+
textContent: localization.getString("statistics_chart"),
|
|
12535
|
+
});
|
|
12536
|
+
headerRow.appendChild(sparklineCell);
|
|
12537
|
+
var percentCell = DocumentHelper.createElement("th", "sa-statistics-table__cell-header", {
|
|
12538
|
+
textContent: localization.getString("percentage"),
|
|
12539
|
+
});
|
|
12540
|
+
headerRow.appendChild(percentCell);
|
|
12541
|
+
var valueCell = DocumentHelper.createElement("th", "sa-statistics-table__cell-header", {
|
|
12542
|
+
textContent: localization.getString("responses"),
|
|
12543
|
+
});
|
|
12544
|
+
headerRow.appendChild(valueCell);
|
|
12545
|
+
tableNode.appendChild(headerRow);
|
|
12546
|
+
for (let index = data.length - 1; index >= 0; index--) {
|
|
12547
|
+
var row = DocumentHelper.createElement("tr");
|
|
12548
|
+
var labelCell = DocumentHelper.createElement("td", "sa-statistics-table__cell", {
|
|
12549
|
+
textContent: labels[index],
|
|
12550
|
+
});
|
|
12551
|
+
row.appendChild(labelCell);
|
|
12552
|
+
var sparklineCell = DocumentHelper.createElement("td", "sa-statistics-table__cell");
|
|
12553
|
+
var outerBar = DocumentHelper.createElement("div", "sa-choices-sparkline");
|
|
12554
|
+
var innerBar = DocumentHelper.createElement("div", "sa-choices-sparkline-value");
|
|
12555
|
+
innerBar.style.width = texts[idx][index] + "%";
|
|
12556
|
+
outerBar.appendChild(innerBar);
|
|
12557
|
+
sparklineCell.appendChild(outerBar);
|
|
12558
|
+
row.appendChild(sparklineCell);
|
|
12559
|
+
var percentCell = DocumentHelper.createElement("td", "sa-statistics-table__cell sa-statistics-table__cell-value", {
|
|
12560
|
+
textContent: "" + texts[idx][index] + "%",
|
|
12561
|
+
});
|
|
12562
|
+
row.appendChild(percentCell);
|
|
12563
|
+
var valueCell = DocumentHelper.createElement("td", "sa-statistics-table__cell sa-statistics-table__cell-value", {
|
|
12564
|
+
textContent: data[index],
|
|
12565
|
+
});
|
|
12566
|
+
row.appendChild(valueCell);
|
|
12567
|
+
tableNode.appendChild(row);
|
|
12568
|
+
}
|
|
12569
|
+
container.className = "sa-statistics-table__container";
|
|
12570
|
+
container.appendChild(tableNode);
|
|
12571
|
+
});
|
|
12822
12572
|
});
|
|
12823
12573
|
}
|
|
12574
|
+
destroy(node) {
|
|
12575
|
+
node.innerHTML = "";
|
|
12576
|
+
}
|
|
12577
|
+
}
|
|
12578
|
+
class StatisticsTable extends SelectBase {
|
|
12579
|
+
constructor(question, data, options, name) {
|
|
12580
|
+
super(question, data, options, name || "choices");
|
|
12581
|
+
this._statisticsTableAdapter = new StatisticsTableAdapter(this);
|
|
12582
|
+
this.showPercentages = true;
|
|
12583
|
+
}
|
|
12824
12584
|
destroyContent(container) {
|
|
12825
|
-
this.
|
|
12585
|
+
this._statisticsTableAdapter.destroy(container);
|
|
12826
12586
|
super.destroyContent(container);
|
|
12827
12587
|
}
|
|
12828
12588
|
renderContentAsync(container) {
|
|
12829
12589
|
return __awaiter(this, void 0, void 0, function* () {
|
|
12830
|
-
const
|
|
12831
|
-
|
|
12832
|
-
yield this._wordcloudAdapter.create(chartNode);
|
|
12590
|
+
const tableNode = DocumentHelper.createElement("div");
|
|
12591
|
+
yield this._statisticsTableAdapter.create(tableNode);
|
|
12833
12592
|
container.innerHTML = "";
|
|
12834
|
-
container.appendChild(
|
|
12593
|
+
container.appendChild(tableNode);
|
|
12594
|
+
return container;
|
|
12595
|
+
});
|
|
12596
|
+
}
|
|
12597
|
+
destroy() {
|
|
12598
|
+
this._statisticsTableAdapter.destroy(this.contentContainer);
|
|
12599
|
+
super.destroy();
|
|
12600
|
+
}
|
|
12601
|
+
}
|
|
12602
|
+
class StatisticsTableBoolean extends BooleanModel {
|
|
12603
|
+
constructor(question, data, options, name) {
|
|
12604
|
+
super(question, data, options, name || "options");
|
|
12605
|
+
this._statisticsTableAdapter = new StatisticsTableAdapter(this);
|
|
12606
|
+
this.showPercentages = true;
|
|
12607
|
+
}
|
|
12608
|
+
destroyContent(container) {
|
|
12609
|
+
this._statisticsTableAdapter.destroy(container);
|
|
12610
|
+
super.destroyContent(container);
|
|
12611
|
+
}
|
|
12612
|
+
renderContentAsync(container) {
|
|
12613
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
12614
|
+
const tableNode = DocumentHelper.createElement("div");
|
|
12615
|
+
yield this._statisticsTableAdapter.create(tableNode);
|
|
12616
|
+
container.innerHTML = "";
|
|
12617
|
+
container.appendChild(tableNode);
|
|
12835
12618
|
return container;
|
|
12836
12619
|
});
|
|
12837
12620
|
}
|
|
12838
|
-
destroy() {
|
|
12839
|
-
this.
|
|
12840
|
-
super.destroy();
|
|
12621
|
+
destroy() {
|
|
12622
|
+
this._statisticsTableAdapter.destroy(this.contentContainer);
|
|
12623
|
+
super.destroy();
|
|
12624
|
+
}
|
|
12625
|
+
}
|
|
12626
|
+
VisualizationManager.registerVisualizer("radiogroup", StatisticsTable);
|
|
12627
|
+
VisualizationManager.registerVisualizer("dropdown", StatisticsTable);
|
|
12628
|
+
VisualizationManager.registerVisualizer("checkbox", StatisticsTable);
|
|
12629
|
+
VisualizationManager.registerVisualizer("boolean", StatisticsTableBoolean);
|
|
12630
|
+
|
|
12631
|
+
class NpsVisualizerWidget {
|
|
12632
|
+
constructor(_model, _data) {
|
|
12633
|
+
this._model = _model;
|
|
12634
|
+
this._data = _data;
|
|
12635
|
+
this._renderedTarget = undefined;
|
|
12636
|
+
}
|
|
12637
|
+
renderScorePart(partId, value, percent) {
|
|
12638
|
+
const scorePartElement = DocumentHelper.createElement("div", "sa-visualizer-nps__score-part");
|
|
12639
|
+
const titleElement = DocumentHelper.createElement("div", "sa-visualizer-nps__score-part-title");
|
|
12640
|
+
titleElement.innerText = localization.getString(partId);
|
|
12641
|
+
scorePartElement.appendChild(titleElement);
|
|
12642
|
+
const valuesElement = DocumentHelper.createElement("div", "sa-visualizer-nps__score-part-values");
|
|
12643
|
+
scorePartElement.appendChild(valuesElement);
|
|
12644
|
+
const valueElement = DocumentHelper.createElement("div", "sa-visualizer-nps__score-part-value");
|
|
12645
|
+
valueElement.innerText = "" + value;
|
|
12646
|
+
valuesElement.appendChild(valueElement);
|
|
12647
|
+
if (percent) {
|
|
12648
|
+
const percentElement = DocumentHelper.createElement("div", "sa-visualizer-nps__score-part-percent");
|
|
12649
|
+
percentElement.innerText = "" + percent + "%";
|
|
12650
|
+
valuesElement.appendChild(percentElement);
|
|
12651
|
+
}
|
|
12652
|
+
return scorePartElement;
|
|
12653
|
+
}
|
|
12654
|
+
render(target) {
|
|
12655
|
+
this._renderedTarget = target;
|
|
12656
|
+
var npsElement = DocumentHelper.createElement("div", "sa-visualizer-nps");
|
|
12657
|
+
npsElement.appendChild(this.renderScorePart("npsScore", this.npsScore));
|
|
12658
|
+
npsElement.appendChild(this.renderScorePart("npsPromoters", this._data.promoters, this.promotersPercent));
|
|
12659
|
+
npsElement.appendChild(this.renderScorePart("npsPassives", this._data.total - this._data.promoters - this._data.detractors, this.passivePercent));
|
|
12660
|
+
npsElement.appendChild(this.renderScorePart("npsDetractors", this._data.detractors, this.detractorsPercent));
|
|
12661
|
+
target.appendChild(npsElement);
|
|
12662
|
+
}
|
|
12663
|
+
get npsScore() {
|
|
12664
|
+
return toPrecision(((this._data.promoters - this._data.detractors) / this._data.total) * 100, this._model.precision);
|
|
12665
|
+
}
|
|
12666
|
+
get promotersPercent() {
|
|
12667
|
+
return toPrecision(this._data.promoters / this._data.total * 100, this._model.precision);
|
|
12668
|
+
}
|
|
12669
|
+
get passivePercent() {
|
|
12670
|
+
return toPrecision((this._data.total - this._data.promoters - this._data.detractors) / this._data.total * 100, this._model.precision);
|
|
12671
|
+
}
|
|
12672
|
+
get detractorsPercent() {
|
|
12673
|
+
return toPrecision(this._data.detractors / this._data.total * 100, this._model.precision);
|
|
12674
|
+
}
|
|
12675
|
+
dispose() {
|
|
12676
|
+
if (!!this._renderedTarget) {
|
|
12677
|
+
this._renderedTarget.innerHTML = "";
|
|
12678
|
+
this._renderedTarget = undefined;
|
|
12679
|
+
}
|
|
12841
12680
|
}
|
|
12842
12681
|
}
|
|
12843
|
-
|
|
12844
|
-
VisualizationManager.registerVisualizer("comment", WordCloud);
|
|
12845
|
-
VisualizationManager.registerVisualizer("multipletext", WordCloud);
|
|
12846
|
-
|
|
12847
|
-
class TextTableAdapter {
|
|
12682
|
+
class NpsAdapter {
|
|
12848
12683
|
constructor(model) {
|
|
12849
12684
|
this.model = model;
|
|
12850
12685
|
}
|
|
12851
|
-
|
|
12686
|
+
get npsVisualizer() {
|
|
12687
|
+
return this._npsVisualizer;
|
|
12688
|
+
}
|
|
12689
|
+
create(element) {
|
|
12852
12690
|
return __awaiter(this, void 0, void 0, function* () {
|
|
12853
|
-
const
|
|
12854
|
-
|
|
12855
|
-
|
|
12856
|
-
|
|
12857
|
-
if (data.length === 0) {
|
|
12858
|
-
container.appendChild(emptyTextNode);
|
|
12859
|
-
return;
|
|
12860
|
-
}
|
|
12861
|
-
const tableNode = (DocumentHelper.createElement("table", "sa-text-table"));
|
|
12862
|
-
tableNode.style.backgroundColor = this.model.backgroundColor;
|
|
12863
|
-
container.appendChild(tableNode);
|
|
12864
|
-
if (this.model.columns) {
|
|
12865
|
-
var row = DocumentHelper.createElement("tr");
|
|
12866
|
-
this.model.columns.forEach(column => {
|
|
12867
|
-
var td = DocumentHelper.createElement("th", "sa-text-table__cell", {
|
|
12868
|
-
textContent: column.title,
|
|
12869
|
-
});
|
|
12870
|
-
row.appendChild(td);
|
|
12871
|
-
});
|
|
12872
|
-
tableNode.appendChild(row);
|
|
12873
|
-
}
|
|
12874
|
-
data.forEach((rowData) => {
|
|
12875
|
-
var row = DocumentHelper.createElement("tr");
|
|
12876
|
-
for (var i = 0; i < columnCount; i++) {
|
|
12877
|
-
const column = this.model.columns[i];
|
|
12878
|
-
var td = DocumentHelper.createElement("td", "sa-text-table__cell" + ((column === null || column === void 0 ? void 0 : column.type) == "number" ? " sa-text-table__cell--number" : ""), {
|
|
12879
|
-
textContent: rowData[i],
|
|
12880
|
-
});
|
|
12881
|
-
row.appendChild(td);
|
|
12882
|
-
}
|
|
12883
|
-
tableNode.appendChild(row);
|
|
12884
|
-
});
|
|
12885
|
-
container.className = "sa-text-table__container";
|
|
12886
|
-
container.appendChild(tableNode);
|
|
12691
|
+
const data = yield this.model.getCalculatedValues();
|
|
12692
|
+
this._npsVisualizer = new NpsVisualizerWidget(this.model, data);
|
|
12693
|
+
this._npsVisualizer.render(element);
|
|
12694
|
+
return this._npsVisualizer;
|
|
12887
12695
|
});
|
|
12888
12696
|
}
|
|
12889
12697
|
destroy(node) {
|
|
12890
|
-
|
|
12698
|
+
if (this._npsVisualizer && typeof this._npsVisualizer.dispose === "function") {
|
|
12699
|
+
this._npsVisualizer.dispose();
|
|
12700
|
+
}
|
|
12701
|
+
this._npsVisualizer = undefined;
|
|
12891
12702
|
}
|
|
12892
12703
|
}
|
|
12893
|
-
class
|
|
12704
|
+
class NpsVisualizer extends VisualizerBase {
|
|
12894
12705
|
constructor(question, data, options, name) {
|
|
12895
|
-
super(question, data, options, name || "
|
|
12896
|
-
this.
|
|
12897
|
-
|
|
12898
|
-
get columns() {
|
|
12899
|
-
const columns = [];
|
|
12900
|
-
if (this.question.getType() == "multipletext") {
|
|
12901
|
-
this.question.items.forEach(item => {
|
|
12902
|
-
columns.push({ name: item.name, title: item.title, type: item.inputType });
|
|
12903
|
-
});
|
|
12904
|
-
}
|
|
12905
|
-
return columns;
|
|
12706
|
+
super(question, data, options, name || "nps");
|
|
12707
|
+
this.precision = 2;
|
|
12708
|
+
this._npsAdapter = new NpsAdapter(this);
|
|
12906
12709
|
}
|
|
12907
12710
|
getCalculatedValuesCore() {
|
|
12908
|
-
let result =
|
|
12909
|
-
|
|
12910
|
-
|
|
12911
|
-
|
|
12912
|
-
|
|
12913
|
-
|
|
12914
|
-
|
|
12915
|
-
|
|
12916
|
-
|
|
12917
|
-
|
|
12918
|
-
|
|
12919
|
-
|
|
12920
|
-
if (typeof rowValue === "object") {
|
|
12921
|
-
Object.keys(rowValue).forEach((key) => dataStrings.push(rowValue[key]));
|
|
12922
|
-
}
|
|
12923
|
-
else {
|
|
12924
|
-
dataStrings.push(rowValue);
|
|
12925
|
-
}
|
|
12926
|
-
}
|
|
12927
|
-
result.push(dataStrings);
|
|
12928
|
-
if (dataStrings.length > columnCount) {
|
|
12929
|
-
columnCount = dataStrings.length;
|
|
12930
|
-
}
|
|
12711
|
+
let result = {
|
|
12712
|
+
detractors: 0,
|
|
12713
|
+
passive: 0,
|
|
12714
|
+
promoters: 0,
|
|
12715
|
+
total: 0,
|
|
12716
|
+
};
|
|
12717
|
+
this.data.forEach((row) => {
|
|
12718
|
+
const rowValue = row[this.question.name];
|
|
12719
|
+
const scoreValue = parseInt(rowValue);
|
|
12720
|
+
if (!Number.isNaN(scoreValue)) {
|
|
12721
|
+
if (scoreValue <= NpsVisualizer.DetractorScore) {
|
|
12722
|
+
result.detractors++;
|
|
12931
12723
|
}
|
|
12932
|
-
|
|
12724
|
+
else if (scoreValue >= NpsVisualizer.PromoterScore) {
|
|
12725
|
+
result.promoters++;
|
|
12726
|
+
}
|
|
12727
|
+
else {
|
|
12728
|
+
result.passive++;
|
|
12729
|
+
}
|
|
12730
|
+
result.total++;
|
|
12731
|
+
}
|
|
12933
12732
|
});
|
|
12934
|
-
return
|
|
12733
|
+
return result;
|
|
12935
12734
|
}
|
|
12936
12735
|
destroyContent(container) {
|
|
12937
|
-
this.
|
|
12736
|
+
this._npsAdapter.destroy(container);
|
|
12938
12737
|
super.destroyContent(container);
|
|
12939
12738
|
}
|
|
12940
12739
|
renderContentAsync(container) {
|
|
12941
12740
|
return __awaiter(this, void 0, void 0, function* () {
|
|
12942
|
-
const
|
|
12943
|
-
|
|
12741
|
+
const npsNode = DocumentHelper.createElement("div");
|
|
12742
|
+
container.appendChild(npsNode);
|
|
12743
|
+
yield this._npsAdapter.create(npsNode);
|
|
12944
12744
|
container.innerHTML = "";
|
|
12945
|
-
container.appendChild(
|
|
12745
|
+
container.appendChild(npsNode);
|
|
12946
12746
|
return container;
|
|
12947
12747
|
});
|
|
12948
12748
|
}
|
|
12949
12749
|
destroy() {
|
|
12950
|
-
this.
|
|
12750
|
+
this._npsAdapter.destroy(this.contentContainer);
|
|
12951
12751
|
super.destroy();
|
|
12952
12752
|
}
|
|
12953
12753
|
}
|
|
12954
|
-
|
|
12955
|
-
|
|
12956
|
-
VisualizationManager.registerVisualizer("
|
|
12754
|
+
NpsVisualizer.DetractorScore = 6;
|
|
12755
|
+
NpsVisualizer.PromoterScore = 9;
|
|
12756
|
+
// VisualizationManager.registerVisualizer("rating", NpsVisualizer);
|
|
12957
12757
|
|
|
12958
|
-
class
|
|
12959
|
-
constructor(
|
|
12960
|
-
|
|
12758
|
+
class RankingModel extends SelectBase {
|
|
12759
|
+
constructor(question, data, options, name) {
|
|
12760
|
+
super(question, data, options, name || "ranking");
|
|
12761
|
+
}
|
|
12762
|
+
getQuestionResults() {
|
|
12763
|
+
const name = this.question.name;
|
|
12764
|
+
return this.data.map((dataItem) => dataItem[name]);
|
|
12765
|
+
}
|
|
12766
|
+
getEmptyData() {
|
|
12767
|
+
const choices = this.getValues();
|
|
12768
|
+
let data = [];
|
|
12769
|
+
data.length = choices.length;
|
|
12770
|
+
data.fill(0);
|
|
12771
|
+
return data;
|
|
12772
|
+
}
|
|
12773
|
+
getCalculatedValuesCore() {
|
|
12774
|
+
const results = this.getQuestionResults();
|
|
12775
|
+
const choices = this.getValues();
|
|
12776
|
+
let plotlyData = this.getEmptyData();
|
|
12777
|
+
results.forEach((result) => {
|
|
12778
|
+
this.applyResultToPlotlyData(result, plotlyData, choices);
|
|
12779
|
+
});
|
|
12780
|
+
return [plotlyData];
|
|
12781
|
+
}
|
|
12782
|
+
applyResultToPlotlyData(result, plotlyData, choices) {
|
|
12783
|
+
if (!result || !plotlyData || !choices)
|
|
12784
|
+
return;
|
|
12785
|
+
result.forEach((resultValue, resultValueIndex, result) => {
|
|
12786
|
+
let index = choices.indexOf(resultValue);
|
|
12787
|
+
plotlyData[index] =
|
|
12788
|
+
+plotlyData[index] + (result.length - resultValueIndex);
|
|
12789
|
+
});
|
|
12790
|
+
}
|
|
12791
|
+
}
|
|
12792
|
+
VisualizationManager.registerVisualizer("ranking", RankingModel);
|
|
12793
|
+
|
|
12794
|
+
class PivotModel extends SelectBase {
|
|
12795
|
+
constructor(questions, data, options, name, isRoot = true) {
|
|
12796
|
+
super(null, data, options, name || "pivot");
|
|
12797
|
+
this.questions = questions;
|
|
12798
|
+
this.isRoot = isRoot;
|
|
12799
|
+
this.valueType = "enum";
|
|
12800
|
+
this._cachedValues = undefined;
|
|
12801
|
+
this._continuousData = undefined;
|
|
12802
|
+
this._cachedIntervals = undefined;
|
|
12803
|
+
this._intervalPrecision = 2;
|
|
12804
|
+
this.axisYSelectors = [];
|
|
12805
|
+
this.axisYQuestionNames = [];
|
|
12806
|
+
this.questionsY = [];
|
|
12807
|
+
this.questions = this.questions.filter((question) => ["matrixdropdown", "matrixdynamic", "matrix", "file", "signature", "multipletext", "comment", "html", "image"].indexOf(question.getType()) === -1);
|
|
12808
|
+
if (this.options.intervalPrecision !== undefined) {
|
|
12809
|
+
this._intervalPrecision = this.options.intervalPrecision;
|
|
12810
|
+
}
|
|
12811
|
+
this.axisXQuestionName = this.questions.length > 0 ? this.questions[0].name : undefined;
|
|
12812
|
+
this.registerToolbarItem("axisXSelector", () => this.axisXSelector = DocumentHelper.createSelector(this.questions.map((question) => {
|
|
12813
|
+
return {
|
|
12814
|
+
value: question.name,
|
|
12815
|
+
text: question.title || question.name,
|
|
12816
|
+
};
|
|
12817
|
+
}), (option) => this.axisXQuestionName === option.value, (e) => {
|
|
12818
|
+
this.axisXQuestionName = e.target.value;
|
|
12819
|
+
this.updateQuestionsSelection();
|
|
12820
|
+
this.updateToolbar();
|
|
12821
|
+
this.setupPivot();
|
|
12822
|
+
}, () => this.isXYChart() ? localization.getString("axisXSelectorTitle") : localization.getString("axisXAlternativeSelectorTitle")));
|
|
12823
|
+
this.registerToolbarItem("axisYSelector0", this.createYSelecterGenerator());
|
|
12824
|
+
this.setupPivot();
|
|
12825
|
+
}
|
|
12826
|
+
createYSelecterGenerator() {
|
|
12827
|
+
const selectorIndex = this.axisYSelectors.length;
|
|
12828
|
+
return () => {
|
|
12829
|
+
let selector = this.axisYSelectors[selectorIndex];
|
|
12830
|
+
if (!selector) {
|
|
12831
|
+
selector = this.createAxisYSelector(selectorIndex);
|
|
12832
|
+
this.axisYSelectors.push(selector);
|
|
12833
|
+
}
|
|
12834
|
+
else {
|
|
12835
|
+
selector["__updateSelect"] && selector["__updateSelect"]();
|
|
12836
|
+
}
|
|
12837
|
+
return selector;
|
|
12838
|
+
};
|
|
12839
|
+
}
|
|
12840
|
+
setAxisQuestions(...axisQuestionNames) {
|
|
12841
|
+
if (axisQuestionNames.length < 1) {
|
|
12842
|
+
return;
|
|
12843
|
+
}
|
|
12844
|
+
this.axisXQuestionName = axisQuestionNames[0];
|
|
12845
|
+
this.axisYQuestionNames = axisQuestionNames.splice(1);
|
|
12846
|
+
this.setupPivot();
|
|
12847
|
+
}
|
|
12848
|
+
onAxisYSelectorChanged(index, value) {
|
|
12849
|
+
this.axisYQuestionNames[index] = value;
|
|
12850
|
+
if (index < this.axisYSelectors.length - 1) {
|
|
12851
|
+
if (!value) {
|
|
12852
|
+
for (let i = index + 1; i < this.axisYSelectors.length; ++i) {
|
|
12853
|
+
this.unregisterToolbarItem("axisYSelector" + i);
|
|
12854
|
+
}
|
|
12855
|
+
this.axisYSelectors = this.axisYSelectors.slice(0, index + 1);
|
|
12856
|
+
this.axisYQuestionNames = this.axisYQuestionNames.slice(0, index + 1);
|
|
12857
|
+
}
|
|
12858
|
+
}
|
|
12859
|
+
else {
|
|
12860
|
+
if (!!value) {
|
|
12861
|
+
this.registerToolbarItem("axisYSelector" + this.axisYSelectors.length, this.createYSelecterGenerator());
|
|
12862
|
+
}
|
|
12863
|
+
}
|
|
12864
|
+
this.updateQuestionsSelection();
|
|
12865
|
+
this.updateToolbar();
|
|
12866
|
+
this.setupPivot();
|
|
12961
12867
|
}
|
|
12962
|
-
|
|
12963
|
-
|
|
12964
|
-
|
|
12965
|
-
|
|
12966
|
-
|
|
12967
|
-
|
|
12968
|
-
|
|
12969
|
-
if (datasets.length === 0 || datasets[0].length === 0) {
|
|
12970
|
-
container.appendChild(emptyTextNode);
|
|
12971
|
-
return;
|
|
12868
|
+
updateQuestionsSelection() {
|
|
12869
|
+
const selectedQuestions = [this.axisXQuestionName];
|
|
12870
|
+
for (let i = 0; i < this.axisYQuestionNames.length; ++i) {
|
|
12871
|
+
const questionName = this.axisYQuestionNames[i];
|
|
12872
|
+
if (selectedQuestions.indexOf(questionName) !== -1) {
|
|
12873
|
+
this.onAxisYSelectorChanged(i, undefined);
|
|
12874
|
+
break;
|
|
12972
12875
|
}
|
|
12973
|
-
|
|
12974
|
-
|
|
12975
|
-
|
|
12976
|
-
|
|
12977
|
-
|
|
12978
|
-
|
|
12979
|
-
|
|
12980
|
-
|
|
12981
|
-
|
|
12982
|
-
|
|
12983
|
-
textContent: localization.getString("statistics_chart"),
|
|
12984
|
-
});
|
|
12985
|
-
headerRow.appendChild(sparklineCell);
|
|
12986
|
-
var percentCell = DocumentHelper.createElement("th", "sa-statistics-table__cell-header", {
|
|
12987
|
-
textContent: localization.getString("percentage"),
|
|
12988
|
-
});
|
|
12989
|
-
headerRow.appendChild(percentCell);
|
|
12990
|
-
var valueCell = DocumentHelper.createElement("th", "sa-statistics-table__cell-header", {
|
|
12991
|
-
textContent: localization.getString("responses"),
|
|
12992
|
-
});
|
|
12993
|
-
headerRow.appendChild(valueCell);
|
|
12994
|
-
tableNode.appendChild(headerRow);
|
|
12995
|
-
for (let index = data.length - 1; index >= 0; index--) {
|
|
12996
|
-
var row = DocumentHelper.createElement("tr");
|
|
12997
|
-
var labelCell = DocumentHelper.createElement("td", "sa-statistics-table__cell", {
|
|
12998
|
-
textContent: labels[index],
|
|
12999
|
-
});
|
|
13000
|
-
row.appendChild(labelCell);
|
|
13001
|
-
var sparklineCell = DocumentHelper.createElement("td", "sa-statistics-table__cell");
|
|
13002
|
-
var outerBar = DocumentHelper.createElement("div", "sa-choices-sparkline");
|
|
13003
|
-
var innerBar = DocumentHelper.createElement("div", "sa-choices-sparkline-value");
|
|
13004
|
-
innerBar.style.width = texts[idx][index] + "%";
|
|
13005
|
-
outerBar.appendChild(innerBar);
|
|
13006
|
-
sparklineCell.appendChild(outerBar);
|
|
13007
|
-
row.appendChild(sparklineCell);
|
|
13008
|
-
var percentCell = DocumentHelper.createElement("td", "sa-statistics-table__cell sa-statistics-table__cell-value", {
|
|
13009
|
-
textContent: "" + texts[idx][index] + "%",
|
|
13010
|
-
});
|
|
13011
|
-
row.appendChild(percentCell);
|
|
13012
|
-
var valueCell = DocumentHelper.createElement("td", "sa-statistics-table__cell sa-statistics-table__cell-value", {
|
|
13013
|
-
textContent: data[index],
|
|
13014
|
-
});
|
|
13015
|
-
row.appendChild(valueCell);
|
|
13016
|
-
tableNode.appendChild(row);
|
|
12876
|
+
else {
|
|
12877
|
+
selectedQuestions.push(questionName);
|
|
12878
|
+
}
|
|
12879
|
+
}
|
|
12880
|
+
}
|
|
12881
|
+
createAxisYSelector(selectorIndex) {
|
|
12882
|
+
const getChoices = () => {
|
|
12883
|
+
const choices = this.questions.filter(q => {
|
|
12884
|
+
if (q.name === this.axisXQuestionName) {
|
|
12885
|
+
return false;
|
|
13017
12886
|
}
|
|
13018
|
-
|
|
13019
|
-
|
|
12887
|
+
const usedIndex = this.axisYQuestionNames.indexOf(q.name);
|
|
12888
|
+
return usedIndex == -1 || usedIndex >= selectorIndex;
|
|
12889
|
+
}).map((question) => {
|
|
12890
|
+
return {
|
|
12891
|
+
value: question.name,
|
|
12892
|
+
text: question.title || question.name,
|
|
12893
|
+
};
|
|
13020
12894
|
});
|
|
13021
|
-
|
|
12895
|
+
return [{ value: "", text: localization.getString("notSelected") }].concat(choices);
|
|
12896
|
+
};
|
|
12897
|
+
if (getChoices().length == 1) {
|
|
12898
|
+
return undefined;
|
|
12899
|
+
}
|
|
12900
|
+
const selector = DocumentHelper.createSelector(getChoices, (option) => this.axisYQuestionNames[selectorIndex] === option.value, (e) => { this.onAxisYSelectorChanged(selectorIndex, e.target.value); }, () => selectorIndex ? undefined : (this.isXYChart() ? localization.getString("axisYSelectorTitle") : localization.getString("axisYAlternativeSelectorTitle")));
|
|
12901
|
+
return selector;
|
|
13022
12902
|
}
|
|
13023
|
-
|
|
13024
|
-
|
|
12903
|
+
setChartType(chartType) {
|
|
12904
|
+
const prev2Dchart = this.isXYChart();
|
|
12905
|
+
super.setChartType(chartType);
|
|
12906
|
+
if (prev2Dchart !== this.isXYChart()) {
|
|
12907
|
+
this.updateToolbar();
|
|
12908
|
+
}
|
|
13025
12909
|
}
|
|
13026
|
-
|
|
13027
|
-
|
|
13028
|
-
constructor(question, data, options, name) {
|
|
13029
|
-
super(question, data, options, name || "choices");
|
|
13030
|
-
this._statisticsTableAdapter = new StatisticsTableAdapter(this);
|
|
13031
|
-
this.showPercentages = true;
|
|
12910
|
+
isXYChart() {
|
|
12911
|
+
return ["pie", "doughnut"].indexOf(this.chartType) === -1;
|
|
13032
12912
|
}
|
|
13033
|
-
|
|
13034
|
-
|
|
13035
|
-
|
|
12913
|
+
getQuestionValueType(question) {
|
|
12914
|
+
const questionType = question.getType();
|
|
12915
|
+
if (questionType === "text" && (question["inputType"] === "date" || question["inputType"] === "datetime")) {
|
|
12916
|
+
return "date";
|
|
12917
|
+
}
|
|
12918
|
+
else if (questionType === "text" || questionType === "rating" || questionType === "expression" || questionType === "range") {
|
|
12919
|
+
return "number";
|
|
12920
|
+
}
|
|
12921
|
+
return "enum";
|
|
13036
12922
|
}
|
|
13037
|
-
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13043
|
-
|
|
13044
|
-
|
|
12923
|
+
setupPivot() {
|
|
12924
|
+
const questionX = this.questions.filter((q) => q.name === this.axisXQuestionName)[0];
|
|
12925
|
+
if (!questionX) {
|
|
12926
|
+
return;
|
|
12927
|
+
}
|
|
12928
|
+
this.question = questionX;
|
|
12929
|
+
this.valueType = this.getQuestionValueType(questionX);
|
|
12930
|
+
this.questionsY = this.axisYQuestionNames.map((name) => {
|
|
12931
|
+
const questionY = this.questions.filter((q) => q.name === name)[0];
|
|
12932
|
+
if (!!questionY) {
|
|
12933
|
+
return this.getQuestionValueType(questionY) === "enum" ? new SelectBase(questionY, []) : new VisualizerBase(questionY, []);
|
|
12934
|
+
}
|
|
12935
|
+
}).filter((q) => !!q);
|
|
12936
|
+
this.onDataChanged();
|
|
13045
12937
|
}
|
|
13046
|
-
|
|
13047
|
-
this.
|
|
13048
|
-
|
|
12938
|
+
reset() {
|
|
12939
|
+
this._continuousData = undefined;
|
|
12940
|
+
this._cachedValues = undefined;
|
|
12941
|
+
this._cachedIntervals = undefined;
|
|
13049
12942
|
}
|
|
13050
|
-
|
|
13051
|
-
|
|
13052
|
-
|
|
13053
|
-
|
|
13054
|
-
|
|
13055
|
-
this.showPercentages = true;
|
|
12943
|
+
getContinuousValue(value) {
|
|
12944
|
+
if (this.valueType === "date") {
|
|
12945
|
+
return Date.parse(value);
|
|
12946
|
+
}
|
|
12947
|
+
return parseFloat(value);
|
|
13056
12948
|
}
|
|
13057
|
-
|
|
13058
|
-
this.
|
|
13059
|
-
|
|
12949
|
+
getString(value) {
|
|
12950
|
+
if (this.valueType === "date") {
|
|
12951
|
+
return new Date(value).toLocaleDateString();
|
|
12952
|
+
}
|
|
12953
|
+
return "" + value;
|
|
13060
12954
|
}
|
|
13061
|
-
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
yield this._statisticsTableAdapter.create(tableNode);
|
|
13065
|
-
container.innerHTML = "";
|
|
13066
|
-
container.appendChild(tableNode);
|
|
13067
|
-
return container;
|
|
13068
|
-
});
|
|
12955
|
+
toPrecision(value) {
|
|
12956
|
+
const base = Math.pow(10, this._intervalPrecision);
|
|
12957
|
+
return Math.round(base * value) / base;
|
|
13069
12958
|
}
|
|
13070
|
-
|
|
13071
|
-
this.
|
|
13072
|
-
|
|
12959
|
+
getSelectedItemByText(itemText) {
|
|
12960
|
+
if (this.hasCustomIntervals || this.getContinuousValues().length > PivotModel.UseIntervalsFrom) {
|
|
12961
|
+
const interval = this.intervals.filter(interval => interval.label === itemText)[0];
|
|
12962
|
+
return new ItemValue(interval, interval !== undefined ? interval.label : "");
|
|
12963
|
+
}
|
|
12964
|
+
const labels = this.getLabels();
|
|
12965
|
+
const labelIndex = labels.indexOf(itemText);
|
|
12966
|
+
return new ItemValue(this.getValues()[labelIndex], labels[labelIndex]);
|
|
13073
12967
|
}
|
|
13074
|
-
|
|
13075
|
-
|
|
13076
|
-
|
|
13077
|
-
|
|
13078
|
-
|
|
13079
|
-
|
|
13080
|
-
class NpsVisualizerWidget {
|
|
13081
|
-
constructor(_model, _data) {
|
|
13082
|
-
this._model = _model;
|
|
13083
|
-
this._data = _data;
|
|
13084
|
-
this._renderedTarget = undefined;
|
|
12968
|
+
/**
|
|
12969
|
+
* Updates visualizer data.
|
|
12970
|
+
*/
|
|
12971
|
+
updateData(data) {
|
|
12972
|
+
this.reset();
|
|
12973
|
+
super.updateData(data);
|
|
13085
12974
|
}
|
|
13086
|
-
|
|
13087
|
-
|
|
13088
|
-
|
|
13089
|
-
titleElement.innerText = localization.getString(partId);
|
|
13090
|
-
scorePartElement.appendChild(titleElement);
|
|
13091
|
-
const valuesElement = DocumentHelper.createElement("div", "sa-visualizer-nps__score-part-values");
|
|
13092
|
-
scorePartElement.appendChild(valuesElement);
|
|
13093
|
-
const valueElement = DocumentHelper.createElement("div", "sa-visualizer-nps__score-part-value");
|
|
13094
|
-
valueElement.innerText = "" + value;
|
|
13095
|
-
valuesElement.appendChild(valueElement);
|
|
13096
|
-
if (percent) {
|
|
13097
|
-
const percentElement = DocumentHelper.createElement("div", "sa-visualizer-nps__score-part-percent");
|
|
13098
|
-
percentElement.innerText = "" + percent + "%";
|
|
13099
|
-
valuesElement.appendChild(percentElement);
|
|
13100
|
-
}
|
|
13101
|
-
return scorePartElement;
|
|
12975
|
+
onDataChanged() {
|
|
12976
|
+
this.reset();
|
|
12977
|
+
super.onDataChanged();
|
|
13102
12978
|
}
|
|
13103
|
-
|
|
13104
|
-
this.
|
|
13105
|
-
|
|
13106
|
-
|
|
13107
|
-
|
|
13108
|
-
|
|
13109
|
-
|
|
13110
|
-
|
|
12979
|
+
getContinuousValues() {
|
|
12980
|
+
if (this._cachedValues === undefined) {
|
|
12981
|
+
this._continuousData = [];
|
|
12982
|
+
if (this.valueType === "enum") {
|
|
12983
|
+
this._cachedValues = [];
|
|
12984
|
+
return this._cachedValues;
|
|
12985
|
+
}
|
|
12986
|
+
const hash = {};
|
|
12987
|
+
this.data.forEach(dataItem => {
|
|
12988
|
+
const answerData = dataItem[this.name];
|
|
12989
|
+
if (answerData !== undefined) {
|
|
12990
|
+
// TODO: _continuousData should be sorted in order to speed-up statistics calculation in the getData function
|
|
12991
|
+
this._continuousData.push({ continuous: this.getContinuousValue(answerData), row: dataItem });
|
|
12992
|
+
hash[answerData] = { value: answerData, row: dataItem };
|
|
12993
|
+
}
|
|
12994
|
+
});
|
|
12995
|
+
this._cachedValues = Object.keys(hash).map(key => ({ original: hash[key].value, continuous: this.getContinuousValue(key), row: hash[key].row }));
|
|
12996
|
+
this._cachedValues.sort((a, b) => a.continuous - b.continuous);
|
|
12997
|
+
}
|
|
12998
|
+
return this._cachedValues;
|
|
13111
12999
|
}
|
|
13112
|
-
|
|
13113
|
-
return
|
|
13000
|
+
isSupportAnswersOrder() {
|
|
13001
|
+
return false;
|
|
13114
13002
|
}
|
|
13115
|
-
|
|
13116
|
-
return
|
|
13003
|
+
isSupportMissingAnswers() {
|
|
13004
|
+
return false;
|
|
13117
13005
|
}
|
|
13118
|
-
get
|
|
13119
|
-
return
|
|
13006
|
+
get needUseRateValues() {
|
|
13007
|
+
return this.question.getType() == "rating" && Array.isArray(this.question["rateValues"]) && this.question["rateValues"].length > 0;
|
|
13120
13008
|
}
|
|
13121
|
-
|
|
13122
|
-
|
|
13009
|
+
getSeriesValues() {
|
|
13010
|
+
if (!this.questionsY || this.questionsY.length === 0) {
|
|
13011
|
+
return this.options.seriesValues || [];
|
|
13012
|
+
}
|
|
13013
|
+
const seriesValues = [];
|
|
13014
|
+
this.questionsY.forEach(q => {
|
|
13015
|
+
if (this.getQuestionValueType(q.question) === "enum") {
|
|
13016
|
+
seriesValues.push.apply(seriesValues, q.getValues().reverse());
|
|
13017
|
+
}
|
|
13018
|
+
else {
|
|
13019
|
+
seriesValues.push(q.question.name);
|
|
13020
|
+
}
|
|
13021
|
+
});
|
|
13022
|
+
return seriesValues;
|
|
13123
13023
|
}
|
|
13124
|
-
|
|
13125
|
-
if (
|
|
13126
|
-
this.
|
|
13127
|
-
this._renderedTarget = undefined;
|
|
13024
|
+
getSeriesLabels() {
|
|
13025
|
+
if (this.questionsY.length === 0) {
|
|
13026
|
+
return this.getSeriesValues();
|
|
13128
13027
|
}
|
|
13028
|
+
const seriesLabels = [];
|
|
13029
|
+
this.questionsY.forEach(q => {
|
|
13030
|
+
if (this.getQuestionValueType(q.question) === "enum") {
|
|
13031
|
+
seriesLabels.push.apply(seriesLabels, q.getLabels().reverse());
|
|
13032
|
+
}
|
|
13033
|
+
else {
|
|
13034
|
+
seriesLabels.push(q.question.title || q.question.name);
|
|
13035
|
+
}
|
|
13036
|
+
});
|
|
13037
|
+
return seriesLabels;
|
|
13129
13038
|
}
|
|
13130
|
-
|
|
13131
|
-
|
|
13132
|
-
|
|
13133
|
-
|
|
13039
|
+
getValues() {
|
|
13040
|
+
if (this.valueType === "enum") {
|
|
13041
|
+
return super.getValues().reverse();
|
|
13042
|
+
}
|
|
13043
|
+
return this.intervals.map(interval => interval.start);
|
|
13134
13044
|
}
|
|
13135
|
-
|
|
13136
|
-
|
|
13045
|
+
getLabels() {
|
|
13046
|
+
if (this.valueType === "enum") {
|
|
13047
|
+
return super.getLabels().reverse();
|
|
13048
|
+
}
|
|
13049
|
+
return this.intervals.map(interval => interval.label);
|
|
13137
13050
|
}
|
|
13138
|
-
|
|
13139
|
-
return
|
|
13140
|
-
const data = yield this.model.getCalculatedValues();
|
|
13141
|
-
this._npsVisualizer = new NpsVisualizerWidget(this.model, data);
|
|
13142
|
-
this._npsVisualizer.render(element);
|
|
13143
|
-
return this._npsVisualizer;
|
|
13144
|
-
});
|
|
13051
|
+
get hasCustomIntervals() {
|
|
13052
|
+
return !!this.questionOptions && Array.isArray(this.questionOptions.intervals);
|
|
13145
13053
|
}
|
|
13146
|
-
|
|
13147
|
-
if (this.
|
|
13148
|
-
this.
|
|
13054
|
+
get intervals() {
|
|
13055
|
+
if (this.hasCustomIntervals) {
|
|
13056
|
+
return this.questionOptions.intervals;
|
|
13149
13057
|
}
|
|
13150
|
-
this.
|
|
13058
|
+
if (this.question.getType() == "rating") {
|
|
13059
|
+
if (this.needUseRateValues) {
|
|
13060
|
+
const rateValues = this.question["rateValues"];
|
|
13061
|
+
rateValues.sort((iv1, iv2) => iv1.value - iv2.value);
|
|
13062
|
+
return rateValues.map((rateValue, i) => ({
|
|
13063
|
+
start: rateValue.value,
|
|
13064
|
+
end: i < rateValues.length - 1 ? rateValues[i + 1].value : rateValue.value + 1,
|
|
13065
|
+
label: rateValue.text
|
|
13066
|
+
}));
|
|
13067
|
+
}
|
|
13068
|
+
else {
|
|
13069
|
+
const rateIntervals = [];
|
|
13070
|
+
for (let i = (this.question["rateMin"] || 0); i <= (this.question["rateMax"] || (PivotModel.IntervalsCount - 1)); i += (this.question["rateStep"] || 1)) {
|
|
13071
|
+
rateIntervals.push({
|
|
13072
|
+
start: i,
|
|
13073
|
+
end: i + 1,
|
|
13074
|
+
label: "" + (!!this.question["rateMin"] && !!this.question["rateMax"] ? i : (i + "-" + (i + 1)))
|
|
13075
|
+
});
|
|
13076
|
+
}
|
|
13077
|
+
return rateIntervals;
|
|
13078
|
+
}
|
|
13079
|
+
}
|
|
13080
|
+
if (this._cachedIntervals === undefined) {
|
|
13081
|
+
const continuousValues = this.getContinuousValues();
|
|
13082
|
+
this._cachedIntervals = [];
|
|
13083
|
+
if (continuousValues.length) {
|
|
13084
|
+
let start = continuousValues[0].continuous;
|
|
13085
|
+
const end = continuousValues[continuousValues.length - 1].continuous;
|
|
13086
|
+
const intervalsCount = PivotModel.IntervalsCount;
|
|
13087
|
+
const delta = (end - start) / intervalsCount;
|
|
13088
|
+
for (let i = 0; i < intervalsCount; ++i) {
|
|
13089
|
+
const next = start + delta;
|
|
13090
|
+
const istart = this.toPrecision(start);
|
|
13091
|
+
const inext = this.toPrecision(next);
|
|
13092
|
+
this._cachedIntervals.push({
|
|
13093
|
+
start: istart,
|
|
13094
|
+
end: i < intervalsCount - 1 ? inext : inext + delta / 100,
|
|
13095
|
+
label: "" + this.getString(istart) + "-" + this.getString(inext)
|
|
13096
|
+
});
|
|
13097
|
+
start = next;
|
|
13098
|
+
}
|
|
13099
|
+
}
|
|
13100
|
+
}
|
|
13101
|
+
return this._cachedIntervals;
|
|
13151
13102
|
}
|
|
13152
|
-
|
|
13153
|
-
|
|
13154
|
-
constructor(question, data, options, name) {
|
|
13155
|
-
super(question, data, options, name || "nps");
|
|
13156
|
-
this.precision = 2;
|
|
13157
|
-
this._npsAdapter = new NpsAdapter(this);
|
|
13103
|
+
convertFromExternalData(externalCalculatedData) {
|
|
13104
|
+
return [externalCalculatedData];
|
|
13158
13105
|
}
|
|
13159
|
-
|
|
13160
|
-
|
|
13161
|
-
|
|
13162
|
-
|
|
13163
|
-
|
|
13164
|
-
|
|
13165
|
-
|
|
13166
|
-
|
|
13167
|
-
|
|
13168
|
-
|
|
13169
|
-
|
|
13170
|
-
|
|
13171
|
-
|
|
13172
|
-
|
|
13173
|
-
|
|
13174
|
-
|
|
13106
|
+
getSeriesValueIndexes() {
|
|
13107
|
+
const seriesValueIndexes = {};
|
|
13108
|
+
let valueIndex = 0;
|
|
13109
|
+
for (var i = 0; i < this.questionsY.length; ++i) {
|
|
13110
|
+
const questionValueType = this.getQuestionValueType(this.questionsY[i].question);
|
|
13111
|
+
if (questionValueType === "enum") {
|
|
13112
|
+
this.questionsY[i].getValues().reverse().forEach((value) => {
|
|
13113
|
+
seriesValueIndexes[this.questionsY[i].name + "_" + value] = valueIndex++;
|
|
13114
|
+
});
|
|
13115
|
+
}
|
|
13116
|
+
else {
|
|
13117
|
+
seriesValueIndexes[this.questionsY[i].name] = valueIndex++;
|
|
13118
|
+
}
|
|
13119
|
+
}
|
|
13120
|
+
return seriesValueIndexes;
|
|
13121
|
+
}
|
|
13122
|
+
updateStatisticsSeriesValue(statistics, dataRow, valueIndex, seriesValueIndexes) {
|
|
13123
|
+
for (let j = 0; j < this.questionsY.length; ++j) {
|
|
13124
|
+
if (dataRow[this.questionsY[j].name] !== undefined) {
|
|
13125
|
+
const questionValueType = this.getQuestionValueType(this.questionsY[j].question);
|
|
13126
|
+
if (questionValueType === "enum" || questionValueType === "date") {
|
|
13127
|
+
const seriesValueIndex = seriesValueIndexes[this.questionsY[j].name + "_" + dataRow[this.questionsY[j].name]];
|
|
13128
|
+
statistics[seriesValueIndex][valueIndex]++;
|
|
13175
13129
|
}
|
|
13176
13130
|
else {
|
|
13177
|
-
|
|
13131
|
+
const seriesValueIndex = seriesValueIndexes[this.questionsY[j].name];
|
|
13132
|
+
statistics[seriesValueIndex][valueIndex] += parseFloat(dataRow[this.questionsY[j].name]);
|
|
13178
13133
|
}
|
|
13179
|
-
result.total++;
|
|
13180
13134
|
}
|
|
13181
|
-
}
|
|
13182
|
-
return result;
|
|
13135
|
+
}
|
|
13183
13136
|
}
|
|
13184
|
-
|
|
13185
|
-
|
|
13186
|
-
|
|
13137
|
+
getCalculatedValuesCore() {
|
|
13138
|
+
const statistics = [];
|
|
13139
|
+
const series = this.getSeriesValues();
|
|
13140
|
+
if (series.length === 0) {
|
|
13141
|
+
series.push("");
|
|
13142
|
+
}
|
|
13143
|
+
const seriesValueIndexes = this.getSeriesValueIndexes();
|
|
13144
|
+
if (this.valueType === "enum") {
|
|
13145
|
+
const values = this.getValues();
|
|
13146
|
+
const valueIndexes = {};
|
|
13147
|
+
values.forEach((value, index) => {
|
|
13148
|
+
valueIndexes[value] = index;
|
|
13149
|
+
});
|
|
13150
|
+
for (var i = 0; i < series.length; ++i) {
|
|
13151
|
+
statistics.push(values.map(i => 0));
|
|
13152
|
+
}
|
|
13153
|
+
this.data.forEach(dataRow => {
|
|
13154
|
+
const answerData = dataRow[this.name];
|
|
13155
|
+
if (answerData !== undefined && valueIndexes[answerData] !== undefined) {
|
|
13156
|
+
const valueIndex = valueIndexes[answerData];
|
|
13157
|
+
if (this.questionsY.length === 0) {
|
|
13158
|
+
statistics[0][valueIndex]++;
|
|
13159
|
+
}
|
|
13160
|
+
else {
|
|
13161
|
+
this.updateStatisticsSeriesValue(statistics, dataRow, valueIndex, seriesValueIndexes);
|
|
13162
|
+
}
|
|
13163
|
+
}
|
|
13164
|
+
});
|
|
13165
|
+
}
|
|
13166
|
+
else {
|
|
13167
|
+
this.getContinuousValues();
|
|
13168
|
+
const intervals = this.intervals;
|
|
13169
|
+
for (var i = 0; i < series.length; ++i) {
|
|
13170
|
+
statistics.push(intervals.map(i => 0));
|
|
13171
|
+
}
|
|
13172
|
+
this._continuousData.forEach(dataValue => {
|
|
13173
|
+
for (let valueIndex = 0; valueIndex < intervals.length; ++valueIndex) {
|
|
13174
|
+
if (intervals[valueIndex].start <= dataValue.continuous && (dataValue.continuous < intervals[valueIndex].end || valueIndex == intervals.length - 1)) {
|
|
13175
|
+
if (this.questionsY.length === 0) {
|
|
13176
|
+
statistics[0][valueIndex]++;
|
|
13177
|
+
}
|
|
13178
|
+
else {
|
|
13179
|
+
this.updateStatisticsSeriesValue(statistics, dataValue.row, valueIndex, seriesValueIndexes);
|
|
13180
|
+
}
|
|
13181
|
+
break;
|
|
13182
|
+
}
|
|
13183
|
+
}
|
|
13184
|
+
});
|
|
13185
|
+
}
|
|
13186
|
+
return statistics;
|
|
13187
13187
|
}
|
|
13188
|
-
|
|
13189
|
-
return
|
|
13190
|
-
const npsNode = DocumentHelper.createElement("div");
|
|
13191
|
-
container.appendChild(npsNode);
|
|
13192
|
-
yield this._npsAdapter.create(npsNode);
|
|
13193
|
-
container.innerHTML = "";
|
|
13194
|
-
container.appendChild(npsNode);
|
|
13195
|
-
return container;
|
|
13196
|
-
});
|
|
13188
|
+
getValueType() {
|
|
13189
|
+
return this.valueType;
|
|
13197
13190
|
}
|
|
13198
|
-
|
|
13199
|
-
|
|
13200
|
-
|
|
13191
|
+
isSupportSoftUpdateContent() {
|
|
13192
|
+
return false;
|
|
13193
|
+
}
|
|
13194
|
+
renderToolbar(container) {
|
|
13195
|
+
if (!this.haveCommercialLicense && this.isRoot) {
|
|
13196
|
+
const banner = createCommercialLicenseLink();
|
|
13197
|
+
container.appendChild(banner);
|
|
13198
|
+
}
|
|
13199
|
+
container.className += " sa-pivot__header";
|
|
13200
|
+
super.renderToolbar(container);
|
|
13201
13201
|
}
|
|
13202
13202
|
}
|
|
13203
|
-
|
|
13204
|
-
|
|
13205
|
-
|
|
13203
|
+
PivotModel.IntervalsCount = 10;
|
|
13204
|
+
PivotModel.UseIntervalsFrom = 10;
|
|
13205
|
+
VisualizationManager.registerPivotVisualizer(PivotModel);
|
|
13206
13206
|
|
|
13207
13207
|
export { AlternativeVisualizersWrapper as A, BooleanModel as B, DataProvider as D, HistogramModel as H, Matrix as M, NpsAdapter as N, PivotModel as P, RankingModel as R, SelectBase as S, Text as T, VisualizationComposite as V, WordCloud as W, __awaiter as _, NpsVisualizer as a, NpsVisualizerWidget as b, NumberModel as c, PostponeHelper as d, StatisticsTable as e, StatisticsTableAdapter as f, StatisticsTableBoolean as g, TextTableAdapter as h, VisualizationManager as i, VisualizationMatrixDropdown as j, VisualizationMatrixDynamic as k, VisualizationPanel as l, VisualizationPanelDynamic as m, VisualizerBase as n, VisualizerFactory as o, WordCloudAdapter as p, getBestIntervalMode as q, hideEmptyAnswersInData as r, intervalCalculators as s, textHelper as t, defaultStatisticsCalculator as u };
|
|
13208
13208
|
//# sourceMappingURL=shared2.mjs.map
|