JavaScript
Chrome
Chromium
Vivaldi

memo: テキスト全選択の JavaScript コードが動かなくなったので修正した

pre タグの内側に書かれたテキストを1クリックで全選択するためのコードが、 Chromium ベースのブラウザで動かなくなりました。

対処として、以下のように .addRange() の前に .removeAllRanges() を追加して動くようにしました。

<script type="text/javascript">
function select_contents(obj) {

    var s = window.getSelection();
    var range = document.createRange();
    range.selectNodeContents(obj);

    s.removeAllRanges();    // ←追加

    s.addRange(range);
}
</script>

どういうこと?

pre タグの内側をクリックするとテキスト部分を全選択する、という処理を以下のように実装し、問題なく動いていました(2017年4月頃確認)。

<script type="text/javascript">
function select_contents(obj) {

    var s = window.getSelection();
    var range = document.createRange();
    range.selectNodeContents(obj);
    s.addRange(range);
}
</script>

<pre id="output_txt" onclick="select_contents(this);">
...
</pre>

ところが先日、この処理が Chromium ベースのブラウザで動かなくなっていることを確認しました(2017/07/05 確認)。

すなわち、

  • クリックしても全選択されない
  • 以下の警告メッセージがブラウザのコンソールに出力された
[Deprecation] The behavior that Selection.addRange() merges existing Range and the specified Range was removed.

調べてみると、つまりこういうことだそうです。

Selection API: addRange() ignores additional Ranges

In a case where document already has text selection and Selection.addRange() is called, Blink merges the Range and the existing text selection into one if they have overlap, and does nothing otherwise.

We'll change it so that Blink always ignore the Range. It matches to Edge.

cf. Chorome Platform Status https://www.chromestatus.com/features/6680566019653632

ざっくり: Selection に既に何か設定されているときに .addRange() しても無視されるよ。

環境

動かなくなったことを確認したブラウザ:

  • Google Chrome 59.0.3071.86
  • Vivaldi 1.10.867.42

以下のブラウザでは、いままで通り動くことを確認しました。

  • Firefox 54.0.1

対処

Selection に既に設定されている値(Range)を取り払ってから .addRange() するようコードを修正しました。

すなわち

s.addRange(range);



s.removeAllRanges();    // 追加
s.addRange(range);

としました。

これで、処理が動かなくなっていたブラウザでも、当初の想定通り動くことを確認しました。

参考文献