rubixkube
rubixkube

Reputation: 97

Drag and drop remove target element

I feel like this should be really simple. I wrote a codepen for it, just to talk out the problem https://codepen.io/rubixKube/pen/yPXPzr.

I am trying to remove the parent node (span) without removing the thing I just dropped it into.

Just wondering if someone out there has a better idea of how to do this.

I've tried this on my onmouse event:

//capturing the elements in variables
var mytarget = event.target;
var mytargetsibling = event.target.previousElementSibling;

//next three lines are just how drag and drop works
event.preventDefault();
var data = event.dataTransfer.getData("text");
event.target.appendChild(document.getElementById(data));

//trying to remove it AND then put the child back
this.parentNode.remove(this);
mytargetsibling.appendChild(mytarget);

function allowDrop(ev) {
  ev.preventDefault();
}

function drag(ev) {
  ev.dataTransfer.setData("text", ev.target.id);
}

function drop(ev) {
  ev.preventDefault();
  var data = ev.dataTransfer.getData("text");
  ev.target.appendChild(document.getElementById(data));
}
.tags {
  padding: 6px;
}

.drop-area {
  border: 1px solid red;
}

.drag-this {
  background: blue;
  color: white;
}
<ul>
  <li>
    <span class="header tags">Apple</span>
    <span class="drop-area target-drop tags" ondrop="drop(event)" ondragover="allowDrop(event)">Drop HERE</span>
  </li>
</ul>
<ul>
  <li><span id="drag1" class="drag-this tags" draggable="true" ondragstart="drag(event)">Apple</span></li>
</ul>

Upvotes: 1

Views: 1263

Answers (1)

David Thomas
David Thomas

Reputation: 253308

I'd suggest that, rather than event.target.appendChild() you use instead: event.target.parentNode.replaceChild(newElement, event.target) which will, as the method-name suggests, replace the existing child (event.target) with the new child (newElement):

function allowDrop(ev) {
  ev.preventDefault();
}

function drag(ev) {
  ev.dataTransfer.setData("text", ev.target.id);
}

function drop(ev) {
  ev.preventDefault();
  var data = ev.dataTransfer.getData("text"),

    // cached as a variable to simplify the later
    // code for readability:
    elToAdd = document.getElementById(data),

    // we're accessing this node twice, so caching it here:
    dropBefore = ev.target;

  // moving from the dropBefore node to its parentNode,
  // and calling the replaceChild() method to insert
  // 'elToAdd' in place of the existing 'dropBefore' node:
  dropBefore.parentNode.replaceChild(elToAdd, dropBefore);
}
.tags {
  padding: 6px;
}

.drop-area {
  border: 1px solid red;
}

.drag-this {
  background: blue;
  color: white;
}
<ul>
  <li>
    <span class="header tags">Apple</span>
    <span class="drop-area target-drop tags" ondrop="drop(event)" ondragover="allowDrop(event)">Drop HERE</span>
  </li>
</ul>
<ul>
  <li><span id="drag1" class="drag-this tags" draggable="true" ondragstart="drag(event)">Apple</span></li>
</ul>

Or, instead, you could use Node.replaceWith():

function allowDrop(ev) {
  ev.preventDefault();
}

function drag(ev) {
  ev.dataTransfer.setData("text", ev.target.id);
}

function drop(ev) {
  ev.preventDefault();
  var data = ev.dataTransfer.getData("text"),

    // caching as variables to simplify the later
    // code for readability:
    elToAdd = document.getElementById(data),
    dropBefore = ev.target;

  // using childNode.replaceWith() to insert the 
  // elToAdd Node in place of the existing
  // dropBefore Node:
  dropBefore.replaceWith(elToAdd);
}
.tags {
  padding: 6px;
}

.drop-area {
  border: 1px solid red;
}

.drag-this {
  background: blue;
  color: white;
}
<ul>
  <li>
    <span class="header tags">Apple</span>
    <span class="drop-area target-drop tags" ondrop="drop(event)" ondragover="allowDrop(event)">Drop HERE</span>
  </li>
</ul>
<ul>
  <li><span id="drag1" class="drag-this tags" draggable="true" ondragstart="drag(event)">Apple</span></li>
</ul>

References:

Upvotes: 1

Related Questions