26

Is there a cross-browser way to get HTML of selected text?

Haris
  • 1,029
  • 3
  • 12
  • 26
  • possible duplicate of [Getting selected text in a browser, cross-platform.](http://stackoverflow.com/questions/10478/getting-selected-text-in-a-browser-cross-platform) – Sarfraz Nov 14 '10 at 09:38
  • 7
    None of the answers to that question are very good, and it's a different question: it asks for the selected text, not the HTML of the selected text. – Tim Down Nov 14 '10 at 11:32
  • Already answered on SO http://stackoverflow.com/questions/10478/getting-selected-text-in-a-browser-cross-platform – wiifm Nov 14 '10 at 09:36
  • 2
    A duplicate of this question was recently posted (with more answers): http://stackoverflow.com/questions/5643635/how-to-get-selected-html-text-with-javascript – Anderson Green Jan 20 '13 at 22:24
  • Possible duplicate of [Getting selected text in a browser, cross-platform](https://stackoverflow.com/questions/10478/getting-selected-text-in-a-browser-cross-platform) – Ethan Oct 22 '17 at 09:10
  • @Booligoosh: That's a different question that's asking for the plain text of the selection, not the HTML. – Tim Down Oct 23 '17 at 10:01
  • @TimDown Oops, my bad :\ – Ethan Oct 23 '17 at 10:02

2 Answers2

48

This function will do it in all major browsers:

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;
        }
    }
    return html;
}


// bind events for selection

document.addEventListener('mouseup', function(){
  var selectedHTML = getSelectionHtml();
  if( selectedHTML )
    console.log( selectedHTML )
});

document.addEventListener('keyup', function(e){ 
  var selectedHTML, key = e.keyCode || e.which; 
  if( key == 16 ){ // if "shift" key was released
    selectedHTML = getSelectionHtml();
    if( selectedHTML )
      console.log( selectedHTML )
  }
});
<ul contenteditable>
  <li><p>Select <b>this</b> <em>text</em> right <i>here</i></p></li>
  <li>Or <b>this text</b></li>
</ul>
vsync
  • 118,978
  • 58
  • 307
  • 400
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • 3
    The problem with this solution is that when you select the caps-locked part of

    first paragraph TEXT TO

    BE SELECTED second paragraph

    you don't get expected "TEXT TO

    BE SELECTED" but "

    TEXT TO

    BE SELECTED

    - for some reason browser ads tags that are not in the selection in order to close the ones that are. Is there any way how to get only what really is in the selection?
    – HonzaBé Aug 08 '15 at 06:19
  • 3
    An HTML document is fundamentally a tree of nodes. Once the initial HTML text has been parsed, it's essentially gone and you have to deal in nodes. It would be possible (but relatively complicated) to convert the selection into the kind of string you suggest but there's no guarantee it would match the original HTML text, which is just one of many equally valid ways of representing the document. – Tim Down Aug 10 '15 at 08:50
  • I actually want the behavior that @honzzz don't But I am getting what he wants.

    first paragraph TEXT TO

    BE SELECTED second paragraph

    shall be returning

    TEXT TO

    BE SELECTED

    rather than TEXT TO

    BE SELECTED

    – Stotra May 25 '22 at 18:24
0

If you just need the text of the selection, use .toString():

window.getSelection()?.toString()
'Is there a cross-browser way to get HTML of selected text?'
jameshfisher
  • 34,029
  • 31
  • 121
  • 167