3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

クリックした位置の node を取得する方法 [クロスブラウザ対応]

Last updated at Posted at 2019-03-04

クリックした位置の node を取得する方法を勘違いしていたのでメモ。

const sel = window.getSelection()
const range = sel.getRangeAt(0)

この window.getSelection()getRangeAt(0) を使うことで選択しているテキストの node 範囲を取得することができる。非常に便利。これをクリックイベントで使うことでクリックした位置の node も取得できるのだけど iOS Safari ではなぜか取得できない現象に衝突。

普通に選択したり textarea など入力フォームでフォーカスされていれば正常に取得はできるが、なんでもない DOM の場合は取得が下記のようなエラーメッセージでできなかった。

IndexSizeError: The index is not in the allowed range.

iOS Safari でクリックした位置の node を取得するには document.caretRangeFromPoint() を使う。ただし caretRangeFromPoint は標準ではないので仕方なく使う感じ。

document.querySelector('.example').addEventListener('click', e => {
  // これはだめ
  // const sel = window.getSelection()
  // const range = sel.getRangeAt(0)

  const range = document.caretRangeFromPoint(e.clientX, e.clientY)
})

これで iOS Safari でもクリックした位置の node が取得できる。

ただし、Firefox では caretRangeFromPoint はサポートしていないので(Chrome はサポートしている)、別の方法を使う。

if (document.caretRangeFromPoint) {
  range = document.caretRangeFromPoint(e.clientX, e.clientY)
} else {
  range = document.createRange()
  range.setStart(e.rangeParent, e.rangeOffset)

  // もしくは
  // range = document.caretPositionFromPoint(e.clientX, e.clientY)

  // もしくは
  // const sel = window.getSelection()
  // range = sel.getRangeAt(0)
}

Firefox の場合はクリックしたイベントオブジェクトに rangeParentrangeOffset が生えているので、これを元に Range オブジェクトを作成すれば同様の node が取得可能。

また caretPositionFromPoint を使って(字面が似てるけど Range と Position と違う)取得することも可能。ただし、これは Range オブジェクトじゃなくて CaretPosition オブジェクトが返ってくるので注意。

ただクリックした位置の node と考えると Range オブジェクトである必要はないので、基本は caretPositionFromPoint で CaretPosition を取得するのを軸にして、対応していないブラウザの場合は caretRangeFromPoint で逃げるというのが現時点での対応方法かな。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?