Home

Show Ambiguous Link Texts

Source code for bookmarklet Show Ambiguous Link Texts.



javascript:
(function(){
        function linktext(node, ic)
    {
        function ns(nxi)
        {
            var str = "";

            var nx = nxi;
            while (nx != null)
            {
                if (nx.tagName == "IMG") {
                    if ( ic != null ) {++ic.count;}
                    str += (nx.hasAttribute("ALT") ? nx.alt : nx.src);
                }
                else if (nx.data != null
                    && nx.nodeType != 8 // COMMENT_NODE
                    && nx.parentNode.tagName != "SCRIPT") {
                    str += nx.data;
                }
                str += ns(nx.firstChild);
                nx = nx.nextSibling;
            }
            return str;
        }

        if (node.href == null || node.href.length == 0) {return null;}
        var nx = ns(node.firstChild);
        return nx.replace( /\s+/mg, " ").replace( /^\s/, "" ).replace( /\s+$/, "" );
    }

    var lts = [];


    function refs( href )
    {
        this.refs = [];
        this.refs[ href ] = 0;
        this.links = [];
    }

    function eD(dt)
    {
        var c = dt.getElementsByTagName( "A" );
        for (var k = 0; k < c.length; ++k) {
            var lt = linktext( c[k], null );
            if ( lt != null )
            {
                if (c[k].title.length > 0)
                {
                    lt = c[k].title + ": " + lt;
                }
                var href = c[k].href;
                var b = lts[ lt ] = (lts[ lt ] != null ? lts[ lt ] : new refs(href));
                b.refs[href] = href; // store href for consistency check
                b.links.push( c[k] );
            }
        }
    }


    // "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 duptext_count = 0, dupinstance_count = 0;
for (var lkt in lts)
{
    var lt = lts[lkt];
    {
        var count = 0;
        for (var j in lt.refs)
        {
            // The enumeration may show a number of non-keys (Array object properties),
            // so a consistency check is necessary.
            count += (lt.refs[j] == j ? 1 : 0);
        }
        if ( count > 1 )
        {
            ++duptext_count;
            var lcnt = lt.links.length;
            dupinstance_count += lcnt;
            for (var ii = 0; ii < lcnt; ++ii)
            {
                lt.links[ii].style.border = "thick dashed red";
                lt.links[ii].title = "[" + lkt + "](" + (ii + 1) + "/" + lcnt + ")";
            }
        }
    }
}

var st = "No ambiguous links found";
if ( duptext_count > 0 )
{
    st = "Ambiguous link texts: " + duptext_count + " (" + dupinstance_count + " instances)";
}
alert(st);

}());