JavaScript(Greasemonkey経由)で“ title”を設定できない< a>の属性タグ
-
06-07-2019 - |
質問
Greasemonkeyに配線した以下の(かなり)簡単なJavaScriptスニペットがあります。ページをたどり、< a>を探します。 hrefが tinyurl.com
を指し、" title"を追加するタグリンクの実際の宛先を識別する属性。重要なコードの多くは、XPath実装を保持する内部コンポーネントが変更されたときに動作を終了する古い(サポートされていない)Greasemonkeyスクリプトからのものです。私のスクリプト:
(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(/&/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);
}
}
})();
(&quot; providers&quot;連想配列がそのまま設定される理由は、他のURL短縮サービスにも対応できるようにこれを拡張できるようにするためです。)
調査対象のリンクがパターンに一致する場合と一致しない場合に、コードのすべての分岐に正しく到達していることを確認しました。何が起こっていないか は、「タイトル」への変更です。アンカータグの属性。 Firebugでこれを見て、左右に alert()
呼び出しをスローしましたが、変更されることはありません。前の反復では、次の形式のすべての式:
link.title = "...";
元々:
link.setAttribute("title", "...");
それでもうまくいきませんでした。私はJavaScriptやGreasemonkeyの初心者ではありませんが、これには困惑しています!
解決
if
の本文を代わりにこのコードに置き換えてみてください。
aTags[i].addEventListener("mouseover", (function(source, fragment)
{
return function()
{
if (this.title == "")
{
(providers[source])(this, fragment);
}
}
})(data[1], data[2]), false) ;
ループが完了した後、 aTags = null;
を実行します。
問題は、ifステートメントブロックが真のスコープではないため、var'dのすべてが外部関数スコープに属することです。したがって、イベントハンドラーとして提供する内部関数は、最後のパスのソース、リンク、およびフラグメントを使用します。さらに、DOMオブジェクトへの参照を維持すると、循環参照によるメモリリークが発生します。
上記の方法では、関数呼び出しを介してパスごとに新しいスコープが作成されるため、各ソースとフラグメントは独自のスコープ内にあります。また、イベントリスナーとして呼び出される関数には、アタッチ先の要素を指す this
プロパティがあるため、DOM要素を含む循環参照が回避されます。