text-input-guard 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/text-input-guard.cjs +88 -7
- package/dist/cjs/text-input-guard.min.cjs +1 -1
- package/dist/esm/text-input-guard.js +88 -7
- package/dist/esm/text-input-guard.min.js +1 -1
- package/dist/umd/text-input-guard.js +88 -7
- package/dist/umd/text-input-guard.min.js +1 -1
- package/package.json +1 -1
|
@@ -270,7 +270,7 @@ class SwapState {
|
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
/**
|
|
273
|
-
* The script is part of
|
|
273
|
+
* The script is part of TextInputGuard.
|
|
274
274
|
*
|
|
275
275
|
* AUTHOR:
|
|
276
276
|
* natade-jp (https://github.com/natade-jp)
|
|
@@ -620,6 +620,8 @@ class HistoryQueue {
|
|
|
620
620
|
}
|
|
621
621
|
}
|
|
622
622
|
|
|
623
|
+
let globalGuardId = 0; // デバッグ用のガードID生成
|
|
624
|
+
|
|
623
625
|
class InputGuard {
|
|
624
626
|
/**
|
|
625
627
|
* InputGuard の内部状態を初期化する(DOM/設定/イベント/パイプラインを持つ)
|
|
@@ -627,6 +629,12 @@ class InputGuard {
|
|
|
627
629
|
* @param {AttachOptions} options
|
|
628
630
|
*/
|
|
629
631
|
constructor(element, options) {
|
|
632
|
+
/**
|
|
633
|
+
* ガードID(デバッグ用、インスタンスごとにユニーク)
|
|
634
|
+
* @type {number}
|
|
635
|
+
*/
|
|
636
|
+
this.id = ++globalGuardId;
|
|
637
|
+
|
|
630
638
|
/**
|
|
631
639
|
* attach対象の元の要素(swap前の原本)
|
|
632
640
|
* detach時の復元や基準参照に使う
|
|
@@ -708,7 +716,7 @@ class InputGuard {
|
|
|
708
716
|
/**
|
|
709
717
|
* 実際に送信を担う要素(swap時は hidden(raw) 側)
|
|
710
718
|
* swapしない場合は originalElement と同一
|
|
711
|
-
* @type {
|
|
719
|
+
* @type {HTMLInputElement|HTMLTextAreaElement}
|
|
712
720
|
*/
|
|
713
721
|
this.hostElement = element;
|
|
714
722
|
|
|
@@ -819,6 +827,11 @@ class InputGuard {
|
|
|
819
827
|
*/
|
|
820
828
|
this.onFocus = this.onFocus.bind(this);
|
|
821
829
|
|
|
830
|
+
/**
|
|
831
|
+
* keydownイベントハンドラ(this固定)
|
|
832
|
+
*/
|
|
833
|
+
this.onKeyDown = this.onKeyDown.bind(this);
|
|
834
|
+
|
|
822
835
|
/**
|
|
823
836
|
* キャレット/選択範囲の変化イベントハンドラ(this固定)
|
|
824
837
|
*/
|
|
@@ -874,6 +887,14 @@ class InputGuard {
|
|
|
874
887
|
this.revertRequest = null;
|
|
875
888
|
}
|
|
876
889
|
|
|
890
|
+
/**
|
|
891
|
+
* デバッグ用の文字列化
|
|
892
|
+
* @returns {string}
|
|
893
|
+
*/
|
|
894
|
+
toString() {
|
|
895
|
+
return `[TextInputGuard#${this.id} kind=${this.kind} host=${this.hostElement.tagName.toLowerCase()}#${this.hostElement.id}] value=${this.hostElement.value}]`;
|
|
896
|
+
}
|
|
897
|
+
|
|
877
898
|
/**
|
|
878
899
|
* 初期化処理(swap適用 → パイプライン構築 → イベント登録 → 初回評価)
|
|
879
900
|
* @returns {void}
|
|
@@ -1078,6 +1099,7 @@ class InputGuard {
|
|
|
1078
1099
|
this.displayElement.addEventListener("beforeinput", this.onBeforeInput);
|
|
1079
1100
|
this.displayElement.addEventListener("blur", this.onBlur);
|
|
1080
1101
|
this.displayElement.addEventListener("focus", this.onFocus);
|
|
1102
|
+
this.displayElement.addEventListener("keydown", this.onKeyDown);
|
|
1081
1103
|
}
|
|
1082
1104
|
|
|
1083
1105
|
/**
|
|
@@ -1091,6 +1113,7 @@ class InputGuard {
|
|
|
1091
1113
|
this.displayElement.removeEventListener("beforeinput", this.onBeforeInput);
|
|
1092
1114
|
this.displayElement.removeEventListener("blur", this.onBlur);
|
|
1093
1115
|
this.displayElement.removeEventListener("focus", this.onFocus);
|
|
1116
|
+
this.displayElement.removeEventListener("keydown", this.onKeyDown);
|
|
1094
1117
|
}
|
|
1095
1118
|
|
|
1096
1119
|
/**
|
|
@@ -1263,8 +1286,8 @@ class InputGuard {
|
|
|
1263
1286
|
// アンドゥリドゥの特殊処理
|
|
1264
1287
|
if (inputType === "historyUndo" || inputType === "historyRedo") {
|
|
1265
1288
|
let newText = null;
|
|
1266
|
-
console.log(inputType);
|
|
1267
|
-
console.log(this.history.toString());
|
|
1289
|
+
// console.log(inputType);
|
|
1290
|
+
// console.log(this.history.toString());
|
|
1268
1291
|
if (inputType === "historyUndo") {
|
|
1269
1292
|
newText = this.history.undo();
|
|
1270
1293
|
} else if (inputType === "historyRedo") {
|
|
@@ -1508,6 +1531,19 @@ class InputGuard {
|
|
|
1508
1531
|
}
|
|
1509
1532
|
this.existBeforeInputEvent = true;
|
|
1510
1533
|
this.beforeInputSnapshot = { selection, inputType, insertedText };
|
|
1534
|
+
|
|
1535
|
+
// アンドゥリドゥの beforeinput はフォーカスされている要素以外にも発生することがあるため、
|
|
1536
|
+
// 正しく判定するために onKeyDown で捕まえて、必要なときだけ onBeforeInput のスナップを作る
|
|
1537
|
+
if (inputType === "historyUndo" || inputType === "historyRedo") {
|
|
1538
|
+
e.preventDefault();
|
|
1539
|
+
|
|
1540
|
+
// フォーカス中ではない要素に飛んできたUndo/Redoは止めるだけ
|
|
1541
|
+
if (document.activeElement !== this.displayElement) {
|
|
1542
|
+
return;
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
this.evaluateInput();
|
|
1546
|
+
}
|
|
1511
1547
|
}
|
|
1512
1548
|
|
|
1513
1549
|
/**
|
|
@@ -1564,6 +1600,51 @@ class InputGuard {
|
|
|
1564
1600
|
this.history.push(raw);
|
|
1565
1601
|
}
|
|
1566
1602
|
|
|
1603
|
+
/**
|
|
1604
|
+
* keydownイベント:特殊な用途向けに提供(例:Enterで確定させたいなど)
|
|
1605
|
+
* @param {Event} e
|
|
1606
|
+
* @returns {void}
|
|
1607
|
+
*/
|
|
1608
|
+
onKeyDown(e) {
|
|
1609
|
+
if (!(e instanceof KeyboardEvent)) {
|
|
1610
|
+
return;
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
// アンドゥ及びリドゥの onBeforeInput はフォーカスされている要素以外にも発生することがあるため
|
|
1614
|
+
// 正しく判定するために onKeyDown で捕まえて、必要なときだけ onBeforeInput のスナップを作る
|
|
1615
|
+
|
|
1616
|
+
const isUndo = (e.ctrlKey || e.metaKey) && !e.shiftKey && e.key.toLowerCase() === "z";
|
|
1617
|
+
const isRedo =
|
|
1618
|
+
((e.ctrlKey || e.metaKey) && e.shiftKey && e.key.toLowerCase() === "z") ||
|
|
1619
|
+
((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "y");
|
|
1620
|
+
|
|
1621
|
+
if (!isUndo && !isRedo) {
|
|
1622
|
+
return;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
// ここでチェックする
|
|
1626
|
+
if (document.activeElement !== this.displayElement) {
|
|
1627
|
+
return;
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
// ブラウザのデフォルトの undo/redo をキャンセルして、自前でUndo/Redo を発生させる
|
|
1631
|
+
e.preventDefault();
|
|
1632
|
+
|
|
1633
|
+
// 擬似beforeinputのスナップを作る
|
|
1634
|
+
this.beforeInputSnapshot = {
|
|
1635
|
+
selection: this.readSelection(this.displayElement),
|
|
1636
|
+
inputType: isUndo ? "historyUndo" : "historyRedo",
|
|
1637
|
+
insertedText: ""
|
|
1638
|
+
};
|
|
1639
|
+
|
|
1640
|
+
this.existBeforeInputEvent = true;
|
|
1641
|
+
try {
|
|
1642
|
+
this.evaluateInput();
|
|
1643
|
+
} finally {
|
|
1644
|
+
this.existBeforeInputEvent = false;
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1567
1648
|
/**
|
|
1568
1649
|
* キャレット/選択範囲の変化を lastAcceptedSelection に反映する
|
|
1569
1650
|
* - 値が変わっていない状態でもキャレットは動くため、block時に自然な位置へ戻すために使う
|
|
@@ -1907,7 +1988,7 @@ class InputGuard {
|
|
|
1907
1988
|
|
|
1908
1989
|
/**
|
|
1909
1990
|
* 外部に公開する Guard API を生成して返す
|
|
1910
|
-
* -
|
|
1991
|
+
* - TextInputGuard 自体を公開せず、最小の操作だけを渡す
|
|
1911
1992
|
* @returns {Guard}
|
|
1912
1993
|
*/
|
|
1913
1994
|
getGuard() {
|
|
@@ -7701,11 +7782,11 @@ const rules = {
|
|
|
7701
7782
|
|
|
7702
7783
|
/**
|
|
7703
7784
|
* バージョン(ビルド時に置換したいならここを差し替える)
|
|
7704
|
-
* 例: rollup replace で ""1.2.
|
|
7785
|
+
* 例: rollup replace で ""1.2.2"" を package.json の version に置換
|
|
7705
7786
|
*/
|
|
7706
7787
|
// @ts-ignore
|
|
7707
7788
|
// eslint-disable-next-line no-undef
|
|
7708
|
-
const version = "1.2.
|
|
7789
|
+
const version = "1.2.2" ;
|
|
7709
7790
|
|
|
7710
7791
|
/**
|
|
7711
7792
|
* UMD公開時のグローバルオブジェクト
|