Sourabh
Sourabh

Reputation: 1303

Text Highlighting using native javascript no jquery

I am currently working in native JS and I am trying to build the highlight text feature in a contenteditable div. I have successfully built the highlight feature but I am encountering a problem when I want to toggle between the highlight and unhighlight text using a single button. So I am getting the selected text and the range of the selected text via

var selectedText = window.getSelection();
var range = selectedText.getRangeAt(0);

and I am wrapping the selected text using surroundContents that is a function of range object.

var wrapper = document.createElement("span");
wrapper.setAttribute("class","highlight");

But now when I am trying to unhighlight some part of the highlighted text and some part of plain text the natural behavior should unhighlight the highlighted text and highlight the plain text. To achieve this I am cloning the range via

var clone = range.cloneContents()
var nodeInBetween = clone.childNodes //array of nodes between the start and end nodes.

Now there are two problems I am facing. First I need to remove the span.highlight nodes and replace it with a TextNode again in order to make it unhighlight-ed and I need some method to wrap a textnode with a span. Unfortunately there is no way to wrap a textnode as one can for range variable.

Upvotes: 0

Views: 331

Answers (1)

KooiInc
KooiInc

Reputation: 122936

I have experimented with a (recursive) highlighter method in this jsFiddle. It may be of use to you. The actual method:

function highLight(term,root,forElements,styleclass){
    root = root || document.querySelector('body');
    term = term instanceof Array ? term.join('|') : term;

    if (!term) {throw TypeError('Highlighter needs a term to highlight anything');}

    forElements = forElements && forElements instanceof Array 
                    ? forElements.join(',') 
                    : /string/i.test(typeof forElements) ? forElements : '*';
    styleclass = styleclass || 'highlight';

    var allDiv = root.querySelectorAll(forElements),
        re = RegExp(term,'gi'),
        highlighter = function(a){return '<span class="'+styleclass+'">'+a+'</span>'};

    for (var i=0; i<allDiv.length; i+=1){
        // recurse children
        if (allDiv[i].querySelectorAll(forElements).length){
            highLight.call(null,term, allDiv[i],forElements,styleclass);
        }
        // replace term(s) in text nodes
        var node = allDiv[i];
        for (node=node.firstChild; node; node=node.nextSibling) {
            if (node.nodeType===3){
                var re = RegExp(term,'gi');
                node.data = node.data.replace(re,highlighter);
            }
        }

    }
    //finally, replace all text data html encoded brackets
    root.innerHTML = root.innerHTML
                      .replace(/&lt;/gi,'<')
                      .replace(/&gt;/gi,'>');
}

Upvotes: 0

Related Questions