補完機能がほとんど形になり、クロスデバイス(及びブラウザ)への対応を行っています。
~入力した文字を別の文字に置き換えるというのはJavaScriptで入力した文字を選択状態にし、上書きをするという方法を使っているのですが、いつもの通りIEでは`HTMLInputElement.setRangeText()`に対応しておらず、Polyfillも見つからなかったので対応は見送りました。**便利を享受したければIEを捨てるのです!**~
**訂正:IE対応しました。** 参考:[カーソル位置に任意の文字列を挿入する](https://hi97.hamazo.tv/e8318233.html)(自著)
~一方~クロスデバイスの対応としてはスマートフォンでも動くようにする必要があります。
物理キーボードを使うスマートフォンユーザはほとんどいないと思うので、補完候補が表示されてもタップで選ぶ必要があります。
Vue.jsの@clickで動くのかと思っていたのですが、反応するときと反応しない時がありうまくメソッドが呼び出されていませんでした(失敗するほうが圧倒的に多かった)。
スマートフォンではclickイベントではなくtouchstartを拾う必要があったので、@clickを使わずに、別途Vue.jsのマウント時にリスナーを登録するようにしました。
PCではtouchstartイベントに対応していないので、振り分ける必要がありましたが、[タップイベントが使えるか判定して、touchstartかclickか切り替える方法 | キタックCGソリューションセンター|Webマーケティング](https://cgsc.info/programming/20151203_touchstart-or-click)に解決方法が載っていたのでそれを使います。
```js
mounted() {
/* 省略 */
this.list = this.popup.querySelector("ul") as HTMLUListElement;
const type = null === window.ontouchstart ? "touchstart" : "click";
this.list.addEventListener(type, ev => {
ev.preventDefault();
const str = (ev.target as HTMLElement).textContent || "";
const tag = this.searchObject(str);
this.upsert(tag);
});
}
```
Vueの@clickではタグを生成すると同時にメソッドに引数が渡せたのですが、今回は後から付け足すような形なので、ulタグ下の項目をタップして、表示されてるテキストの内容から該当するタグを見つけてくるようにしました。
あとは@clickで使っていた`upsert()`メソッドにデータを渡して置換の処理を行います。
スマートフォンではタップするとタップ情報が残ってしまっているのか、キャレットの位置がずれてしまいましたが。`preventDefault()`で以降のイベントを発火させないことで、ちゃんと閉じタグの前にキャレットが来るようになりました。