Drag and Drop 0.2

前回あったカードがどこかへ行ってしまう不具合を修正しました。 具体的には onload 時にスクロールのイベントリスナーを追加し、テーブル(div 要素) の左上のクライアント座標を、スクロール後に取得し直すように変更しました。

実行結果

ソース


dragndrop02.html

JavaScript のソースファイルを指定します。フォルダ名、ファイル名とも変更しています。
<script type="text/javascript" src="js/dragondrop02/dragndrop02.js"></script>

この HTML で使う style を指定します。前回から変更はありません。

<style>
#table {
    width: 97%;
    height: 300px;
    padding: 10px;
	background-color: tan;
	position: relative;
}
#card1, #card2 {
	position: absolute;
}
#card1 {
	z-index: 1;
	left: 10px;
	top: 10px;
}
#card2 {
	z-index: 2;
	left: 20px;
	top: 20px;
}
</style>
カード2枚(img 要素)とテーブル(div 要素)。前回から変更ありません。
<h2>実行結果</h2>
<div id="table">
<img src="img/card1.png" id="card1">
<img src="img/card2.png" id="card2">
</div>

dragndrop02.js

前回のドラッグアンドドロップの処理に、スクロール後、テーブルの左上のクライアント座標 tableX, tableY を取得し直す処理を加えました。スクロール直後はまださらにスクロール する可能性があるので、500ms 待ってから取得します。

window.onload = function() {
    var offsetX = 0;
    var offsetY = 0;
    var table = document.getElementById('table');
    var tableX = table.getBoundingClientRect().left;
    var tableY = table.getBoundingClientRect().top;
    var timeoutID;
    window.addEventListener('scroll',
        function () {
            // wait 500ms after scroll stop
            clearTimeout(timeoutID);
            timeoutID = setTimeout(function() {
                // update tableX and tableY
                table = document.getElementById('table');
                tableX = table.getBoundingClientRect().left;
                tableY = table.getBoundingClientRect().top;
            }, 500);
        });
    var cards = document.querySelectorAll('[id^="card"]');
    for (var i = 0; i < cards.length; i++) {
        var card = cards[i];
        card.addEventListener('dragstart',
            function(e) {
                e.dataTransfer.setData('text', e.target.id);
                x = e.clientX;
                y = e.clientY;
                var card = document.getElementById(e.target.id);
                offsetX = x - card.getBoundingClientRect().left;
                offsetY = y - card.getBoundingClientRect().top;
            }, false);
    }    
    // drop
    var dzone = document.getElementById('table');
    var zTop = 2;
    dzone.addEventListener('dragenter',
        function(e) {
            e.preventDefault();
        }, false);
    dzone.addEventListener('dragover',
        function(e) {
            e.preventDefault();
        }, false);
    dzone.addEventListener('drop',
        function(e) {
            e.preventDefault();
            rx = e.clientX - tableX;
            ry = e.clientY - tableY;
            var id = e.dataTransfer.getData('text');
            var card = document.getElementById(id);
            card.style.left = String(rx - offsetX) + 'px';
            card.style.top = String(ry - offsetY) + 'px';
            card.style.zIndex = ++zTop;
       }, false);
}

既知の問題点

カードがテーブルからはみ出す

マウスポインタがテーブルの中であればドロップが実行されます。 テーブルの端でドロップするとカードがはみ出すことがあります。 この問題はあまり支障がないので今のところ直す予定はありません。