mirror of
https://github.com/discourse/discourse.git
synced 2025-06-08 00:27:32 +08:00
UX: re-check triggerRule to avoid autocomplete in code (#30961)
Re-checks triggerRule when navigating around with arrow keys and after continued typing. ref /t/-/23884
This commit is contained in:
@ -555,7 +555,7 @@ export default function (options) {
|
||||
if (options.onKeyUp && key !== options.key) {
|
||||
let match = options.onKeyUp(options.textHandler.value, cp);
|
||||
|
||||
if (match) {
|
||||
if (match && (await checkTriggerRule())) {
|
||||
completeStart = cp - match[0].length;
|
||||
let term = match[0].substring(1, match[0].length);
|
||||
updateAutoComplete(dataSource(term, options));
|
||||
@ -567,8 +567,8 @@ export default function (options) {
|
||||
if (key === options.key) {
|
||||
let prevChar = options.textHandler.value.charAt(cp - 2);
|
||||
if (
|
||||
(await checkTriggerRule()) &&
|
||||
(!prevChar || ALLOWED_LETTERS_REGEXP.test(prevChar))
|
||||
(!prevChar || ALLOWED_LETTERS_REGEXP.test(prevChar)) &&
|
||||
(await checkTriggerRule())
|
||||
) {
|
||||
completeStart = cp - 1;
|
||||
updateAutoComplete(dataSource("", options));
|
||||
|
@ -737,10 +737,7 @@ export default class TextareaTextManipulation {
|
||||
}
|
||||
|
||||
async inCodeBlock() {
|
||||
return inCodeBlock(
|
||||
this.$textarea.value ?? this.$textarea.val(),
|
||||
caretPosition(this.$textarea)
|
||||
);
|
||||
return await this.autocompleteHandler.inCodeBlock();
|
||||
}
|
||||
|
||||
@bind
|
||||
@ -869,9 +866,9 @@ export class TextareaAutocompleteHandler {
|
||||
}
|
||||
|
||||
async inCodeBlock() {
|
||||
return inCodeBlock(
|
||||
this.$textarea.value ?? this.$textarea.val(),
|
||||
caretPosition(this.$textarea)
|
||||
return await inCodeBlock(
|
||||
this.textarea.value ?? this.$textarea.val(),
|
||||
caretPosition(this.textarea)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -185,10 +185,19 @@ module("Unit | Utility | autocomplete", function (hooks) {
|
||||
|
||||
assert.dom(element).hasValue(":smile: ");
|
||||
|
||||
await triggerArrowKey(element, "ArrowLeft");
|
||||
await triggerArrowKey(element, "ArrowLeft");
|
||||
await triggerArrowKey(element, "ArrowLeft");
|
||||
await triggerArrowKey(element, "ArrowRight");
|
||||
async function triggerArrowKey(key) {
|
||||
await triggerKeyEvent(element, "keydown", key, { code: key });
|
||||
await triggerKeyEvent(element, "keyup", key, { code: key });
|
||||
|
||||
const pos = element.selectionStart;
|
||||
const direction = key === "ArrowLeft" ? -1 : 1;
|
||||
element.setSelectionRange(pos + 1 * direction, pos + 1 * direction);
|
||||
}
|
||||
|
||||
await triggerArrowKey("ArrowLeft");
|
||||
await triggerArrowKey("ArrowLeft");
|
||||
await triggerArrowKey("ArrowLeft");
|
||||
await triggerArrowKey("ArrowRight");
|
||||
|
||||
assert.strictEqual(element.selectionStart, 6);
|
||||
|
||||
@ -196,19 +205,38 @@ module("Unit | Utility | autocomplete", function (hooks) {
|
||||
// triggerArrowKey isn't triggering the event the autocomplete listens to
|
||||
assert.dom("#ac-testing").doesNotExist();
|
||||
|
||||
await triggerArrowKey(element, "ArrowRight");
|
||||
await triggerArrowKey("ArrowRight");
|
||||
await simulateKey(element, "\b");
|
||||
|
||||
assert.dom(element).hasValue(":smile ");
|
||||
assert.dom("#ac-testing").exists();
|
||||
});
|
||||
|
||||
test("Autocomplete respects triggerRule on continued typing", async function (assert) {
|
||||
const element = textArea();
|
||||
|
||||
$(element).autocomplete({
|
||||
key: ":",
|
||||
template,
|
||||
transformComplete: (e) => e.slice(1),
|
||||
dataSource: () => [":smile:"],
|
||||
triggerRule: async (_, { inCodeBlock }) => !(await inCodeBlock()),
|
||||
});
|
||||
|
||||
await simulateKeys(element, "```\n:");
|
||||
|
||||
assert.dom("#ac-testing").doesNotExist();
|
||||
|
||||
await simulateKey(element, "smil");
|
||||
|
||||
assert.dom("#ac-testing").doesNotExist();
|
||||
|
||||
await simulateKey(element, "\n```\n:");
|
||||
|
||||
assert.dom("#ac-testing").exists();
|
||||
|
||||
await simulateKey(element, "smil");
|
||||
|
||||
assert.dom("#ac-testing").exists();
|
||||
});
|
||||
});
|
||||
|
||||
async function triggerArrowKey(element, key) {
|
||||
await triggerKeyEvent(element, "keydown", key, { code: key });
|
||||
await triggerKeyEvent(element, "keyup", key, { code: key });
|
||||
|
||||
const pos = element.selectionStart;
|
||||
const direction = key === "ArrowLeft" ? -1 : 1;
|
||||
element.setSelectionRange(pos + 1 * direction, pos + 1 * direction);
|
||||
}
|
||||
|
Reference in New Issue
Block a user