【JavaScript】execCommand()が非推奨に…その代替方法とかコード例

次のAPIがいつの間にか非推奨になってました。

Document.execCommand()

どうして非推奨になったかは不明だけど、
ウェブ標準から削除されるのは確実です。

だから代替の方法を探すことにしました。

その代替コードとか色々まとめてみます。

今までのdocument.execCommand()の使われ方

これは以下のような処理ができるAPIでした

  • 編集可能なdiv要素などがある
  • その中で適当にテキストを選択する
  • 選択テキストを操作することが可能
  • 太字だったり、背景色変えたり…

具体的に例を出すならこういう使い方をします。

▼ 編集可能 contenteditable="true"  のdiv要素がある

▼ 選択テキストを太字にする

上記コードだったら document.execCommand('bold', false)  から太字にするコマンドを発行し、実際に選択テキストが太字になります。

使用できるコマンドは太字・斜体・背景色・ハイパーリンク・アラインメント・コピー・貼り付け・切り取り……挙げてけばキリがないです。

そういうAPIが昔は使えてました(昔は)

いつの間にかdocument.execCommand()が非推奨に…

ところが現在は非推奨になっています。
そして将来はウェブ標準からも削除される予定です。

▼ 非推奨であることのソース

非推奨: この機能は非推奨になりました。まだ対応しているブラウザーがあるかもしれませんが、すでに関連するウェブ標準から削除されているか、削除の手続き中であるか、互換性のためだけに残されている可能性があります。使用を避け、できれば既存のコードは更新してください。このページの下部にある互換性一覧表を見て判断してください。この機能は突然動作しなくなる可能性があることに注意してください。

引用元 : https://developer.mozilla.org/ja/docs/Web/API/Document/execCommand

「この機能は突然動作しなくなる可能性」

怖いですね、怖い (-_-;)

だから一切使うことは控えるべきAPIです。

代替APIとしてRange.surroundContents()を使えばいい

それでは何を代替に使えばいいのか…

次のAPIを代わりに使えばOKです。

Range.surroundContents()

しかもdocument.execCommandよりも汎用性あります。

▼ 例えば先ほどのコードを書き直した結果

▼ 太字にできた

Range.surroundContents()を使ってdiv要素内の選択領域を太字にした時の様子

初めに装飾用のspan要素を作成します。

そのあと選択範囲オブジェクトを取得し、 selectedTextRange.surroundContents(span)  のように選択範囲を囲んであげるだけです。

これからはこの方法を使っていきます。

汎用性も高いRange.surroundContents()を使うのがベスト

あとこのAPIは汎用性も高いのがグッド。

▼ execCommand vs surroundContentsの違い

  • 前者はコマンド種類が固定されてて汎用性低
  • 後者は自由にカスタムできるから汎用性高

1度に複数の装飾ができるのも利点だと思います。

▼ 例えば太字+文字色赤に変えるコード例

▼ テキスト選択領域が太字+赤色になった

Range.surroundContents()を使って編集可能div要素内の選択領域を太字+赤字にした時の様子

もしこれが document.execCommand()  だったら2回コマンド実行しないといけないし、使用できるコマンドも制限があります。

そこらへんの不便さというか汎用性のなさ、それも非推奨になった原因かもしれません。(とはいえ突然動作しなくなるのは少し不親切な気もする)

とりあえず Range.surroundContents()  を使えばOKです

この記事と関連があるかもしれない記事紹介

最後に関連があるかもしれない記事を紹介します。

▼ JSでクリップボードのコピーを取得・書き換えする方法

▼ JS・jQueryでクリップボードの貼り付けを検知する方法

関連性としては高いと思う

実際、当記事に出てきた window.getSelection()  は選択領域を取得するためのものだし、それを使ってクリップボードを取得・書き換えとかもできます。

以上、execCommand() が非推奨という話でした。ではまた

これからは Range.surroundContents() を使っていきます。