Skip to content

Commit

Permalink
PR: A11Y Matrix-Dropdown (Multi-Select) (#7339)
Browse files Browse the repository at this point in the history
* work for the surveyjs/service#1586

* work for the surveyjs/service#1586

* work for the surveyjs/service#1586

* work for the surveyjs/service#1586

* work for the #7273 (fixed vue3)

* work for the #7274

* work for the #7274 (lint)

* work for the #7274

* Fix unit tests #7274

* work for the #7274

* work for the #7274

---------

Co-authored-by: Andrew Telnov <andrew.telnov@gmail.com>
  • Loading branch information
dmitry-kurmanov and andrewtelnov committed Nov 15, 2023
1 parent d38cb7a commit 37553a9
Show file tree
Hide file tree
Showing 19 changed files with 78 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@
[disabled]="model.isInputReadOnly"
[attr.id]="model.inputId + '_' + row.name + '_' + columnIndex"
(change)="onChange(row, column)"
[attr.aria-required]="model.ariaRequired"
[attr.aria-required]="model.a11y_input_ariaRequired"
[attr.aria-label]="model.getCellAriaLabel(row.locText.renderedHtml, column.locText.renderedHtml)"
[attr.aria-invalid]="model.ariaInvalid"
[attr.aria-describedby]="model.ariaDescribedBy"
[attr.aria-invalid]="model.a11y_input_ariaInvalid"
[attr.aria-describedby]="model.a11y_input_ariaDescribedBy"
/>
<span [class]="model.cssClasses.materialDecorator">
<svg *ngIf="model.itemSvgIcon" [class]="model.cssClasses.itemDecorator">
Expand Down
6 changes: 3 additions & 3 deletions packages/survey-vue3-ui/src/Matrix.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@
:value="column.value"
:disabled="question.isInputReadOnly"
:id="question.inputId + '_' + row.name + '_' + columnIndex"
:aria-required="question.ariaRequired"
:aria-required="question.a11y_input_ariaRequired"
:aria-label="question.getCellAriaLabel(row.locText.renderedHtml, column.locText.renderedHtml)"
:aria-invalid="question.ariaInvalid"
:aria-describedby="question.ariaDescribedBy"
:aria-invalid="question.a11y_input_ariaInvalid"
:aria-describedby="question.a11y_input_ariaDescribedBy"
/>
<span :class="question.cssClasses.materialDecorator">
<svg
Expand Down
2 changes: 1 addition & 1 deletion src/knockout/templates/question-matrix.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
<label data-bind="css: question.getItemClass(row, $data), event: { mousedown: question.koMouseDown }" >
<input
type="radio"
data-bind="css: question.cssClasses.itemValue, attr: { name: row.fullName, 'aria-required': question.ariaRequired, 'aria-label': question.getCellAriaLabel($parent.locText.renderedHtml, $data.locText.renderedHtml), 'aria-invalid': question.ariaInvalid, 'aria-describedby': question.ariaDescribedBy, id: question.inputId + '_' + row.name + '_' + $index() }, checkedValue: $data.value, checked: row.value, enable: !question.isInputReadOnly"
data-bind="css: question.cssClasses.itemValue, attr: { name: row.fullName, 'aria-required': question.a11y_input_ariaRequired, 'aria-label': question.getCellAriaLabel($parent.locText.renderedHtml, $data.locText.renderedHtml), 'aria-invalid': question.a11y_input_ariaInvalid, 'aria-describedby': question.a11y_input_ariaDescribedBy, id: question.inputId + '_' + row.name + '_' + $index() }, checkedValue: $data.value, checked: row.value, enable: !question.isInputReadOnly"
/>
<span data-bind="css: question.cssClasses.materialDecorator">
<!-- ko if: question.itemSvgIcon -->
Expand Down
7 changes: 7 additions & 0 deletions src/martixBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,16 @@ export class QuestionMatrixBaseModel<TRow, TColumn> extends Question {
this.setPropertyValue("rowTitleWidth", val);
}

//a11y
public getCellAriaLabel(rowTitle:string, columnTitle:string):string {
return `row ${rowTitle}, column ${columnTitle}`;
}

public get isNewA11yStructure(): boolean {
return true;
}
// EO a11y

}

