Breaks span in drag & drop - javascript

Tell me please. If you drag a span specifically to another span and not to a free space, some kind of merging occurs (see gif).
How to fix this error?
Thank you in advance.
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));
}
#div1,
#div2 {
float: left;
width: 100%;
height: 100%;
margin: 10px;
padding: 10px;
display: inline-block;
}
.drop {
width:100px;
height:50px;
display:block;
border:1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="background:#fafafa;width:100%;height:440px;padding-top:10px;">
<div style="text-align:center;width:49%;height: 100%;display:inline-block;border-right:1px solid #e0e0e0;">
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<span class="drop" draggable="true" ondragstart="drag(event)" id="drag1" data-orderID="1">SPAN 1</span>
</div>
</div>
<div style="text-align:center;width:49%;height: 100%;display:inline-block;">
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)">
<span class="drop" draggable="true" ondragstart="drag(event)" id="drag2" data-orderID="2">SPAN 2</span>
</div>
</div>
</div>

If you don't want the drop inside the span, you can prevent the drop from that node. <span class="drop" ondrop="event.stopPropagation();" That makes sure your handler on the containing div doesn't get called.
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));
}
#div1,
#div2 {
float: left;
width: 100%;
height: 100%;
margin: 10px;
padding: 10px;
display: inline-block;
}
.drop {
width:100px;
height:50px;
display:block;
border:1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="background:#fafafa;width:100%;height:440px;padding-top:10px;">
<div style="text-align:center;width:49%;height: 100%;display:inline-block;border-right:1px solid #e0e0e0;">
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<span class="drop" draggable="true" ondragstart="drag(event)" id="drag1" data-orderID="1">SPAN 1</span>
</div>
</div>
<div style="text-align:center;width:49%;height: 100%;display:inline-block;">
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)">
<span class="drop" ondrop="event.stopPropagation();" draggable="true" ondragstart="drag(event)" id="drag2" data-orderID="2">SPAN 2</span>
</div>
</div>
</div>

Your drop event is triggered on the span not on the containing div.
So the dragged element is appended to the span it's dragged onto.
You can prevent this by altering the line
ev.target.appendChild(document.getElementById(data));
to
ev.target.closest('div').appendChild(document.getElementById(data));

Related

In HTML, how can I stop images from vanishing when dragged over another image?

I'm trying to create a visual card counter. Basically images of cards that can be moved into different divisions.
I've started with code from https://www.w3schools.com/html/html5_draganddrop.asp
It works OK, but leaves me with one problem: If one image is dragged on top of another it disappears. Looking at the code, it seems to nest within the image it is dragged onto.
I've found several pages describing similar problems but not been able to get the proposed solutions working for me.
In short, I would like the dragged image to behave as if it had been dropped next to the static image; even if it is dropped on top by mistake.
Thanks in advance!
<!DOCTYPE HTML>
<html>
<head>
<style>
#div1 {
float: left;
width: 200px;
height: 335px;
margin: 10px;
padding: 10px;
border: 1px solid black;
background-color: aqua;
}
#div2, #div3 {
float: right;
width: 200px;
height: 335px;
margin: 10px;
padding: 10px;
border: 1px solid black;
background-color: rgba(255, 0, 0, 0.548);
}
</style>
<script>
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));
}
</script>
</head>
<body>
<h2>Twilight Stuggle Card Tracker</h2>
<p>Drag the image back and forth between the two div elements.</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<h2>USA</h2>
<img src="imgeurope-scoring.jpg" draggable="true" ondragstart="drag(event)" id="drag1" width="90" height="126">
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)">
<img src="imgduck-and-cover.jpg" draggable="true" ondragstart="drag(event)" id="drag2" width="90" height="126">
</div>
<div id="div3" ondrop="drop(event)" ondragover="allowDrop(event)">
<img src="imgduckpix.GIF" draggable="true" ondragstart="drag(event)" id="drag3" width="190" height="28">
<img src="imgfive-year-plan.jpg" draggable="true" ondragstart="drag(event)" id="drag4" width="105" height="147">
</div>
</body>
</html>
When you drop an image directly over another image element, then ev.target will be that image. So go and check what element type you have in there, and if it is an image, go up to the parent element first.
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text"), target = ev.target;
if(target.nodeName == "IMG") {
target = target.parentNode;
}
target.appendChild(document.getElementById(data));
}

