The below is meant for simulating a drag and drop effect. I’m manually changing the styles both on mousedown
and mouseup
events using Object.assign(target.style, ...)
. If I replace the assigment statements with .dragging
class that contains the mousedown
styles, followed by removing that class on mouseup
, the associated left
and top
attributes set in mouseup
stay after removing the .dragging
class.
Here’s the working version:
(function() {
let targets = document.querySelectorAll('.draggable');
let offsetX;
let offsetY;
targets.forEach((target) => {
target.isMouseDown = false;
target.initialOffsetLeft = target.offsetLeft;
target.initialOffsetTop = target.offsetTop;
target.addEventListener('mousedown', (e) => {
if (e.buttons === 1) {
Object.assign(target.style, {
transition: null,
zIndex: 10000,
position: 'relative'
});
target.isMouseDown = true;
offsetX = target.initialOffsetLeft + e.offsetX;
offsetY = target.initialOffsetTop + e.offsetY;
}
});
document.addEventListener('mouseup', (e) => {
e.preventDefault();
target.isMouseDown = false;
Object.assign(target.style, {
transition: 'all 0.5s ease',
zIndex: null,
left: '0',
top: '0'
});
});
document.addEventListener('mousemove', (e) => {
e.preventDefault();
if (target.isMouseDown) {
target.style.left = e.pageX - offsetX + 'px';
target.style.top = e.pageY - offsetY + 'px';
}
});
});
})();
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Roboto', sans-serif
}
.draggable {
display: flex;
padding: 10px 12px;
margin-top: 0px;
margin-left: 0px;
margin-bottom: 11px;
border-radius: 5px;
margin-right: 5px;
background-color: #000000;
cursor: grab;
flex-grow: 1;
color: #ffffff;
border: 1px solid #6c757d;
}
.my-card-group {
margin-top: 30px;
background-color: #000000;
margin-right: 2%;
margin-left: 2%;
border: 1px solid #6c757d;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
<div class="card group">
<div class="my-card-group">
<div class="card-body">
<div class="draggable">
Lorem ipsum dolor sit amet 1
</div>
<div class="draggable">
Lorem ipsum dolor sit amet 2
</div>
<div class="draggable">
Lorem ipsum dolor sit amet 3
</div>
</div>
</div>
</div>
Here’s what I do to replace the Object.assign(...)
statements with .dragging
class:
(function() {
let targets = document.querySelectorAll('.draggable');
let offsetX;
let offsetY;
targets.forEach((target) => {
target.isMouseDown = false;
target.initialOffsetLeft = target.offsetLeft;
target.initialOffsetTop = target.offsetTop;
target.addEventListener('mousedown', (e) => {
if (e.buttons === 1) {
target.classList.add('dragging') // replaced with this
target.isMouseDown = true;
offsetX = target.initialOffsetLeft + e.offsetX;
offsetY = target.initialOffsetTop + e.offsetY;
}
});
document.addEventListener('mouseup', (e) => {
e.preventDefault();
target.isMouseDown = false;
target.classList.remove('dragging') // replaced with this
});
document.addEventListener('mousemove', (e) => {
e.preventDefault();
if (target.isMouseDown) {
target.style.left = e.pageX - offsetX + 'px';
target.style.top = e.pageY - offsetY + 'px';
}
});
});
})();
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Roboto', sans-serif
}
.draggable {
display: flex;
padding: 10px 12px;
border-radius: 5px;
margin: 0 5px 11px 0;
background-color: #000000;
cursor: grab;
flex-grow: 1;
color: #ffffff;
border: 1px solid #6c757d;
transition: all 0.5s ease; /*added this*/
z-index: unset; /*added this*/
left: 0; /*added this*/
top: 0 /*added this*/
}
.dragging { /*added this*/
z-index: 10000;
position: relative;
transition: all 0s;
}
.my-card-group {
margin-top: 30px;
background-color: #000000;
margin-right: 2%;
margin-left: 2%;
border: 1px solid #6c757d;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
<div class="card group">
<div class="my-card-group">
<div class="card-body">
<div class="draggable">
Lorem ipsum dolor sit amet 1
</div>
<div class="draggable">
Lorem ipsum dolor sit amet 2
</div>
<div class="draggable">
Lorem ipsum dolor sit amet 3
</div>
</div>
</div>
</div>
This breaks how the dragging works because left
and top
as well as transition
attributes persist after .dragging
is removed, and the next time any of the .draggable
is dragged, it starts where its previous drag ended and with a transition delay set by .dragging
. Is there a way to achieve the initial behavior using a similar approach?