Backstage of theater.js

2007/11/15(木) ドラッグアンドドロップサンプル

[]ドラッグアンドドロップサンプル

某所で回答したものを保存します。

・・・prototype.jsからいろいろ持ってきたのがバレバレですが^^;*1

>>>(圧縮版はこちら。)<<<

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 //EN">
<html>
<head>
<script>
function getStyle(elem, IEStyleProp, CSSStyleProp){
  if(elem.currentStyle){
    return elem.currentStyle[IEStyleProp];
  }else if(window.getComputedStyle){
    var compStyle = window.getComputedStyle(elem, "");
    return compStyle.getPropertyValue(CSSStyleProp);
  }
}

function pointerX(event) {
  return event.pageX || (event.clientX +
  (document.documentElement.scrollLeft || document.body.scrollLeft));
}

function pointerY(event) {
  return event.pageY || (event.clientY +
  (document.documentElement.scrollTop || document.body.scrollTop));
}

function stop(event) {
  if (event.preventDefault) {
    event.preventDefault();
    event.stopPropagation();
  } else {
    event.returnValue = false;
    event.cancelBubble = true;
  }
}

function observe(element, name, observer) {
  if (element.addEventListener) {
    element.addEventListener(name, observer, false);
  } else if (element.attachEvent) {
    element.attachEvent('on' + name, observer);
  }
}

function stopObserving(element, name, observer) {
  if (element.removeEventListener) {
    element.removeEventListener(name, observer, false);
  } else if (element.detachEvent) {
    try {
      element.detachEvent('on' + name, observer);
    } catch (e) {}
  }
}

/**
 * 要素ドラッガブル化関数
 *   id : 対象要素ID
 */
function makeDraggable(id){
  var element = document.getElementById(id);
  var pos = getStyle(element, 'position', 'position');
  if (pos == 'static' || !pos) {
    element.style.position = 'relative';
    if (window.opera) {
      element.style.top = 0;
      element.style.left = 0;
    }
  }
  element.style.cursor = "pointer";
  observe(element, "mousedown", start);
  var dx = dy = 0;

  function start(event){
    event = event || window.event;
    var x = getStyle(element, 'left', 'left');
    var y = getStyle(element, 'top', 'top');
    x = (!x || x == 'auto') ? 0 : parseInt(x);
    y = (!y || y == 'auto') ? 0 : parseInt(y);
    dx = pointerX(event) - x;
    dy = pointerY(event) - y;
    observe(document, "mousemove", move);
    observe(document, "mouseup", end);
    stop(event);
  }

  function move(event){
    event = event || window.event;
    var x = parseInt(pointerX(event) - dx);
    var y = parseInt(pointerY(event) - dy);
    element.style.left = x + "px";
    element.style.top = y + "px";
    stop(event);
  }

  function end(event){
    event = event || window.event;
    stopObserving(document, "mousemove", move);
    stopObserving(document, "mouseup", end);
    stop(event);
  }
}

function init(){
  makeDraggable("test1");
  makeDraggable("test2");
  makeDraggable("test3");
}
</script>
<style>
div{
border:solid blue 2px;background-color:yellow;
};
</style>
</head>
<body onload="init();">
<div id="test1" style="width:300px;height:300px;">TEST1
<div id="test2" style="width:200px;height:200px;">TEST2
<div id="test3" style="width:100px;height:100px;">TEST3
</div>
</div>
</div>
</body>
</html>

【注】DIV要素の(幅OR高さ)AND背景色をつけないと、IEで初回ドロップ後にイベントの有効範囲が文字の部分だけになります・・・。

*1:prototype.jsにドラッグアンドドロップ化機能そのものはありません。prototypeを使用しているscript.aculo.usにはあります。