Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the highlighted text position in .html() and .text()

I am using the following script to get the position of highlighted text:

function getSelectionCharOffsetsWithin(element) {
    var start = 0, end = 0;
    var sel, range, priorRange;
    if (typeof window.getSelection != "undefined") {
        range = window.getSelection().getRangeAt(0);
        priorRange = range.cloneRange();
        priorRange.selectNodeContents(element);
        priorRange.setEnd(range.startContainer, range.startOffset);
        start = priorRange.toString().length;
        end = start + range.toString().length;
    } else if (typeof document.selection != "undefined" &&
        (sel = document.selection).type != "Control") {
        range = sel.createRange();
        priorRange = document.body.createTextRange();
        priorRange.moveToElementText(element);
        priorRange.setEndPoint("EndToStart", range);
        start = priorRange.text.length;
        end = start + range.text.length;
    }
    return {
        start: start,
        end: end
    };
  }

function alertSelection() {
    var mainDiv = document.getElementById("detailBoxParagraph");
    var sel = getSelectionCharOffsetsWithin(mainDiv);
    alert(sel.start + ": " + sel.end);
}

Now, if i use this on $('p').text(), which contains

Lorem ipsum dolor sit amet, consetetur sadipscing elitr.

everything works just fine. But i also need to get the position in $('p').html() which is obviously different because of the <b> tag

Lorem ipsum dolor `<b>sit</b>` amet, consetetur sadipscing elitr.

How do i prevent or change this?

Edit:

I forgot to say, my first thought was to count the times the tag occures, then use that value to calculate the new position, but this is idiotic somehow.

My second approach was to replace the tag with an asterisk for the work with .text()

Edit #2

Here is a messy fiddle showing the problem. If you highlight text with the mouse, then click the button, the first time it will correctly be set to bold. Second time won't work correctly.

I will clean the fiddle up soon

http://jsfiddle.net/UpLaw/2/

Edit #3

i played around a little with the highlight plugin mentioned below but i wasn't able to limit the function to affect only the marked string. It will either highlight all matching words or just the first appearence. Can anyone help?

Here is the necessary code:

jQuery.fn.highlight = function(pat) {
this.length = 1 ;

function innerHighlight(node, pat) {

    var skip = 0;
    if (node.nodeType == 3) {
        var pos = node.data.toUpperCase().indexOf(pat);
        if (pos >= 0) {
            var spannode = document.createElement('span');
            spannode.className = 'highlight';
            var middlebit = node.splitText(pos);
            var endbit = middlebit.splitText(pat.length);
            var middleclone = middlebit.cloneNode(true);
            spannode.appendChild(middleclone);
            middlebit.parentNode.replaceChild(spannode, middlebit);
            skip = 1;
        }
    }
    else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {

        for (var i = 0; i < 1; ++i) { // So it will highlight only the first occurence. 
            i += innerHighlight(node.childNodes[i], pat);
        }
    }
    return skip;
}
return this.length && pat && pat.length ? this.each(function() {
    innerHighlight(this, pat.toUpperCase());

}) : this;
};

Edit #4

Okay, i tried to understand that javscript. As far as i see, this can not be done since highlight() is called with a simple string as a parameter. It can not know the position of this string. Could / Should i parse the position, then try to search from that position, highlight the first occurence, then abort?

like image 267
Wottensprels Avatar asked Apr 19 '13 11:04

Wottensprels


1 Answers

From your comment, this is what you want to accomplish.

i will try to explain this as good as i can. English is not my native language, so sorry for the confusion. I would like to insert a html-tag before and after the highlighted text. To achieve this, i will have to get the beginning and end of the text.

Assuming sit is the highlighted selection you want to process.

You can use .wrap() or .after() and .before() to accomplish this.

function alertSelection() {
    $("b", $('#detailBoxParagraph')).wrap('<i/>'); // make the  highlighted section inside a tag.

    $("b", $('#detailBoxParagraph')).before('<u>Content inserted before </u> '); // insert an html before highlighted selections.

    $("b", $('#detailBoxParagraph')).after(' <u>Content inserted after </u>'); // insert an html after highlighted selections.
}

$(function () {
    alertSelection();
})

Here I'm making the highlighted text italics.

See sample in jsFiddle

Reference

  • .wrap()
  • .before()
  • .after()

If you are trying to accomplish the selected text to highlight, you can use jQuery highlight plugin.

See sample in jsFiddle.

function getSelectionText() {
    var text = "";
    if (window.getSelection) {
        text = window.getSelection().toString();
    } else if (document.selection && document.selection.type != "Control") {
        text = document.selection.createRange().text;
    }
    return text;
}

$(function () {
    $('#detailBoxParagraph').mouseup(function (e){
        $(this).removeHighlight();
        $(this).highlight(getSelectionText());
   });
});
like image 165
Sen Jacob Avatar answered Oct 23 '22 07:10

Sen Jacob