47

With a contenteditable element how can I replace the selected content with my own html?

Brigand
  • 84,529
  • 20
  • 165
  • 173
Frodik
  • 14,986
  • 23
  • 90
  • 141
  • The second part of this question (“replace selected text with html of my own”) is not answered in he question linked as a reference for this one being a duplicate. – Brian M. Hunt Jul 15 '14 at 23:49
  • I removed the already answered part to comply with the "one question per question" rule. – Brigand Jul 16 '14 at 00:16
  • Related - https://stackoverflow.com/q/3997659/104380 – vsync Sep 20 '20 at 11:18

2 Answers2

70

See here for working jsFiddle: http://jsfiddle.net/dKaJ3/2/

function getSelectionHtml() {
    var html = "";
    if (typeof window.getSelection != "undefined") {
        var sel = window.getSelection();
        if (sel.rangeCount) {
            var container = document.createElement("div");
            for (var i = 0, len = sel.rangeCount; i < len; ++i) {
                container.appendChild(sel.getRangeAt(i).cloneContents());
            }
            html = container.innerHTML;
        }
    } else if (typeof document.selection != "undefined") {
        if (document.selection.type == "Text") {
            html = document.selection.createRange().htmlText;
        }
    }
    alert(html);
}

Code taken from Tim Down: Return HTML from a user-selected text

Community
  • 1
  • 1
NakedBrunch
  • 48,713
  • 13
  • 73
  • 98
  • BTW - Never call the function `getSelection()`, as this will override the default and cause stack recursion – tetris11 Jan 06 '13 at 17:17
  • works great! thanks. how would I now replace the selected text with something else in same position as the text is? – Varun Apr 10 '13 at 02:51
  • nevermind, found the answer: http://stackoverflow.com/questions/3997659/replace-selected-text-in-contenteditable-div?rq=1 – Varun Apr 10 '13 at 03:25
  • Nice, But one more question please, it return the selected text from whole document, how can get only a selected div. May be a div with a distinct class? – Pritom Jun 24 '13 at 10:59
  • It's not solving the problem: how would you replace the selection, if there are at least two similar strings? – k102 Mar 23 '16 at 13:27
54

To get the selected HTML, you can use the function I wrote for this question. To replace the selection with your own HTML, you can use this function. Here's a version of the replacer function that inserts an HTML string instead of a DOM node:

function replaceSelectionWithHtml(html) {
    var range;
    if (window.getSelection && window.getSelection().getRangeAt) {
        range = window.getSelection().getRangeAt(0);
        range.deleteContents();
        var div = document.createElement("div");
        div.innerHTML = html;
        var frag = document.createDocumentFragment(), child;
        while ( (child = div.firstChild) ) {
            frag.appendChild(child);
        }
        range.insertNode(frag);
    } else if (document.selection && document.selection.createRange) {
        range = document.selection.createRange();
        range.pasteHTML(html);
    }
}

replaceSelectionWithHtml("<b>REPLACEMENT HTML</b>");
Community
  • 1
  • 1
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • Please define `node`. I think we can just delete this line `html = (node.nodeType == 3) ? node.data : node.outerHTML;` – FirstVertex Jun 25 '14 at 14:06
  • @HDog: Yes, you're right. Looks like a copy-pasted line I forgot to remove. I've deleted it now. Thanks. – Tim Down Jun 25 '14 at 19:03
  • Why is 'html' both a parameter to the function and a local variable declaration? It works because of http://stackoverflow.com/a/27963351/578812 but it seems confusing at first glance. – Craig A Jul 27 '16 at 18:31
  • @CraigA: It's a mistake. I suspect I copied and adapted a function that didn't have the `html` parameter. Thanks for pointing it out. – Tim Down Jul 28 '16 at 08:26
  • Wonderful answer! But there's one thing I don't get, why is this valid syntax: `var frag = document.createDocumentFragment(), child;` . Why doesn't the comma raise an error? I'd be very grateful if you could explain how this statement works – flen Feb 28 '17 at 09:29
  • 1
    @flen: The `var` statement in JavaScript allows you to declare multiple variables in a single statement, separated by comma, each variable optionally having an initial value. [More info at MDN](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/var) – Tim Down Feb 28 '17 at 10:54
  • @TimDown Thanks a lot! Now I got it, `child` is just a variable declaration, without any assingment. Just like `var frag = 42; var child;` – flen Mar 01 '17 at 19:55
  • @TimDown, I've used this on a ContentEditable div. But it seems you can Undo/Redo anything inserted via this snippet. Is there any way to do it so Undo/Redo captures it? Thanks – Xahed Kamal Mar 27 '18 at 18:19
  • @XahedKamal: I don't think so. I believe that changes made by using [`document.execCommand()`](https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand) go onto the browser undo stack but there's no command that gives you precise control over what HTML is inserted and how it's inserted. – Tim Down Mar 28 '18 at 10:06