<div class='dragExercise'>
<div class='dragHomeField dragField'>
<span><span>零</span><span>líng</span></span>
</div>
<div class='dragActiveField dragField'>
<span><span>一</span><span>yī</span></span>
<span><span>二</span><span>èr</span></span>
<span><span>三</span><span>sān</span></span>
<span><span>四</span><span>sì</span></span>
</div>
</div>
<div class='dragExercise'>
<div class='dragHomeField dragField'>
<span><span>五</span><span>wǔ</span></span>
</div>
<div class='dragActiveField dragField'>
<span><span>六</span><span>liù</span></span>
<span><span>七</span><span>qī</span></span>
<span><span>八</span><span>bā</span></span>
<span><span>九</span><span>jiǔ</span></span>
<span><span>十</span><span>shí</span></span>
<span><span>十一</span><span>shí yī</span></span>
<span><span>十二</span><span>shí èr</span></span>
<span><span>十三</span><span>shí sān</span></span>
<span><span>十四</span><span>shí sì</span></span>
</div>
</div>
body {
height: 2000px;
width: 400px;
}
div {
padding: 10px;
}
.dragExercise {
background: lavender;
padding: 20px;
margin: 20px;
}
.dragField {
min-height: 67px;
padding: 0 10px 0 10px;
}
.dragField > span {
display: inline-block;
}
.dragActiveField {
border: 2px solid #9b9dad;
border-style: dashed;
background: #f5f5f5;
}
span {
padding: 5px;
}
.dragSpan {
background: lightsteelblue;
border-radius: 5px;
cursor: pointer;
position: relative;
margin: 5px 4px 5px 0;
}
.dragSpan > span {
display: block;
text-align: center;
}
.inDrag {
position: absolute;
box-shadow: 0 0 16px 3px rgba(0, 0, 0, 0.52);
z-index: 1000;
}
.dragSpan,.leftHandler,.rightHandler {transition: .5s;}
.leftHandler,.rightHandler {width: calc(50% + 4px);
height: calc(100% + 10px);
background: transparent;
opacity: 0.5;
position: absolute;
top: -5px;
left: 50%;
padding: 0;
}
.leftHandler {
width: 50%;
left: 0;
}
/*
Единственная ошибка осталась, когда вводишь между элементами, то временно сохраняется margin между элементами.
Хотя при переходе на третий элемент margin затирается.
*/
console.clear();
document.querySelectorAll(".dragExercise > div > span").forEach(e => {
e.classList.add("dragSpan");
if (e.nextSibling.nodeType === 3) e.nextSibling.remove();
makeHandlers(e);
});
function makeHandlers(el) {
let rightHandler = document.createElement("span");
rightHandler.classList.add("rightHandler");
let leftHandler = document.createElement("span");
leftHandler.classList.add("leftHandler");
el.append(leftHandler, rightHandler);
}
let dragExercises = document.querySelectorAll(".dragExercise");
dragExercises.forEach(e => {
e.addEventListener('ontouchstart' in window ? "touchstart" : "mousedown", function(event) {
event.preventDefault();
let target = event.target.closest(".dragSpan");
if (!target) return;
let shiftX = event.clientX - target.getBoundingClientRect().left;
let shiftY = event.clientY - target.getBoundingClientRect().top;
target.style.opacity = "0.3";
let newTarget = document.createElement("span");
newTarget.innerHTML = target.innerHTML;
newTarget.classList.add("inDrag", "dragSpan");
newTarget.style.left =
target.getBoundingClientRect().left + pageXOffset + "px";
newTarget.style.top =
target.getBoundingClientRect().top +
pageYOffset +
"px" -
+getComputedStyle(target).marginTop.slice(0, -2);
target.after(newTarget);
if (target.nextElementSibling.nextElementSibling && target.nextElementSibling.nextElementSibling.classList.contains('dragSpan'))
target.nextElementSibling.nextElementSibling.querySelector('.leftHandler').style.display = 'none';
if (target.previousElementSibling && target.previousElementSibling.classList.contains('dragSpan'))
target.previousElementSibling.querySelector('.rightHandler').style.display = 'none';
document.addEventListener('ontouchstart' in window ? "touchmove" : "mousemove", onMouseMove);
document.addEventListener('ontouchstart' in window ? "touchend" : "mouseup", onMouseUp);
moveAt(event.pageX, event.pageY);
let elemBelow;
let parentElemBelow;
let checkElemBelow = null;
let checkParentElemBelow = null;
let newMargin =
newTarget.offsetWidth +
+getComputedStyle(newTarget).marginRight.slice(0, -2);
function moveAt(pageX, pageY) {
let newLeft = pageX - shiftX;
let newTop =
pageY - shiftY - +getComputedStyle(target).marginTop.slice(0, -2);
let rightEdge =
e.offsetWidth -
newTarget.offsetWidth +
e.getBoundingClientRect().left +
pageXOffset;
let bottomEdge =
e.offsetHeight -
newTarget.offsetHeight +
e.getBoundingClientRect().top +
pageYOffset - +getComputedStyle(target).marginTop.slice(0, -2);
newTarget.style.left =
Math.min(
rightEdge,
Math.max(e.getBoundingClientRect().left + pageXOffset, newLeft)
) + "px";
newTarget.style.top =
Math.min(
bottomEdge,
Math.max(e.getBoundingClientRect().top + pageYOffset - +getComputedStyle(target).marginTop.slice(0, -2), newTop)
) + "px";
}
function onMouseMove(event) {
moveAt(event.pageX, event.pageY);
newTarget.style.display = "none";
elemBelow = document.elementFromPoint(event.clientX, event.clientY);
newTarget.style.display = "";
if (elemBelow)
elemBelow =
elemBelow.closest(".rightHandler") ||
elemBelow.closest(".leftHandler") ||
elemBelow.closest(".dragField") ||
null;
if (elemBelow)
parentElemBelow =
elemBelow.closest(".dragSpan") ||
elemBelow.closest(".dragField") ||
null;
if (!e.contains(parentElemBelow)) {parentElemBelow = null; elemBelow = null; return;}
if (
!parentElemBelow ||
elemBelow === checkElemBelow ||
parentElemBelow === target
) return;
checkElemBelow = elemBelow;
e.querySelectorAll('.dragSpan').forEach(el => {el.style.marginRight = '';
el.style.marginLeft = '';})
e.querySelectorAll('.rightHandler').forEach(el => {el.style.width = '';})
e.querySelectorAll('.leftHandler').forEach(el => {el.style.width = '';
el.style.left = '';})
if (elemBelow && elemBelow.classList.contains('rightHandler')) {
parentElemBelow.style.marginRight = '13px';
elemBelow.style.width = +elemBelow.offsetWidth + 13 + 'px';
}
if (elemBelow && elemBelow.classList.contains('leftHandler')) {
parentElemBelow.style.marginLeft = '13px';
elemBelow.style.width = +elemBelow.offsetWidth + 13 + 'px'
elemBelow.style.left = '-13px';
}
}
function onMouseUp() {
e.querySelectorAll('.dragSpan').forEach(el => {el.style.marginRight = '';
el.style.marginLeft = '';})
e.querySelectorAll('.rightHandler').forEach(el => {el.style.width = '';
el.style.display = '';})
e.querySelectorAll('.leftHandler').forEach(el => {el.style.width = '';
el.style.display = '';
el.style.left = '';})
if (parentElemBelow && elemBelow) {
if (elemBelow.classList.contains('rightHandler')) {
parentElemBelow.after(target);
target.style.background = '#b0dec9';
setTimeout(() => {target.style.background = ''; }, 1000)
}
if (elemBelow.classList.contains('leftHandler')) {
parentElemBelow.before(target);
target.style.background = '#b0dec9';
setTimeout(() => {target.style.background = ''; }, 1000)
}
if (parentElemBelow.classList.contains('dragField')) {
parentElemBelow.append(target);
target.style.background = '#b0dec9';
setTimeout(() => {target.style.background = ''; }, 1000)
}
}
newTarget.remove();
target.style.opacity = "";
document.removeEventListener('ontouchstart' in window ? "touchend" : "mouseup", onMouseUp);
document.removeEventListener('ontouchstart' in window ? "touchmove" : "mousemove", onMouseMove);
}
});
});
document.ondragstart = function() {
return false;
};
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.