<div class='dragExercise'>
  <div class='dragHomeField dragField'>
    <span><span></span><span>líng</span></span>
    </div> 
  <div class='dragActiveField dragField'>
    <span><span></span><span></span></span>
    <span><span></span><span>èr</span></span>
    <span><span></span><span>sān</span></span>
    <span><span></span><span></span></span>
    </div> 
</div>

<div class='dragExercise'>
  <div class='dragHomeField dragField'>
    <span><span></span><span></span></span>
    </div> 
  <div class='dragActiveField dragField'>
    <span><span></span><span>liù</span></span>
    <span><span></span><span></span></span>
    <span><span></span><span></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;
};

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.