Serializer.addClass(
Expand Down
9 changes: 9 additions & 0 deletions src/question_matrixdropdownbase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ export class MatrixDropdownCell {
) {
this.questionValue = this.createQuestion(column, row, data);
this.questionValue.updateCustomWidget();
this.updateCellQuestionTitleDueToAccessebility(row);
}
private updateCellQuestionTitleDueToAccessebility(row: MatrixDropdownRowModelBase): void {
this.questionValue.locTitle.onGetTextCallback = (str: string): string => {
if(!row || !row.getSurvey()) return this.questionValue.title;
const rowTitle = row.locText && row.locText.renderedHtml;
if(!rowTitle) return this.questionValue.title;
return this.column.colOwner.getCellAriaLabel(rowTitle, this.questionValue.title);
};
}
public locStrsChanged() {
this.question.locStrsChanged();
Expand Down
3 changes: 2 additions & 1 deletion src/question_matrixdropdowncolumn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +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;
}

function onUpdateSelectBaseCellQuestion(
Expand Down Expand Up @@ -486,7 +487,7 @@ export class MatrixDropdownColumn extends Base
this.callOnCellQuestionUpdate(cellQuestion, row);
return cellQuestion;
}
startLoadingFromJson(json?: any) {
startLoadingFromJson(json?: any): void {
super.startLoadingFromJson(json);
if (!!json && !json.cellType && !!json.choices) {
json.cellType = this.colOwner.getCellType();
Expand Down
12 changes: 6 additions & 6 deletions src/question_matrixdropdownrendered.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,19 +95,19 @@ export class QuestionMatrixDropdownRenderedCell {
}
public get headers(): string {
if(this.cell && this.cell.column) {
if(this.cell.column.cellHint === " ") {
return "";
}
if(!!this.cell.column.cellHint) {
return this.cell.column.locCellHint.renderedHtml;
}
if (this.matrix.IsMultiplyColumn(this.cell.column)) {
if(!!this.item) {
return this.item.locText.renderedHtml;
} else {
return "";
}
}
let cellHint = this.cell.column.cellHint;
if(!!cellHint) {
if(cellHint.trim() === "") return "";
return this.cell.column.locCellHint.renderedHtml;
}
return this.cell.column.title;
}
if(this.hasQuestion && this.question.isVisible) {
return this.question.locTitle.renderedHtml;
Expand Down
6 changes: 3 additions & 3 deletions src/react/reactquestion_matrix.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,10 @@ export class SurveyQuestionMatrixRow extends ReactSurveyElement {
disabled={this.isDisplayMode}
checked={isChecked}
onChange={this.handleOnChange}
aria-required={this.question.ariaRequired}
aria-required={this.question.a11y_input_ariaRequired}
aria-label={this.question.getCellAriaLabel(row.locText.renderedHtml, column.locText.renderedHtml)}
aria-invalid={this.question.ariaInvalid}
aria-describedby={this.question.ariaDescribedBy}
aria-invalid={this.question.a11y_input_ariaInvalid}
aria-describedby={this.question.a11y_input_ariaDescribedBy}
/>
<span className={this.question.cssClasses.materialDecorator}>
{this.question.itemSvgIcon ?
Expand Down
6 changes: 3 additions & 3 deletions src/vue/matrix.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@
:value="column.value"
:disabled="question.isInputReadOnly"
:id="question.inputId + '_' + row.name + '_' + columnIndex"
:aria-required="question.ariaRequired"
:aria-required="question.a11y_input_ariaRequired"
:aria-label="question.getCellAriaLabel(row.locText.renderedHtml, column.locText.renderedHtml)"
:aria-invalid="question.ariaInvalid"
:aria-describedby="question.ariaDescribedBy"
:aria-invalid="question.a11y_input_ariaInvalid"
:aria-describedby="question.a11y_input_ariaDescribedBy"
/>
<span :class="question.cssClasses.materialDecorator">
<svg v-if="question.itemSvgIcon" :class="question.cssClasses.itemDecorator">
Expand Down
2 changes: 1 addition & 1 deletion testCafe/questions/allTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ var json = {
.parent("[data-name]")
.find("tr").withText("Row 1");
await t
.click(matrixDropdownRow.find("div[aria-label='Column 1']"))
.click(matrixDropdownRow.find("div[aria-label='row Row 1, column Column 1']"))
.click(getListItemByText("1"));

await t.click(
Expand Down
8 changes: 4 additions & 4 deletions tests/markup/snapshots/martix-celltype-text-a11y.snap.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</td>
<td class="sv_matrix_cell" colspan="1" data-responsive-title="Number of people" title="Number of people">
<div>
<input aria-invalid="false" aria-label="Number of people" aria-required="false" autocomplete="" class="sv_q_text_root" id="testid0row1cell1i" min="0" placeholder="" step="any" type="number">
<input aria-invalid="false" aria-label="row Age 0-4, column Number of people" aria-required="false" autocomplete="" class="sv_q_text_root" id="testid0row1cell1i" min="0" placeholder="" step="any" type="number">
</div>
</td>
</tr>
Expand All @@ -26,7 +26,7 @@
</td>
<td class="sv_matrix_cell" colspan="1" data-responsive-title="Number of people" title="Number of people">
<div>
<input aria-invalid="false" aria-label="Number of people" aria-required="false" autocomplete="" class="sv_q_text_root" id="testid0row3cell1i" min="0" placeholder="" step="any" type="number">
<input aria-invalid="false" aria-label="row Age 5-11, column Number of people" aria-required="false" autocomplete="" class="sv_q_text_root" id="testid0row3cell1i" min="0" placeholder="" step="any" type="number">
</div>
</td>
</tr>
Expand All @@ -36,7 +36,7 @@
</td>
<td class="sv_matrix_cell" colspan="1" data-responsive-title="Number of people" title="Number of people">
<div>
<input aria-invalid="false" aria-label="Number of people" aria-required="false" autocomplete="" class="sv_q_text_root" id="testid0row5cell1i" min="0" placeholder="" step="any" type="number">
<input aria-invalid="false" aria-label="row Age 12-15, column Number of people" aria-required="false" autocomplete="" class="sv_q_text_root" id="testid0row5cell1i" min="0" placeholder="" step="any" type="number">
</div>
</td>
</tr>
Expand All @@ -46,7 +46,7 @@
</td>
<td class="sv_matrix_cell" colspan="1" data-responsive-title="Number of people" title="Number of people">
<div>
<input aria-invalid="false" aria-label="Number of people" aria-required="false" autocomplete="" class="sv_q_text_root" id="testid0row7cell1i" min="0" placeholder="" step="any" type="number">
<input aria-invalid="false" aria-label="row Age 16+, column Number of people" aria-required="false" autocomplete="" class="sv_q_text_root" id="testid0row7cell1i" min="0" placeholder="" step="any" type="number">
</div>
</td>
</tr>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
</td>
<td class="sd-question--error sd-table__cell" colspan="1" data-responsive-title="col1" title="col1">
<div class="sd-table__question-wrapper">
<input aria-describedby="testid0row0cell1_errors" aria-invalid="true" aria-label="col1" aria-required="true" autocomplete="" class="sd-input sd-input--error sd-text" id="testid0row0cell1i" placeholder="" type="text">
<input aria-describedby="testid0row0cell1_errors" aria-invalid="true" aria-label="row row1, column col1" aria-required="true" autocomplete="" class="sd-input sd-input--error sd-text" id="testid0row0cell1i" placeholder="" type="text">
</div>
</td>
</tr>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
</td>
<td class="sd-question--error sd-table__cell" colspan="1" data-responsive-title="col1" title="col1">
<div class="sd-table__question-wrapper">
<input aria-describedby="testid0row1cell1_errors" aria-invalid="true" aria-label="col1" aria-required="true" autocomplete="" class="sd-input sd-input--error sd-text" id="testid0row1cell1i" placeholder="" type="text">
<input aria-describedby="testid0row1cell1_errors" aria-invalid="true" aria-label="row row1, column col1" aria-required="true" autocomplete="" class="sd-input sd-input--error sd-text" id="testid0row1cell1i" placeholder="" type="text">
</div>
</td>
</tr>
Expand Down
8 changes: 4 additions & 4 deletions tests/markup/snapshots/matrixdropdown-vertical.snap.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
</td>
<td class="sd-table__cell" colspan="1" data-responsive-title="" title="">
<div class="sd-table__question-wrapper">
<input aria-invalid="false" aria-label="" aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row1cell1i" placeholder="" type="text">
<input aria-invalid="false" aria-label="row Row 1, column " aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row1cell1i" placeholder="" type="text">
</div>
</td>
<td class="sd-table__cell" colspan="1" data-responsive-title="" title="">
<div class="sd-table__question-wrapper">
<input aria-invalid="false" aria-label="" aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row1cell2i" placeholder="" type="text">
<input aria-invalid="false" aria-label="row Row 2, column " aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row1cell2i" placeholder="" type="text">
</div>
</td>
</tr>
Expand All @@ -36,12 +36,12 @@
</td>
<td class="sd-table__cell" colspan="1" data-responsive-title="" title="">
<div class="sd-table__question-wrapper">
<input aria-invalid="false" aria-label="" aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row3cell1i" placeholder="" type="text">
<input aria-invalid="false" aria-label="row Row 1, column " aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row3cell1i" placeholder="" type="text">
</div>
</td>
<td class="sd-table__cell" colspan="1" data-responsive-title="" title="">
<div class="sd-table__question-wrapper">
<input aria-invalid="false" aria-label="" aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row3cell2i" placeholder="" type="text">
<input aria-invalid="false" aria-label="row Row 2, column " aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row3cell2i" placeholder="" type="text">
</div>
</td>
</tr>
Expand Down
8 changes: 4 additions & 4 deletions tests/markup/snapshots/matrixdropdown.snap.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
</td>
<td class="sd-table__cell" colspan="1" data-responsive-title="" title="">
<div class="sd-table__question-wrapper">
<input aria-invalid="false" aria-label="" aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row1cell1i" placeholder="" type="text">
<input aria-invalid="false" aria-label="row Row 1, column " aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row1cell1i" placeholder="" type="text">
</div>
</td>
<td class="sd-table__cell" colspan="1" data-responsive-title="" title="">
<div class="sd-table__question-wrapper">
<input aria-invalid="false" aria-label="" aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row1cell2i" placeholder="" type="text">
<input aria-invalid="false" aria-label="row Row 1, column " aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row1cell2i" placeholder="" type="text">
</div>
</td>
</tr>
Expand All @@ -36,12 +36,12 @@
</td>
<td class="sd-table__cell" colspan="1" data-responsive-title="" title="">
<div class="sd-table__question-wrapper">
<input aria-invalid="false" aria-label="" aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row3cell1i" placeholder="" type="text">
<input aria-invalid="false" aria-label="row Row 2, column " aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row3cell1i" placeholder="" type="text">
</div>
</td>
<td class="sd-table__cell" colspan="1" data-responsive-title="" title="">
<div class="sd-table__question-wrapper">
<input aria-invalid="false" aria-label="" aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row3cell2i" placeholder="" type="text">
<input aria-invalid="false" aria-label="row Row 2, column " aria-required="false" autocomplete="" class="sd-input sd-text" id="testid0row3cell2i" placeholder="" type="text">
</div>
</td>
</tr>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
</td>
<td class="sd-table__cell" colspan="1" data-responsive-title="col1" title="col1">
<div class="sd-table__question-wrapper">
<fieldset aria-invalid="false" aria-label="col1" aria-required="true" class="sd-selectbase sd-selectbase--row" role="radiogroup">
<fieldset aria-invalid="false" aria-label="row row1, column col1" aria-required="true" class="sd-selectbase sd-selectbase--row" role="radiogroup">
<div class="sd-item sd-item--allowhover sd-radio sd-radio--allowhover sd-selectbase__item sd-selectbase__item--inline" role="presentation">
<label class="sd-selectbase__label">
<input class="sd-item__control sd-radio__control sd-visuallyhidden" id="testid0row1cell1i_0" name="col1_testid0row1cell1" type="radio" value="Item 1">
Expand All @@ -43,8 +43,8 @@
</td>
<td class="sd-table__cell" colspan="1" data-responsive-title="col2" title="col2">
<div class="sd-table__question-wrapper">
<fieldset aria-invalid="false" aria-label="col2" aria-required="true" class="sd-selectbase sd-selectbase--row" role="listbox">
<legend class="sv-hidden">col2</legend>
<fieldset aria-invalid="false" aria-label="row row1, column col2" aria-required="true" class="sd-selectbase sd-selectbase--row" role="listbox">
<legend class="sv-hidden">row row1, column col2</legend>
<div class="sd-checkbox sd-checkbox--allowhover sd-item sd-item--allowhover sd-selectbase__item sd-selectbase__item--inline" role="presentation">
<label class="sd-selectbase__label">
<input class="sd-checkbox__control sd-item__control sd-visuallyhidden" id="testid0row1cell3i_0" name="col2Item 1" role="option" type="checkbox" value="Item 1">
Expand Down
16 changes: 16 additions & 0 deletions tests/question_matrixdropdownbasetests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,22 @@ QUnit.test("checkIfValueInRowDuplicated has only one duplicated error", function
assert.equal(q.errors.length, 1, "One error only");
assert.equal(q.errors[0].getErrorType(), "keyduplicationerror", "Correct error is added");
});
QUnit.test("Cell question title and question.locTitle.renderedHtml", function (assert) {
const survey = new SurveyModel({
elements: [
{
type: "matrixdropdown",
name: "matrix",
columns: [{ name: "col1" }],
rows: ["item1"]
},
],
});
const matrix = <QuestionMatrixDropdownModelBase>survey.getQuestionByName("matrix");
const cellQuestion = matrix.visibleRows[0].cells[0].question;
assert.equal(cellQuestion.title, "col1", "Question title is column title");
assert.equal(cellQuestion.locTitle.renderedHtml, "row item1, column col1", "Question rendered title is prepared for accessibility");
});
QUnit.test("checkIfValueInRowDuplicated has only one duplicated error", function (assert) {
const survey = new SurveyModel({
"elements": [
Expand Down
6 changes: 3 additions & 3 deletions tests/question_matrixdynamictests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8028,9 +8028,9 @@ QUnit.test("getTitle", function (assert) {
const question = survey.getAllQuestions()[0];
var renderedTable = question.renderedTable;
const row = renderedTable.rows[1];
assert.equal(row.cells[0].getTitle(), "true hint");
assert.equal(row.cells[1].getTitle(), "col2");
assert.equal(row.cells[2].getTitle(), "");
assert.equal(row.cells[0].getTitle(), "true hint", "cell0");
assert.equal(row.cells[1].getTitle(), "col2", "cell1");
assert.equal(row.cells[2].getTitle(), "", "cell2");
});
QUnit.test("matrixdropdowncolumn renderAs property", function (assert) {
const survey = new SurveyModel({
Expand Down

0 comments on commit 37553a9

Please sign in to comment.