TL;DR:documentにマウスイベントリスナを設定する


HTMLの要素をドラッグできるようにするときに、ウィンドウ外にドラッグされるとマウスイベントが受け取れなくてドラッグしっぱなしになってしまうとか、お絵かきで線を引きっぱなしになってしまうという悲しいことがよくあった。

たまたまjQueryUIのsortableを使ってみたところウィンドウ外でもドラッグできているので、どうやっているのかソースを見てみた。その名のui/widgets/sortable.jsではやってなくて、mouse.jsで、対象の要素や親じゃなくてdocumentmousemovemouseupのイベントリスナを登録している。

ということなので、jQueryを使わないで素のJSでdocument.addEventListener()を使ってテストしたところ望み通りに動いた(デモソース)。

  • windowにマウスイベントリスナを設定しても同様に受け取れた
  • FireFoxだとsetCapture()でキャプチャできる、が他のブラウザでは未実装…
  • addEventListenerの第3引数のuseCaptureというのは今回の用途とは関係なくて、イベントをキャプチャフェーズで呼び出すかどうか、ということだった
  • Plnkrの編集画面や埋め込みのようにiframe内で動かされるとその外にマウスが出てしまうとイベントは取れない模様。
    • その場合にはmouseleaveを受け取ったら解除してやるとよい