JSFiddle - React, Tailwind, and code Playground

by Martin Parenteau

HTML

<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<div id="main-input" contenteditable="true">

    <span style="font-size: 24px">Hello <span style="color: rgb(255, 0, 0)"> red world!</span> and black text</span>
    <br>
    <span style="color: rgb(0, 180, 0)"><b>Green text</b></span>

</div>

JavaScript

var $mainInput = $('#main-input');
var draggedText;
var dragStartContainer;
var dragEndContainer;
var dragStartOffset;
var dragEndOffset;

$mainInput.on('dragstart', function(e) {
    var dragRange = getSelectionRange();
    dragStartContainer = dragRange.startContainer;
    dragEndContainer = dragRange.endContainer;
    dragStartOffset = dragRange.startOffset;
    dragEndOffset = dragRange.endOffset;
    draggedText = e.originalEvent.dataTransfer.getData("text");
});

$mainInput.on('drop', function(e) {
    // Get caret at mouse cursor position
    var range = createCollapsedRangeFromPoint(e.clientX, e.clientY);
    var container = range.startContainer;
    // If text is moved to another container, do it manually
    if (container && (container !== dragStartContainer || container !== dragEndContainer)) {
        e.preventDefault();
        // Insert dragged text at caret position
        var startOffset = range.startOffset;
        var str = container.textContent;
        var strPrepend = str.substr(0, range.startOffset);
        var strAppend = str.substr(range.startOffset);
        container.textContent = strPrepend + draggedText + strAppend;
        // Delete text at original position
        var spaceCount = getSpaceCountAtStart(container);
        setSelectionRange(dragStartContainer, dragEndContainer, dragStartOffset, dragEndOffset);
        document.execCommand("delete", false);
        var spaceCountCorrection = getSpaceCountAtStart(container) - spaceCount;
        // Select text at new position
        var startRemoved = (dragEndContainer === container ? dragEndOffset - 1 : 0);
        var startOffset = Math.max(0, startOffset + spaceCountCorrection - startRemoved);
        var endOffset = startOffset + draggedText.length;
        setSelectionRange(container, container, startOffset, endOffset);
    }
});

// Get the number of spaces at start of container
// After moving text, that number may change
// and screw up range position calculations
function...