Abounding in TheVicious response: when you do appendChild(elemento)
and the item you selected using id
that is repeated, you are trying to add a child you already have, identified by that id.
In other words, if all draggable divs have the same id drag1
the node identified by document.getElementById('drag1')
is always the first node of the document with that id
. In this case, the first node #drag1
within #div1
and, if it does not have children, then the first node #drag1
within #div2
. In practice, if you put your children's content, you'll see that dragging the second one actually drags the first one :
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {drag1
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
#div1, #div2 {
float: left;
width: 200px;
height: 200px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
<h2>Drag and Drop</h2>
<p>Drag the image back and forth between the two div elements.</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<input type="text" draggable="true" ondragstart="drag(event)" id="drag1" value="soy el primero">
<input type="text" draggable="true" ondragstart="drag(event)" id="drag1" value="soy el segundo">
<input type="text" draggable="true" ondragstart="drag(event)" id="drag1" value="soy el tercero">
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
Then:
You move a node from #div1
to #div2
, this is the first node #drag1
child of #div1
and you can move it.
The node identified by #drag1
now the first child of #div1
, which originally was in the second place. The item you moved went to third place.
Already at this point you can not move anything back, because what is in the #div2
when trying to select it returns a reference to the first child of #div1
.
After the 3 children are moved from #div1
to #div2
, there is no longer any node #drag1
in #div1
therefore the first node #drag1
is the first child node of #div2
. You can move any of those children to #div1
but you will be moving the first one.
When you move one of those back, again the selector #drag1
is a reference to the first child of #div1
ignoring what is inside #div2
.
One solution is to give a unique id to each input you want to move, but you could actually do the same without using ids
for the draggables. It would be a matter of storing a reference to the moving element in a global variable element
.
With this you could have infinite draggable nodes and not have to worry about giving them a unique id:
var element=null;
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
element=ev.target;
}
function drop(ev) {
ev.preventDefault();
ev.target.appendChild(element);
element=null;
}
#div1, #div2 {
float: left;
width: 200px;
height: 200px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
<h2>Drag and Drop</h2>
<p>Drag the image back and forth between the two div elements.</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<input type="text" draggable="true" ondragstart="drag(event)" value="soy el primero" >
<input type="text" draggable="true" ondragstart="drag(event)" value="soy el segundo" >
<input type="text" draggable="true" ondragstart="drag(event)" value="soy el tercero">
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
Final suggestion
Let's add some style to the subject so that it looks nice, and also let's make sure that only the elements #div1
and #div2
can receive children . Otherwise, you can drag one input into another and it will disappear.
var element = null;
function allowDrop(ev) {
ev.target.classList.add('feedme');
ev.preventDefault();
}
function removeDrop(ev) {
ev.target.classList.remove('feedme');
ev.preventDefault();
}
function drag(ev) {
element = ev.target;
element.parentNode.classList.add('feedme');
element.classList.add('dragging');
}
function drop(ev) {
ev.preventDefault();
ev.target.classList.remove('feedme');
element.classList.remove('dragging');
if (ev.target.classList.contains('droppable')) {
ev.target.appendChild(element);
}
element = null;
}
#div1,
#div2 {
float: left;
width: 200px;
height: 200px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
#div1 input,
#div2 input {
cursor: ew-resize;
}
#div1.feedme,
#div2.feedme {
background: #FFFFEE;
}
.dragging {
border: 1px dashed #00F;
cursor: move;
}
<h2>Drag and Drop</h2>
<p>Drag the image back and forth between the two div elements.</p>
<div id="div1" class="droppable" ondrop="drop(event)" ondragover="allowDrop(event)" ondragleave="removeDrop(event)">
<input type="text" draggable="true" ondragstart="drag(event)" value="soy el primero">
<input type="text" draggable="true" ondragstart="drag(event)" value="soy el segundo">
<input type="text" draggable="true" ondragstart="drag(event)" value="soy el tercero">
</div>
<div id="div2" class="droppable" ondrop="drop(event)" ondragover="allowDrop(event)" ondragleave="removeDrop(event)"></div>