JSFiddle - React, Tailwind, and code Playground

by jcreamer898

HTML

<div id="editor" contenteditable="true">
    foo bar bam
</div>

JavaScript

var log = function() { console.log.apply(console, arguments); };
document.getElementById('editor').addEventListener('keyup', function(e) {
    if (e.which === 32 && e.ctrlKey) {
        insertNodeOverSelection($('<span />').autocomplete({
            minLength: 0,
            source: ['monkey', 'rabbit', 'goose', 'dog'],
            select: function(e, ui) {
                $(this).autocomplete('destroy');
                this.textContent = ui.item.value;
                return false;
            }
        })[0], this);
        
        $('#editor span.ui-autocomplete-input').autocomplete('search', '');
    }
});

//$('#editor').autocomplete();

function isOrContainsNode(ancestor, descendant) {
    var node = descendant;
    while (node) {
        if (node === ancestor) {
            return true;
        }
        node = node.parentNode;
    }
    return false;
}

function insertNodeOverSelection(node, containerNode) {
    var sel, range, html;
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            if (isOrContainsNode(containerNode, range.commonAncestorContainer)) {
                range.deleteContents();
                range.insertNode(node);
            } else {
                containerNode.appendChild(node);
            }
        }
    } else if (document.selection && document.selection.createRange) {
        range = document.selection.createRange();
        if (isOrContainsNode(containerNode, range.parentElement())) {
            html = (node.nodeType == 3) ? node.data : node.outerHTML;
            range.pasteHTML(html);
        } else {
            containerNode.appendChild(node);
        }
    }
}