Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

window.getSelection() offset with HTML tags?

If I have the following HTML:

<div class="content">
Vivamus <span>luctus</span> urna sed urna ultricies ac tempor dui sagittis.
</div>

And I run an event on mouseup that sees the ranges of the selected text:

$(".content").on("mouseup", function () {
    var start = window.getSelection().baseOffset;
    var end = window.getSelection().focusOffset;
    if (start < end) {
        var start = window.getSelection().baseOffset;
        var end = window.getSelection().focusOffset;
    } else {
        var start = window.getSelection().focusOffset;
        var end = window.getSelection().baseOffset;
    }
    console.log(window.getSelection());
    console.log(start + ", " + end);
});

And I select the word Vivamus from the content, it will log 1, 8, as that is the range of the selection.

If, however, I select the word urna, it will log 15, 20, but won't take into account the <span> elements of the HTML.

Is there anyway for focusOffset and baseOffset to also count for HTML tags, instead of just the text?

like image 882
Charlie Avatar asked Mar 03 '13 01:03

Charlie


1 Answers

Update

Live Example: http://jsfiddle.net/FLwxj/61/

Using a clearSelection() function and a replace approach, I was able to achieve the desired result.

var txt = $('#Text').html();
$('#Text').html(
    txt.replace(/<\/span>(?:\s)*<span class="highlight">/g, '')
);
clearSelection();

Sources:

  • clearSelection(): https://stackoverflow.com/a/6562764/1085891
  • Replace approach: https://stackoverflow.com/a/7168142/1085891

Below you'll find some working solutions to your problem. I placed them in order of code efficiency.

Working Solutions

  • https://stackoverflow.com/a/8697302/1085891 (live example)

    window.highlight = function() {
        var selection = window.getSelection().getRangeAt(0);
        var selectedText = selection.extractContents();
        var span = document.createElement("span");
        span.style.backgroundColor = "yellow";
        span.appendChild(selectedText);
        span.onclick = function (ev) {
        this.parentNode.insertBefore(
            document.createTextNode(this.innerHTML), 
            this
        );
        this.parentNode.removeChild(this);
        }
        selection.insertNode(span);
    }
    
  • https://stackoverflow.com/a/1623974/1085891 (live example)

    $(".content").on("mouseup", function () {
       makeEditableAndHighlight('yellow'); 
    });
    
    function makeEditableAndHighlight(colour) {
        sel = window.getSelection();
        if (sel.rangeCount && sel.getRangeAt) {
        range = sel.getRangeAt(0);
        }
        document.designMode = "on";
        if (range) {
        sel.removeAllRanges();
        sel.addRange(range);
        }
        // Use HiliteColor since some browsers apply BackColor to the whole block
        if (!document.execCommand("HiliteColor", false, colour)) {
        document.execCommand("BackColor", false, colour);
        }
        document.designMode = "off";
    }
    
    function highlight(colour) {
        var range, sel;
        if (window.getSelection) {
        // IE9 and non-IE
        try {
            if (!document.execCommand("BackColor", false, colour)) {
            makeEditableAndHighlight(colour);
            }
        } catch (ex) {
            makeEditableAndHighlight(colour)
        }
        } else if (document.selection && document.selection.createRange) {
        // IE <= 8 case
        range = document.selection.createRange();
        range.execCommand("BackColor", false, colour);
        }
    }
    
  • https://stackoverflow.com/a/12823606/1085891 (live example)

Other helpful solutions:

  • http://tech.pro/tutorial/1075/javascript-highlighting-selected-text
like image 73
JSuar Avatar answered Oct 18 '22 17:10

JSuar