How to get event property again for already dragged image - javascript

I have image that I want to drag and drop infinitely.From first box to second box when I move,image disappear from first box.Not to lose image created same image on first box again using .appendchild(img) method.I want to drag image from initial position,not from where I dropped.So I changed draggable property as false when I dropped image into box.It creates image on first box,there's no problem.But I can't drag and drop it from first box to third again because that image has no event properties.I want to give them those properties again and it should be repeated because I want to do it forever.
Here's what I tried
<!DOCTYPE HTML>
<html>
<head>
<style>
#div1, #div2,#div3 {
float: left;
width: 100px;
height: 35px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
</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));
var img = document.createElement("img");
img.src = "https://mikasasports.com/wp-content/uploads/2015/04/MVA2001.png";
var src = document.getElementById("div1");
img.style.width="88px";
img.style.height="31px";
src.appendChild(img);
drag1.draggable=false;
}
</script>
</head>
<body>
<h2>Drag and Drop</h2>
<p>Drag the image back and forth between the three div elements.</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<img src="https://mikasasports.com/wp-content/uploads/2015/04/MVA2001.png" draggable="true" ondragstart="drag(event)" id="drag1" width="88" height="31">
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div id="div3" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
</body>
</html>

Related

append the element before and after on drop it

I'm trying to make a website that use drag and drop functionality to build a website. But I'm facing the problem that the element is not being append before another element like the code I have shown. please help me so it can drop the elements before and after a specific element not just at the end of all the elements.
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: 500px;
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)">
<button draggable="true" ondragstart="drag(event)" id="drag1">button1</button>
<button draggable="true" ondragstart="drag(event)" id="drag2">button2</button>
<button draggable="true" ondragstart="drag(event)" id="drag3">button3</button>
<button draggable="true" ondragstart="drag(event)" id="drag4">button4</button>
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)">
</div>
I'm using javascript.
That's actually quite tricky to achieve, you need to implement your own logic for inserting the element to the correct position in the list.
Here is an example where you can move items between divs and reorder items in the same div
(Note that I only implemented the logic for drag/drop items horizontally in a single line by using left offset, if you have multiple lines items list, you need to implement your own)
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.currentTarget is the div that the elements are dropped
const currentDragElementOffset = ev.clientX
const items = ev.currentTarget.children
//empty list, just append and return
if (items.length === 0) {
ev.currentTarget.appendChild(document.getElementById(data))
return
}
// non-empty list
for (let i = 0; i < items.length; i++) {
const item = items[i]
const {
left,
width
} = item.getBoundingClientRect()
// find the offset left from the center of the item
const currentElementLeftOffset = left + width / 2;
if (currentDragElementOffset < currentElementLeftOffset) {
ev.currentTarget.insertBefore(document.getElementById(data), item)
return
}
// found no insertion point, that means item was dragged to the end of the list
if (i === items.length - 1 && currentDragElementOffset > currentElementLeftOffset) {
ev.currentTarget.appendChild(document.getElementById(data))
}
}
}
#div1,
#div2 {
float: left;
width: 500px;
height: 35px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
<!DOCTYPE html>
<html>
<body>
<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)">
<button draggable="true" ondragstart="drag(event)" id="drag1">
button1
</button>
<button draggable="true" ondragstart="drag(event)" id="drag2">
button2
</button>
<button draggable="true" ondragstart="drag(event)" id="drag3">
button3
</button>
<button draggable="true" ondragstart="drag(event)" id="drag4">
button4
</button>
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
</body>
</html>
Simply use the CSS property order.
The drop zones must have display: flex or display: inline-flex (see .zone in Example - CSS)
Each item that is draggable should have style="order: number " (see Example - JS)
Also, to avoid an item appending to another item, use event.currentTarget instead of event.target in the drop() function (see drop() in Example - JS). In the example, the repetitive parts in HTML have been streamlined (see Figure I):
Figure I
Original Post
Example
Attributes on each element in HTML
Attributes assigned to each element by .forEach()
Inline events on each element in HTML
Onevent properties bound to each element by .forEach()
Example
Details are commented
/*
Collect all .btn into a NodeList
Iterate through NodeList with .forEach()
Bind dragstart event to current <button>
Add inline style "order" with the value of current index
Add "draggable" attribute with the value of true
*/
document.querySelectorAll('.btn').forEach((b, i) => {
b.ondragstart = drag;
b.style.order = i;
b.setAttribute('draggable', true);
});
/*
Collect all .zone into a NodeList
Iterate through NodeList with .forEach()
Bind drop event to current <div>
Bind dragover event to current <div>
*/
document.querySelectorAll('.zone').forEach(z => {
z.ondrop = drop;
z.ondragover = allowDrop;
});
function allowDrop(e) {
e.preventDefault();
}
function drag(e) {
e.dataTransfer.setData("text", e.target.id);
}
function drop(e) {
e.preventDefault();
let data = e.dataTransfer.getData("text");
/*
Change e.target to e.currentTarget to prevent any <button>
appending onto another <button>. e.currentTarget will always
point to .zone
*/
e.currentTarget.append(document.getElementById(data));
}
.zone {
display: flex;
align-items: center;
width: 500px;
height: 35px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
.btn {
margin: 0 10px;
cursor: move;
}
<h2>Drag and Drop</h2>
<p>Drag the buttons back and forth between the two div elements.</p>
<div class="zone">
<button id='b1' class='btn'>button1</button>
<button id='b2' class='btn'>button2</button>
<button id='b3' class='btn'>button3</button>
<button id='b4' class='btn'>button4</button>
</div>
<div class="zone"></div>
You should use .prepend() method for inserting element before the other element.
Element.prepend() method inserts a set of Node objects or string objects before the first child of the Element. String objects are inserted as equivalent Text nodes.
Here's a Working Code :
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.prepend(document.getElementById(data));
}
#div1,
#div2 {
float: left;
width: 500px;
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)">
<button draggable="true" ondragstart="drag(event)" id="drag1">button1</button>
<button draggable="true" ondragstart="drag(event)" id="drag2">button2</button>
<button draggable="true" ondragstart="drag(event)" id="drag3">button3</button>
<button draggable="true" ondragstart="drag(event)" id="drag4">button4</button>
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)">
</div>

