EditContext APIを理解する
EditContext APIとはなんぞや
EditContext APIはChrome121版でリリースされた比較的新しい機能です。
現在執筆時点(2024/04/19)ではchromiumベース以外のブラウザではまだ実装されていないのでご注意ください。
この機能は、一言で言うならばcontenteditable
からDom Viewの機能を落としたようなものになっており、IMEやText Bufferに関する機能を提供してくれます。
contenteditableの何が辛かったのか?
contenteditableは、特定の要素を編集可能にしてくれる属性です。
ただし、近年のテキスト入力型のインターフェースの機能は多様化しており、contenteditable
属性のついたtextareaだけでは表現が難しい場合があります。
その場合、contenteditable
のついた要素上で編集を行いつつ見た目のDOMは別で表示し、contenteditable
のDOMは非表示にしたくなるでしょう。
この実装方針はバグを生みやすくアクセシビリティにも問題があるため、text bufferとDom Viewを疎結合にすることを可能にするインターフェースが必要になり、EditContext APIが誕生しました。
contenteditable
が実際に問題になっている例
Real-world Examples of Text Input Issues in Top Sites and Frameworks
上記に実際に問題になっている例が挙げられています。上記からMonacoの例を見てみましょう。
Monacoはまさに入力時のみにcontenteditableなtexareaを用意する手法をとっており、その結果読み上げ時の単語にアウトラインがつかなかったりなどのアクセシビリティ的な問題が起きています。
参考:読み上げdemo video
実際にEditContext APIを使ってみる
EditContext
の初期化の記法は下記です。
const editContext = new EditContext();
element.editContext = editContext;
実際に入力されたtext bufferのアクセスはeditContext.text
でアクセスすることができます。
下記のようにelementのイベントにhookすることで、text bufferとDOM Viewの同期を実装することが可能です。
editContext.addEventListener("textupdate", (event) => {
element.textContent = editContext.text;
});
また、編集可能領域の変更やユーザーのselectionの変更をeditContext
に通知する必要があります。
const controlBound = element.getBoundingClientRect();
const selection = document.getSelection();
const selectionBound = selection?.getRangeAt(0).getBoundingClientRect();
editContext.updateControlBounds(controlBound); // 編集可能領域の変更通知
editContext.updateSelectionBounds(selectionBound); // selectionの変更通知
実際にEditContext APIを利用した、入力と出力のDOMを分離する実装サンプルを作成しました。
(キーボードインターフェースを介して入力用DOMに入力し、入力用DOMを介して出力DOMに出力し...なんだか不思議な気持ちになりますね)
おまけ:リッチテキスト界隈にどれぐらい影響があるのか
今回EditContext API調査を始めたきっかけはリッチテキストエディタにどれぐらいの影響があるかを知るためでした。
自分の感想としてはDom Viewと入力の分離がメインとなっており、各エディタの仕組みを大きく変えずに置換できるもののように感じました。
また、リッチテキストエディタ系のライブラリに関しては、多くはcontenteditable
のついた要素をそのままDom Viewとしても扱っており、今回問題視されているようなことは起きていなさそうでした。
(仕方なく現状はcontenteditableのDOMを直接扱っている、という側面はあるかもしれませんが)
一部のライブラリではEditContext APIが話題に上がっているものもあるため、今後の課題に応じて内部実装が置換されていく可能性はありそうです。
参考資料
Discussion