Skip to content

Commit

Permalink
#5405 Better Keyboard navigation in survey - finish input, focus swit…
Browse files Browse the repository at this point in the history
…ch (#5619)

* #5405 Better Keyboard navigation in survey - finish input, focus switch
Fixes #5405

* #5405 Better Keyboard navigation in survey - finish input, focus switch
Fixes #5405

* dropdown support #5405

* #5405 Better Keyboard navigation in survey - finish input, focus switch
Fixes #5405

* Describe enterKeyAction

---------

Co-authored-by: Roman Tsukanov <roman.tsukanov@devexpress.com>
  • Loading branch information
novikov82 and Roman Tsukanov authored Mar 31, 2023
1 parent 5ae2096 commit 849aaf2
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 2 deletions.
3 changes: 3 additions & 0 deletions src/dropdownListModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ListModel } from "./list";
import { PopupModel } from "./popup";
import { Question } from "./question";
import { QuestionDropdownModel } from "./question_dropdown";
import { SurveyModel } from "./survey";
import { CssClassBuilder } from "./utils/cssClassBuilder";
import { IsTouch } from "./utils/devices";
import { doKey2ClickBlur, doKey2ClickUp } from "./utils/utils";
Expand Down Expand Up @@ -386,10 +387,12 @@ export class DropdownListModel extends Base {
if (event.keyCode === 13 && this.question.searchEnabled && !this.inputString && this.question instanceof QuestionDropdownModel && !this._markdownMode && this.question.value) {
this._popupModel.isVisible = false;
this.onClear(event);
(this.question.survey as SurveyModel).questionEditFinishCallback(this.question, event);
}
else {
this.listModel.selectFocusedItem();
this.onFocus(event);
(this.question.survey as SurveyModel).questionEditFinishCallback(this.question, event);
}
event.preventDefault();
event.stopPropagation();
Expand Down
4 changes: 4 additions & 0 deletions src/question_text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { CustomError } from "./error";
import { settings } from "./settings";
import { QuestionTextBase } from "./question_textbase";
import { ExpressionRunner } from "./conditions";
import { SurveyModel } from "./survey";

/**
* A class that describes the Text question type.
Expand Down Expand Up @@ -429,6 +430,9 @@ export class QuestionTextModel extends QuestionTextBase {
if(this.isInputTextUpdate) {
this._isWaitingForEnter = event.keyCode === 229;
}
if (event.keyCode === 13) {
(this.survey as SurveyModel).questionEditFinishCallback(this, event);
}
}
public onChange = (event: any): void => {
if (event.target === document.activeElement) {
Expand Down
10 changes: 10 additions & 0 deletions src/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
* ```
*/
export var settings = {
/**
* Specifies an action to perform when users press the Enter key within a survey.
*
* Possible values:
*
* - `"moveToNextEditor"` - Moves focus to the next editor.
* - `"loseFocus"` - Removes focus from the current editor.
* - `"default"` - Behaves as a standard `<input>` element.
*/
enterKeyAction: "default" as "moveToNextEditor" | "loseFocus" | "default",
/**
* An object that configures string comparison.
*
Expand Down
14 changes: 14 additions & 0 deletions src/survey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6674,6 +6674,20 @@ export class SurveyModel extends SurveyElementCore
return true;
}

public questionEditFinishCallback(question: Question, event: any) {
if (settings.enterKeyAction == "loseFocus") event.target.blur();
if (settings.enterKeyAction == "moveToNextEditor") {
const allQuestions = this.currentPage.questions;
const questionIndex = allQuestions.indexOf(question);
if (questionIndex > -1 && questionIndex < allQuestions.length - 1) {
allQuestions[questionIndex + 1].focus();
}
else {
event.target.blur();
}
}
}

public getElementWrapperComponentName(element: any, reason?: string): string {
if (reason === "logo-image") {
return "sv-logo-image";
Expand Down
2 changes: 1 addition & 1 deletion testCafe/questions/text.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { frameworks, url, initSurvey, getSurveyResult, getQuestionValue, getQuestionJson } from "../helper";
import { Selector, fixture, test } from "testcafe";
import { Selector, fixture, test, ClientFunction } from "testcafe";
// eslint-disable-next-line no-undef
const assert = require("assert");
const title = "text";
Expand Down
77 changes: 76 additions & 1 deletion testCafe/survey/focusQuestionEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,79 @@ frameworks.forEach(async framework => {
await t.click(Selector(".sv_qstn input").nth(1));
await t.expect(ClientFunction(() => window["raisedFocusEvent"])()).ok();
});
});

test("enterKeyAction", async (t) => {
const characterCounter = Selector(".sv-remaining-character-counter");

await initSurvey(framework, {
"logoPosition": "right",
"pages": [
{
"name": "page1",
"elements": [
{
"type": "text",
"name": "question1"
},
{
"type": "dropdown",
"name": "question2",
"choices": ["item1", "item2"]
},
{
"type": "text",
"name": "question3"
}
]
},
{
"name": "page2",
"elements": [
{
"type": "text",
"name": "question4"
}
]
}
]
});

await ClientFunction(() => {
window["Survey"].settings.enterKeyAction = "loseFocus";
})();

const q1Input = Selector("div[data-name=question1] input");
const q2Input = Selector("div[data-name=question2] input");
const q3Input = Selector("div[data-name=question3] input");
const q4Input = Selector("div[data-name=question4] input");
await t
.typeText(q1Input, "abc")
.expect(q1Input.focused).ok()
.pressKey("Enter")
.expect(q1Input.focused).notOk()
.typeText(q2Input, "it")
.expect(q2Input.focused).ok()
.pressKey("Enter")
.expect(q2Input.focused).notOk();

await ClientFunction(() => {
window["Survey"].settings.enterKeyAction = "moveToNextEditor";
})();

await t
.typeText(q1Input, "abc")
.expect(q1Input.focused).ok()
.pressKey("Enter")
.typeText(q2Input, "it")
.expect(q2Input.focused).ok()
.pressKey("Enter")
.expect(q3Input.focused).ok()
.typeText(q3Input, "mnk")
.pressKey("Enter")
.expect(q3Input.focused).notOk();
await ClientFunction(() => {
window["Survey"].settings.enterKeyAction = "default";
})();
});

});

0 comments on commit 849aaf2

Please sign in to comment.