Skip to content

Commit 9b1328a

Browse files
committed
オートコンプリート欄に対応
1 parent d61d4a6 commit 9b1328a

3 files changed

Lines changed: 50 additions & 8 deletions

File tree

examples/dev/text.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ <h1>text rule dev test</h1>
2929

3030
<label>
3131
文字列入力:
32-
<input id="input" type="text" />
32+
<input id="input" type="text" list="suggestions" />
33+
<datalist id="suggestions">
34+
<option value="りんご"></option>
35+
<option value="みかん"></option>
36+
<option value="バナナ"></option>
37+
</datalist>
3338
</label>
3439

3540
<div style="margin-top: 20px">

examples/dev/text.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { attach, rules } from "../../src/main.js";
33
const input = document.getElementById("input");
44
const output = document.getElementById("output");
55

6+
// input.value = "あいうえお";
7+
68
const guard = attach(input, {
79
rules: [
810
rules.kana({
@@ -11,10 +13,13 @@ const guard = attach(input, {
1113
rules.filter({
1214
category: ["katakana-full"],
1315
allow: /[ ]/
14-
})
16+
}),
17+
rules.prefix({ text: "[" }),
18+
rules.suffix({ text: "]" })
1519
]
1620
});
17-
guard.setValue("123");
21+
22+
// guard.setValue("123");
1823
const el = guard.getDisplayElement();
1924

2025
function renderState() {

src/text-input-guard.js

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -986,7 +986,13 @@ class InputGuard {
986986
// console.log("[text-input-guard] input");
987987
// compositionend後に input が来た場合、フォールバックを無効化
988988
this.pendingCompositionCommit = false;
989-
this.evaluateInput();
989+
try {
990+
this.evaluateInput();
991+
} finally {
992+
// beforeinput が来ない入力経路(autocomplete等)で
993+
// 古い snapshot を使い回さないよう、1イベントごとに破棄する
994+
this.beforeInputSnapshot = null;
995+
}
990996
}
991997

992998
/**
@@ -1145,17 +1151,43 @@ class InputGuard {
11451151
const ctx = this.createCtx();
11461152
ctx.afterText = current;
11471153

1148-
// beforeinput が取得できない経路(初回評価)では
1149-
// 差分再構成を行うと lastAcceptedValue 基準で値を落とす可能性があるため、
1150-
// 現在の全文を正規化して扱うフォールバックへ切り替える。
1151-
if (!this.beforeInputSnapshot) {
1154+
/**
1155+
* 入力値情報のみを使用するフォールバック
1156+
* @returns {GuardContext}
1157+
*/
1158+
const applyFullNormalizeFromCurrent = () => {
11521159
let newText = current;
11531160
ctx.beforeText = "";
11541161
newText = this.runNormalizeChar(newText, ctx);
11551162
newText = this.runNormalizeStructure(newText, ctx);
11561163
this.setDisplayValuePreserveCaret(display, newText, ctx);
11571164
ctx.afterText = newText;
11581165
return ctx;
1166+
};
1167+
1168+
// beforeinput が取得できない経路(初回評価)では
1169+
// 差分再構成を行うと lastAcceptedValue 基準で値を落とす可能性があるため、
1170+
// 現在の全文を正規化して扱うフォールバックへ切り替える。
1171+
if (!this.beforeInputSnapshot) {
1172+
return applyFullNormalizeFromCurrent();
1173+
}
1174+
1175+
// オートコンプリート等では beforeinput は来ても data が空のことがあり、
1176+
// 差分情報だけでは再構成不能になる。表示値がすでに変わっている場合は
1177+
// 再構成を諦めて current 全体の正規化に切り替える。
1178+
const isDeleteInput =
1179+
ctx.inputType === "deleteContentBackward" ||
1180+
ctx.inputType === "deleteContentForward";
1181+
const isInsertLikeInput =
1182+
ctx.inputType === "" ||
1183+
ctx.inputType?.startsWith("insert");
1184+
const lacksDelta =
1185+
ctx.insertedText === "" &&
1186+
ctx.beforeText !== current &&
1187+
isInsertLikeInput &&
1188+
!isDeleteInput;
1189+
if (lacksDelta) {
1190+
return applyFullNormalizeFromCurrent();
11591191
}
11601192

11611193
// 元のテキスト

0 commit comments

Comments
 (0)