Home

Highlight Find

Source code for bookmarklet Highlight Find.



javascript:
(function(){
        function travTree(node, ifun)
    {
        var counter = 0;
        function ns(nxi, level)
        {
            var nx = nxi;
            while (nx)
            {
                ++counter;
                ifun(nx);
                ns(nx.firstChild, level + 1);
                nx = level > 0 ? nx.nextSibling : null;
            }
        }

        ns( node, 0 );
        return counter;
    }
    var rp = 0;

    var rei = (window.getSelection ? window.getSelection().toString() : null);
    if (rei == null || !/\S+/.test(rei))
    {
        rei = prompt( "Regular expression: " );
    }
    else
    {
        rei = rei.replace( /[\[\]\|(){}?*.+\\]/g, function(m){ return "\\" + m;} )
            .replace( /\s/g, "\\s" );
    }

    if (rei == null || !/\S+/.test(rei)) {return;}

    var re;
    try {
        re = new RegExp(rei, "i");
    }
    catch(e) {
        alert("Bad search expression: " + e); return;
    }

    var found = [];

    var currDoc;

    function eN(n)
    {
        if ( n.data != null
            && n.nodeType != 8 // COMMENT_NODE
            && n.nodeType != 4 // CDATA_SECTION_NODE
            && n.parentNode.tagName != "SCRIPT" && re.test(n.data)) {
            found.push([n, currDoc]);
        }
    }

    function eD(dt, f) {
        currDoc = dt;
        var bod = dt.getElementsByTagName("BODY")[0];
        travTree(bod, eN);
    }


    // "dIr" == "documentIterator"
    function dIr(dt, f) {
        function ifsr( fs )
        {
            for (var i = 0; i < fs.length; ++i)
            {
                try {
                    dIr(fs[i].contentDocument, fs[i]); // recursive call
                }
                catch (e) {
                    alert(e || "Unspecified error");
                }
            }
        }

        if (dt == null) {return;}
        eD(dt, f);
        ifsr( dt.getElementsByTagName("FRAME") );
        ifsr( dt.getElementsByTagName("IFRAME") );
    }

    // iterate through all documents
    dIr(document, null);
    var offset = null;
    var text = null;

    function mtch(str, offset_, s)
    {
        text = offset = null;
        if (str.length > 0)
        {
            text = str; offset = offset_;
        }
        return str;
    }

    function hl( node )
    {
        var s = node[0].data;
        var dt = node[1];

        var nns = dt.createDocumentFragment();

        var count = 0; // for endless-loop prevention
        do
        {
            offset = null;
            text = null;

            // call only for side effects
            s.replace(
                re, mtch
                );
            if ( offset != null )
            {
                ++rp;
                nns.appendChild(
                    dt.createTextNode(s.substring(0, offset))
                    );
                var sp = dt.createElement("SPAN");
                sp.style.border = "thin solid red";
                sp.appendChild( dt.createTextNode(text) );
                nns.appendChild(sp);

                s = s.substring(offset + text.length);
            }
        } while (offset != null && ++count < 1000);

        if (s.length > 0)
        {
            nns.appendChild(
                dt.createTextNode(s)
                );
        }
        node[0].parentNode.replaceChild(nns, node[0]);

    }

    for (var i = 0; i < found.length; ++i)
    {
        var node = found[i];
        hl(node);
    }

    alert("Found: " + rp + ".");
}());