How to set if..else statement in JS drag and drop

The result i want from the the below code is:
1. There are three text: Drag me!, Drag me2!, Drag me3!
2. One of the text will be drag to the last empty box
3. demo2 will display the text of the drop text
But what i have done will only display the "Drag me3!"
How can I done the 1, 2 & 3 by using if...else statement?
function dragStart(ev) {
ev.dataTransfer.setData("Text", ev.target.id);
document.getElementById("demo").innerHTML = "Started to drag the p element";
}
function allowDrop(ev) {
ev.preventDefault();
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
document.getElementById("demo").innerHTML = "The p element was dropped";
var x = document.getElementById("dragtarget1").textContent;
var y = document.getElementById("dragtarget2").textContent;
var z = document.getElementById("dragtarget3").textContent;
document.getElementById("demo2").innerHTML = x;
document.getElementById("demo2").innerHTML = y;
document.getElementById("demo2").innerHTML = z;
}
.droptarget {
float: left;
width: 100px;
height: 35px;
margin: 15px;
padding: 10px;
border: 1px solid #aaaaaa;
}
<div class="droptarget" ondrop="drop(event)" ondragover="allowDrop(event)">
<p ondragstart="dragStart(event)" draggable="true" id="dragtarget1">Drag me!</p>
</div>
<div class="droptarget" ondrop="drop(event)" ondragover="allowDrop(event)">
<p ondragstart="dragStart(event)" draggable="true" id="dragtarget2">Drag me2!</p>
</div>
<div class="droptarget" ondrop="drop(event)" ondragover="allowDrop(event)">
<p ondragstart="dragStart(event)" draggable="true" id="dragtarget3">Drag me3!</p>
</div>
<div class="droptarget" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<p style="clear:both;"><strong>Note:</strong> drag events are not supported in Internet Explorer 8 and earlier versions or Safari 5.1 and earlier versions.</p>
<p id="demo"></p>
<p id="demo2"></p>
The reason why you are seeing the behavior that you listed above is because of your line of code var x = document.getElementById("dragtarget").textContent;. What this code is doing is getting the text context of the element with that specific ID (dragtarget) and setting it to the inner HTML content of the id=demo2 every time. Instead of searching for a specific element with a specific ID, you need to use a more dynamic solution that looks in the event object received by the drop() function to determine what text to set in the demo2 element.

How to get the Row and Column that a cloned image is in?

I would like to know how to show what Row and Column that a cloned image is in. For example if I want the drag the image to Row 1 Column 5, on dropping it there is it possible to have Row 1 Column 5 values be inputted into a memory array?
Also is it possible to drop the image in Row 1 Column 5 and set this as the state 'on' which would be inputted into a memory array?
<style>
#div1 {position:absolute;width:100px;height:25px;top:150px;left:200px;padding:0px;border:1px solid #aaaaaa;border-color: white white white black;}
#div2 {position:absolute;width:100px;height:25px;top:150px;left:300px;padding:0px;border:1px solid #aaaaaa;border-color: white white white white;}
#div3 {position:absolute;width:100px;height:25px;top:150px;left:400px;padding:0px;border:1px solid #aaaaaa;border-color: white white white white;}
#div4 {position:absolute;width:100px;height:25px;top:150px;left:500px;padding:0px;border:1px solid #000000;border-color: white white white white;}
#div5 {position:absolute;width:100px;height:25px;top:150px;left:600px;padding:0px;border:1px solid #000000;border-color: white white white white;}
#div6 {position:absolute;width:100px;height:25px;top:150px;left:700px;padding:0px;border:1px solid #aaaaaa;border-color: white white white white;}
#div7 {position:absolute;width:100px;height:25px;top:150px;left:800px;padding:0px;border:1px solid #aaaaaa;border-color: white black white white;
</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).cloneNode(true));}
</script>
<body>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)" ></div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)" ></div>
<div id="div3" ondrop="drop(event)" ondragover="allowDrop(event)" ></div>
<div id="div4" ondrop="drop(event)" ondragover="allowDrop(event)" ></div>
<div id="div5" ondrop="drop(event)" ondragover="allowDrop(event)" ></div>
<div id="div6" ondrop="drop(event)" ondragover="allowDrop(event)" ></div>
<div id="div7" ondrop="drop(event)" ondragover="allowDrop(event)" ></div
</body>
<img id="drag1" src="bat.png" draggable="true" ondragstart="drag(event)" width="100" height="25" align="center">
<img id="drag2" src="ball.png" draggable="true" ondragstart="drag(event)" width="100" height="25" align="center">
I think i need a bit more specific information but, this should get you in the right direction:
Basically on the drop function, you want to push your target values (in this case the div1, div2 etc) divs into an array as objects
var memoryArray = [];
function drop(ev) {
var _target = ev.target;
var targetId = _target.getAttribute('id');
var elem = document.getElementById(targetId)
setTimeout(function(){
var imgSrc = elem.getElementsByTagName('img')[0].src;
var object = {
id:elem.id ,
image: imgSrc
}
memoryArray.push(object)
console.log(memoryArray)
}, 20)
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data).cloneNode(true));
}
There are many ways to achieve this, this is just one.
Here is a fiddle

