Draggable的な実装

こんなん
Draggable Test 1
これでもいいんだけど、これドラッグ中に要素からマウスポインタが外れると動かなくなるという問題がある。コードはこんな感じ。

var div = document.querySelector(".box")
  , startX = 0
  , startY = 0
  , currentX = 0
  , currentY = 0
  , start = false;

div.addEventListener("mousedown", function(event) {
  event.preventDefault();
  startX = event.pageX;
  startY = event.pageY;
  currentX = parseInt(div.style.left, 10) || 0;
  currentY = parseInt(div.style.top, 10) || 0;
  start = true;
}, false);

div.addEventListener("mousemove", function(event) {
  if (start) {
    div.style.left = (event.pageX + currentX - startX) + "px";
    div.style.top  = (event.pageY + currentY - startY) + "px";
  }
}, false);

div.addEventListener("mouseup", function(event) {
  start = false;
}, false);

これはイベントを要素にbindしてるのでマウスが外れたとき動かなくなるのは当然。

どうするかというと親要素にbindしてバブリングフェーズでmousemoveをキャッチする。ここではdocumentにbindしてる。

var div = document.querySelector(".box")
  , startX = 0
  , startY = 0
  , currentX = 0
  , currentY = 0
  , start = false;

div.addEventListener("mousedown", function(event) {
  event.preventDefault();
  startX = event.pageX;
  startY = event.pageY;
  currentX = parseInt(div.style.left, 10) || 0;
  currentY = parseInt(div.style.top, 10) || 0;
  start = true;
}, false);

document.addEventListener("mousemove", function(event) {
  if (start) {
    div.style.left = (event.pageX + currentX - startX) + "px";
    div.style.top  = (event.pageY + currentY - startY) + "px";
  }
}, false);

document.addEventListener("mouseup", function(event) {
  start = false;
}, false);

そうするとこんな感じになる。
Draggable Test 2