2011-07-16 6 views
0

ドラッグ&ドロップ機能をHTML5で作成して、あるリストから別のリストにドラッグできるようにしようとしています。私はドラッグ可能な項目とドロップイベントが追加された項目を持つ別のリストを持つ1つのリストを持っています。問題は、どの要素にドロップするかにかかわらず、最後に追加されたドロップイベントが呼び出されることです。HTML5で複数のドロップイベントが発生する

ご協力ありがとうございます。

私は以下の私のコードを含めました:

<!DOCTYPE html> 

<head> 
<title>List Conversion Test</title> 

<style type="text/css"> 

#list, #cart { 
    display: inline; 
    float: left; 
    border: 1px solid #444; 
    margin: 25px; 
    padding: 10px; 
} 

#list p { 
    background-color: #036; 
    color: #fff; 
} 
#cart p { 
    background-color: #363; 
    color: #fff; 
} 

.listitem { 

} 

.listitem_done { 
    text-decoration: line-through; 
} 

.product { 
    background-color: #CCC; 
} 

.product_over { 
    background-color: #363; 
} 

</style> 


<script type="text/javascript" src="http://html5demos.com/js/h5utils.js"></script> 

</head> 

<body> 

<article> 
    <div id="list"> 
    <p>On My List</p> 
    <ul> 
     <li class="listitem" id="L001">Shopping List Item #1</li> 
     <li class="listitem" id="L002">Shopping List Item #2</li> 
    </ul> 
    <div id="done"> 
     <p>In My Cart</p> 
     <ul></ul> 
    </div> 
    </div> 

    <div id="cart"> 
    <p>Cart</p> 
    <ul> 
     <li class="product" id="P001">Product #1</li> 
     <li class="product" id="P002">Product #2</li> 
    </ul> 
    </div> 

</article> 
<script> 

    // make list items draggable 
    var list = document.querySelectorAll('li.listitem'), thisItem = null; 
    for (var i = 0; i < list.length; i++) { 
    thisItem = list[i]; 

    thisItem.setAttribute('draggable', 'true'); 

    addEvent(thisItem, 'dragstart', function (e) { 
     e.dataTransfer.effectAllowed = 'copy'; 
     e.dataTransfer.setData('Text', this.id); 
    }); 
    } 


    // give products drop events 
    var products = document.querySelectorAll('li.product'), thisProduct = null; 
    for (var i = 0; i < products.length; i++) { 
    thisProduct = products[i]; 

    addEvent(thisProduct, 'dragover', function (e) { 
     if (e.preventDefault) e.preventDefault(); 
     this.className = 'product_over'; 
     e.dataTransfer.dropEffect = 'copy'; 
     return false; 
    }); 

    addEvent(thisProduct, 'dragleave', function() { 
    this.className = 'product'; 
    }); 

    addEvent(thisProduct, 'drop', function (e) { 
     //alert(thisProduct.id); 
     if (e.stopPropagation) e.stopPropagation(); 
     var thisItem = document.getElementById(e.dataTransfer.getData('Text')); 
     thisItem.parentNode.removeChild(thisItem); 
     thisProduct.className = 'product'; 
     handleDrop(thisItem, thisProduct); 
     return false; 
    }); 

    } 

    // handle the drop 
    function handleDrop(i, p) { 
    alert(i.id + ' to ' + p.id); 
    var done = document.querySelector('#done > ul'); 
    done.appendChild(i); 
    i.className = 'listitem_done'; 
    } 


</script> 

</body> 
</html> 

答えて

1

それがループ内(たとえば、コールバック関数のような)関数を定義するために、多くの場合、悪い考えだ理由です。ループ内にthisProductを割り当てていますが、ループの次の繰り返しのために再割り当てされます。クロージャが設定される方法、各コールバックは同じ変数thisProductにバインドされ、最新の値が使用されます。

一つの可能​​な修正がthisProductがこのjsFiddleは今私のために働くように思われるような

(function(thisProduct) { 
    addEvent(thisProduct, 'drop', function (e) { 
     //alert(thisProduct.id); 
     if (e.stopPropagation) e.stopPropagation(); 
     var thisItem = document.getElementById(e.dataTransfer.getData('Text')); 
     thisItem.parentNode.removeChild(thisItem); 
     thisProduct.className = 'product'; 
     handleDrop(thisItem, thisProduct); 
     return false; 
    }); 
}(thisProduct)); 

必要とされている新しいクロージャを作成することです。詳細については、hereを参照してください。

+0

ありがとうございます!最後のIDがいつも出現していたのは理にかなっています。 MDNリンクは有用でした。私は閉鎖について学ぶことが少しあるようです。 – Paul

+0

問題ありません!お力になれて、嬉しいです :) –