简体   繁体   中英

How do I wrap a text selection from window.getSelection().getRangeAt(0) with an html tag?

How do I take a selection from window.getSelection().getRangeAt(0) and surround it with an HTML tag such as 'span' or 'mark'? I prefer a straight javascript or jQuery solution.

I am able to output the selected text using alert, but have not yet figure out how to surround it with additional markup. I have seen many examples of running execCommand on the selection, but that is not what I'm looking for.

See my working example at jsfiddle

Any ideas? Thanks

If the selected text is all contained within a single text node, you can use the surroundContents() method of the Range. However, that doesn't work in the general case. The thing to do is surround each text node within the Range in a <span> . My Rangy library has a module that does this and works cross-browser (IE <= 8 does not natively support DOM Range).

Example code using Rangy:

<style type="text/css">
    span.highlighted {
        background-color: yellow;
    }
</style>
<script type="text/javascript">
    var highlightApplier;

    window.onload = function() {
        rangy.init();
        highlightApplier = rangy.createCssClassApplier("highlighted ", true);
    };

    function applyHighlight() {
        highlightApplier.applyToSelection();
    }
</script>

(Answering my own question based on a similar question I found when I posted mine...)

The guys in this Q&A thread were on an interesting track. It just used a different format than I was looking for. Modifying their code, I was able to do the following:

<h3><a href="#" id="btnRange">Display Range</a> |
<a href="#" id="btnMark">Mark Range</a></h3>

<div contenteditable="true" id="editor">
    This is sample text. You should be able to type in this box or select anywhere in this div and then click the link at the top to get the selected range.
</div>

<script type="text/javascript">
    var btnDisplay = $("#btnRange"),
        btnMark = $("#btnMark");

    btnDisplay.click(function() {
        alert(window.getSelection().getRangeAt(0));
        return false;
    });

    btnMark.click(function() {
        var range = window.getSelection().getRangeAt(0);
        var newNode = document.createElement("mark");
        range.surroundContents(newNode);
        return false;
    });

I could further abstract the code in the btnMark.click() function to accept a tag name and then create a row of buttons to markup the code with mark, pre, blockquote.

A working solution can be found here: http://jsfiddle.net/3tvSL/

First get the range:

var savedRange;
savedRange = window.getSelection().getRangeAt(0);

On button click:

   function formatCode(e){
        var textAreaVal = document.getElementById('divWithContentEditable').innerText;
        if(textAreaVal.length>0){
            var newtxt = '<pre><code>'+savedRange+'</code></pre>'
            replaceIt($('#topicDetails')[0], newtxt);
        }
    }

Add/Replace elements around the text:

replaceIt(txtarea, newtxt) {
    $(txtarea).text(newtxt));  
}

Of course, you can use Rangy but I find adding extra 500kb for simple requirement is not recommended.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM