Highlight text using Javascript

I am trying to do below thing.

User will select text on webpage and then I want to highlight that text using some color.
And also I want to store that information to database so when user come to that page again I can show already highlighted text.
Below is my approach.

  1. When user select text I will use window.getSelection() api and find the selected text.(Successfully done)
  2. Then I will find start element using anchorNode in window.getSelection() .And I will find xpath of that element to store in database.(Successfully done)
  3. I will do same for end element using baseNode in window.getSelection() .And I will find xpath of that element to store in database.(Successfully done)
  4. Now I will get starting and ending position in paticular node.(I am confused here, I can get position using anchorOffset but that will be relative position to particular element not parent element).

– Now when user refresh the page I will fetch all highlights from database and highlight already highlighted parts.
1. Find elements(start and end) using xpath. (Successfully done)
2. When I start highlighting I will wrap some text with tag to highlight that text like <span class="highlight">.......</span>.
3. When I add those highlights tags again xpath will change for all elements and also when user delete those highlight text those xpaths will change.(I am confused here).
4.suppose structure is complex like “<div><pre>Hello <code> Test</code></pre></div>” and user is selecting text from “E” in hello to “last T” in test than how to highlight that.

There is one library “http://annotatorjs.org/”.I can say I need something like that.
Anything am I missing here?
Or my way is wrong here?
Any simple steps will be helpful.

I have tried below code.Although it is not full code because it is too big.

function getXPath(element) {
    var xpath = '';
    for (; element && element.nodeType == 1 && element.id !== 'text-wrapper-inner' && element.tagName !== 'HL'; element = element.parentNode) {
        var id = $(element.parentNode).children(element.tagName).index(element) + 1;
        id > 1 ? (id = '[' + id + ']') : (id = '');
        xpath = '/' + element.tagName.toLowerCase() + id + xpath;
    }
    return xpath;
}

function getElementFromXpath(xpath) {
    var element = document.evaluate('./' + xpath, document.getElementById('text-wrapper-inner'), null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    return element;
}

function showHighlightedNotes(ele, offset, id, index) {
    vm.cloneElement = vm.cloneElement || $("#text-wrapper-inner").clone();
    var element = $(vm.cloneElement).children($(ele)[0])[0];
    if (element.nodeType !== 3) {
        var text = element.innerHTML;
        text = text.replace(/&nbsp;/g, " ");
        if (text.indexOf(" ", offset) > -1) {
            var start = text.substr(0, offset);
            var space_pos = text.indexOf(" ", offset);
            var word = "<hl class='highlight' id=" + id + "><sup>[" + index + "]</sup>" + text.substr(offset, (space_pos - offset)) + "</hl>";
            var end = text.substr(space_pos);
            element.innerHTML = start + word + end;
        } else {
            var start = "",
                end = "";
            if (offset === 0) {
                start = "<hl class='highlight' id=" + id + "><sup>[" + index + "]</sup>" + text.substr(offset) + "</hl>";
            } else {
                start = text.substr(0, offset);
                end = "<hl class='highlight' id=" + id + "><sup>[" + index + "]</sup>" + text.substr(offset) + "</hl>";
            }
            element.innerHTML = start + end;
        }
    } else if (element.nodeType === 3) {
        var text = element.nodeValue;
        if (text.indexOf(" ", offset) > -1) {
            var start = text.substr(0, offset);
            var space_pos = text.indexOf(" ", offset);
            var word = "<hl class='highlight' id=" + id + "><sup>[" + index + "]</sup>" + text.substr(offset, (space_pos - offset)) + "</hl>";
            var end = text.substr(space_pos);
            var span = document.createElement('hl');
            span.innerHTML = start + word + end;
            element.parentNode.replaceChild(span, element);
        } else {
            var start = "",
                end = "";
            if (offset === 0) {
                start = "<hl class='highlight' id=" + id + "><sup>[" + index + "]</sup>" + text.substr(offset) + "</hl>";
            } else {
                start = text.substr(0, offset);
                end = "<hl class='highlight' id=" + id + "><sup>[" + index + "]</sup>" + text.substr(offset) + "</hl>";
            }
            var span = document.createElement('hl');
            span.innerHTML = start + end;
            element.parentNode.replaceChild(span, element);
        }

    }
    //Unwrap all HL tag who doesn't have highlight class
    $('hl:not(".highlight")').contents().unwrap();

    $('hl.highlight sup').on('click', function cb(event) {
        vm.mouseOverId = parseInt($(this).parent().attr('id'));

        var mouseX = event.offsetX;//event.pageX - event.target.offsetParent.offsetLeft;
        var mouseY = event.offsetY;//event.pageY - event.target.offsetParent.offsetTop - 50;
        $('.dehighlight-over')
            .css('display', 'inline-block')
            .css('top', mouseY)
            .css('left', mouseX);
    })
    $(document).on('click', function cb(event) {
        if (event.target.tagName !== 'HL' && event.target.tagName !== 'SUP') {
            $('.dehighlight-over').css('display', 'none')
        }
    })
}

I tried a similar thing a few years ago and it’s not an easy thing to do. I think for something like this it might be helpful to study what others have done.

Check out AnnotatorJS, specifically:

Edit: Wow, jumped the gun a bit. Didn’t notice you actually mentioned it. I got a little excited when I saw what you were trying to do.

Thanks Oz for your help.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.