Reputation: 12181
I'm trying to learn the drag and drop example from the WWWC (here) and I can get the list items to be removed from the original list when dragged away, but not appear in the new list. Any ideas why not? I have tried on Safari 5.1.1, Chrome 15, and Firefox 7.0.1.
<head>
<title>Drag 'N Drop</title>
</head>
<p>What fruits do you like?</p>
<ol ondragstart="dragStartHandler(event)" ondragend="dragEndHandler(event)">
<li draggable="true" data-value="fruit-apple">Apples</li>
<li draggable="true" data-value="fruit-orange">Oranges</li>
<li draggable="true" data-value="fruit-pear">Pears</li>
</ol>
<script>
var internalDNDType = 'text/plain'; // set this to something specific to your site
function dragStartHandler(event) {
if (event.target instanceof HTMLLIElement) {
// use the element's data-value="" attribute as the value to be moving:
event.dataTransfer.setData(internalDNDType, event.target.dataset.value);
event.dataTransfer.effectAllowed = 'move'; // only allow moves
} else {
event.preventDefault(); // don't allow selection to be dragged
}
}
function dragEndHandler(event) {
// remove the dragged element
event.target.parentNode.removeChild(event.target);
}
</script>
<p>Drop your favorite fruits below:</p>
<div dropzone="move s:text/plain" ondrop="dropHandler(event)">
<ol dropzone="move s:text/plain" ondrop="dropHandler(event)">
<!-- don't forget to change the "text/x-example" type to something
specific to your site -->
<li>Bananas</li>
</ol>
</br>
</br>
</br>
</div>
<script>
var internalDNDType = 'text/plain'; // set this to something specific to your site
function dropHandler(event) {
var li = document.createElement('li');
var data = event.dataTransfer.getData(internalDNDType);
if (data == 'fruit-apple') {
li.textContent = 'Apples';
} else if (data == 'fruit-orange') {
li.textContent = 'Oranges';
} else if (data == 'fruit-pear') {
li.textContent = 'Pears';
} else {
li.textContent = 'Unknown Fruit';
}
event.target.appendChild(li);
}
</script>
Upvotes: 0
Views: 6977
Reputation: 590
The short answer would be that you also need to add a dragover listener to the drop area in order to allow the drop action to happen.
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault(); // Necessary. Allows us to drop.
}
e.dataTransfer.dropEffect = 'move';
return false;
}
You have a detailed explanation in this step by step tutorial (although the elements in that tutorial act as both draggable elements and drop areas)
However, Chris, as much as I am glad you are experimenting with the native HTML5 drag and drop feature please accept my humble opinion when I say that your code has way too many serious mistakes both at markup level and Javascript level. i.e. missing tags, closing tags that don't exist, wrong attribute namespaces, repeated listeners in chained elements, repeated variables inside the same scope, etc. I'd suggest to go through several code reviews first.
Upvotes: 0
Reputation: 75757
There are a couple of issues. First, your dropzone needs to cancel the event on drag over:
<ol dropzone="move s:text/plain" ondrop="dropHandler(event)" ondragover="dragOverHandler(event)">
function dragOverHandler(event) {
event.preventDefault();
return false;
}
Second, your dropHandler
handler function is going to get fired several times because the drop target, most of the time, is going to be an li
element rather than the ol
(and possibly also the div
, but I ignored that element). So either add code to only handle the event at the ol
, or cancel the event in dropHandler
with stopPropagation
.
Finally, the default action (at least in Firefox, didn't check other browsers) when an item is dropped is to try and navigate to the URL represented by the text/plain
value, so you should add some event.preventDefault()
in likely places. Here's an updated dropHandler
function:
function dropHandler(event) {
var li = document.createElement('li');
var data = event.dataTransfer.getData(internalDNDType);
if (data == 'fruit-apple') {
li.textContent = 'Apples';
} else if (data == 'fruit-orange') {
li.textContent = 'Oranges';
} else if (data == 'fruit-pear') {
li.textContent = 'Pears';
} else {
li.textContent = 'Unknown Fruit';
}
event.target.appendChild(li);
event.stopPropagation();
event.preventDefault();
return false;
}
Upvotes: 2