4

I want to have a button that adds a highlight to the currently selected text. I plan on doing this with the caret position of the selection. I have the following code:

function getCaretCharacterOffsetWithin(element) {
    var caretOffset = 0;
    var doc = element.ownerDocument || element.document;
    var win = doc.defaultView || doc.parentWindow;
    var sel;
    if (typeof win.getSelection != "undefined") {
        sel = win.getSelection();
        if (sel.rangeCount > 0) {
            var range = win.getSelection().getRangeAt(0);
            var preCaretRange = range.cloneRange();
            preCaretRange.selectNodeContents(element);
            preCaretRange.setEnd(range.endContainer, range.endOffset);
            caretOffset = preCaretRange.toString().length;
        }
    } else if ( (sel = doc.selection) && sel.type != "Control") {
        var textRange = sel.createRange();
        var preCaretTextRange = doc.body.createTextRange();
        preCaretTextRange.moveToElementText(element);
        preCaretTextRange.setEndPoint("EndToEnd", textRange);
        caretOffset = preCaretTextRange.text.length;
    }
    return caretOffset;
}

function showCaretPos() {
    var el = document.getElementById("test");
    var caretPosEl = document.getElementById("caretPos");
    caretPosEl.innerHTML = "Caret position: " + getCaretCharacterOffsetWithin(el);
}

document.body.onkeyup = showCaretPos;
document.body.onmouseup = showCaretPos;
Non-editable text. Editable is below:
<div id="test" contenteditable="true">Hello, some <b>bold</b> and <i>italic and <b>bold</b></i> text</div>
<div id="caretPos"></div>

The above code finds the caret position. How can I now use the caret position to highlight only that position of text.

Possible Idea Get caret position from above and now substr() to add highlight. str.substr(above caret position).

What is the best way to accomplish this?

EDIT

I don't want to change the color selection. I only want to use the caret position to then add a div that acts as a highlighter. For example:

Hi, my name is Bob.

Now, I use the caret position to track the position for only my text selection. Now, I replace the text with the original text but also with a div for the text selection.

Let's say I want highlight the phrase name is. I'm using this method of using caret position to not highlight every instance of this phrase. Only the exact position of where the phrase is. For example, let's my text has the phrase name is twice, it will only highlight the phrase that matches the caret position. Then, replace the text with something like: <div id='highlight'> name is </div>

  • 1
    Currently selected text should be already highlighted automatically, please elaborate your question. – Teemu Aug 26 '16 at 19:25
  • I believe this is what you're trying to accomplish? https://css-tricks.com/overriding-the-default-text-selection-color-with-css/ – Robert Wade Aug 26 '16 at 20:03
  • @Teemu I don't mean selecting the text. I mean using the cursor position to change the position of the text to also include a highlight. I want the highlight to stay, like a yellow background... – Great Day Today Aug 26 '16 at 22:20
  • Then just wrap the selection in a styled element, see [execCommand('insertHTML'...)](https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand). Doesn't work for MS browsers, though. – Teemu Aug 26 '16 at 22:25
  • When you say caret position, that's like one point in text, you need to specify start and end of a selection (end being the position of where the caret should be.) When you wrap the text in a div it will seperate itself from the text. If you use an inline element like a `` then the text won't be disrupted. – zer00ne Aug 26 '16 at 23:32
  • @zer00ne That's true. How would you accomplish this? – Great Day Today Aug 26 '16 at 23:34
  • The r[ange API](https://developer.mozilla.org/en-US/docs/Web/API/Range) – zer00ne Aug 26 '16 at 23:36
  • @zer00ne I don't expect you to do all the work. Would you just showing an example of how to properly calculate the start and end points with the Range API? I can figure out the rest myself... – Great Day Today Aug 27 '16 at 00:22
  • @GreatDayToday Later on I could try helping you, I got to go to work. I'm thinking along the lines of `selectNodeContents` which you actually use in your function. – zer00ne Aug 27 '16 at 01:42

1 Answers1

1

In the following Snippet are 2 functions that do the same thing except that the first one uses a <span> and the second one uses a <div>. What the functions do is essentially...

  1. ...removes the selected content (text)...
  2. ...creates a <span> or <div>...
  3. ...sets the backgroundColor to yellow...
  4. ...the content is then appended to the <span/div>...
  5. ...then finally the <span/div> is inserted into the range.

The <span> as you can see is probably a better choice. Using a <div> is just plain messy.

SNIPPET

var spanEdit = document.getElementById('spanEdit');
var divEdit = document.getElementById('divEdit');

function highlightSpan() {
  var range = document.getSelection().getRangeAt(0);
  var contents = range.extractContents();
  var node = document.createElement('span');
  node.style.backgroundColor = "yellow";
  node.appendChild(contents);
  range.insertNode(node);
}

function highlightDiv() {
  var range = document.getSelection().getRangeAt(0);
  var contents = range.extractContents();
  var node = document.createElement('div');
  node.style.backgroundColor = "yellow";
  node.appendChild(contents);
  range.insertNode(node);
}

spanEdit.onkeyup = highlightSpan;
spanEdit.onmouseup = highlightSpan;

divEdit.onkeyup = highlightDiv;
divEdit.onmouseup = highlightDiv;
<div id='spanEdit' contenteditable="true">Highlight inserted span. This uses extractContents() method.</div>
<div>&nbsp;</div>
<div id='divEdit' contenteditable="true">Highlight inserted div. This uses extractContents() method.</div>

The functions are an adaptation from this post

Community
  • 1
  • 1
zer00ne
  • 41,936
  • 6
  • 41
  • 68