drag and drop text exercise

I am making an exercise in which text id drag from div(contain words) then drop them into text-fields (these are 3)..Each field has its own text to be placed .. I have already drag and drop the text but cant able to compare them for particular fields .. Please help me.. Here is my code :
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
#div1 {width:350px;height:70px;padding:10px;border:1px solid #aaaaaa;}
#div2 {width:350px;height:70px;padding:10px;border:1px solid #aaaaaa;}
#div3 {width:350px;height:70px;padding:10px;border:1px solid #aaaaaa;}
</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>
verbs
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
noun
<div id="div3" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
adjetives
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<div id="drag1" draggable="true" ondragstart="drag(event)">I play the guitar</div>
<div id="drag2" draggable="true" ondragstart="drag(event)">The piano is black</div>
</body>
</html>
There are a couple of things you need to change here.
You need to drag words and not sentences
<div id="drag1">I
<span id="play" draggable="true" ondragstart="drag(event)"><b>play</b></span> the
<span id="guitar" draggable="true" ondragstart="drag(event)"><b>guitar</b></span>
</div>
There should be some list containing the allowed words for each type
var nouns = ['guitar'];
var verbs = ['play'];
Finally there should be a condition during drop event
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("Text");
if(ev.target.id =='verb' && verbs.indexOf(data) != -1){
ev.target.appendChild(document.getElementById(data));
}
else{
alert(data + ' is not a ' + ev.target.id +'. Try again');
}
}
Here is a demo for a single sentence

swapping child elements of div using javascript by drag and drop

I tried swapping two elements inside div1 and div2 tag but only the first replace function executes properly the other element is not swapped
either one of the div is getting swapped at once but when i try to swap both at same time it doesn't happen please help me out
*
<head>
<style type="text/css">
#div1 {
width:350px;
height:70px;
padding:10px;
border:1px solid #aaaaaa;
}
#div2 {
width:350px;
height:70px;
padding:10px;
border:1px solid #aaaaaa;
}
</style>
<script>
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
var child = ev.target;
var parents = child.parentNode;
ev.dataTransfer.setData("child1", child.id);
ev.dataTransfer.setData("parent1", parents.id);
}
function drop(ev) {
ev.preventDefault();
var childid1 = ev.dataTransfer.getData("child1");
var parentid1 = ev.dataTransfer.getData("parent1");
var parent1 = document.getElementById(parentid1);
var c = ev.currentTarget.childNodes;
var childid2 = c[1].id;
parent1.replaceChild(c[1], document.getElementById(childid1));
var parent2 = ev.currentTarget;
parent2.removeChild(c[1]);
parent2.appendChild(document.getElementById(childid1));
}
</script>
</head>
<body>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<img id="drag1" src="img_logo.gif" draggable="true" ondragstart="drag(event)" width="336" height="69">
</div>
<br>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)">
<img id="drag2" src="img_logo.gif" draggable="true" ondragstart="drag(event)" width="236" height="49">
</div>
</body>
I think your fundamental flaw is that you do not cater for the fact that when you do your first replaceChild, the image you are inserting is removed from its parent so it is no longer there to replace with the second image.
I found your variable names somewhat confusing, and have rewritten your code in a simpler fashion as follows:
function allowDrop (ev) {
ev.preventDefault ();
}
function drag (ev) {
ev.dataTransfer.setData ("src", ev.target.id);
}
function drop (ev) {
ev.preventDefault ();
var src = document.getElementById (ev.dataTransfer.getData ("src"));
var srcParent = src.parentNode;
var tgt = ev.currentTarget.firstElementChild;
ev.currentTarget.replaceChild (src, tgt);
srcParent.appendChild (tgt);
}
You can test this code at jsFiddle

Categories