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
|
@@ -272,7 +272,7 @@ class SwapState {
|
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
/**
|
|
275
|
-
* The script is part of
|
|
275
|
+
* The script is part of TextInputGuard.
|
|
276
276
|
*
|
|
277
277
|
* AUTHOR:
|
|
278
278
|
* natade-jp (https://github.com/natade-jp)
|
|
@@ -622,6 +622,8 @@ class HistoryQueue {
|
|
|
622
622
|
}
|
|
623
623
|
}
|
|
624
624
|
|
|
625
|
+
let globalGuardId = 0; // デバッグ用のガードID生成
|
|
626
|
+
|
|
625
627
|
class InputGuard {
|
|
626
628
|
/**
|
|
627
629
|
* InputGuard の内部状態を初期化する(DOM/設定/イベント/パイプラインを持つ)
|
|
@@ -629,6 +631,12 @@ class InputGuard {
|
|
|
629
631
|
* @param {AttachOptions} options
|
|
630
632
|
*/
|
|
631
633
|
constructor(element, options) {
|
|
634
|
+
/**
|
|
635
|
+
* ガードID(デバッグ用、インスタンスごとにユニーク)
|
|
636
|
+
* @type {number}
|
|
637
|
+
*/
|
|
638
|
+
this.id = ++globalGuardId;
|
|
639
|
+
|
|
632
640
|
/**
|
|
633
641
|
* attach対象の元の要素(swap前の原本)
|
|
634
642
|
* detach時の復元や基準参照に使う
|
|
@@ -710,7 +718,7 @@ class InputGuard {
|
|
|
710
718
|
/**
|
|
711
719
|
* 実際に送信を担う要素(swap時は hidden(raw) 側)
|
|
712
720
|
* swapしない場合は originalElement と同一
|
|
713
|
-
* @type {
|
|
721
|
+
* @type {HTMLInputElement|HTMLTextAreaElement}
|
|
714
722
|
*/
|
|
715
723
|
this.hostElement = element;
|
|
716
724
|
|
|
@@ -821,6 +829,11 @@ class InputGuard {
|
|
|
821
829
|
*/
|
|
822
830
|
this.onFocus = this.onFocus.bind(this);
|
|
823
831
|
|
|
832
|
+
/**
|
|
833
|
+
* keydownイベントハンドラ(this固定)
|
|
834
|
+
*/
|
|
835
|
+
this.onKeyDown = this.onKeyDown.bind(this);
|
|
836
|
+
|
|
824
837
|
/**
|
|
825
838
|
* キャレット/選択範囲の変化イベントハンドラ(this固定)
|
|
826
839
|
*/
|
|
@@ -876,6 +889,14 @@ class InputGuard {
|
|
|
876
889
|
this.revertRequest = null;
|
|
877
890
|
}
|
|
878
891
|
|
|
892
|
+
/**
|
|
893
|
+
* デバッグ用の文字列化
|
|
894
|
+
* @returns {string}
|
|
895
|
+
*/
|
|
896
|
+
toString() {
|
|
897
|
+
return `[TextInputGuard#${this.id} kind=${this.kind} host=${this.hostElement.tagName.toLowerCase()}#${this.hostElement.id}] value=${this.hostElement.value}]`;
|
|
898
|
+
}
|
|
899
|
+
|
|
879
900
|
/**
|
|
880
901
|
* 初期化処理(swap適用 → パイプライン構築 → イベント登録 → 初回評価)
|
|
881
902
|
* @returns {void}
|
|
@@ -1080,6 +1101,7 @@ class InputGuard {
|
|
|
1080
1101
|
this.displayElement.addEventListener("beforeinput", this.onBeforeInput);
|
|
1081
1102
|
this.displayElement.addEventListener("blur", this.onBlur);
|
|
1082
1103
|
this.displayElement.addEventListener("focus", this.onFocus);
|
|
1104
|
+
this.displayElement.addEventListener("keydown", this.onKeyDown);
|
|
1083
1105
|
}
|
|
1084
1106
|
|
|
1085
1107
|
/**
|
|
@@ -1093,6 +1115,7 @@ class InputGuard {
|
|
|
1093
1115
|
this.displayElement.removeEventListener("beforeinput", this.onBeforeInput);
|
|
1094
1116
|
this.displayElement.removeEventListener("blur", this.onBlur);
|
|
1095
1117
|
this.displayElement.removeEventListener("focus", this.onFocus);
|
|
1118
|
+
this.displayElement.removeEventListener("keydown", this.onKeyDown);
|
|
1096
1119
|
}
|
|
1097
1120
|
|
|
1098
1121
|
/**
|
|
@@ -1265,8 +1288,8 @@ class InputGuard {
|
|
|
1265
1288
|
// アンドゥリドゥの特殊処理
|
|
1266
1289
|
if (inputType === "historyUndo" || inputType === "historyRedo") {
|
|
1267
1290
|
let newText = null;
|
|
1268
|
-
console.log(inputType);
|
|
1269
|
-
console.log(this.history.toString());
|
|
1291
|
+
// console.log(inputType);
|
|
1292
|
+
// console.log(this.history.toString());
|
|
1270
1293
|
if (inputType === "historyUndo") {
|
|
1271
1294
|
newText = this.history.undo();
|
|
1272
1295
|
} else if (inputType === "historyRedo") {
|
|
@@ -1510,6 +1533,19 @@ class InputGuard {
|
|
|
1510
1533
|
}
|
|
1511
1534
|
this.existBeforeInputEvent = true;
|
|
1512
1535
|
this.beforeInputSnapshot = { selection, inputType, insertedText };
|
|
1536
|
+
|
|
1537
|
+
// アンドゥリドゥの beforeinput はフォーカスされている要素以外にも発生することがあるため、
|
|
1538
|
+
// 正しく判定するために onKeyDown で捕まえて、必要なときだけ onBeforeInput のスナップを作る
|
|
1539
|
+
if (inputType === "historyUndo" || inputType === "historyRedo") {
|
|
1540
|
+
e.preventDefault();
|
|
1541
|
+
|
|
1542
|
+
// フォーカス中ではない要素に飛んできたUndo/Redoは止めるだけ
|
|
1543
|
+
if (document.activeElement !== this.displayElement) {
|
|
1544
|
+
return;
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
this.evaluateInput();
|
|
1548
|
+
}
|
|
1513
1549
|
}
|
|
1514
1550
|
|
|
1515
1551
|
/**
|
|
@@ -1566,6 +1602,51 @@ class InputGuard {
|
|
|
1566
1602
|
this.history.push(raw);
|
|
1567
1603
|
}
|
|
1568
1604
|
|
|
1605
|
+
/**
|
|
1606
|
+
* keydownイベント:特殊な用途向けに提供(例:Enterで確定させたいなど)
|
|
1607
|
+
* @param {Event} e
|
|
1608
|
+
* @returns {void}
|
|
1609
|
+
*/
|
|
1610
|
+
onKeyDown(e) {
|
|
1611
|
+
if (!(e instanceof KeyboardEvent)) {
|
|
1612
|
+
return;
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
// アンドゥ及びリドゥの onBeforeInput はフォーカスされている要素以外にも発生することがあるため
|
|
1616
|
+
// 正しく判定するために onKeyDown で捕まえて、必要なときだけ onBeforeInput のスナップを作る
|
|
1617
|
+
|
|
1618
|
+
const isUndo = (e.ctrlKey || e.metaKey) && !e.shiftKey && e.key.toLowerCase() === "z";
|
|
1619
|
+
const isRedo =
|
|
1620
|
+
((e.ctrlKey || e.metaKey) && e.shiftKey && e.key.toLowerCase() === "z") ||
|
|
1621
|
+
((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "y");
|
|
1622
|
+
|
|
1623
|
+
if (!isUndo && !isRedo) {
|
|
1624
|
+
return;
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
// ここでチェックする
|
|
1628
|
+
if (document.activeElement !== this.displayElement) {
|
|
1629
|
+
return;
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
// ブラウザのデフォルトの undo/redo をキャンセルして、自前でUndo/Redo を発生させる
|
|
1633
|
+
e.preventDefault();
|
|
1634
|
+
|
|
1635
|
+
// 擬似beforeinputのスナップを作る
|
|
1636
|
+
this.beforeInputSnapshot = {
|
|
1637
|
+
selection: this.readSelection(this.displayElement),
|
|
1638
|
+
inputType: isUndo ? "historyUndo" : "historyRedo",
|
|
1639
|
+
insertedText: ""
|
|
1640
|
+
};
|
|
1641
|
+
|
|
1642
|
+
this.existBeforeInputEvent = true;
|
|
1643
|
+
try {
|
|
1644
|
+
this.evaluateInput();
|
|
1645
|
+
} finally {
|
|
1646
|
+
this.existBeforeInputEvent = false;
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1569
1650
|
/**
|
|
1570
1651
|
* キャレット/選択範囲の変化を lastAcceptedSelection に反映する
|
|
1571
1652
|
* - 値が変わっていない状態でもキャレットは動くため、block時に自然な位置へ戻すために使う
|
|
@@ -1909,7 +1990,7 @@ class InputGuard {
|
|
|
1909
1990
|
|
|
1910
1991
|
/**
|
|
1911
1992
|
* 外部に公開する Guard API を生成して返す
|
|
1912
|
-
* -
|
|
1993
|
+
* - TextInputGuard 自体を公開せず、最小の操作だけを渡す
|
|
1913
1994
|
* @returns {Guard}
|
|
1914
1995
|
*/
|
|
1915
1996
|
getGuard() {
|
|
@@ -7703,11 +7784,11 @@ const rules = {
|
|
|
7703
7784
|
|
|
7704
7785
|
/**
|
|
7705
7786
|
* バージョン(ビルド時に置換したいならここを差し替える)
|
|
7706
|
-
* 例: rollup replace で ""1.2.
|
|
7787
|
+
* 例: rollup replace で ""1.2.2"" を package.json の version に置換
|
|
7707
7788
|
*/
|
|
7708
7789
|
// @ts-ignore
|
|
7709
7790
|
// eslint-disable-next-line no-undef
|
|
7710
|
-
const version = "1.2.
|
|
7791
|
+
const version = "1.2.2" ;
|
|
7711
7792
|
|
|
7712
7793
|
/**
|
|
7713
7794
|
* UMD公開時のグローバルオブジェクト
|