Reputation: 140112
It should be a combination of CSS and JavaScript. The steps to do should be:
But what are the details?
Upvotes: 27
Views: 79966
Reputation: 2180
w3schools got a nice example: https://www.w3schools.com/howto/howto_js_draggable.asp
HTML:
<!-- Draggable DIV -->
<div id="mydiv">
<!-- Include a header DIV with the same name as the draggable DIV, followed by "header" -->
<div id="mydivheader">Click here to move</div>
<p>Move</p>
<p>this</p>
<p>DIV</p>
</div>
CSS:
#mydiv {
position: absolute;
z-index: 9;
background-color: #f1f1f1;
border: 1px solid #d3d3d3;
text-align: center;
}
#mydivheader {
padding: 10px;
cursor: move;
z-index: 10;
background-color: #2196F3;
color: #fff;
}
JS:
// Make the DIV element draggable:
dragElement(document.getElementById("mydiv"));
function dragElement(elmnt) {
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
if (document.getElementById(elmnt.id + "header")) {
// if present, the header is where you move the DIV from:
document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
} else {
// otherwise, move the DIV from anywhere inside the DIV:
elmnt.onmousedown = dragMouseDown;
}
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
// get the mouse cursor position at startup:
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
// call a function whenever the cursor moves:
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
// calculate the new cursor position:
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
// set the element's new position:
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
}
function closeDragElement() {
// stop moving when mouse button is released:
document.onmouseup = null;
document.onmousemove = null;
}
}
Upvotes: 0
Reputation: 313
You can do this by using following code
$(function() {
$("#imageListId").sortable({
update: function(event, ui) {
getIdsOfImages();
} //end update
});
});
function getIdsOfImages() {
var values = [];
$('.listitemClass').each(function(index) {
values.push($(this).attr("id")
.replace("imageNo", ""));
});
$('#outputvalues').val(values);
}
/* text align for the body */
body {
text-align: center;
}
/* image dimension */
img {
height: 200px;
width: 350px;
}
/* imagelistId styling */
#imageListId {
margin: 0;
padding: 0;
list-style-type: none;
}
#imageListId div {
margin: 0 4px 4px 4px;
padding: 0.4em;
display: inline-block;
}
/* Output order styling */
#outputvalues {
margin: 0 2px 2px 2px;
padding: 0.4em;
padding-left: 1.5em;
width: 250px;
border: 2px solid dark-green;
background: gray;
}
.listitemClass {
border: 1px solid #006400;
width: 350px;
}
.height {
height: 10px;
}
<link href="https://code.jquery.com/ui/1.10.4/themes/ui-lightness/jquery-ui.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>
Drag Drop feature
</title>
</head>
<body>
<h1 style="color:green">GeeksforGeeks</h1>
<b>Drag and drop using jQuery UI Sortable</b>
<div class="height"></div><br>
<div id = "imageListId">
<div id="imageNo1" class = "listitemClass">
<img src="images/geeksimage1.png" alt="">
</div>
<div id="imageNo2" class = "listitemClass">
<img src="images/geeksimage2.png" alt="">
</div>
<div id="imageNo3" class = "listitemClass">
<img src="images/geeksimage3.png" alt="">
</div>
<div id="imageNo4" class = "listitemClass">
<img src="images/geeksimage4.png" alt="">
</div>
<div id="imageNo5" class = "listitemClass">
<img src="images/geeksimage5.png" alt="">
</div>
<div id="imageNo6" class = "listitemClass">
<img src="images/geeksimage6.png" alt="">
</div>
</div>
<div id="outputDiv">
<b>Output of ID's of images : </b>
<input id="outputvalues" type="text" value="" />
</div>
</body>
</html>
Upvotes: -1
Reputation: 474
See the demo for a better idea.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<style>
body,
html {
width: 100%;
height: 100%;
padding: 0px;
margin: 0px;
}
#box {
width: 100px;
height: 100px;
margin: auto;
background-color: lightblue;
}
#box:active {
border: 1px solid black;
box-shadow: 2px 2px 5px 5px #bbb6b6;
}
</style>
</head>
<body>
<div id="box"></div>
</body>
<script>
var box = document.getElementById("box");
var diff = {};
var getBoxPos = function() {
return {
x: box.getBoundingClientRect().x,
y: box.getBoundingClientRect().y
};
};
var calcDiff = function(x, y) {
var boxPos = getBoxPos();
diff = {
x: x - boxPos.x,
y: y - boxPos.y
};
};
var handleMouseMove = function(event) {
var x = event.x;
var y = event.y;
x -= diff.x;
y -= diff.y;
console.log("X " + x + " Y " + y);
box.style.position = "absolute";
box.style.transform = "translate(" + x + "px ," + y + "px)";
};
box.addEventListener("mousedown", function(e) {
calcDiff(e.x, e.y);
box.addEventListener("mousemove", handleMouseMove, true);
});
box.addEventListener("mouseup", function(e) {
console.log("onmouseup");
box.removeEventListener("mousemove", handleMouseMove, true);
});
</script>
</html>
Upvotes: 1
Reputation: 61023
The standard Drag and Drop API is widely recognized to suck big hairy donkey balls. So I wouldn't recommend doing it from scratch. But since that's your question, there are one set of requirements for making something draggable, and one set of requirements for properly setting up a drop zone:
Dragging:
Note: e.dataTransfer.setDragImage
can be used to set an alternate drag image (the default is a transparent image of the dom node being dragged.
Note2: e.dataTransfer.setData
can be used inside the dragstart
event to set some data that can be gotten back from the drop event.
Dropping:
dragover
event, e.preventDefault
must be calleddrop
event, e.preventDefault
must be calledExample:
<body>
<div id="dragme" draggable="true">Drag Me</div>
<div id="dropzone">Drop Here</div>
</body>
<script>
var dragme = document.getElementById('dragme')
var dropzone = document.getElementById('dropzone')
dragme.addEventListener('dragstart',function(e){
dropzone.innerHTML = "drop here"
})
dropzone.addEventListener('dragover',function(e){
e.preventDefault()
})
dropzone.addEventListener('drop',function(e){
e.preventDefault()
dropzone.innerHTML = "dropped"
})
</script>
However, there are a whole lot of gotchas in using this API, including that:
dragmove
event over a dropzone and a dragmove
event related to a draggable itemdragmove
fires even if your mouse isn't movingdragleave
and dragenter
fire even if your mouse isn't moving in or out of the listening dom node (it fires whenever it crosses a child-parent bounary for some stupid reason)I wrote a drag and drop library that makes it a ton easier to use the standard drag and drop API without all those gotchas. Check it out here:
https://github.com/fresheneesz/drip-drop
Upvotes: 6
Reputation: 3497
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));
}
.mydiv {
float: left;
width: 100px;
height: 35px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<h2>Drag and Drop</h2>
<div id="div1" class="mydiv" ondrop="drop(event)" ondragover="allowDrop(event)">
<img src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a" draggable="true" ondragstart="drag(event)" id="drag1" width="88" height="31">
</div>
<div id="div2" class="mydiv" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div id="div3" class="mydiv" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div id="div4" class="mydiv" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
</body>
</html>
Upvotes: 4
Reputation: 1367
If you are reading this in the year 2017 or later, you might want to have a look at the HTML5 Drag and Drop API:
https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API
Example:
<!DOCTYPE HTML>
<html>
<head>
<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>
<style>
.draggable {
border: 1px solid black;
width: 30px;
height: 20px;
float: left;
margin-right: 5px;
}
#target {
border: 1px solid black;
width: 150px;
height: 100px;
padding: 5px;
}
</style>
</head>
<body>
<h1>Drag and Drop</h1>
<h2>Target</h2>
<div id="target" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<h2>Draggable Elements</h2>
<div id="draggable1" class="draggable" draggable="true" ondragstart="drag(event)"></div>
<div id="draggable2" class="draggable" draggable="true" ondragstart="drag(event)"></div>
<div id="draggable3" class="draggable" draggable="true" ondragstart="drag(event)"></div>
</body>
</html>
Upvotes: 6
Reputation: 12091
Here's an example from Javascript, the Definitive Guide (updated here):
/**
* Drag.js: drag absolutely positioned HTML elements.
*
* This module defines a single drag() function that is designed to be called
* from an onmousedown event handler. Subsequent mousemove event will
* move the specified element. A mouseup event will terminate the drag.
* If the element is dragged off the screen, the window does not scroll.
* This implementation works with both the DOM Level 2 event model and the
* IE event model.
*
* Arguments:
*
* elementToDrag: the element that received the mousedown event or
* some containing element. It must be absolutely positioned. Its
* style.left and style.top values will be changed based on the user's
* drag.
*
* event: ethe Event object for the mousedown event.
*
* Example of how this can be used:
* <script src="Drag.js"></script> <!-- Include the Drag.js script -->
* <!-- Define the element to be dragged -->
* <div style="postion:absolute; left:100px; top:100px; width:250px;
* background-color: white; border: solid black;">
* <!-- Define the "handler" to drag it with. Note the onmousedown attribute. -->
* <div style="background-color: gray; border-bottom: dotted black;
* padding: 3px; font-family: sans-serif; font-weight: bold;"
* onmousedown="drag(this.parentNode, event);">
* Drag Me <!-- The content of the "titlebar" -->
* </div>
* <!-- Content of the draggable element -->
* <p>This is a test. Testing, testing, testing.<p>This is a test.<p>Test.
* </div>
*
* Author: David Flanagan; Javascript: The Definitive Guide (O'Reilly)
* Page: 422
**/
function drag(elementToDrag, event)
{
// The mouse position (in window coordinates)
// at which the drag begins
var startX = event.clientX, startY = event.clientY;
// The original position (in document coordinates) of the
// element that is going to be dragged. Since elementToDrag is
// absolutely positioned, we assume that its offsetParent is the
//document bodt.
var origX = elementToDrag.offsetLeft , origY = elementToDrag.offsetTop;
// Even though the coordinates are computed in different
// coordinate systems, we can still compute the difference between them
// and use it in the moveHandler() function. This works because
// the scrollbar positoin never changes during the drag.
var deltaX = startX - origX, deltaY = startY - origY;
// Register the event handlers that will respond to the mousemove events
// and the mouseup event that follow this mousedown event.
if (document.addEventListener) //DOM Level 2 event model
{
// Register capturing event handlers
document.addEventListener("mousemove", moveHandler, true);
document.addEventListener("mouseup", upHandler, true);
}
else if (document.attachEvent) //IE 5+ Event Model
{
//In the IE event model, we capture events by calling
//setCapture() on the element to capture them.
elementToDrag.setCapture();
elementToDrag.attachEvent("onmousemove", moveHandler);
elementToDrag.attachEvent("onmouseup", upHandler);
// Treat loss of mouse capture as a mouseup event.
elementToDrag.attachEvent("onclosecapture", upHandler);
}
else //IE 4 Event Model
{
// In IE 4, we can't use attachEvent() or setCapture(), so we set
// event handlers directly on the document object and hope that the
// mouse event we need will bubble up.
var oldmovehandler = document.onmousemove; //used by upHandler()
var olduphandler = document.onmouseup;
document.onmousemove = moveHandler;
document.onmouseup = upHandler;
}
// We've handled this event. Don't let anybody else see it.
if (event.stopPropagation) event.stopPropagation(); // DOM Level 2
else event.cancelBubble = true; // IE
// Now prevent any default action.
if (event.preventDefault) event.preventDefault(); // DOM Level 2
else event.returnValue = false; // IE
/**
* This is the handler that captures mousemove events when an element
* is being dragged. It is responsible for moving the element.
**/
function moveHandler(e)
{
if (!e) e = window.event; // IE Event Model
// Move the element to the current mouse position, adjusted as
// necessary by the offset of the initial mouse-click.
elementToDrag.style.left = (e.clientX - deltaX) + "px";
elementToDrag.style.top = (e.clientY - deltaY) + "px";
// And don't let anyone else see this event.
if (e.stopPropagation) e.stopPropagation(); // DOM Level 2
else e.cancelBubble = true; // IE
}
/**
* This is the handler that captures the final mouseup event that
* occurs at the end of a drag.
**/
function upHandler(e)
{
if (!e) e = window.event; //IE Event Model
// Unregister the capturing event handlers.
if (document.removeEventListener) // DOM event model
{
document.removeEventListener("mouseup", upHandler, true);
document.removeEventListener("mousemove", moveHandler, true);
}
else if (document.detachEvent) // IE 5+ Event Model
{
elementToDrag.detachEvent("onlosecapture", upHandler);
elementToDrag.detachEvent("onmouseup", upHandler);
elementToDrag.detachEvent("onmousemove", moveHandler);
elementToDrag.releaseCapture();
}
else //IE 4 Event Model
{
//Restore the original handlers, if any
document.onmouseup = olduphandler;
document.onmousemove = oldmovehandler;
}
// And don't let the event propagate any further.
if (e.stopPropagation) e.stopPropagation(); //DOM Level 2
else e.cancelBubble = true; //IE
}
}
function closeMe(elementToClose)
{
elementToClose.innerHTML = '';
elementToClose.style.display = 'none';
}
function minimizeMe(elementToMin, maxElement)
{
elementToMin.style.display = 'none';
}
Upvotes: 16
Reputation: 82523
Yeah, you can use jQuery if you want a bloated library with far more functions than you need! Or if you want to be more of an elitist, use Waltern Zorn's drag and drop library, which is one tenth of the size.
Upvotes: 2
Reputation: 268492
Check out the jQueryUI addons draggable and droppable.
Literally hundreds of hours have been invested into the jQuery framework to make complicated tasks like this almost trivial. Take advantage of the jQuery team's efforts to make programming rich cross-browser applications easier on us all ;)
If you insist on trying this with raw javascript. You'll want to do a few things. One, programmatically set all draggable items to a relative/absolute positioning. If you click a particular item, cause it's top/left values in CSS to reflect the changes made by the x,y axis of the mouse until the click is released. Additionally, you'll want to update the z-index of each draggable when it's clicked to bring it into view.
Tutorial: How to Drag and Drop with Javascript
Upvotes: 39