Dropping content into textarea

I'm trying to drag the content of the paragraph into the textarea. The text disappears when I try to drop it in the textarea. I want it to have the same behavior as the div with id div1
code
function drag(ev) {
ev.dataTransfer.setData("Text", ev.target.id);
}
function drop(ev) {
var data = ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
ev.preventDefault();
}
#div1 {
width: 350px;
height: 70px;
padding: 10px;
border: 1px solid #aaaaaa;
}
<br/>
<p id="drag1" draggable='true' ondragstart="drag(event)">
here is some text foo-bar
</p>
<textarea class="textarea" ondrop="drop(event)" ondragover="event.preventDefault()" placeholder="Drag and Drop image , Or paste image here" style="width: 810px; height: 200px"></textarea>
<div id="div1" ondrop="drop(event)" ondragover="event.preventDefault()"></div>
The issue is with this line:
ev.target.appendChild(document.getElementById(data));
You don't want to append a child to the textarea, you want to set it's value. See belwo snippet.
function drag(ev) {
ev.dataTransfer.setData("Text", ev.target.id);
}
function drop(ev) {
var data = ev.dataTransfer.getData("Text");
ev.target.value =(document.getElementById(data).innerText);
ev.preventDefault();
}
#div1 {
width: 350px;
height: 70px;
padding: 10px;
border: 1px solid #aaaaaa;
}
<br/>
<p id="drag1" draggable='true' ondragstart="drag(event)">
here is some text foo-bar
</p>
<textarea class="textarea" ondrop="drop(event)" ondragover="event.preventDefault()" placeholder="Drag and Drop image , Or paste image here" style="width: 810px; height: 200px"></textarea>
<div id="div1" ondrop="drop(event)" ondragover="event.preventDefault()"></div>

Unable to load saved position of dropped item from local storage using javascript

I am new to programming; this is my very first question on Stake-overflow.
I want to save the position of the dropped div in local storage and retrieve this position when I refresh the page.
Here is what I have achieved so far using Javascript:
1) I can store the position of dropped div in local storage (by calling a function on enddrop event.)
2) I can retrieve the stored position (by calling a function on onload event)
What I want:
1) I want to position the dropped div according to retrieved position (position left and top from local storage.)
Here is my code:
HTML
<!DOCTYPE HTML>
<html>
<head>
</head>
<body onload="get_pos(event)">
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div style="margin-left:50px;" id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div style="margin-left:100px;" id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div draggable="true" ondragstart="drag(event)" ondragend="set_pos(event);get_pos(event);" id="drag1">
pTop: <span id="pt"></span> <br>
pLeft: <span id="pl"></span>
<span style="margin-left:80px;">Drag Me!</span>
</div>
</body>
</html>
CSS
#div1 {
width: 300px;
height: 70px;
padding: 10px;
margin: 20px;
border: 1px solid #aaaaaa;
}
#drag1 {
width: 250px;
height: 60px;
padding: 5px;
background: lightgray;
border: 1px solid #aaaaaa;
}
Javascript:
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));
}
function set_pos(e) {
var div = document.getElementById("drag1");
var rect = div.getBoundingClientRect();
x = rect.left;
y = rect.top;
// Store
localStorage.setItem("pTop", y);
localStorage.setItem("pLeft", x);
}
function get_pos(e) {
var a = localStorage.getItem("pTop");
var b = localStorage.getItem("pLeft");
document.getElementById("drag1").style.top = a+"px";
document.getElementById("drag1").style.left = b+"px";
document.getElementById("pt").innerHTML = a+"px";
document.getElementById("pl").innerHTML = b+"px";
}
Any help would be appreciated!
I have made it dynamic, you can now drag divs, images, I took care about the order of the dragged elements. now you can modifie it to store in your server instead of the client. happy coding :)
<!DOCTYPE HTML>
<html lang="en-us">
<head>
<title>Retrieve drag position</title>
<meta charset="utf-8">
<style>
* {
box-sizing: border-box;
}
.drop_box {
width: 100px;
height: 120px;
margin: 10px;
padding: 5px;
border: 1px solid black;
}
img, .dragged_box {
width: 90px;
height: 30px;
}
.red {
background-color: red;
}
.blue {
background-color: blue;
}
.green {
background-color: green;
}
</style>
</head>
<body onload="retrieve()">
<div class="dragged_box red" draggable="true" ondragstart="drag(event)" id="drag_div1"></div>
<div class="dragged_box blue" draggable="true" ondragstart="drag(event)" id="drag_div2"></div>
<div class="dragged_box green" draggable="true" ondragstart="drag(event)" id="drag_div3"></div>
<img src="https://img.icons8.com/color/48/000000/bungalow.png" draggable="true" ondragstart="drag(event)" id="drag_img1">
<img src="https://img.icons8.com/ios-filled/50/000000/bungalow.png" draggable="true" ondragstart="drag(event)" id="drag_img2">
<img src="https://img.icons8.com/ios/50/000000/bungalow.png" draggable="true" ondragstart="drag(event)" id="drag_img3">
<div class="drop_box" id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="drop_box" id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="drop_box" id="div3" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="drop_box" id="div4" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<script>
var draggedImages = {
draggedIds: [],
droppedIds: []
}
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var id = ev.dataTransfer.getData("text");
if(draggedImages.draggedIds.indexOf(id) === -1) {
draggedImages.draggedIds.push(id);
draggedImages.droppedIds.push(ev.target.id);
}else {
var ind = draggedImages.draggedIds.indexOf(id);
// to keep the order of images
draggedImages.draggedIds.splice(ind, 1);
draggedImages.droppedIds.splice(ind, 1);
draggedImages.draggedIds.push(id);
draggedImages.droppedIds.push(ev.target.id);
}
localStorage["draggedImages"] = JSON.stringify(draggedImages);
ev.target.appendChild(document.getElementById(id));
}
function retrieve() {
if(localStorage["draggedImages"]) {
draggedImages = JSON.parse(localStorage["draggedImages"]);
draggedImages.draggedIds.forEach(function(draggedId, ind) {
document.getElementById(draggedImages.droppedIds[ind]).appendChild(document.getElementById(draggedId));
});
}
}
</script>
</body>
</html>

