Search code examples
javascriptwysiwygcontenteditable

How to insert a space after insert node


I want to insert a space after insert a node, the problem is the space that I insert is inside a node, not after the a node.

I have other solution, which is inserting a span and putting a space into the span node, but i think it should have a better solution.

var $preload = $('<a href="url">test.txt</a>');
editor.insertNodeAtCaret($preload.get(0)); 
insertTextAtCursor('\u00A0', true);

function insertNodeAtCaret(node) {
   if (typeof window.getSelection != "undefined") {
       var sel = window.getSelection();
       if (sel.rangeCount) {
           var range = sel.getRangeAt(0);
           range.collapse(false);
           range.insertNode(node);
           range = range.cloneRange();
           range.selectNodeContents(node);
           range.collapse(false);
           sel.removeAllRanges();
           sel.addRange(range);
      }
  } else if (typeof document.selection != "undefined" && document.selection.type != "Control") {
       var html = (node.nodeType == 1) ? node.outerHTML : node.data;
       var id = "marker_" + ("" + Math.random()).slice(2);
       html += '<span id="' + id + '"></span>';
       var textRange = document.selection.createRange();
       textRange.collapse(false);
       textRange.pasteHTML(html);
       var markerSpan = document.getElementById(id);
       textRange.moveToElementText(markerSpan);
       textRange.select();
       markerSpan.parentNode.removeChild(markerSpan);
    }
};



function insertTextAtCursor(text, moveTheCursor) {
    var sel, range, html;
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.deleteContents();
            var textNode = document.createTextNode(text);
            range.insertNode(textNode);
                if(moveTheCursor){
                    range.setStartAfter(textNode);
                    sel.removeAllRanges();
                    sel.addRange(range);
                 }
        }
   } else if (document.selection && document.selection.createRange) {
        document.selection.createRange().text = text;
    }
  };

Solution

  • I suggest adapting insertNodeAtCaret to insert multiple nodes:

    function insertNodesAtCaret() {
        var i, len, node, sel, range, html, id;
        var escapeHtml = function(text) {
            var div = document.createElement("div");
            div.appendChild( document.createTextNode(text) );
            return div.innerHTML;
        };
        
        if (typeof window.getSelection != "undefined") {
            sel = window.getSelection();
            if (sel.rangeCount) {
                range = sel.getRangeAt(0);
                range.collapse(false);
                for (i = 0, len = arguments.length, node; i < len; ++i) {
                    node = arguments[i];
                    if (typeof node == "string") {
                        node = document.createTextNode(node);
                    }
                    range.insertNode(node);
                    range.setStartAfter(node);
                    range.collapse(true);
                }
                range = range.cloneRange();
                range.selectNodeContents(node);
                range.collapse(false);
                sel.removeAllRanges();
                sel.addRange(range);
            }
        } else if (typeof document.selection != "undefined" && document.selection.type != "Control") {
            html = "";
            for (i = 0, len = arguments.length, node; i < len; ++i) {
                node = arguments[i];
                if (typeof node == "string") {
                    html += escapeHtml(node);
                } else if (node.nodeType == 1) {
                    html += node.outerHTML;
                } else if (node.nodeType == 3) {
                    html += escapeHtml(node.data);
                }
            }
            id = "marker_" + ("" + Math.random()).slice(2);
            html += '<span id="' + id + '"></span>';
            var textRange = document.selection.createRange();
            textRange.collapse(false);
            textRange.pasteHTML(html);
            var markerSpan = document.getElementById(id);
            textRange.moveToElementText(markerSpan);
            textRange.select();
            markerSpan.parentNode.removeChild(markerSpan);
        }
    }
    
    function insertElementAndSpace() {
        var aEl = document.createElement("a");
        aEl.href = "http://stackoverflow.com?";
        aEl.appendChild( document.createTextNode("LINK TEXT") );
      
        insertNodesAtCaret(aEl, "\u00a0");
    }
    <input type="button" onmousedown="insertElementAndSpace(); return false;" value="Insert">
    <div contenteditable="true">
        This is some editable text. Put the caret somewhere in here and press the button.
    </div>