UNPKG

survey-analytics

Version:

SurveyJS Dashboard is a UI component for visualizing and analyzing survey data. It interprets the form JSON schema to identify question types and renders collected responses using interactive charts and tables.

1,364 lines (1,353 loc) 565 kB
/*! * surveyjs - SurveyJS Dashboard library v2.5.19 * Copyright (c) 2015-2026 Devsoft Baltic OÜ - http://surveyjs.io/ * License: MIT (http://www.opensource.org/licenses/mit-license.php) */ import { D as DocumentHelper, l as localization, c as createImagesContainer, d as createLinksContainer, e as createCommercialLicenseLink, f as svgTemplate } from './shared.mjs'; export { s as setupLocale, a as surveyStrings } from './shared.mjs'; import { ItemValue, settings, Serializer, surveyLocalization, hasLicense, EventBase, Event } from 'survey-core'; import { TabulatorFull } from 'tabulator-tables'; class TableExtensions { constructor(table) { this.table = table; this.renderedExtensions = []; } render(targetNode, location, options) { var extensions = TableExtensions.extensions[location]; if (!!extensions) { extensions = this.sortExtensions(extensions); extensions.forEach((extension) => { if (!!extension.render && this.table.allowExtension(extension)) { var action = extension.render(this.table, options); if (!!action) { targetNode.appendChild(action); this.renderedExtensions.push(extension); } } }); } } destroy() { this.renderedExtensions.forEach((extension) => { if (!!extension.destroy) extension.destroy(); }); this.renderedExtensions = []; } static registerExtension(extension) { if (!this.extensions[extension.location]) this.extensions[extension.location] = []; this.extensions[extension.location].push(extension); } static removeExtension(extension) { if (!extension) { return; } const extensions = TableExtensions.extensions[extension.location]; const index = extensions.indexOf(extension); if (index >= 0) { extensions.splice(index, 1); } } static unregisterExtension(location, actionName) { if (!actionName) { return; } if (!!location) { const extension = TableExtensions.findExtension(location, actionName); TableExtensions.removeExtension(extension); } else { Object.keys(this.extensions).forEach((location) => TableExtensions.unregisterExtension(location, actionName)); } } static findExtension(location, actionName) { if (!this.extensions[location]) return null; var extension = this.extensions[location].filter(function (extension) { return extension.name == actionName; })[0]; return extension || null; } static getExtensions(location) { if (!this.extensions[location]) return []; return this.extensions[location].slice(0); } sortExtensions(extensions) { if (!Array.isArray(extensions)) return; return [] .concat(extensions.filter((extension) => extension.visibleIndex >= 0)) .sort((firstExtension, secondExtension) => { return firstExtension.visibleIndex - secondExtension.visibleIndex; }); } } TableExtensions.extensions = {}; TableExtensions.registerExtension({ location: "row", name: "details", visibleIndex: 0, render: (_table, options) => { const btn = DocumentHelper.createSvgButton("detail"); btn.title = localization.getString("showMinorColumns"); btn.className += " sa-table__row-extension"; btn.onclick = () => { options.row.toggleDetails(); }; return btn; }, }); TableExtensions.registerExtension({ location: "row", name: "select", visibleIndex: -1, render: function (_table, opt) { var row = opt.row; var checkbox = DocumentHelper.createElement("input", "sa-table__row-extension", { type: "checkbox", }); checkbox.checked = row.getIsSelected(); checkbox.onchange = function () { row.toggleSelect(); }; return checkbox; }, }); TableExtensions.registerExtension({ location: "header", name: "filter", visibleIndex: 0, render: function (table) { const input = DocumentHelper.createInput("sa-table__global-filter sa-table__header-extension", localization.getString("filterPlaceholder")); input.onchange = (event) => { table.applyFilter(event.target.value); }; return input; }, }); TableExtensions.registerExtension({ location: "header", name: "showcolumn", visibleIndex: 2, destroy: function () { this.onDestroy(); }, render: function (table) { const dropdown = DocumentHelper.createElement("select", "sa-table__show-column sa-table__header-extension"); function update() { var hiddenColumns = table.columns.filter((column) => !column.isVisible); if (hiddenColumns.length == 0) { dropdown.style.display = "none"; return; } dropdown.style.display = "inline-block"; dropdown.innerHTML = ""; var option = DocumentHelper.createElement("option", "", { text: localization.getString("showColumn"), disabled: true, selected: true, }); dropdown.appendChild(option); hiddenColumns.forEach((column) => { var text = column.displayName || column.name; if (!!text && text.length > 20) { text = text.substring(0, 20) + "..."; } var option = DocumentHelper.createElement("option", "", { text: text, title: column.displayName, value: column.name, }); dropdown.appendChild(option); }); } dropdown.onchange = (e) => { const val = e.target.value; e.stopPropagation(); if (!val) return; table.setColumnVisibility(val, true); }; update(); var onVisibilityChangedCallback = () => { update(); }; table.onColumnsVisibilityChanged.add(onVisibilityChangedCallback); this.onDestroy = () => { table.onColumnsVisibilityChanged.remove(onVisibilityChangedCallback); }; return dropdown; }, }); TableExtensions.registerExtension({ location: "header", name: "showentries", visibleIndex: 3, render: function (table) { if (table.options.paginationEnabled === false) { return DocumentHelper.createElement("div"); } function getEntriesDropdown(table) { const el = DocumentHelper.createElement("select"); var optionsValues = table.paginationSizeSelector || ["1", "5", "10", "25", "50", "75", "100"]; optionsValues.forEach(function (val) { var option = DocumentHelper.createElement("option", "", { value: val, text: val, }); el.appendChild(option); }); el.value = String(table.getPageSize()); el.onchange = () => { table.setPageSize(Number(el.value)); }; return el; } const selectorContainer = DocumentHelper.createElement("div", "sa-table__entries"); const spaceSpan = DocumentHelper.createElement("span", "sa-table__header-space"); const showSpan = DocumentHelper.createElement("span", "sa-table__entries-label sa-table__entries-label--right", { innerText: localization.getString("showLabel"), }); const entriesSpan = DocumentHelper.createElement("span", "sa-table__entries-label sa-table__entries-label--left", { innerText: localization.getString("entriesLabel"), }); selectorContainer.appendChild(spaceSpan); selectorContainer.appendChild(showSpan); selectorContainer.appendChild(getEntriesDropdown(table)); selectorContainer.appendChild(entriesSpan); return selectorContainer; }, }); TableExtensions.registerExtension({ location: "header", name: "removerows", visibleIndex: -1, render: function (table) { var btn = DocumentHelper.createElement("button", "sa-table__btn sa-table__btn--green sa-table__header-extension ", { innerText: localization.getString("removeRows") }); btn.onclick = function () { table.getCreatedRows().forEach(function (row) { if (row.getIsSelected()) { row.remove(); } }); }; return btn; }, }); TableExtensions.registerExtension({ location: "header", name: "changelocale", visibleIndex: 1, render: function (table) { var locales = table.getLocales(); if (table.options.disableLocaleSwitch || locales.length < 2) return null; const el = (DocumentHelper.createElement("select", "sa-table__header-extension", {})); var optionsValues = [localization.getString("changeLocale")].concat(locales); optionsValues.forEach(function (val) { var option = DocumentHelper.createElement("option", "", { value: val, text: localization.localeNames[val] || localization.getString(val) || val, }); el.appendChild(option); }); el.onchange = () => { table.locale = el.value; }; return el; }, }); var QuestionLocation; (function (QuestionLocation) { QuestionLocation[QuestionLocation["Column"] = 0] = "Column"; QuestionLocation[QuestionLocation["Row"] = 1] = "Row"; })(QuestionLocation || (QuestionLocation = {})); var ColumnDataType; (function (ColumnDataType) { ColumnDataType[ColumnDataType["Text"] = 0] = "Text"; ColumnDataType[ColumnDataType["FileLink"] = 1] = "FileLink"; ColumnDataType[ColumnDataType["Image"] = 2] = "Image"; ColumnDataType[ColumnDataType["NestedTable"] = 3] = "NestedTable"; ColumnDataType[ColumnDataType["Html"] = 4] = "Html"; })(ColumnDataType || (ColumnDataType = {})); TableExtensions.registerExtension({ location: "column", name: "drag", visibleIndex: 0, render: function (table, options) { const btn = DocumentHelper.createElement("button", "sa-table__svg-button sa-table__drag-button"); btn.appendChild(DocumentHelper.createSvgElement("drag")); btn.addEventListener("mousedown", () => { table.enableColumnReorder(); document.body.addEventListener("mouseup", () => { table.disableColumnReorder(); }, { once: true }); }); return btn; }, }); TableExtensions.registerExtension({ location: "column", name: "sort", visibleIndex: 1, render: function (table, options) { const descTitle = localization.getString("descOrder"); const ascTitle = localization.getString("ascOrder"); var btn = DocumentHelper.createSvgButton("sorting"); btn.title = ""; var direction = "asc"; btn.onclick = () => { if (direction == "asc") { btn.title = descTitle; direction = "desc"; } else { btn.title = ascTitle; direction = "asc"; } table.sortByColumn(options.columnName, direction); }; btn.ondrag = (e) => { e.stopPropagation(); }; return btn; }, }); TableExtensions.registerExtension({ location: "column", name: "hide", visibleIndex: 2, render: function (table, options) { var btn = DocumentHelper.createSvgButton("hide"); btn.title = localization.getString("hideColumn"); btn.onclick = () => { table.setColumnVisibility(options.columnName, false); }; return btn; }, }); TableExtensions.registerExtension({ location: "column", name: "movetodetails", visibleIndex: 3, render: function (table, options) { const button = DocumentHelper.createSvgButton("movetodetails"); button.title = localization.getString("moveToDetail"); button.onclick = (e) => { e.stopPropagation(); table.setColumnLocation(options.columnName, QuestionLocation.Row); }; return button; }, }); TableExtensions.registerExtension({ location: "column", name: "filter", visibleIndex: 4, render: function (table, options) { var el = DocumentHelper.createInput("sa-table__filter", localization.getString("filterPlaceholder")); el.onclick = (e) => e.stopPropagation(); el.onchange = (e) => { table.applyColumnFilter(options.columnName, el.value); }; return el; }, }); TableExtensions.registerExtension({ location: "column", name: "makepublic", visibleIndex: -1, render: function (table, options) { const button = DocumentHelper.createElement("button"); const makePrivateSvg = DocumentHelper.createSvgElement("makeprivate"); const makePublicSvg = DocumentHelper.createSvgElement("makepublic"); const column = table.getColumnByName(options.columnName); updateState(column); button.appendChild(makePrivateSvg); button.appendChild(makePublicSvg); button.onclick = (e) => { e.stopPropagation(); column.isPublic = !column.isPublic; updateState(column); table.onPermissionsChangedCallback && table.onPermissionsChangedCallback(table); }; function updateState(column) { if (column.isPublic) { button.className = "sa-table__svg-button"; button.title = localization.getString("makePrivateColumn"); makePrivateSvg.style.display = "none"; makePublicSvg.style.display = "block"; } else { button.className = "sa-table__svg-button sa-table__svg-button--active"; button.title = localization.getString("makePublicColumn"); makePrivateSvg.style.display = "block"; makePublicSvg.style.display = "none"; } } return button; }, }); class Details { constructor(table, row, targetNode) { this.table = table; this.row = row; this.targetNode = targetNode; this.location = "details"; this.createShowAsColumnButton = (columnName) => { const button = DocumentHelper.createElement("button", "sa-table__btn sa-table__btn--gray"); button.appendChild(document.createTextNode(localization.getString("showAsColumn"))); button.onclick = (e) => { e.stopPropagation(); this.table.setColumnLocation(columnName, QuestionLocation.Column); }; return button; }; this.detailsTable = DocumentHelper.createElement("table", "sa-table__detail-table"); this.table.onColumnsLocationChanged.add(() => { this.close(); }); } open() { this.detailsTable.innerHTML = ""; var rows = []; this.table.columns .filter((column) => column.location === QuestionLocation.Row && column) .forEach((column) => { var row = DocumentHelper.createElement("tr", "sa-table__detail"); var td1 = DocumentHelper.createElement("td"); td1.appendChild(document.createTextNode(column.displayName)); var td2 = DocumentHelper.createElement("td"); td2.textContent = this.row.getRowData()[column.name]; if (column.dataType === ColumnDataType.Image) { td2.innerHTML = "<image src='" + td2.textContent + "'/>"; } var td3 = DocumentHelper.createElement("td"); td3.appendChild(this.createShowAsColumnButton(column.name)); row.appendChild(td1); row.appendChild(td2); row.appendChild(td3); rows.push(row); }); var row = DocumentHelper.createElement("tr", "sa-table__detail"); var td = DocumentHelper.createElement("td", "", { colSpan: 3 }); var extensions = new TableExtensions(this.table); extensions.render(td, "details", { row: this.row }); if (td.children.length != 0) { row.appendChild(td); rows.push(row); } rows.forEach((row) => { this.detailsTable.appendChild(row); }); this.targetNode.appendChild(this.detailsTable); } close() { if (!!this.detailsTable.parentNode) { this.detailsTable.parentNode.removeChild(this.detailsTable); } } } class BaseColumn { constructor(question, table) { this.question = question; this.table = table; this.isVisible = true; this.isPublic = true; this.location = QuestionLocation.Column; this.dataType = this.getDataType(); this.updateWhenQuestionIsReady(question, table); } updateWhenQuestionIsReady(question, table) { if (!question || question.isReady) return; question.waitForQuestionIsReady().then(() => { if (!table.isInitialized) return; try { table.lockStateChanged(); table.refresh(!table.isInitTableDataProcessing); } finally { table.unlockStateChanged(); } }); } get name() { if (!this.nameValue) { this.name = this.getName(); } return this.nameValue; } set name(val) { this.nameValue = val; } get displayName() { if (!this.displayNameValue) { this.displayName = this.getDisplayName(); } return this.displayNameValue; } set displayName(val) { this.displayNameValue = val; } getDisplayName() { var _a; return this.table.useNamesAsTitles ? this.question.name : (((_a = this.question.locTitle) === null || _a === void 0 ? void 0 : _a.renderedHtml) || this.question.title || "").trim() || this.question.name; } getName() { return this.question.name; } getDataType() { return ColumnDataType.Text; } getDisplayValueCore(data) { return data[this.name]; } getDisplayValue(data, table, options) { let displayValue = this.getDisplayValueCore(data); const question = this.question; if (!!question) { if (options.useValuesAsLabels) { displayValue = question.value; } else { displayValue = question.displayValue; } } return displayValue; } formatDisplayValue(displayValue) { return typeof displayValue === "string" ? displayValue : JSON.stringify(displayValue) || ""; } getCellData(table, data) { const displayValue = this.getDisplayValue(data, table, table.options); return { question: this.question, displayValue: this.formatDisplayValue(displayValue) }; } toJSON() { return { name: this.name, displayName: this.displayName, dataType: this.dataType, isVisible: this.isVisible, isPublic: this.isPublic, location: this.location }; } fromJSON(data) { Object.keys(data).forEach(key => { this[key] = data[key]; }); } } class DefaultColumn extends BaseColumn { getDisplayValue(data, table, options) { return this.getDisplayValueCore(data); } } class SelectBaseColumn extends BaseColumn { get isOtherInSeparateColumn() { return this.question.hasOther && this.question.getStoreOthersAsComment(); } getItemDisplayText(item, options) { return options.useValuesAsLabels ? item.value : item.textOrHtml; } getDisplayValue(data, table, options) { const prevSeparator = settings.choicesSeparator; settings.choicesSeparator = table.itemsDelimiter; const value = options.useValuesAsLabels ? this.question.renderedValue : this.question.displayValue; settings.choicesSeparator = prevSeparator; return value; } } class CheckboxColumn extends SelectBaseColumn { getDisplayValue(data, table, options) { if (this.isOtherInSeparateColumn) { const selectedItems = this.question.selectedItems; const res = selectedItems.map(item => this.getItemDisplayText(item, options)); return res.join(table.itemsDelimiter); } return super.getDisplayValue(data, table, options); } } class FlattenedCheckboxColumn extends BaseColumn { constructor(question, choiceValue, choiceText, table) { super(question, table); this.choiceValue = choiceValue; this.choiceText = choiceText; } getDataType() { return ColumnDataType.Html; } getName() { return `${this.question.name}.${this.choiceValue}`; } getDisplayName() { var _a; const questionDisplayName = this.table.useNamesAsTitles ? this.question.name : (((_a = this.question.locTitle) === null || _a === void 0 ? void 0 : _a.renderedHtml) || this.question.title || "").trim() || this.question.name; const choiceDisplayText = this.table.useNamesAsTitles ? this.choiceValue : this.choiceText; return `${questionDisplayName} - ${choiceDisplayText}`; } getDisplayValue(data, table, options) { const questionValue = data[this.question.name]; if (!Array.isArray(questionValue)) { return ""; } const index = questionValue.indexOf(this.choiceValue); if (index < 0) { return ""; } // Default to checkmark if not specified const displayMode = options.multiSelectColumnValueFormat || "checkmark"; return displayMode === "checkmark" ? "&#10004;" : (index + 1).toString(); } } class SingleChoiceColumn extends SelectBaseColumn { getDisplayValue(data, table, options) { if (this.isOtherInSeparateColumn) { const selectedItem = this.question.selectedItem; if (!selectedItem) return ""; return this.getItemDisplayText(selectedItem, options); } return super.getDisplayValue(data, table, options); } } class CommentColumn extends BaseColumn { getName() { return `${this.question.name}${settings.commentPrefix}`; } getDisplayName() { return this.question.commentText; } getDisplayValue(data, table, options) { return this.question.comment; } } class OtherColumn extends CommentColumn { getDisplayName() { return this.question.otherText; } } class MatrixColumn extends BaseColumn { constructor(question, row, table) { var _a; super(question, table); this.row = row; this.valueName = this.question.name; this.valuePath = (_a = this.row) === null || _a === void 0 ? void 0 : _a.value; } getName() { var _a; return this.question.name + "." + ((_a = this.row) === null || _a === void 0 ? void 0 : _a.value); } getDisplayName() { const table = this.table; const question = this.question; const row = this.row; return (table.useNamesAsTitles ? question.name : (question.title || "").trim() || question.name) + " - " + (table.useNamesAsTitles ? row === null || row === void 0 ? void 0 : row.value : row === null || row === void 0 ? void 0 : row.locText.textOrHtml); } getDisplayValue(data, table, options) { let displayValue = data[this.valueName]; if (this.valuePath && typeof displayValue === "object") { displayValue = displayValue[this.valuePath]; if (displayValue !== undefined) { if (Array.isArray(displayValue)) { const res = []; displayValue.forEach(itemValue => { const item = ItemValue.getItemByValue(this.question.columns, itemValue); if (!!item) { res.push(options.useValuesAsLabels ? item.value : item.locText.textOrHtml); } }); displayValue = res.join(table.itemsDelimiter); } else { const choiceValue = ItemValue.getItemByValue(this.question.columns, displayValue); if (!!choiceValue) { displayValue = options.useValuesAsLabels ? choiceValue.value : choiceValue.locText.textOrHtml; } } } } return displayValue; } } class ImageColumn extends BaseColumn { getDataType() { return ColumnDataType.Image; } } class FileColumn extends BaseColumn { getDataType() { return ColumnDataType.FileLink; } getDisplayValue(data, table, options) { let displayValue = this.getDisplayValueCore(data); if (Array.isArray(displayValue)) { displayValue = Table.showFilesAsImages ? createImagesContainer(displayValue).outerHTML : createLinksContainer(displayValue).outerHTML; } return displayValue; } } class MatrixDropdownColumn extends BaseColumn { constructor(question, row, col, table) { super(question, table); this.row = row; this.col = col; this.rowValue = this.row.value; this.colName = this.col.name; } getName() { return this.question.name + "." + this.row.value + "." + this.col.name; } getDisplayName() { const table = this.table; const question = this.question; return (this.table.useNamesAsTitles ? question.name : (question.title || "").trim() || question.name) + " - " + (table.useNamesAsTitles ? this.row.value : this.row.locText.textOrHtml) + " - " + (table.useNamesAsTitles ? this.col.name : this.col.locTitle.textOrHtml); } getDisplayValue(data, table, options) { let displayValue = data[this.question.name]; const question = this.question; if (this.rowValue && this.colName && typeof displayValue === "object") { let [rowId, colId] = [this.rowValue, this.colName]; displayValue = question.value; if (!options.useValuesAsLabels) { displayValue = question.displayValue; rowId = question.rows.filter(row => row.value === this.rowValue)[0].text; colId = question.getColumnByName(this.colName).title; } displayValue = (displayValue[rowId] && displayValue[rowId][colId]) || ""; } return displayValue; } } class CustomQuestionColumn extends BaseColumn { constructor(question, table) { super(question, table); this.updateWhenQuestionIsReady(question.contentQuestion, table); } } class CompositeQuestionColumn extends BaseColumn { constructor(question, table) { super(question, table); const questionList = []; this.question.contentPanel.addQuestionsToList(questionList); questionList.forEach((q) => { this.updateWhenQuestionIsReady(q, table); }); } } class MatrixDynamicColumn extends BaseColumn { getDataType() { return this.table.options.useNestedTables ? ColumnDataType.NestedTable : ColumnDataType.Text; } getDisplayValue(data, table, options) { if (table.options.useNestedTables) { return this.getDisplayValueCore(data); } return super.getDisplayValue(data, table, options); } getCellData(table, data) { const displayValue = this.getDisplayValue(data, table, table.options); const formattedValue = table.options.useNestedTables && Array.isArray(displayValue) ? displayValue : (typeof displayValue === "string" ? displayValue : JSON.stringify(displayValue) || ""); return { question: this.question, displayValue: formattedValue }; } } class PanelDynamicColumn extends BaseColumn { getDataType() { return this.table.options.useNestedTables ? ColumnDataType.NestedTable : ColumnDataType.Text; } getDisplayValue(data, table, options) { if (table.options.useNestedTables) { return this.getDisplayValueCore(data); } return super.getDisplayValue(data, table, options); } getCellData(table, data) { const displayValue = this.getDisplayValue(data, table, table.options); const formattedValue = table.options.useNestedTables && Array.isArray(displayValue) ? displayValue : (typeof displayValue === "string" ? displayValue : JSON.stringify(displayValue) || ""); return { question: this.question, displayValue: formattedValue }; } } class DefaultColumnsBuilder { createColumn(question, table) { return new BaseColumn(question, table); } buildColumnsCore(question, table) { const columns = []; columns.push(this.createColumn(question, table)); return columns; } buildColumns(question, table) { const columns = this.buildColumnsCore(question, table); if (question.hasComment) { columns.push(new CommentColumn(question, table)); } return columns; } } class ColumnsBuilderFactory { constructor() { this.columnsBuilders = {}; this.defaultColumnsBuilder = new DefaultColumnsBuilder(); } registerBuilderColumn(type, columnsBuilder) { this.columnsBuilders[type] = columnsBuilder; } getColumnsBuilder(type) { return this.columnsBuilders[type] || this.defaultColumnsBuilder; } } ColumnsBuilderFactory.Instance = new ColumnsBuilderFactory(); class SelectBaseColumnsBuilder extends DefaultColumnsBuilder { buildColumns(question, table) { const columns = super.buildColumns(question, table); if (question.hasOther && question.getStoreOthersAsComment()) { columns.push(new OtherColumn(question, table)); } return columns; } } class CheckboxColumnsBuilder extends SelectBaseColumnsBuilder { createColumn(question, table) { return new CheckboxColumn(question, table); } buildColumnsCore(question, table) { if (table.options.splitMultiSelectIntoColumns) { const columns = []; question.visibleChoices.forEach(choice => { columns.push(new FlattenedCheckboxColumn(question, choice.value, choice.text, table)); }); return columns; } return super.buildColumnsCore(question, table); } } ColumnsBuilderFactory.Instance.registerBuilderColumn("checkbox", new CheckboxColumnsBuilder()); ColumnsBuilderFactory.Instance.registerBuilderColumn("tagbox", new CheckboxColumnsBuilder()); class SingleChoiceColumnsBuilder extends SelectBaseColumnsBuilder { createColumn(question, table) { return new SingleChoiceColumn(question, table); } } ColumnsBuilderFactory.Instance.registerBuilderColumn("radiogroup", new SingleChoiceColumnsBuilder()); ColumnsBuilderFactory.Instance.registerBuilderColumn("dropdown", new SingleChoiceColumnsBuilder()); class MatrixColumnsBuilder extends DefaultColumnsBuilder { buildColumnsCore(questionBase, table) { const question = questionBase; const columns = []; question.rows.forEach(row => { columns.push(new MatrixColumn(question, row, table)); }); return columns; } } ColumnsBuilderFactory.Instance.registerBuilderColumn("matrix", new MatrixColumnsBuilder()); class ImageColumnsBuilder extends DefaultColumnsBuilder { createColumn(question, table) { return new ImageColumn(question, table); } } ColumnsBuilderFactory.Instance.registerBuilderColumn("signaturepad", new ImageColumnsBuilder()); class FileColumnsBuilder extends DefaultColumnsBuilder { createColumn(question, table) { return new FileColumn(question, table); } } ColumnsBuilderFactory.Instance.registerBuilderColumn("file", new FileColumnsBuilder()); class MatrixDropdownColumnBuilder extends DefaultColumnsBuilder { buildColumns(questionBase, table) { const question = questionBase; const isDetailRowLocation = question.rows.length > 5; const columns = []; question.rows.forEach(row => { question.columns.forEach(col => { const column = new MatrixDropdownColumn(question, row, col, table); if (isDetailRowLocation) { column.location = QuestionLocation.Row; } columns.push(column); }); }); return columns; } } ColumnsBuilderFactory.Instance.registerBuilderColumn("matrixdropdown", new MatrixDropdownColumnBuilder()); class CustomColumnsBuilder extends DefaultColumnsBuilder { createColumn(question, table) { return new CustomQuestionColumn(question, table); } } ColumnsBuilderFactory.Instance.registerBuilderColumn("custom", new CustomColumnsBuilder()); class CompositeColumnsBuilder extends DefaultColumnsBuilder { getDisplayName(question, table) { var _a; return table.useNamesAsTitles ? question.name : (((_a = question.locTitle) === null || _a === void 0 ? void 0 : _a.renderedHtml) || question.title || "").trim() || question.name; } buildColumnsCore(question, table) { if (CompositeColumnsBuilder.ShowAsSeparateColumns) { const innerQuestions = []; question.contentPanel.addQuestionsToList(innerQuestions); let columns = []; innerQuestions.forEach(innerQuestion => { const builder = ColumnsBuilderFactory.Instance.getColumnsBuilder(innerQuestion.getType()); const cols = builder.buildColumns(innerQuestion, table); cols.forEach(col => { col.name = question.name + "." + col.name; col.displayName = this.getDisplayName(question, table) + " - " + this.getDisplayName(innerQuestion, table); }); columns = columns.concat(cols); }); return columns; } return super.buildColumnsCore(question, table); } createColumn(question, table) { return new CompositeQuestionColumn(question, table); } } CompositeColumnsBuilder.ShowAsSeparateColumns = true; ColumnsBuilderFactory.Instance.registerBuilderColumn("composite", new CompositeColumnsBuilder()); class MatrixDynamicColumnsBuilder extends DefaultColumnsBuilder { createColumn(question, table) { return new MatrixDynamicColumn(question, table); } } ColumnsBuilderFactory.Instance.registerBuilderColumn("matrixdynamic", new MatrixDynamicColumnsBuilder()); class PanelDynamicColumnsBuilder extends DefaultColumnsBuilder { createColumn(question, table) { return new PanelDynamicColumn(question, table); } } ColumnsBuilderFactory.Instance.registerBuilderColumn("paneldynamic", new PanelDynamicColumnsBuilder()); // export type GetDataFn = (params: { filter?: any, limit?: number, offset?: number, callback?: (response: { data: Array<Object>, total: number, error?: any }) => void }) => Promise<{ data: Array<Object>, total: number, error?: any }> | void; class TableEvent extends EventBase { } class Table { constructor(_survey, data, _options = {}, _columnsData = []) { this._survey = _survey; this.data = data; this._options = _options; this._columnsData = _columnsData; this.haveCommercialLicense = false; this.currentPageSize = 5; this._rows = []; this.isInitialized = false; /** * Sets pagination selector content. */ this.paginationSizeSelector = [1, 5, 10, 25, 50, 100]; this.onColumnsVisibilityChanged = new TableEvent(); this.onColumnsLocationChanged = new TableEvent(); this.onRowRemoved = new TableEvent(); this.buildColumns = (survey) => { let columns = []; this._survey.getAllQuestions().forEach((question) => { if (!this.isNonValueQuestion(question)) { const builder = ColumnsBuilderFactory.Instance.getColumnsBuilder(question.getTemplate()); columns = columns.concat(builder.buildColumns(question, this)); } }); return columns; }; this._lockStateChanged = false; /** * Fires when table state changed. */ this.onStateChanged = new TableEvent(); if (!this._options) { this._options = {}; } if (typeof this._options.useNestedTables === "undefined") { this._options.useNestedTables = true; } this.initialize(); this.extensions = new TableExtensions(this); const f = hasLicense; this.haveCommercialLicense = (!!f && f(4)) || Table.haveCommercialLicense || (!!_options && (typeof _options.haveCommercialLicense !== "undefined" ? _options.haveCommercialLicense : false)); } initialize() { this.isInitialized = false; this.currentPageSize = this.options.pageSize || 5; this.currentPageNumber = 1; this._columns = this.buildColumns(this._survey); this.initTableData(this.data); localization.currentLocale = this._survey.locale; if (this._columnsData.length !== 0) { this.updateColumnsFromData(this._columnsData); } this.isInitialized = true; } getTableData() { return [].concat(this.tableData || []); } getData() { return this.data; } get survey() { return this._survey; } get options() { return this._options; } render(targetNode) { if (typeof targetNode === "string") { targetNode = document.getElementById(targetNode); } targetNode.innerHTML = ""; if (!this.haveCommercialLicense) { targetNode.appendChild(createCommercialLicenseLink()); } } enableColumnReorder() { this.isColumnReorderEnabled = true; } disableColumnReorder() { this.isColumnReorderEnabled = false; } getPageNumber() { return this.currentPageNumber; } setPageNumber(value) { this.currentPageNumber = value; } /** * Returns current page size. */ getPageSize() { return this.currentPageSize; } /** * Sets current page size. */ setPageSize(value) { this.currentPageSize = value; this.stateChanged(); } getCreatedRows() { return [].concat(this._rows); } clearCreatedRows() { this._rows.forEach((row) => { row.destroy(); }); this._rows = []; } get useNamesAsTitles() { return this._options && this._options.useNamesAsTitles === true; } get itemsDelimiter() { return this._options && this._options.itemsDelimiter || ", "; } isNonValueQuestion(question) { return Serializer.isDescendantOf(question.getType(), "nonvalue"); } isColumnVisible(column) { if (column.location !== QuestionLocation.Column) return false; return column.isVisible; } get columns() { return [].concat(this._columns); } set columns(columns) { this._columns = columns; this.refresh(true); this.stateChanged(); } get isInitTableDataProcessing() { return this.isInitTableDataProcessingValue; } initTableData(data) { if (!Array.isArray(data)) { this.tableData = undefined; return; } this.isInitTableDataProcessingValue = true; this.tableData = (data || []).map((item) => this.processLoadedDataItem(item)); this.isInitTableDataProcessingValue = false; } processLoadedDataItem(item) { var dataItem = {}; this._survey.data = item; this._columns.forEach((column) => { const opt = column.getCellData(this, item); if (typeof this._options.onGetQuestionValue === "function") { this._options.onGetQuestionValue(opt); } dataItem[column.name] = opt.displayValue; }); return dataItem; } moveColumn(from, to) { var deletedColumns = this._columns.splice(from, 1); this._columns.splice(to, 0, deletedColumns[0]); this.stateChanged(); } setColumnLocation(columnName, location) { this.getColumnByName(columnName).location = location; this.onColumnsLocationChanged.fire(this, { columnName: columnName, location: location, }); this.stateChanged(); } getColumnByName(columnName) { return this._columns.filter((column) => column.name === columnName)[0]; } setColumnVisibility(columnName, isVisible) { var column = this.getColumnByName(columnName); column.isVisible = isVisible; this.onColumnsVisibilityChanged.fire(this, { columnName: columnName, columnVisibility: isVisible, }); this.stateChanged(); } setColumnWidth(columnName, width) { var column = this.getColumnByName(columnName); column.width = width; this.stateChanged(); } removeRow(row) { var index = this._rows.indexOf(row); this._rows.splice(index, 1); this.onRowRemoved.fire(this, { row: row }); } /** * Returns current locale of the table. * If locales more than one, the language selection dropdown will be added in the toolbar */ get locale() { return localization.currentLocale; } /** * Sets locale for table. */ set locale(newLocale) { this._survey.locale = newLocale; localization.currentLocale = newLocale; this.columns.forEach(c => c.displayName = undefined); this.refresh(true); this.stateChanged(); } lockStateChanged() { this._lockStateChanged = true; } unlockStateChanged() { this._lockStateChanged = false; } stateChanged() { if (this._lockStateChanged) return; this.onStateChanged.fire(this, this.state); } getLocales() { return [].concat(this._survey.getUsedLocales()); } supportSoftRefresh() { return false; } softRefresh() { this.hardRefresh(); } hardRefresh() { this.initTableData(this.data); if (this.isRendered) { this.currentPageNumber = this.getPageNumber(); const targetNode = this.renderResult; this.destroy(); this.render(targetNode); this.setPageSize(this.currentPageSize); this.setPageNumber(this.currentPageNumber); } } refresh(hard = false) { if (hard || !this.supportSoftRefresh()) { this.hardRefresh(); } else { this.softRefresh(); } } destroy() { this.clearCreatedRows(); this.extensions.destroy(); this.renderResult.innerHTML = ""; this.renderResult = undefined; } get isRendered() { return !!this.renderResult; } /** * Table state getter. */ get state() { return { locale: localization.currentLocale, elements: JSON.parse(JSON.stringify(this._columns)), pageSize: this.currentPageSize, }; } /** * Table state setter. */ set state(newState) { if (!newState) return; if (typeof newState.elements !== "undefined") { this.updateColumnsFromData(newState.elements); } if (typeof newState.locale !== "undefined") { localization.currentLocale = newState.locale; this._survey.locale = newState.locale; this.initTableData(this.data); } if (typeof newState.pageSize !== "undefined") { this.currentPageSize = newState.pageSize; } this.refresh(true); } /** * Resets table state. */ resetState() { this._survey.locale = surveyLocalization.defaultLocale; this.initialize(); this.refresh(true); this.stateChanged(); } updateColumnsFromData(columnsData) { const columns = this._columns; columns.forEach(column => { const el = columnsData.filter(el => column.name === el.name)[0]; if (!!el) { column.fromJSON(el); column.visibleIndex = columnsData.indexOf(el); } }); columnsData.forEach(el => { let column = columns.filter(column => column.name === el.name)[0]; if (!column) { column = new DefaultColumn(undefined, this); column.fromJSON(el); column.visibleIndex = columnsData.indexOf(el); columns.push(column); } }); this._columns = this._columns.sort((col1, col2) => col1.visibleIndex - col2.visibleIndex); } /** * Gets table permissions. */ get permissions() { return this._columns.map((column) => { return { name: column.name, isPublic: column.isPublic, }; }); } /** * Sets table permissions. */ set permissions(permissions) { const updatedElements = this._columns.map((column) => { permissions.forEach((permission) => { if (permission.name === column.name) column.isPublic = permission.isPublic; }); return column; }); this._columns = [].concat(updatedElements); this.onPermissionsChangedCallback && this.onPermissionsChangedCallback(this); } get allowSorting() { return this.options.allowSorting === undefined || this.options.allowSorting === true; } allowExtension(extension) { if (extension.location === "column" && extension.name === "sort") { return this.allowSorting; } return true; } } Table.showFilesAsImages = false; Table.haveCommercialLicense = false; class TableRow { constructor(table, extensionsContainer, detailsContainer) { this.table = table; this.extensionsContainer = extensionsContainer; this.detailsContainer = detailsContainer; this.detailedRowClass = "sa-table__detail-row"; this.isDetailsExpanded = false; this.onToggleDetails = new Event(); this.onColumnLocationChangedCallback = () => { this.closeDetails(); }; this.details = new Details(table, this, detailsContainer); this.extensions = new TableExtensions(table); table.onColumnsLocationChanged.add(this.onColumnLocationChangedCallback); } render() { this.extensions.render(this.extensionsContainer, "row", { row: this }); } openDetails() { this.details.open(); this.getElement().className += " " + this.detailedRowClass; this.onToggleDetails.fire(this, { isExpanded: true }); this.isDetailsExpanded = true; } closeDetails() { this.details.close(); this.getElement().classList.remove(this.detailedRowClass); this.onToggleDetails.fire(this, { isExpanded: false }); this.isDetailsExpanded = false; } toggleDetails() { if (this.isDetailsExpanded) { this.closeDetails(); } else this.openDetails(); } getIsSelected() { return this.isSelected; } toggleSelect() { this.isSelected = !this.isSelected; } remove() { this.table.removeRow(this); this.destroy(); } destroy() { this.table.onColumnsLocationChanged.remove(this.onColumnLocationChangedCallback); this.extensions.destroy(); } } const ARIAL_FONT = "AAEAAAAXAQAABABwRFNJRyQ9+ecABX+MAAAafEdERUZeI11yAAV1GAAAAKZHU1VC1fDdzAAFdcAAAAmqSlNURm0qaQYABX9sAAAAHkxUU0iAZfo8AAAceAAABo5PUy8yDN8yawAAAfgAAABWUENMVP17PkMABXTgAAAANlZETVhQkmr1AAAjCAAAEZRjbWFw50BqOgAA0cQAABdqY3Z0IJYq0nYAAPqgAAAGMGZwZ23MeVmaAADpMAAABm5nYXNwABgACQAFdNAAAAAQZ2x5Zg73j+wAARr8AAPnYmhkbXi+u8OXAAA0nAAAnShoZWFkzpgmkgAAAXwAAAA2aGhlYRIzEv8AAAG0AAAAJGhtdHgONFhAAAACUAAAGihrZXJuN2E5NgAFAmAAABVgbG9jYQ5haTIAAQDQAAAaLG1heHALRwyoAAAB2AAAACBuYW1lwPJlOwAFF8AAABsNcG9zdI/p134ABTLQAABB/3ByZXBS/sTpAADvoAAACv8AAQAAAAMAAObouupfDzz1CBsIAAAAAACi4ycqAAAAALnVtPb6r/1nEAAIDAAAAAkAAQABAAAAAAABAAAHPv5OAEMQAPqv/iYQAAABAAAAAAAAAAAAAAAAAAAGigABAAAGigEAAD8AdgAHAAIAEAAvAFYAAAQNCv8AAwACAAEDiAGQAAUAAAWaBTMAAAEbBZoFMwAAA9EAZgISCAUCCwYEAgICAgIEAAB6h4AAAAAAAAAIAAAAAE1vbm8AQAAg//wF0/5RATMHPgGyQAAB////AAAAAAYAAQAAAAAAAjkAAAI5AAACOQCwAtcAXgRzABUEcwBJBx0AdwVWAFgBhwBaAqoAfAKqAHwDHQBABKwAcgI5AKoCqg