Frage

Ich habe die folgenden (ziemlich) einfache JavaScript-Snippet, dass ich in Grease verdrahtet. Es geht durch eine Seite, sucht nach Tags href Punkten zu sehen, dessen tinyurl.com, und fügt ein „title“ Attribut, das das wahre Ziel der Verknüpfung identifiziert. Ein Großteil des wichtigen Code stammt aus einem älteren (nicht unterstützt) Greasemonkey-Skript, das Arbeits wird beendet, wenn die innere Komponente, die die XPath Implementierung geändert gehalten. Mein Skript:

(function() {
    var providers = new Array();
    providers['tinyurl.com'] = function(link, fragment) {
        // This is mostly taken from the (broken due to XPath component
        // issues) tinyurl_popup_preview script.
        link.title = "Loading...";
        GM_xmlhttpRequest({
                method: 'GET',
                url: 'http://preview.tinyurl.com/' + fragment,
                onload: function(res) {
                    var re = res.responseText.match("<blockquote><b>(.+)</b></blockquote>");
                    if (re)
                    {
                        link.title = re[1].replace(/\<br \/\>/g, "").replace(/&amp;/g, "&");
                    }
                    else
                    {
                        link.title = "Parsing failed...";
                    }
                },
                onerror: function() {
                    link.title = "Connection failed...";
                }
        });
    };
    var uriPattern = /(tinyurl\.com)\/([a-zA-Z0-9]+)/;
    var aTags = document.getElementsByTagName("a");

    for (i = 0; i < aTags.length; i++)
    {
        var data = aTags[i].href.match(uriPattern);
        if (data != null && data.length > 1 && data[2] != "preview")
        {
            var source = data[1];
            var fragment = data[2];
            var link = aTags[i];
            aTags[i].addEventListener("mouseover", function() {
                if (link.title == "")
                {
                    (providers[source])(link, fragment);
                }
            }, false);
        }
    }
})();

(Der Grund für das „Anbieter“ assoziative Array ist die Art und Weise aufgebaut ist, ist so, dass ich diese erweitern kann andere URL-Verkürzungsdienste sowie zu decken.)

Ich habe festgestellt, dass alle verschiedenen Zweige des Code richtig, in den Fällen erreicht werden, wo der Link funktioniert geprüft und nicht das Muster entspricht. Was nicht geschieht, ist jede Änderung des „title“ -Attribut der Anker-Tags. Ich habe über Firebug, geworfen alert() Anrufe in links und rechts sah dies, und es gerade ändert sich nie. In einer früheren Iteration aller Ausdrücke der Form:

link.title = "...";

hatte ursprünglich gewesen:

link.setAttribute("title", "...");

das hat nicht funktioniert, auch nicht. Ich bin kein Neuling auf JavaScript oder Greasemonkey, aber dieses hat mich ratlos!

War es hilfreich?

Lösung

Versuchen Sie, den Körper des if mit diesem Code zu ersetzen, statt.

        aTags[i].addEventListener("mouseover", (function(source, fragment)
        {
            return function()
            {
                if (this.title == "")
                {
                    (providers[source])(this, fragment);
                }
            }
        })(data[1], data[2]), false) ; 

Hinweis nach der Schleife abgeschlossen tun aTags = null;.

Ihr Problem ist, dass, wenn ein Anweisungsblock nicht ein wahrer Umfang ist, etwas var'd an den äußeren Funktionen Umfang gehören wird. Daher Ihre innere Funktion, die Sie als Event-Handler zur Verfügung stellen würde, um die Quelle, Link und Fragment des letzten Durchgangs verwenden. Additionaly durch Verweise auf DOM Aufrechterhaltung Objekt Sie einen Speicherverlust aufgrund zirkuläre Referenzen haben.

Der obige Ansatz bei jedem Durchlauf über einen Funktionsaufruf einen neuen Bereich erstellen, so dass jede Quelle und Fragment ist in einem eigenen Rahmen. Es nutzt auch die Tatsache, dass eine Funktion als Ereignis-Listener genannt this Eigenschaft hat am Element zeigt auf dem sie angebracht ist, also eine kreisförmige Referenz Vermeidung eines DOM-Element enthält.

scroll top