second and third drag not working in javascript

have two div box. box001, box002
When I drag and drop box002 to another div box001 it get deleted, and box002 elemenets and contents get deleted, When I drag second box002 to second box001 its not working.
how can i achieve this?
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");
alert(data);
var el = document.getElementById(data);
el.parentNode.removeChild(el);
document.getElementsByClassName('box001')[0].style.backgroundColor = 'initial';
document.getElementById('11').innerHTML = '';
var x=document.getElementById(data).id;
var y=document.getElementsByClassName('box001')[0];
}
.box001 {
float: left;
width: 50px;
height: 50px;
border: 1px solid black;
border-radius: 10%;
background-color: #ff0000;
}
.box002 {
width: 50px;
height: 50px;
margin: -50px;
top: 76px;
float: left;
position: absolute;
left: 217px;
}
<div class="box001" ondrop="drop(event)" ondragover="allowDrop(event)" id="10"><p id="11"> 8:30</p></div>
<div class="box001" ondrop="drop(event)" ondragover="allowDrop(event)" id="20" ><p id="12">12:25</p></div>
<div class="box001" ondrop="drop(event)" ondragover="allowDrop(event)" id="30" ><p>01:00</p></div>
<div class="box002" draggable="true" ondragstart="drag(event)" id="11">
<img src="https://picsum.photos/200/300" draggable="true" id="1" style="width:50px; height:50px; border-radius: 50%;" border="rounded"/>
</div>
<div class="box002" draggable="true" ondragstart="drag(event)" id="21">
<img src="https://picsum.photo/200/300" draggable="true" id="2" style="width:50px; height:50px; border-radius: 50%;" border="rounded"/>
</div>
<div class="box002" draggable="true" ondragstart="drag(event)" id="31">
<img src="https://picsum.photo/200/300" draggable="true" id="3" style="width:50px; height:50px; border-radius: 50%;" border="rounded"/>
</div>

Drag a div or image into textarea and put a value inside it

