CSS
jQuery
A jQuery plugin that makes a div draggable with mouse and/or touch device. The code is a modified version of jquery-draggable-touch created by Jonatan Heyman.
The modified code makes sure that the div being dragged stays within the Viewport of the browser. And two lines with
The element that is being dragged is placed on top by setting the Z-index with some more custom added code.
The changes made by me are marked with
The modified code makes sure that the div being dragged stays within the Viewport of the browser. And two lines with
e.preventDefault(); are disabled so you can select/focus input elements within the draggable div.
The element that is being dragged is placed on top by setting the Z-index with some more custom added code.
The changes made by me are marked with
//VDWWD.
Draggable Touch div 1
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Draggable Touch div 2
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="https://www.vanderwaal.eu/favicon.ico" />
<title>VDWWD - Draggable Div with Touch</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
</head>
<body style="background-color: #4b4d66" class="pt-4">
<!-- van der Waal Webdesign -->
<!-- https://www.vanderwaal.eu -->
<div class="container bg-white">
<!-- demo content -->
<div class="row">
<div class="col-12 col-md-6 mx-auto pt-4">
<div class="card draggable-div" id="DraggableTouchDiv1">
<div class="card-header d-flex justify-content-between draggable-div-header">
<h2 class="me-4">Draggable Touch div 1</h2>
<div class="float-end mt-1">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-move">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-move">
<polyline points="5 9 2 12 5 15"></polyline>
<polyline points="9 5 12 2 15 5"></polyline>
<polyline points="15 19 12 22 9 19"></polyline>
<polyline points="19 9 22 12 19 15"></polyline>
<line x1="2" y1="12" x2="22" y2="12"></line>
<line x1="12" y1="2" x2="12" y2="22"></line>
</svg>
<polyline points="5 9 2 12 5 15"></polyline>
<polyline points="9 5 12 2 15 5"></polyline>
<polyline points="15 19 12 22 9 19"></polyline>
<polyline points="19 9 22 12 19 15"></polyline>
<line x1="2" y1="12" x2="22" y2="12"></line>
<line x1="12" y1="2" x2="12" y2="22"></line>
</svg>
</div>
</div>
<div class="card-body">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
<span class="d-none d-sm-block">
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</span>
</div>
</div>
<div class="card draggable-div" id="DraggableTouchDiv2">
<div class="card-body">
<strong>Draggable Touch div 2</strong>
<br />
<br />
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
<span class="d-none d-sm-block">
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</span>
</div>
</div>
</div>
</div>
<!-- footer -->
<div class="row footer-row">
<div class="col text-center pt-5 pb-3">
<a target="_blank" href="https://www.vanderwaal.eu">
<img src="https://www.vanderwaal.eu/images/vdwwd.png" alt="van der Waal Webdesign" title="van der Waal Webdesign" width="300" height="95" />
</a>
</div>
</div>
</div>
<!-- scripts -->
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
<!-- vdwwd scripts and stylesheets -->
<script src="draggable-div-with-touch.js"></script>
<link href="draggable-div-with-touch.css" rel="stylesheet">
<script>
$(function () {
$('.draggable-div').draggableTouch();
});
</script>
</body>
</html>
(function ($) {
//VDWWD: declare some extra variables
var draggable_div_margin = 10;
var draggable_div_emr = 0;
var draggable_div_emb = 0;
var draggable_div_zindex = 500;
//VDWWD: extra margin right when there is a vertical scrollbar
if (document.body.scrollHeight > window.innerHeight) {
draggable_div_emr = 20;
}
//VDWWD: extra margin bottom when there is a horizontal scrollbar
if (document.body.scrollWidth > window.innerWidth) {
draggable_div_emb = 20;
}
$.fn.draggableTouch = function (action) {
//check if the device has touch support, and if not, fallback to use mouse draggableMouse which uses mouse events
if (!("ontouchstart" in document.documentElement)) {
return this.draggableMouse(action);
}
//check if we shall make it not draggable
if (action == "disable") {
this.unbind("touchstart.draggableTouch");
this.unbind("touchmove.draggableTouch");
this.unbind("touchend.draggableTouch");
this.unbind("touchcancel.draggableTouch");
this.trigger("dragdisabled");
return this;
}
this.each(function () {
var $element = $(this);
var offset = null;
var draggingTouchId = null;
var end = function (e) {
//VDWWD: turned off preventDefault otherwise input elements in the div won't work
//e.preventDefault();
var orig = e.originalEvent;
for (var i = 0; i < orig.changedTouches.length; i++) {
var touch = orig.changedTouches[i];
//the only touchend/touchcancel event we care about is the touch that started the dragging
if (touch.identifier != draggingTouchId) {
continue;
}
$element.trigger("dragend", {
top: orig.changedTouches[0].pageY - offset.y,
left: orig.changedTouches[0].pageX - offset.x
});
draggingTouchId = null;
}
};
$element.bind("touchstart.draggableTouch", function (e) {
var orig = e.originalEvent;
//if this element is already being dragged, we can exit early, otherwise we need to store which touch started dragging the element
if (draggingTouchId) {
return;
}
draggingTouchId = orig.changedTouches[0].identifier;
var pos = $(this).position();
//VDWWD: move div to top with z-index
draggable_div_zindex++;
$element.css('z-index', draggable_div_zindex);
offset = {
x: orig.changedTouches[0].pageX - pos.left,
y: orig.changedTouches[0].pageY - pos.top
};
$element.trigger("dragstart", pos);
});
$element.bind("touchmove.draggableTouch", function (e) {
e.preventDefault();
var orig = e.originalEvent;
for (var i = 0; i < orig.changedTouches.length; i++) {
var touch = orig.changedTouches[i];
//the only touchend/touchcancel event we care about is the touch that started the dragging
if (touch.identifier != draggingTouchId) {
continue;
}
//VDWWD: use the setDragDivCss function
setDragDivCss($element, touch.pageY - offset.y, touch.pageX - offset.x);
//$(this).css({
// top: touch.pageY - offset.y,
// left: touch.pageX - offset.x
//});
}
});
$element.bind("touchend.draggableTouch touchcancel.draggableTouch", end);
});
return this;
};
//draggable fallback for when touch is not available
$.fn.draggableMouse = function (action) {
//check if we shall make it not draggable
if (action == "disable") {
this.unbind("mousedown.draggableTouch");
this.unbind("mouseup.draggableTouch");
$(document).unbind("mousemove.draggableTouch");
this.trigger("dragdisabled");
return this;
}
this.each(function () {
var $element = $(this);
var offset = null;
var move = function (e) {
//VDWWD: use the setDragDivCss function
setDragDivCss($element, e.pageY - offset.y, e.pageX - offset.x);
//$element.css({
// top: e.pageY - offset.y,
// left: e.pageX - offset.x,
//});
};
var up = function (e) {
$element.unbind("mouseup.draggableTouch", up);
$(document).unbind("mousemove.draggableTouch", move);
$element.trigger("dragend", {
top: e.pageY - offset.y,
left: e.pageX - offset.x
});
};
$element.bind("mousedown.draggableTouch", function (e) {
var pos = $element.position();
offset = {
x: e.pageX - pos.left,
y: e.pageY - pos.top
};
$(document).bind("mousemove.draggableTouch", move);
$element.bind("mouseup.draggableTouch", up);
$element.trigger("dragstart", pos);
//VDWWD: move div to top with z-index
draggable_div_zindex++;
$element.css('z-index', draggable_div_zindex);
//VDWWD: turned off preventDefault otherwise input elements in the div won't work
//e.preventDefault();
});
});
return this;
};
//VDWWD: separate function to keep the element withing the viewport and apply the corrected css
function setDragDivCss($element, top, left) {
//check if the element does not exceed the viewport at the top of bottom
if (top < draggable_div_margin) {
top = draggable_div_margin;
} else if (top + $element.height() + draggable_div_margin + draggable_div_emb > window.innerHeight) {
top = window.innerHeight - draggable_div_margin - $element.height() - draggable_div_emb;
}
//check if the element does not exceed the viewport at the left of right
if (left < draggable_div_margin) {
left = draggable_div_margin;
} else if (left + $element.width() + draggable_div_margin + draggable_div_emr > window.innerWidth) {
left = window.innerWidth - draggable_div_margin - $element.width() - draggable_div_emr;
}
//apply the position
$element.css({
top: top,
left: left,
});
}
})(jQuery);