Drag and Drop multiple divs as unique - javascript

Hi i'm working with drag and drop but i stopped at this problem.
I have 2 columns and I want to drag divs from source to target column. The problem is that these source divs are reapeated in every source container and I need that when I move one (The div #36406 for example), all others divs in adjacent source containers with the same ID disappear of source column.
edit 1:
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.className);
}
function drop(ev) {
debugger;
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
<div style="height:50px; width:50px; border: 1px solid blue; margin-left:40%" ondrop="drop(event)" ondragover="allowDrop(event)"> DROP HERE'</div> <!-- Target -->
<div class="btn btn-warning '+parcelas[j].idlancamento+'" draggable="true" style="cursor:move" ondragstart="drag(event)">
SOURCE
</div> <!-- source -->

Hi I've posted a working example below. I set each div's data-id attribute to its ID number. I used jQuery in this example (hope that's ok). When the drag event starts, the dragStart() function is called, and it searches for each div that has a matching data-id attribute and sets the opacity to 0. The dragStop() function sets the opacity back to 1. Let me know if you have any further questions :)
function dragStart(ev) {
let id = ev.target.getAttribute("data-id");
$("[data-id=" + id + "]").not(ev.target).css("opacity", 0);
}
function dragStop(ev) {
let id = ev.target.getAttribute("data-id");
$("[data-id=" + id + "]").not(ev.target).css("opacity", 1);
}
function drop(ev) {
debugger;
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
.btn {
background-color: red;
border: 1px solid black;
width: 90px;
height: 40px;
margin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="btn btn-warning '+parcelas[j].idlancamento+'" data-id="123" draggable="true" style="cursor:move" ondragstart="dragStart(event)" ondragend="dragStop(event)">
ID: 123
</div>
<div class="btn btn-warning '+parcelas[j].idlancamento+'" data-id="123" draggable="true" style="cursor:move" ondragstart="dragStart(event)" ondragend="dragStop(event)">
ID: 123
</div>
<div class="btn btn-warning '+parcelas[j].idlancamento+'" data-id="123" draggable="true" style="cursor:move" ondragstart="dragStart(event)" ondragend="dragStop(event)">
ID: 123
</div>
<div class="btn btn-warning '+parcelas[j].idlancamento+'" data-id="000" draggable="true" style="cursor:move" ondragstart="dragStart(event)" ondragend="dragStop(event)">
ID: 000
</div>

Related

How can one use HTML5 drag and drop API with JavaScript to display varying text, depending on which draggable element is dropped?

I am working on a webpage for a class assignment. We are to utilize the HTML5 API drag and drop, which has been successfully implemented. I wanted to go a step further with the drag and drop API by incorporating some JavaScript to change a line of text on the webpage. I anticipated this line of text to be able to change into different statements based on which draggable object was dropped. I was able to achieve a single change to the text, but I was unable to find a way to have the text change to a different message. I consulted with my professor about this and she recommended I ask the question in these forums to find out more information. Is there a way to achieve this effect with the HTML5 API?
The code I started with to get the initial change in text looks like this:
<body>
<main>
<h2 class="center">What are Specializations?</h2>
<p class="center">Specializations in Project Management are similar to certifications, but instead highlight expertise on specific management approaches, task oversight, and industries. </p>
<br>
<br>
<h2 class="center">What Specializations are available?</h2>
<p class="center" id="demo">(Drag and Drop the specializations into the box for more details)</p>
<br>
<br>
<div class="container" style="background-color: #fafad2;">
<div></div>
<div></div>
<div draggable="true" class="box" style="background-color: #AFFF7A; border-color: #000000; padding: 20%;"></div>
<div></div>
<div></div>
</div>
<br>
<div class="container">
<div draggable="true" class="box">PMI-RMP</div>
<div draggable="true" class="box">PMI-SP</div>
<div draggable="true" class="box">AHPP</div>
<div draggable="true" class="box">AM-MC</div>
<div draggable="true" class="box">CD-P</div>
<div draggable="true" class="box">CDBA</div>
<div draggable="true" class="box">BEPC</div>
<div draggable="true" class="box">BEPM</div>
<div draggable="true" class="box">BETI</div>
<div draggable="true" class="box">PMI-CP</div>
<div draggable="true" class="box">OTF</div>
<div draggable="true" class="box">OTI</div>
<div draggable="true" class="box">OTO</div>
</div>
<script>
/* Events fired on the drag target */
document.addEventListener("dragstart", function(event) {
// The dataTransfer.setData() method sets the data type and the value of the dragged data
event.dataTransfer.setData("Text", event.target.id);
});
// Output some text when finished dragging the p element and reset the opacity
document.addEventListener("dragend", function(event) {
document.getElementById("demo").innerHTML = "Finished dragging the p element.";
});
/* Events fired on the drop target */
// By default, data/elements cannot be dropped in other elements. To allow a drop, we must prevent the default handling of the element
document.addEventListener("dragover", function(event) {
event.preventDefault();
});
</script>
</main>
</body>
I would then approach the multi-message display by using a JavaScript event listener and if-else statements, seen in this code:
<body>
<main>
<h2 class="center">What are Specializations?</h2>
<p class="center">Specializations in Project Management are similar to certifications, but instead highlight expertise on specific management approaches, task oversight, and industries. </p>
<br>
<br>
<h2 class="center">What Specializations are available?</h2>
<p class="center" id="demo">(Drag and Drop the specializations into the box for more details)</p>
<br>
<br>
<div class="container" style="background-color: #fafad2;">
<div></div>
<div></div>
<div draggable="true" class="box" style="background-color: #AFFF7A; border-color: #000000; padding: 20%;"></div>
<div></div>
<div></div>
</div>
<br>
<div class="container">
<div draggable="true" class="box">PMI-RMP</div>
<div draggable="true" class="box">PMI-SP</div>
<div draggable="true" class="box">AHPP</div>
<div draggable="true" class="box">AM-MC</div>
<div draggable="true" class="box">CD-P</div>
<div draggable="true" class="box">CDBA</div>
<div draggable="true" class="box">BEPC</div>
<div draggable="true" class="box">BEPM</div>
<div draggable="true" class="box">BETI</div>
<div draggable="true" class="box">PMI-CP</div>
<div draggable="true" class="box">OTF</div>
<div draggable="true" class="box">OTI</div>
<div draggable="true" class="box">OTO</div>
</div>
<script>
/* Events fired on the drag target */
document.addEventListener("dragstart", function(event) {
// The dataTransfer.setData() method sets the data type and the value of the dragged data
event.dataTransfer.setData("Text", event.target.id);
});
// Output some text when finished dragging the p element and reset the opacity
document.addEventListener("dragend", function(event) {
document.getElementById("definition").innerHTML = "(Drag and Drop the specializations into the box for more details)";
var id='1';
if (id=='1') {
document.getElementById("definition").innerHTML = "This is definition 1";
}else if (id=='2'){
document.getElementById("definition").innerHTML = "This is definition 2";
}else if (id=='3'){
document.getElementById("definition").innerHTML = "This is definition 3";
}else (id=='4'){
document.getElementById("definition").innerHTML = "This is definition 4";
}
});
/* Events fired on the drop target */
// By default, data/elements cannot be dropped in other elements. To allow a drop, we must prevent the default handling of the element
document.addEventListener("dragover", function(event) {
event.preventDefault();
});
</script>
</main>
</body>
The CSS utilized:
body {
background-color:#fafad2;
margin: 3%;
}
h1 {
color:#4169E1;
font-family: "Trebuchet MS";
font-size: 300%;
opacity: 75%;
text-shadow: 1px -2px 1px #00008B;
}
h2 {
color:#4682B4;
font-family: "Trebuchet MS";
font-size: 200%;
}
h3 {
color:#B0C4DE;
font-family: "Trebuchet MS";
font-size: 150%;
font-style: italic;
}
main {
padding: 4%;
}
p {
font-family: Georgia;
}
.container {
background-color: #FFFF76;
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-gap: 1%;
padding: 1%;
}
.box {
border: 3px solid #ddd;
background-color: #FFF5EE;
padding: 10%;
margin: 5%;
cursor: move;
text-align: center;
}
.box.over {
border: 4px dashed #666;
}

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.

Drag and drop not working for on the fly elements firefox

I have a page that generates some draggable elements.
However I noticed that on firefox I cannot get them to drag while on chrome I can.To create a new element i press the create item button.Here is my code
/*
* #param event A jquery event that occurs when an object is being dragged
*/
function dragStartHandler(event){
//e refers to a jQuery object
//that does not have dataTransfer property
//so we have to refer to the original javascript event
var originalEvent = event.originalEvent;
var currentElement = originalEvent.target;
console.log("Hack it");
console.log($(currentElement).data());
//We want to store the data-task-id of the object that is being dragged
originalEvent.dataTransfer.setData("text",$(currentElement).data("task-id"));
originalEvent.dataTransfer.effectAllowed = "move";
}
$(document).ready(function(){
//When a new task/item is creatted it is assigned a unique data attribute which is the task index
var taskIndex = 0;
$(".text-info").addClass("text-center");
$(".createTask").addClass("btn-block").on("click",function(){
//Find the category whict this button belongs to
var currentCategory = $(this).parent(".box");
var categoryId = currentCategory.data("category");
//Create a new task
var task = $("<div class='list-group-item droppable' draggable='true' data-task-id="+taskIndex+"></div>");
//Assign a data-task-id attribute and set its text
task.text("Data id = "+taskIndex);
taskIndex++;
task.appendTo($(this).prev(".dropTarget"));
});
$(".droppable").on("dragstart",dragStartHandler);
$(".dropTarget").on("dragenter",function(event){
event.preventDefault();
event.stopPropagation();
$(this).addClass("highlighted-box");
}).on("dragover",false)
.on("drop",function(event){
event.preventDefault();
event.stopPropagation();
var originalEvent = event.originalEvent;
//Retrieve the data-task-id we stored in the event
var taskId = originalEvent.dataTransfer.getData("text");
console.log(taskId);
//The object that will be moved is determined by the id we stored on the event parameter
var objectToMove =$("body").find(`[data-task-id='${taskId}']`);
console.log(objectToMove);
var category = $(this).parent(".box").data("category");
objectToMove.data("category-group",category);
//Remove the square object from its previous position
//and append it to the current dropTarget
$(objectToMove).appendTo(this);
return false;
});
});
.highlighted-box {
box-shadow: 0 0 4px 4px #EBE311;
}
.dropTarget {
height: 10em;
width: 10em;
/* border:2px solid; */
margin: auto;
}
.dropTarget .droppable{
margin: auto;
position: relative;
top: 20%;
}
.droppable {
background-color: dodgerblue;
/* height: 6em;
border-radius: 5px; */
/* box-shadow: 0 0 5px 5px #3D0404; */
/* width: 6em; */
}
#square2{
background-color: red;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<body>
<div class="jumbotron intro text-center">
<h1>Drag and drop demo</h1>
</div>
<div class="row">
<div class="col-md-3 box" data-category="0">
<h1 class="text-info">Ideas</h1>
<div class="dropTarget list-group">
</div>
<div class="btn btn-info createTask">
Create item
</div>
</div>
<div class="col-md-3 box" data-category="1">
<h1 class="text-info">Wornking on</h1>
<div class="dropTarget list-group">
</div>
<div class="btn btn-info createTask">
Create item
</div>
</div>
<div class="col-md-3 box" data-category="2">
<h1 class="text-info">Completed</h1>
<div class="dropTarget list-group">
</div>
<div class="btn btn-info createTask">
Create item
</div>
</div>
<div class="col-md-3 box" data-category="3">
<h1 class="text-info">Accepted</h1>
<div class="dropTarget list-group">
</div>
<div class="btn btn-info createTask">
Create item
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-6">
<div id="square" draggable="true" data-index = "0" class="droppable list-group-item"></div>
</div>
<div class="col-md-6">
<div id="square2" class="droppable list-group-item" draggable="true" data-index="1"></div>
</div>
</div>
</div>
</body>
The problem with my code was the event delegation.
To fix it I did the following:
$("body").on("dragstart",".droppable",dragStartHandler);
Here you can find more more here

making a new div draggable, tried everything

Hello stackoverflow comunity.
I am working on some code that makes draggable resizeable divs. I have it working with the divs that are created originally, but the newly added divs arent becomming draggable.
Here is ALL my code:
<html>
<head>
<script>
var id = 4;
function drag(ev)
{
ev.dataTransfer.setData("Text",ev.target.id);
}
function drop(ev)
{
ev.preventDefault();
ev.target.appendChild(document.getElementById(ev.dataTransfer.getData("Text")));
}
function change(div)
{
var divw=parseInt(div.style.width);
var divh=parseInt(div.style.height);
var imgw=divw-10;
var imgh=divh-10;
div.children[0].style.width=imgw;
div.children[0].style.height=imgh;
div.style.border="dotted 3px grey";
}
function addimg()
{
var main = document.getElementById('main');
var div = document.createElement('div');
div.onmouseout = function() {this.style.border=0};
div.ondragstart = function() {drag(event)};
div.onmousemove = function() {change(this)};
div.setAttribute('draggable', true);
div.id = 'div'+id;
id+=1;
div.style.styleFloat = 'left';
div.style.cssFloat = 'left';
div.style.resize = 'both';
div.style.overflow = 'hidden';
div.style.height = '110px';
div.style.width = '110px';
div.innerHTML = '<img draggable="false" style="width: 100px; height: 100px" src="https://www.google.com/images/srpr/logo11w.png" />';
main.appendChild(div);
}
</script>
</head>
<body>
<center>
<div ID="main" ondragover="event.preventDefault()" ondrop="drop(event)" style="width:900px; height:900px; border: dashed 1px lightgrey;" overflow="auto">
<div onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div1" style="float:left; resize:both; overflow:hidden; height: 110px; width:110px">
<textarea onblur="this.nextElementSibling.innerHTML=this.innerHTML" style="resize:none; width: 100px; height: 100px"></textarea>
<p style="background-color: blue"></p>
</div>
<div style="clear:both"></div>
<div onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div2" style="float:left; resize:both; overflow:hidden; height: 110px; width:110px">
<img draggable="false" style="width: 100px; height: 100px" src="https://www.google.com/images/srpr/logo11w.png" />
</div>
<div onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div3" style="float:left; resize:both; overflow:hidden; height: 110px; width:110px">
<img draggable="false" style="width: 100px; height: 100px" src="https://www.google.com/images/srpr/logo11w.png" />
</div>
</div>
</center>
<button onclick="addimg()">add an image</button>
</body>
</html>
the issue is that the new divs aren't draggable.
P.S. if you use jquery, please explain it very detailed, i have no experience with it.
I m not sure what draggable function in this case is. Is it just dragging this newly added image to this element in top left ? After what that image disappear ?
If this is case, solution is very simple. In function addimage you have wrong line.Your line is:
div.ondragstart = function() {drag(event)};
And it should be
div.ondragstart = function(event) {drag(event)};
In this line you call function without setting event as argument, and you use it in function.
Hope it helps.
One solution is to use the same method used to create the <img> element, to create the <div>:
<html>
<head>
<script>
var id = 4;
function drag(ev) {
ev.dataTransfer.setData("Text",ev.target.id);
}
function drop(ev) {
ev.preventDefault();
document.getElementById('main')
.appendChild(document.getElementById(ev.dataTransfer.getData("Text")));
}
function change(div) {
var divw = parseInt(div.style.width);
var divh = parseInt(div.style.height);
var imgw = divw - 10;
var imgh = divh - 10;
div.children[0].style.width = imgw;
div.children[0].style.height = imgh;
div.style.border = "dotted 3px grey";
}
function addimg() {
var main = document.getElementById('main');
main.innerHTML += '<div id="div'+id+'" onmouseout="this.style.border=0" draggable="true" ' +
'ondragstart="drag(event)" onmousemove="change(this)" style="float:left; ' +
'resize:both; overflow:hidden; height: 110px; width:110px"></div>';
div = document.getElementById('div'+id);
div.innerHTML = '<img draggable="false" style="width: 100px; height: 100px" src="https://www.google.com/images/srpr/logo11w.png" />';
id+=1;
}
</script>
</head>
<body>
<center>
<div ID="main" ondragover="event.preventDefault()" ondrop="drop(event)" style="width:900px; height:900px; border: dashed 1px lightgrey;" overflow="auto">
<div onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div1" style="float:left; resize:both; overflow:hidden; height: 110px; width:110px">
<textarea onblur="this.nextElementSibling.innerHTML=this.innerHTML" style="resize:none; width: 100px; height: 100px"></textarea>
<p style="background-color: blue"></p>
</div>
<div style="clear:both"></div>
<div onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div2" style="float:left; resize:both; overflow:hidden; height: 110px; width:110px">
<img draggable="false" style="width: 100px; height: 100px" src="https://www.google.com/images/srpr/logo11w.png" />
</div>
<div onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div3" style="float:left; resize:both; overflow:hidden; height: 110px; width:110px">
<img draggable="false" style="width: 100px; height: 100px" src="https://www.google.com/images/srpr/logo11w.png" />
</div>
</div>
</center>
<button onclick="addimg()">add an image</button>
</body>
</html>
This should ensure the browser renders the new <div> element in the same way as the existing ones. In addition ensuring that elements are appended back to the main <div> element when they are dropped, will prevent them from disappearing when dropped onto of other elements, as previously.
Using Jquery
On the tip of using jquery, if we include the jquery.min.js library at the top of the file:
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
The change() function can be rewritten as:
function change(div) {
var $div = $(div);
$div.css('border','dotted 3px grey')
.children( ':first' )
.width( $div.width() - 10 )
.height( $div.height() - 10 );
}
This is somewhat shorter than the original. The first line converts the div parameter into a jquery object and stores it in the $div variable. The $ at the beginning of the variable name is just a convention, as the variable contains a jquery object. Caching the jquery object in this variable is more efficient than using $(div) 3 times in the change() function.
Calls to$div.width() and $div.height() perform the same action as the parseInt() calls in the original function. Jquery allows function calls to be 'chained', thus the first call on $div sets the border style and returns the same $div object. The .children() call returns the first child of $div (the <img> element) which then has it's width and height set using the corresponding methods.
It should be noted that jquery is generally thought to be easier to use, and offer good cross browser compatibility (which can be a real headache) rather than more efficient.
Moving style out of elements
We can move the common style attribute out of the individual elements into a separate section in the <head> of the html:
<style>
#main {
width:900px;
height:900px;
border: dashed 1px lightgrey;
overflow: auto;
}
.dragDiv {
float: left;
resize: both;
overflow: hidden;
height: 110px;
width: 110px;
}
.dragDiv img {
width: 100px;
height: 100px
}
.dragDiv textarea {
resize: none;
width: 100px;
height: 100px;
}
</style>
By giving the drag-able <div> elements the class dragDiv we reduce the amount of style duplication:
<div id="main" ondragover="event.preventDefault()" ondrop="drop(event)">
<div class="dragDiv" onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div1">
<textarea onblur="this.nextElementSibling.innerHTML=this.innerHTML"></textarea>
<p style="background-color: blue"></p>
</div>
<div style="clear:both"></div>
<div class="dragDiv" onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div2">
<img draggable="false" src="https://www.google.com/images/srpr/logo11w.png" />
</div>
<div class="dragDiv" onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div3">
<img draggable="false" src="https://www.google.com/images/srpr/logo11w.png" />
</div>
</div>
Is this something like what you are looking for? I'm happy to suggest more alterations, if required.
Jquery offers draggables - which use absolute positioning; resizables; and sortables - which offer similar 'snap on drop' behaviour as the code above. Although I don't suggest you use these instead, they might be good guides as to how you wish your code to behave.

Categories