I'm new in JS and trying to make simple interface with pure JS, where User can dynamically add elements and move them around. I found solutions for create elements and drag'n'drop elements, that perfectly works separatly. But when I tried to unite them, drop function stop working...
What am I doing wrong?
Template:
<head>
<title>Int Demo</title>
<script src='js/script.js'></script>
<style type="text/css">
.wrapper {width: 300px; height: 200px; background: #A3A1A1;}
.textblock {cursor: pointer; background: red;}
</style>
</head>
<body>
<div class="button" id="button">Add Textbox</div>
<div class="wrapper" id="wrapper"></div>
</body>
</html>
My JS file:
document.addEventListener("DOMContentLoaded", function() { init(); }, false);
function init() {
button = document.getElementById('button');
wrapper = document.getElementById('wrapper');
button.addEventListener('click', btnClick, false);
wrapper.ondblclick = catchIt;
}
//add element
function btnClick() {
wrapper.innerHTML += '<p class="draggable textblock">Text Here!</p>';
sessionStorage.inputBoxes = wrapper;
console.log(sessionStorage);
}
// Activate Drag'n'Drop
document.onmousedown = function(e) {
var dragElement = e.target;
if (!dragElement.classList.contains('draggable')) return;
var coords, shiftX, shiftY;
startDrag(e.clientX, e.clientY);
document.onmousemove = function(e) {
moveAt(e.clientX, e.clientY);
};
dragElement.onmouseup = function() {
finishDrag();
};
function startDrag(clientX, clientY) {
shiftX = clientX - dragElement.getBoundingClientRect().left;
shiftY = clientY - dragElement.getBoundingClientRect().top;
dragElement.style.position = 'fixed';
document.body.appendChild(dragElement);
moveAt(clientX, clientY);
};
function finishDrag() {
dragElement.style.top = parseInt(dragElement.style.top) + pageYOffset + 'px';
dragElement.style.position = 'absolute';
document.onmousemove = null;
dragElement.onmouseup = null;
}
function moveAt(clientX, clientY) {
var newX = clientX - shiftX;
var newY = clientY - shiftY;
// bottom offset
var newBottom = newY + dragElement.offsetHeight;
if (newBottom > document.documentElement.clientHeight) {
var docBottom = document.documentElement.getBoundingClientRect().bottom;
var scrollY = Math.min(docBottom - newBottom, 10);
if (scrollY < 0) scrollY = 0;
window.scrollBy(0, scrollY);
newY = Math.min(newY, document.documentElement.clientHeight - dragElement.offsetHeight);
}
// top offset
if (newY < 0) {
var scrollY = Math.min(-newY, 10);
if (scrollY < 0) scrollY = 0;
window.scrollBy(0, -scrollY);
newY = Math.max(newY, 0);
}
if (newX < 0) newX = 0;
if (newX > document.documentElement.clientWidth - dragElement.offsetHeight) {
newX = document.documentElement.clientWidth - dragElement.offsetHeight;
}
dragElement.style.left = newX + 'px';
dragElement.style.top = newY + 'px';
}
return false;
}
I changed
dragElement.onmouseup = function() {
finishDrag();
};
into
document.onmouseup = function() {
finishDrag();
};
and it started working for me. This does mean that the end user will have to keep the mouse button pressed down to continue dragging and that the element will be placed immediately on mouse button up. But I'm assuming that this is the desired functionality, or do you want the drop to happen only on a second mouse click?