I'd like to put a value inside textarea by allowing user to drag a div or image into it.
Here is roughly what my html looks like.
img {
width: 100px;
}
.emote {
position:relative;
background-color:rgba(45,45,45, 0.3);
margin: 20px 0px;
}
.emote .emoteTitle {
position:absolute;
top:50%;
margin-left: 50px;
}
<div class="emote">
<img src="https://images.duckduckgo.com/iu/?u=http%3A%2F%2Ficons.iconarchive.com%2Ficons%2Fpaomedia%2Fsmall-n-flat%2F512%2Fcat-icon.png&f=1" alt="emote1" title="emote1" class="emoteImage">
<span class="emoteTitle">emote1</span>
</div>
<div class="emote">
<img src="https://images.duckduckgo.com/iu/?u=http%3A%2F%2Fes.seaicons.com%2Fwp-content%2Fuploads%2F2015%2F06%2Fsign-check-icon.png&f=1" alt="emote2" title="emote2" class="emoteImage">
<span class="emoteTitle">emote2</span>
</div>
<textarea></textarea>
Fiddle link
So when user drags a div.emote or the image onto text area i want it to put either emote1 or emote2 into it.
What would be the best way to make this work?
Here is a snippet that builds on yours.
When you drop the image on the textarea, its alt text will be added at the cursor position.
You can easily change this to put any value you want, just replace the second argument on .setData('text', emoteImage.alt)
For reference:
https://developer.mozilla.org/en-US/docs/Web/Events/dragstart
https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer
document.querySelectorAll('.emoteImage').forEach((emoteImage) => {
emoteImage.addEventListener('dragstart', (event) => {
event.dataTransfer.setData('text', emoteImage.alt);
event.effectAllowed = "copy";
});
});
img {
width: 100px;
}
.emote {
position:relative;
background-color:rgba(45,45,45, 0.3);
margin: 20px 0px;
}
.emote .emoteTitle {
position:absolute;
top:50%;
margin-left: 50px;
}
<div class="emote">
<img src="https://images.duckduckgo.com/iu/?u=http%3A%2F%2Ficons.iconarchive.com%2Ficons%2Fpaomedia%2Fsmall-n-flat%2F512%2Fcat-icon.png&f=1" alt="emote1" title="emote1" class="emoteImage">
<span class="emoteTitle">emote1</span>
</div>
<div class="emote">
<img src="https://images.duckduckgo.com/iu/?u=http%3A%2F%2Fes.seaicons.com%2Fwp-content%2Fuploads%2F2015%2F06%2Fsign-check-icon.png&f=1" alt="emote2" title="emote2" class="emoteImage">
<span class="emoteTitle">emote2</span>
</div>
<textarea></textarea>
I modified last example from: https://www.w3schools.com/html/html5_draganddrop.asp
This is just a quick template, but I hope you'll know how to modify it further
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.innerHTML = document.getElementById(data).dataset.value;
}
#div1, #div2 {
float: left;
width: 100px;
height: 35px;
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)">
<img src="img_w3slogo.gif" draggable="true" ondragstart="drag(event)" data-value="img1" id="drag1" width="88" height="31">
</div>
<textarea id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"></textarea>
Based on answer from NoOorZ24 here is the final draft.
JsFiddle link: JsFiddle
HTML
<div id="div1" class="emote">
<img src="https://images.duckduckgo.com/iu/?u=http%3A%2F%2Ficons.iconarchive.com%2Ficons%2Fpaomedia%2Fsmall-n-flat%2F512%2Fcat-icon.png&f=1" draggable="true" ondragstart="drag(event)" alt="emote1" title="emote2" class="emoteImage" data-value="img1" id="drag1"
width="88" height="31">
<span class="emoteTitle">emote1</span>
</div>
<div id="div2" class="emote">
<img src="https://images.duckduckgo.com/iu/?u=http%3A%2F%2Fes.seaicons.com%2Fwp-content%2Fuploads%2F2015%2F06%2Fsign-check-icon.png&f=1" draggable="true" ondragstart="drag(event)" alt="emote2" title="emote2" class="emoteImage" data-value="img2" id="drag2"
width="88" height="31">
<span class="emoteTitle">emote2</span>
</div>
<textarea id="div3" ondrop="drop(event)" ondragover="allowDrop(event)"></textarea>
Script
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.innerHTML = document.getElementById(data).dataset.value;
}

Categories

Resources