2

IMDb の評価を非表示にし、ユーザーが後で番組/映画を評価できるようにするリンクに置き換えるクロスブラウザ ユーザースクリプトを作成しようとしています。

Opera では、このアプローチは既に機能していますが、Firefox と Chrome の両方で、未定義の関数や変数に出くわします。これまでの私のコードは次のとおりです。

function hideimdbratings() {

    if (document.getElementsByClassName("star-box")[0]) {

        reenabled = document.getElementsByClassName("star-box")[0].innerHTML;

        document.getElementsByClassName("star-box")[0].innerHTML = '<a href="#" id="showvote" onclick="reenableit();">Rate!</a>';

    }
}

function reenableit() {
    document.getElementsByClassName("star-box")[0].innerHTML = reenabled;
}

window.addEventListener('load', hideimdbratings, false);

最初の部分は正常に動作し、hideimdbratings()実行され、評価が非表示になります。

reenableit()しかし、「Rate!」リンクをクリックすると、Firefox と Chrome の両方がそれが定義されていないと言います。

これを試す:

onclick="document.getElementsByClassName(\"star-box\")[0].innerHTML = reenabled;"

reenabled定義されていないと言う結果になります。

コードをイベントリスナーに直接入れてみました:

window.addEventListener("load", function(e) {
// ...
}, false);

関数を定義するこの方法 (Firefox の unsafeWindow を使用):

var window.reenableit = function() { }

しかし、私が何をしても、 と の両方reenableit()reenabled未定義のままです。私が理解していることから、Opera 以外のブラウザーでは関数も変数もグローバルではありませんが、まだ解決策を見つけることができないようです。

私は何が欠けていますか/間違っていますか?

4

3 に答える 3

1

変数または関数をグローバルにする方法がわかりませんでしたが、問題なく機能する回避策を次に示します。

function hideimdbratings() {
    if (document.getElementsByClassName('star-box')[0]) {

        // hide the "star-box" container
        var b = document.getElementsByClassName('star-box')[0];
        b.style.display = 'none';

        // add the "Rate!" link
        var n = document.createElement('a');
        n.setAttribute('href', 'javascript:void(0);');
        n.setAttribute('onclick', 'document.getElementsByClassName("star-box")[0].style.display = "block"; this.style.display = "none";');
        n.innerHTML = 'Rate!';
        b.parentNode.insertBefore(n, b.nextSibling);
    }
}

window.addEventListener('load', hideimdbratings, false);
于 2013-01-29T18:52:37.457 に答える
1

Chrome のユーザー スクリプトはサンドボックス ( 「孤立した世界」 ) で動作し、Chrome ではページ スコープの JavaScript オブジェクトを設定または使用できないため、このコードは Chrome では機能しません。また、Chrome は を完全に/適切にサポートしていませんunsafeWindow

このコードFirefox+Greasemonkey で を注意深く使用すると機能しますがunsafeWindow、ここではお勧めしません (Chrome では役に立ちません)。

クロスブラウザーの方法でページスコープの JavaScript と対話する必要がある場合の古典的なアプローチは、スクリプト インジェクションを使用することです。これは、Chrome でうまく機能する唯一のものです。

ただし、必要がない場合は、ページスコープ JS をまったく使用しないことが最も賢明です。そして、この質問の内容については、その必要はありません。(ヒント:onclickまたは類似の属性は絶対に使用しないでください。常にaddEventListener()、または同等の属性を使用してください。)

サンドボックスのスコープを離れないようにコードをリファクタリングすると、次のようになります。

function hideImdbRatings () {
    var oldStarBoxHTML;
    var starBox = document.getElementsByClassName ("star-box");
    if (starBox.length) {
        starBox             = starBox[0];
        oldStarBoxHTML      = starBox.innerHTML;
        starBox.innerHTML   = '<a href="#" id="showVote">Rate!</a>';

        document.getElementById ("showVote").addEventListener (
            "click",
            function () {
                //-- "this" is a special javascript scope.
                this.innerHTML = oldStarBoxHTML;
            }
        );
    }
}

window.addEventListener ('load', hideImdbRatings, false);


ただし 2 、これまでのすべてのコードが IMDB の評価ウィジェットの相互作用を妨害していることに気付くでしょう。これはinnerHTML、ウィジェットのイベント ハンドラーを破棄する上書きであるためです。そのように使用しないでくださいinnerHTML

最も賢明なことは、Geoの答えと同様に、次のようにブロックを非表示にすることです。

 function hideImdbRatings () {
    var starBox = document.getElementsByClassName ("star-box");
    if (starBox.length) {
        starBox                 = starBox[0];
        starBox.style.display   = 'none';
        var rateLink            = document.createElement ('a');
        rateLink.id             = 'showVote';
        rateLink.href           = '#';
        rateLink.textContent    = 'Rate!';

        starBox.parentNode.insertBefore (rateLink, starBox);

        document.getElementById ("showVote").addEventListener (
            "click",
            function () {
                //-- "this" is a special javascript scope.
                this.style.display      = 'none';
                starBox.style.display   = 'block';
            }
        );
    }
}

window.addEventListener ('load', hideImdbRatings, false);


スクリプトが Chrome で動作しなくなる可能性がある追加の要因があります。 デフォルトでは、loadイベント後に Chrome ユーザースクリプトが実行される場合があります。 これを回避するには、スクリプトのメタデータ ブロック@run-at document-endで指定します。

于 2013-01-30T11:23:28.793 に答える
0

あはは!それを見つけた。これを試して:

var uw = (this.unsafeWindow) ? this.unsafeWindow : window;
var b = document.getElementsByClassName('star-box')[0];
uw.reenabled = b.innerHTML;
b.innerHTML = '<a href="javascript:void(0);" onclick="document.getElementsByClassName(\'star-box\')[0].innerHTML = reenabled;">Rate!</a>';

この投稿に触発された

于 2013-01-29T21:20:47.927 に答える