diff --git a/packages/survey-angular-ui/src/questions/matrixdropdowncell.component.html b/packages/survey-angular-ui/src/questions/matrixdropdowncell.component.html index 346a56c3db..44f1635e34 100644 --- a/packages/survey-angular-ui/src/questions/matrixdropdowncell.component.html +++ b/packages/survey-angular-ui/src/questions/matrixdropdowncell.component.html @@ -8,7 +8,7 @@
-
div { + & > div { box-sizing: border-box; padding-left: calcSize(2); display: flex; @@ -53,14 +53,14 @@ .sd-row--multiple { row-gap: var(--sd-base-vertical-padding); - &>div { + & > div { padding-left: var(--sd-base-padding); } } } .sd-row--multiple.sd-row--compact { - &>div { + & > div { padding-left: var(--sd-base-padding); } } @@ -69,13 +69,12 @@ margin-left: calcSize(-2); width: calc(100% + 2 * var(--sjs-base-unit, var(--base-unit, 8px))); - &.sd-row--compact { padding: 0; + row-gap: var(--sd-base-vertical-padding); margin-left: calc(-1 * var(--sd-base-padding)); width: calc(100% + var(--sd-base-padding)); } - } .sd-row__panel { @@ -87,4 +86,4 @@ box-sizing: border-box; width: 100%; white-space: nowrap; -} \ No newline at end of file +} diff --git a/src/defaultV2-theme/blocks/sd-table.scss b/src/defaultV2-theme/blocks/sd-table.scss index 030c8b5e78..f2b3039de4 100644 --- a/src/defaultV2-theme/blocks/sd-table.scss +++ b/src/defaultV2-theme/blocks/sd-table.scss @@ -161,6 +161,7 @@ &:not(.sd-table__cell--empty):not(.sd-table__cell--actions):not(:empty) { min-width: calcSize(15); } + .sd-item { text-align: initial; } @@ -253,6 +254,7 @@ .sd-table__cell--footer { text-align: right; + padding-top: calcSize(1); } .sd-table__cell--footer-total { @@ -719,6 +721,30 @@ } } +.sd-table__cell--footer { + .sd-table__question-wrapper--expression { + .sd-expression { + padding: calcSize(1.5) calcSize(2); + border-bottom: 1px solid $border-light; + font-size: calcFontSize(1); + font-weight: 600; + line-height: calcSize(3); + } + } + + .sd-table__question-wrapper--left { + text-align: start; + } + + .sd-table__question-wrapper--center { + text-align: center; + } + + .sd-table__question-wrapper--right { + text-align: end; + } +} + .sd-table.sd-matrixdynamic { table-layout: auto; } \ No newline at end of file diff --git a/src/knockout/templates/question-matrixdynamic.html b/src/knockout/templates/question-matrixdynamic.html index 60f2c332df..fac155152e 100644 --- a/src/knockout/templates/question-matrixdynamic.html +++ b/src/knockout/templates/question-matrixdynamic.html @@ -51,7 +51,7 @@ data-bind="css: $data.className, style: { minWidth: $data.minWidth, width: $data.width }, attr: { 'data-responsive-title': headers, title: $data.getTitle(), colspan: $data.colSpans }, event: {focusin: $data.focusIn }" > -
+
diff --git a/src/knockout/templates/question.html b/src/knockout/templates/question.html index f709828fb8..98a0616081 100644 --- a/src/knockout/templates/question.html +++ b/src/knockout/templates/question.html @@ -10,8 +10,13 @@ + + + + - +
+ diff --git a/src/knockout/templates/questioncontent.html b/src/knockout/templates/questioncontent.html index 51467398cf..88bba0bf6f 100644 --- a/src/knockout/templates/questioncontent.html +++ b/src/knockout/templates/questioncontent.html @@ -1,40 +1,36 @@  \ No newline at end of file diff --git a/src/question_matrixdropdownbase.ts b/src/question_matrixdropdownbase.ts index fadf184f85..21a7fac60a 100644 --- a/src/question_matrixdropdownbase.ts +++ b/src/question_matrixdropdownbase.ts @@ -119,6 +119,9 @@ export class MatrixDropdownCell { public set value(value: any) { this.question.value = value; } + public getQuestionWrapperClassName(className: string): string { + return className; + } public runCondition(values: HashTable, properties: HashTable) { this.question.runCondition(values, properties); } @@ -160,6 +163,22 @@ export class MatrixDropdownTotalCell extends MatrixDropdownCell { this.question.unlocCalculation(); this.question.runIfReadOnly = true; } + public getQuestionWrapperClassName(className: string): string { + let result = super.getQuestionWrapperClassName(className); + if (!result) { + return result; + } + if (this.question.expression && this.question.expression != "''") { + result += " " + className + "--expression"; + } + let alignment = this.column.totalAlignment; + if (alignment === "auto") { + if (this.column.cellType === "dropdown") { + alignment = "left"; + } + } + return result + " " + className + "--" + alignment; + } public getTotalExpression(): string { if (!!this.column.totalExpression) return this.column.totalExpression; if (this.column.totalType == "none") return "''"; diff --git a/src/question_matrixdropdowncolumn.ts b/src/question_matrixdropdowncolumn.ts index 16fdc7b45a..46ec4dbc2f 100644 --- a/src/question_matrixdropdowncolumn.ts +++ b/src/question_matrixdropdowncolumn.ts @@ -31,7 +31,7 @@ export interface IMatrixColumnOwner extends ILocalizableOwner { getCellType(): string; getCustomCellType(column: MatrixDropdownColumn, row: MatrixDropdownRowModelBase, cellType: string): string; onColumnCellTypeChanged(column: MatrixDropdownColumn): void; - getCellAriaLabel(rowTitle:string, columnTitle:string):string; + getCellAriaLabel(rowTitle: string, columnTitle: string): string; } function onUpdateSelectBaseCellQuestion( @@ -223,7 +223,7 @@ export class MatrixDropdownColumn extends Base return true; } public get isColumnVisible(): boolean { - if(this.isDesignMode) return true; + if (this.isDesignMode) return true; return this.visible && this.hasVisibleCell; } /** @@ -245,17 +245,17 @@ export class MatrixDropdownColumn extends Base } public getVisibleMultipleChoices(): Array { const choices = this.templateQuestion.visibleChoices; - if(!Array.isArray(choices)) return []; - if(!Array.isArray(this._visiblechoices)) return choices; + if (!Array.isArray(choices)) return []; + if (!Array.isArray(this._visiblechoices)) return choices; const res = new Array(); - for(let i = 0; i < choices.length; i ++) { + for (let i = 0; i < choices.length; i++) { const item = choices[i]; - if(this._visiblechoices.indexOf(item.value) > -1) res.push(item); + if (this._visiblechoices.indexOf(item.value) > -1) res.push(item); } return res; } public get getVisibleChoicesInCell(): Array { - if(Array.isArray(this._visiblechoices)) return this._visiblechoices; + if (Array.isArray(this._visiblechoices)) return this._visiblechoices; const res = this.templateQuestion.visibleChoices; return Array.isArray(res) ? res : []; } @@ -263,11 +263,11 @@ export class MatrixDropdownColumn extends Base this._visiblechoices = val; } public get isFilteredMultipleColumns(): boolean { - if(!this.showInMultipleColumns) return false; + if (!this.showInMultipleColumns) return false; const choices = this.templateQuestion.choices; - if(!Array.isArray(choices)) return false; - for(let i = 0; i < choices.length; i ++) { - if(choices[i].visibleIf) return true; + if (!Array.isArray(choices)) return false; + for (let i = 0; i < choices.length; i++) { + if (choices[i].visibleIf) return true; } return false; } @@ -586,6 +586,28 @@ export class MatrixDropdownColumn extends Base public set totalDisplayStyle(val: string) { this.setPropertyValue("totalDisplayStyle", val); } + /** + * An alignment for calculated total values. + * + * Possible values: + * + * - `"left"` + * - `"center"` + * - `"right"` + * - `"auto"` (default) - Applies one of the values above based on the column's [cell type](#cellType). + * + * [View Demo](https://surveyjs.io/form-library/examples/aggregate-data-within-form/ (linkStyle)) + * @see totalType + * @see totalFormat + * @see totalCurrency + * @see totalDisplayStyle + */ + public get totalAlignment(): string { + return this.getPropertyValue("totalAlignment"); + } + public set totalAlignment(val: string) { + this.setPropertyValue("totalAlignment", val); + } /** * Specifies a currency used to display calculated total values. Applies only if [`totalDisplayStyle`](#totalDisplayStyle) is set to `"currency"`. * @see totalType @@ -913,6 +935,11 @@ Serializer.addClass( default: "none", choices: ["none", "decimal", "currency", "percent"], }, + { + name: "totalAlignment", + default: "auto", + choices: ["auto", "left", "center", "right"], + }, { name: "totalCurrency", choices: () => { diff --git a/src/question_matrixdropdownrendered.ts b/src/question_matrixdropdownrendered.ts index 7e144823b4..33404ce105 100644 --- a/src/question_matrixdropdownrendered.ts +++ b/src/question_matrixdropdownrendered.ts @@ -95,28 +95,31 @@ export class QuestionMatrixDropdownRenderedCell { } return builder.toString(); } + public get cellQuestionWrapperClassName(): string { + return this.cell.getQuestionWrapperClassName(this.matrix.cssClasses.cellQuestionWrapper); + } public get headers(): string { - if(this.cell && this.cell.column) { + if (this.cell && this.cell.column) { if (this.matrix.IsMultiplyColumn(this.cell.column)) { - if(!!this.item) { + if (!!this.item) { return this.item.locText.renderedHtml; } else { return ""; } } let cellHint = this.cell.column.cellHint; - if(!!cellHint) { - if(cellHint.trim() === "") return ""; + if (!!cellHint) { + if (cellHint.trim() === "") return ""; return this.cell.column.locCellHint.renderedHtml; } - if(this.hasQuestion && this.question.isVisible && this.question.title) + if (this.hasQuestion && this.question.isVisible && this.question.title) return this.question.title; return this.cell.column.title; } - if(this.hasQuestion && this.question.isVisible) { + if (this.hasQuestion && this.question.isVisible) { return this.question.locTitle.renderedHtml; } - if(this.hasTitle) { + if (this.hasTitle) { return this.locTitle.renderedHtml || ""; } return ""; @@ -135,7 +138,7 @@ export class QuestionMatrixDropdownRenderedCell { .toString(); } public focusIn(): void { - if(this.question) { + if (this.question) { this.question.focusIn(); } } @@ -195,7 +198,7 @@ export class QuestionMatrixDropdownRenderedErrorRow extends QuestionMatrixDropdo this.visible = this.cells.some((cell) => cell.question && cell.question.hasVisibleErrors); }; this.cells.forEach((cell) => { - if(cell.question) { + if (cell.question) { cell.question.registerFunctionOnPropertyValueChanged("hasVisibleErrors", callback); } }); @@ -209,7 +212,7 @@ export class QuestionMatrixDropdownRenderedTable extends Base { private hasRemoveRowsValue: boolean; private rowsActions: Array>; private cssClasses: any; - public renderedRowsChangedCallback = ():void=>{}; + public renderedRowsChangedCallback = (): void => { }; @propertyArray({ onPush: (_: any, i: number, target: QuestionMatrixDropdownRenderedTable) => { target.renderedRowsChangedCallback(); @@ -316,14 +319,14 @@ export class QuestionMatrixDropdownRenderedTable extends Base { let res = 0; let dataRowIndex = 0; for (var i = 0; i < this.rows.length; i++) { - if(dataRowIndex === index) { - if (this.rows[i].isErrorsRow|| this.rows[i].isDetailRow) res++; + if (dataRowIndex === index) { + if (this.rows[i].isErrorsRow || this.rows[i].isDetailRow) res++; break; } - res ++; + res++; if (!(this.rows[i].isErrorsRow) && !this.rows[i].isDetailRow) dataRowIndex++; } - if(dataRowIndex < index) return this.rows.length; + if (dataRowIndex < index) return this.rows.length; return res; } private getRenderedDataRowCount(): number { @@ -353,7 +356,7 @@ export class QuestionMatrixDropdownRenderedTable extends Base { ) { removeCount++; } - if(rowIndex > 0 && this.showCellErrorsTop && this.rows[rowIndex - 1].isErrorsRow) { + if (rowIndex > 0 && this.showCellErrorsTop && this.rows[rowIndex - 1].isErrorsRow) { rowIndex--; removeCount++; } @@ -367,11 +370,11 @@ export class QuestionMatrixDropdownRenderedTable extends Base { const rowIndex = this.getRenderedRowIndex(row); if (rowIndex < 0) return; let currentIndex = rowIndex; - if(this.showCellErrorsBottom) currentIndex ++; + if (this.showCellErrorsBottom) currentIndex++; var panelRowIndex = - currentIndex < this.rows.length - 1 && this.rows[currentIndex + 1].isDetailRow - ? currentIndex + 1 - : -1; + currentIndex < this.rows.length - 1 && this.rows[currentIndex + 1].isDetailRow + ? currentIndex + 1 + : -1; if ((isShowing && panelRowIndex > -1) || (!isShowing && panelRowIndex < 0)) return; if (isShowing) { @@ -495,7 +498,7 @@ export class QuestionMatrixDropdownRenderedTable extends Base { return this.hasActionCellInRowsValues[location]; } private hasActionsCellInLocaltion(location: "start" | "end"): boolean { - if(location == "end" && this.hasRemoveRows) return true; + if (location == "end" && this.hasRemoveRows) return true; return this.matrix.visibleRows.some( (row, index) => !this.isValueEmpty(this.getRowActions(index, location))); } @@ -522,17 +525,17 @@ export class QuestionMatrixDropdownRenderedTable extends Base { const renderedRow = this.createHorizontalRow(row, useAsHeader); const errorRow = this.createErrorRow(renderedRow); renderedRow.row = row; - if(index < 0) { + if (index < 0) { index = renderedRows.length; } - if(this.matrix.isMobile) { + if (this.matrix.isMobile) { const cells = []; - for(let i = 0; i < renderedRow.cells.length; i ++) { - if(this.showCellErrorsTop && !errorRow.cells[i].isEmpty) { + for (let i = 0; i < renderedRow.cells.length; i++) { + if (this.showCellErrorsTop && !errorRow.cells[i].isEmpty) { cells.push(errorRow.cells[i]); } cells.push(renderedRow.cells[i]); - if(this.showCellErrorsBottom && !errorRow.cells[i].isEmpty) { + if (this.showCellErrorsBottom && !errorRow.cells[i].isEmpty) { cells.push(errorRow.cells[i]); } } @@ -575,7 +578,7 @@ export class QuestionMatrixDropdownRenderedTable extends Base { if (!this.isValueEmpty(rowActions)) { const cell = new QuestionMatrixDropdownRenderedCell(); const actionContainer = this.matrix.allowAdaptiveActions ? new AdaptiveActionContainer() : new ActionContainer(); - if(!!this.matrix.survey && this.matrix.survey.getCss().actionBar) { + if (!!this.matrix.survey && this.matrix.survey.getCss().actionBar) { actionContainer.cssClasses = this.matrix.survey.getCss().actionBar; } actionContainer.setItems(rowActions); @@ -689,11 +692,11 @@ export class QuestionMatrixDropdownRenderedTable extends Base { const res = this.createErrorRenderedRow(this.cssClasses); for (let i = 0; i < row.cells.length; i++) { const cell = row.cells[i]; - if(!cell.hasQuestion) { + if (!cell.hasQuestion) { res.cells.push(this.createEmptyCell(true)); } else if (this.matrix.IsMultiplyColumn(cell.cell.column)) { - if(cell.isFirstChoice) { + if (cell.isFirstChoice) { res.cells.push(this.createErrorCell(cell.cell)); } else { res.cells.push(this.createEmptyCell(true)); @@ -779,7 +782,7 @@ export class QuestionMatrixDropdownRenderedTable extends Base { buttonCell.colSpans = 2; } buttonCell.isEmpty = true; - if(!panelFullWidth) res.cells.push(buttonCell); + if (!panelFullWidth) res.cells.push(buttonCell); var actionsCell = null; if (this.hasActionCellInRows("end")) { actionsCell = new QuestionMatrixDropdownRenderedCell(); @@ -820,7 +823,7 @@ export class QuestionMatrixDropdownRenderedTable extends Base { } else { const renderedRow = this.createVerticalRow(col, i); const errorRow = this.createErrorRow(renderedRow); - if(this.showCellErrorsTop) { + if (this.showCellErrorsTop) { renderedRows.push(errorRow); renderedRows.push(renderedRow); } else { @@ -845,7 +848,7 @@ export class QuestionMatrixDropdownRenderedTable extends Base { for (var i = 0; i < choices.length; i++) { const renderedRow = this.createVerticalRow(column, index, choices[i], i); const errorRow = this.createErrorRow(renderedRow); - if(this.showCellErrorsTop) { + if (this.showCellErrorsTop) { renderedRows.push(errorRow); renderedRows.push(renderedRow); } else { @@ -1026,7 +1029,7 @@ export class QuestionMatrixDropdownRenderedTable extends Base { ): QuestionMatrixDropdownRenderedCell { var cell = new QuestionMatrixDropdownRenderedCell(); cell.locTitle = locTitle; - if(!!locTitle) { + if (!!locTitle) { locTitle.strChanged(); } if (!!this.cssClasses.cell) { diff --git a/src/react/reactquestion.tsx b/src/react/reactquestion.tsx index ee736af64b..deac0c7355 100644 --- a/src/react/reactquestion.tsx +++ b/src/react/reactquestion.tsx @@ -354,7 +354,7 @@ export class SurveyQuestionAndErrorsCell extends SurveyQuestionAndErrorsWrapped > {this.wrapCell(this.props.cell, ( -
+
{this.renderQuestion()}
) )} diff --git a/src/vue/matrixdropdowncell.vue b/src/vue/matrixdropdowncell.vue index 9cf714114b..044e11b9ff 100644 --- a/src/vue/matrixdropdowncell.vue +++ b/src/vue/matrixdropdowncell.vue @@ -22,7 +22,7 @@ :question="cell.panel" :css="question.cssClasses" > -
+
): void { for (var i = 0; i < objs.length; i++) { objs[i].question = objs[i].question.name; - if(!!objs[i].context) { + if (!!objs[i].context) { objs[i].context = objs[i].context.name; } } @@ -1604,7 +1604,8 @@ QUnit.test("matrixDynamic.addConditionObjectsByContext", function (assert) { QUnit.test("matrixDynamic.getNestedQuestions", function (assert) { const survey = new SurveyModel({ elements: [ - { type: "matrixdynamic", name: "matrix", rowCount: 2, + { + type: "matrixdynamic", name: "matrix", rowCount: 2, columns: [{ name: "col1", cellType: "text", visibleIf: "{row.col2} = 'a'" }, { cellType: "text", name: "col2" }] } ] @@ -8324,12 +8325,18 @@ QUnit.test("Update expressions on setting matrixdropdown rows, Bug#5526", functi rows[0].cells[1].value = 2; rows[1].cells[0].value = 3; rows[1].cells[1].value = 4; - assert.deepEqual(survey.data, { matrix: { row1: { col1: 1, col2: 2, col3: 3, }, - row2: { col1: 3, col2: 4, col3: 7 } }, - "matrix-total": { col1: 4, col3: 10 } }, "#1"); + assert.deepEqual(survey.data, { + matrix: { + row1: { col1: 1, col2: 2, col3: 3, }, + row2: { col1: 3, col2: 4, col3: 7 } + }, + "matrix-total": { col1: 4, col3: 10 } + }, "#1"); matrix.rows = ["row1"]; - assert.deepEqual(survey.data, { matrix: { row1: { col1: 1, col2: 2, col3: 3, } }, - "matrix-total": { col1: 1, col3: 3 } }, "#2"); + assert.deepEqual(survey.data, { + matrix: { row1: { col1: 1, col2: 2, col3: 3, } }, + "matrix-total": { col1: 1, col3: 3 } + }, "#2"); }); QUnit.test("Carry forward in matrix cells", function (assert) { @@ -8437,7 +8444,8 @@ QUnit.test("Do not run total expressions if matrix is read-only, bug#5644", func assert.equal(totalQuestion.isEmpty(), false, "Total Expression question is empty"); assert.deepEqual(survey.data, { q1: 1, q2: 2, "matrix-total": { col1: 3 }, - "matrix": [{ "col1": 1 }] }, "Data set in survey correctly."); + "matrix": [{ "col1": 1 }] + }, "Data set in survey correctly."); }); QUnit.test("Check rightIndents set correctly for detailElements with defaultV2 theme - 5988", function (assert) { const survey = new SurveyModel({ @@ -8518,7 +8526,8 @@ QUnit.test("column validation, bug#6449", function (assert) { } ], "rows": ["Row1"] - }] }); + }] + }); survey.setValue("age", 50); const matrix = survey.getQuestionByName("matrix"); const cellQuestion = matrix.visibleRows[0].cells[0].question; @@ -8531,7 +8540,8 @@ QUnit.test("column validation, bug#6449", function (assert) { QUnit.test("matrixDynamic & defaultValueExpression", function (assert) { const survey = new SurveyModel({ elements: [ - { type: "matrixdynamic", name: "matrix", rowCount: 1, + { + type: "matrixdynamic", name: "matrix", rowCount: 1, columns: [{ name: "col1", cellType: "text", defaultValueExpression: "1 + 1" }, { name: "col2" }] } ] @@ -8545,7 +8555,8 @@ QUnit.test("matrixDynamic & defaultValueExpression", function (assert) { QUnit.test("Errors: matrixdropdown", function (assert) { const survey = new SurveyModel({ elements: [ - { type: "matrixdropdown", name: "matrix", + { + type: "matrixdropdown", name: "matrix", rows: ["Row1", "Row2"], choices: ["Item1"], columns: [{ name: "col1", isRequired: true }, { name: "col2", isRequired: true }] @@ -8590,7 +8601,8 @@ QUnit.test("Errors: matrixdropdown", function (assert) { QUnit.test("Errors: matrixdynamic", function (assert) { const survey = new SurveyModel({ elements: [ - { type: "matrixdynamic", name: "matrix", + { + type: "matrixdynamic", name: "matrix", rowCount: 3, columns: [{ name: "col1" }, { name: "col2" }] } @@ -8647,7 +8659,8 @@ QUnit.test("Errors: matrixdynamic + errors location bottom", function (assert) { const survey = new SurveyModel({ questionErrorLocation: "bottom", elements: [ - { type: "matrixdynamic", name: "matrix", + { + type: "matrixdynamic", name: "matrix", rowCount: 3, columns: [{ name: "col1" }, { name: "col2" }] } @@ -8703,7 +8716,8 @@ QUnit.test("Errors: matrixdynamic + errors location bottom", function (assert) { QUnit.test("Errors: matrixdynamic + showDetailPanel", function (assert) { const survey = new SurveyModel({ elements: [ - { type: "matrixdynamic", name: "matrix", + { + type: "matrixdynamic", name: "matrix", rowCount: 3, detailPanelMode: "underRow", detailElements: [{ type: "text", name: "q1" }], @@ -8757,7 +8771,8 @@ QUnit.test("Errors: matrixdynamic + showDetailPanel + errors bottom", function ( const survey = new SurveyModel({ questionErrorLocation: "bottom", elements: [ - { type: "matrixdynamic", name: "matrix", + { + type: "matrixdynamic", name: "matrix", rowCount: 3, detailPanelMode: "underRow", detailElements: [{ type: "text", name: "q1" }], @@ -8810,7 +8825,8 @@ QUnit.test("Errors: matrixdynamic + showDetailPanel + errors bottom", function ( QUnit.test("Errors: matrixdynamic + vertical columns", function (assert) { const survey = new SurveyModel({ elements: [ - { type: "matrixdynamic", + { + type: "matrixdynamic", name: "matrix", rowCount: 3, columnLayout: "vertical", @@ -8841,7 +8857,8 @@ QUnit.test("Errors: matrixdynamic + vertical columns", function (assert) { QUnit.test("Errors: matrixdropdown + show in multiple columns", function (assert) { const survey = new SurveyModel({ elements: [ - { type: "matrixdropdown", + { + type: "matrixdropdown", name: "matrix", rows: ["row1"], columns: [ @@ -8878,7 +8895,8 @@ QUnit.test("Errors: matrixdropdown + show in multiple columns", function (assert QUnit.test("Errors: matrixdynamic + show in multiple columns + vertical layout", function (assert) { const survey = new SurveyModel({ elements: [ - { type: "matrixdropdown", + { + type: "matrixdropdown", name: "matrix", rows: ["row1"], columnLayout: "vertical", @@ -8926,7 +8944,8 @@ QUnit.test("Errors: matrixdynamic + show in multiple columns + vertical layout", QUnit.test("Errors: matrixdropdown + mobile mode", function (assert) { const survey = new SurveyModel({ elements: [ - { type: "matrixdropdown", name: "matrix", + { + type: "matrixdropdown", name: "matrix", rows: ["Row1", "Row2"], choices: ["Item1"], columns: [{ name: "col1", isRequired: true }, { name: "col2", isRequired: true }] @@ -8955,14 +8974,15 @@ QUnit.test("matrixdynamic.removeRow & confirmActionAsync, #6736", function (asse const survey = new SurveyModel({ elements: [ - { type: "matrixdynamic", name: "matrix", + { + type: "matrixdynamic", name: "matrix", columns: [{ name: "col1" }] } ] }); const q = survey.getQuestionByName("matrix"); q.value = [{ col1: 1 }, { col1: 2 }, { col1: 3 }]; - let f_resFunc = (res: boolean): void => {}; + let f_resFunc = (res: boolean): void => { }; settings.confirmActionAsync = (message: string, resFunc: (res: boolean) => void): boolean => { f_resFunc = resFunc; return true; @@ -8982,7 +9002,8 @@ QUnit.test("matrixdynamic.removeRow & confirmActionAsync, #6736", function (asse QUnit.test("matrix dynamic getPlainData", function (assert) { const survey = new SurveyModel({ elements: [ - { type: "matrixdynamic", name: "matrix", + { + type: "matrixdynamic", name: "matrix", columns: [{ cellType: "text", name: "col1" }, { cellType: "text", name: "col2" }] } ] @@ -9002,7 +9023,8 @@ QUnit.test("matrix dynamic getPlainData", function (assert) { QUnit.test("matrix dynamic getPlainData & comment", function (assert) { const survey = new SurveyModel({ elements: [ - { type: "matrixdynamic", name: "matrix", + { + type: "matrixdynamic", name: "matrix", columns: [{ cellType: "text", name: "col1" }, { cellType: "text", name: "col2" }], showCommentArea: true } @@ -9064,3 +9086,97 @@ QUnit.test("matrix dynamic expression & checkbox ValuePropertyName", function (a assert.deepEqual(matrix.value, [{ testItem: "Item 1", col1: "Item 1 - matrix" }, { testItem: "Item 2", col1: "Item 2 - matrix" }], "matrix value #2"); }); +QUnit.test("Totals alingment", function (assert) { + var json = { + pages: [ + { + name: "page1", + elements: [ + { + type: "matrixdynamic", + name: "question1", + title: "Select Your Coffee", + columns: [ + { + name: "coffee", + title: "Coffee", + cellType: "dropdown", + isRequired: true, + isUnique: true, + choices: [ + { + value: "espresso", + text: "Espresso", + }, + { + value: "ristretto", + text: "Ristretto", + }, + { + value: "macchiato", + text: "Macchiato", + }, + ], + storeOthersAsComment: true, + }, + { + name: "price", + title: "Price", + cellType: "expression", + expression: + "iif({row.coffee} = 'ristretto' or {row.coffee} = 'macchiato' or {row.coffee} = 'cappuchino', '2.5', iif({row.coffee} = 'flatWhite' or {row.coffee} = 'latte', 3, 2))\n", + }, + { + name: "amount", + title: "Num of Items", + cellType: "dropdown", + totalType: "sum", + choicesMin: 1, + choicesMax: 10, + }, + { + name: "totalPerRow", + title: "Total", + cellType: "expression", + totalType: "sum", + totalDisplayStyle: "currency", + totalAlignment: "center", + expression: "{row.price} * {row.amount}", + }, + ], + rowCount: 1, + maxRowCount: 6, + defaultRowValue: { + coffeeItem: "2", + coffee: "espresso", + price: 2, + amount: 1, + totalPerRow: 2, + }, + addRowLocation: "topBottom", + addRowText: "Add Coffee", + }, + ], + }, + ], + }; + + var survey = new SurveyModel(json); + var question = ( + survey.getQuestionByName("question1") + ); + question.cssClassesValue.cellQuestionWrapper = "sd-table__question-wrapper"; + var renderedTable = question.renderedTable; + assert.equal( + renderedTable.footerRow.cells[1].cellQuestionWrapperClassName, + "sd-table__question-wrapper sd-table__question-wrapper--auto" + ); + assert.equal( + renderedTable.footerRow.cells[2].cellQuestionWrapperClassName, + "sd-table__question-wrapper sd-table__question-wrapper--expression sd-table__question-wrapper--left" + ); + assert.equal( + renderedTable.footerRow.cells[3].cellQuestionWrapperClassName, + "sd-table__question-wrapper sd-table__question-wrapper--expression sd-table__question-wrapper--center" + ); +}); \ No newline at end of file diff --git a/visualRegressionTests/tests/defaultV2/etalons/matrixdropdown-with-totals-alignment.png b/visualRegressionTests/tests/defaultV2/etalons/matrixdropdown-with-totals-alignment.png new file mode 100644 index 0000000000..f517e933e3 Binary files /dev/null and b/visualRegressionTests/tests/defaultV2/etalons/matrixdropdown-with-totals-alignment.png differ diff --git a/visualRegressionTests/tests/defaultV2/etalons/matrixdropdown-with-totals.png b/visualRegressionTests/tests/defaultV2/etalons/matrixdropdown-with-totals.png index 30427b0ffe..43f832b828 100644 Binary files a/visualRegressionTests/tests/defaultV2/etalons/matrixdropdown-with-totals.png and b/visualRegressionTests/tests/defaultV2/etalons/matrixdropdown-with-totals.png differ diff --git a/visualRegressionTests/tests/defaultV2/etalons/matrixdynamic-with-totals.png b/visualRegressionTests/tests/defaultV2/etalons/matrixdynamic-with-totals.png index 85280fb53c..516848e87f 100644 Binary files a/visualRegressionTests/tests/defaultV2/etalons/matrixdynamic-with-totals.png and b/visualRegressionTests/tests/defaultV2/etalons/matrixdynamic-with-totals.png differ diff --git a/visualRegressionTests/tests/defaultV2/etalons/responsiveness-matrixdropdown-totals.png b/visualRegressionTests/tests/defaultV2/etalons/responsiveness-matrixdropdown-totals.png index f19061a6cd..ed19916820 100644 Binary files a/visualRegressionTests/tests/defaultV2/etalons/responsiveness-matrixdropdown-totals.png and b/visualRegressionTests/tests/defaultV2/etalons/responsiveness-matrixdropdown-totals.png differ diff --git a/visualRegressionTests/tests/defaultV2/etalons/row-multiple-compact-mode.png b/visualRegressionTests/tests/defaultV2/etalons/row-multiple-compact-mode.png new file mode 100644 index 0000000000..ebe0b95ac5 Binary files /dev/null and b/visualRegressionTests/tests/defaultV2/etalons/row-multiple-compact-mode.png differ diff --git a/visualRegressionTests/tests/defaultV2/matrixdynamic.ts b/visualRegressionTests/tests/defaultV2/matrixdynamic.ts index eb1438a21d..d4eb7166f2 100644 --- a/visualRegressionTests/tests/defaultV2/matrixdynamic.ts +++ b/visualRegressionTests/tests/defaultV2/matrixdynamic.ts @@ -349,4 +349,86 @@ frameworks.forEach(framework => { await takeElementScreenshot("matrixdropdown-with-totals.png", matrixdynamicRoot, t, comparer); }); }); + test("Check MatrixDynamic totals alignment", async (t) => { + await wrapVisualTest(t, async (t, comparer) => { + await t.resizeWindow(1280, 1100); + await initSurvey(framework, { + pages: [ + { + name: "page1", + elements: [ + { + type: "matrixdynamic", + name: "question1", + title: "Select Your Coffee", + columns: [ + { + name: "coffee", + title: "Coffee", + cellType: "dropdown", + isRequired: true, + isUnique: true, + choices: [ + { + value: "espresso", + text: "Espresso", + }, + { + value: "ristretto", + text: "Ristretto", + }, + { + value: "macchiato", + text: "Macchiato", + }, + ], + storeOthersAsComment: true, + }, + { + name: "price", + title: "Price", + cellType: "expression", + expression: + "iif({row.coffee} = 'ristretto' or {row.coffee} = 'macchiato' or {row.coffee} = 'cappuchino', '2.5', iif({row.coffee} = 'flatWhite' or {row.coffee} = 'latte', 3, 2))\n", + }, + { + name: "amount", + title: "Num of Items", + cellType: "dropdown", + totalType: "sum", + choicesMin: 1, + choicesMax: 10, + }, + { + name: "totalPerRow", + title: "Total", + cellType: "expression", + totalType: "sum", + totalDisplayStyle: "currency", + totalAlignment: "center", + expression: "{row.price} * {row.amount}", + }, + ], + rowCount: 1, + maxRowCount: 6, + defaultRowValue: { + coffeeItem: "2", + coffee: "espresso", + price: 2, + amount: 1, + totalPerRow: 2, + }, + addRowLocation: "topBottom", + addRowText: "Add Coffee", + }, + ], + }, + ], + }); + + const matrixdynamicRoot = Selector(".sd-question"); + await resetFocusToBody(); + await takeElementScreenshot("matrixdropdown-with-totals-alignment.png", matrixdynamicRoot, t, comparer); + }); + }); }); \ No newline at end of file diff --git a/visualRegressionTests/tests/defaultV2/survey.ts b/visualRegressionTests/tests/defaultV2/survey.ts index dcfe6217ff..000e9271dc 100644 --- a/visualRegressionTests/tests/defaultV2/survey.ts +++ b/visualRegressionTests/tests/defaultV2/survey.ts @@ -1287,6 +1287,49 @@ frameworks.forEach(framework => { }); }); + test("Check multiple row in compact mode", async (t) => { + await wrapVisualTest(t, async (t, comparer) => { + await t.resizeWindow(700, 1080); + const json = { + pages: [ + { + name: "p1", + elements: [ + { + type: "text", + name: "q1", + title: "Question", + startWithNewLine: false + }, + { + type: "text", + name: "q2", + title: "Question", + startWithNewLine: false + }, + { + type: "text", + name: "q3", + title: "Question", + startWithNewLine: false + }, + { + type: "text", + name: "q4", + title: "Question", + startWithNewLine: false + }, + ] + }, + ] + }; + + await initSurvey(framework, json); + await ClientFunction(() => (window as any).survey.isCompact = true)(); + await takeElementScreenshot("row-multiple-compact-mode.png", Selector(".sd-root-modern"), t, comparer); + }); + }); + test("Check survey logo right with empty title", async (t) => { await wrapVisualTest(t, async (t, comparer) => { await t.resizeWindow(1920, 1080);