簡體   English   中英

如何使GreaseMonkey腳本在顯示之前影響頁面中的元素?

[英]How to make a GreaseMonkey script affect elements in a page before they're displayed?

我正在嘗試確保不顯示某個網站中的圖像,但仍會顯示替代文字。 最初我嘗試使用Stylish(使用Firefox)完成此操作並詢問以下問題:

如何強制顯示圖像的alt文本而不是圖像?

接受的答案為我提供了使用Greasemonkey的替代解決方案。 該腳本使用waitForKeyElements隱藏圖像,即使它們是使用AJAX添加的。

我將給定的腳本更改為以下內容:

// ==UserScript==
// @name     _Hide pics except for alt text
// @include  http://YOUR_SERVER.COM/YOUR_PATH/*
// @require  http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant    GM_addStyle
// ==/UserScript==

GM_addStyle ( "                                 \
    * {                                         \
        background-image: none !important;      \
    }                                           \
" );

waitForKeyElements ("img", hideImageExceptForAltText);

function hideImageExceptForAltText (jNode) {
    var imgAlt = jNode.attr("alt");
    var imgTitle = jNode.attr("title");

    jNode.css("display", "none");

    var newSpan = $("<span></span>");
    newSpan.attr("title", imgTitle);
    newSpan.append(imgAlt);

    jNode.parent().append(newSpan);
}

就像原始腳本一樣,這有一個問題,即在頁面加載時圖像仍會顯示片刻。

是否可以確保給定的功能可以防止頁面上的圖像立即顯示,以便它們根本不可見?

編輯:布洛克亞當斯的回復有我不知道的線索。 如果有人正在尋找這樣的東西,以下是我最終使用的東西。 它在我需要它的網站上運行良好,但我不能保證它可以在除Firefox之外的其他網站或其他瀏覽器上運行。

以下內容隱藏圖像並用鏈接替換它們(背景圖像除外)。 單擊該鏈接將顯示圖像。

// ==UserScript==
// @name        TCRF images
// @namespace   SOMETHING
// @include     http://YOUR_SERVER.COM/YOUR_PATH/*
// @require     http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require     https://gist.github.com/raw/2625891/waitForKeyElements.js
// @version     1
// @grant       GM_addStyle
// @run-at      document-start
// ==/UserScript==

GM_addStyle ( "\
    * {\
       background-image: none !important;\
    }\
\
    img.gmImgHideHidden {\
       display: none !important;\
    }\
" );

var num = 0;

function gmImgHideShowImg(imgId, linkId)
{
    // Using plain JavaScript because the page itself may not have jquery
    var img = document.getElementById(imgId);
    img.className = img.className.replace( /(?:^|\s)gmImgHideHidden(?!\S)/g , '' );

    var lnk = document.getElementById(linkId);
    lnk.parentNode.removeChild(lnk);
}

// Exporting the "show image" function so that it can be used in the webpage
unsafeWindow.gmImgHideShowImg = exportFunction(gmImgHideShowImg, unsafeWindow);

waitForKeyElements ("img", hideImageExceptForAltText);

function hideImageExceptForAltText (jNode) {
    var imgId = jNode.attr("id");

    // Ensuring an id exists so the image can be searched for later
    if(typeof(imgId) == "undefined")
    {
        imgId = "gmImgHideImg" + num;
        jNode.attr("id", imgId);
    }

    var imgDisp = jNode.css("display");

    var imgAlt = jNode.attr("alt");
    jNode.addClass("gmImgHideHidden");

    var linkId = "gmImgHideLink" + num;

    var linkNode = $("<a></a>");
    linkNode.attr("id", linkId);
    linkNode.append("Image: " + imgAlt);
    linkNode.attr("onclick", "gmImgHideShowImg('" + imgId + "', '" + linkId + "'); return false;");

    jNode.parent().append(linkNode);

    num++;
}

MutationObserver毫無疑問是這里最好的解決方案。 結合@run-at document-start早期注入,我們可以使腳本非常防彈。 看看這個小提琴 (用Firefox 40測試)看看它的實際效果。

我認為代碼非常明顯。 我已經注釋了這些細微之處,但如果你有什么不明白的話,請留言。

// ==UserScript==
// @run-at document-start
// ==/UserScript==
"use strict";

/* part one: <img> elements */

(new MutationObserver(function(Records, Obs) {
    for (let R of Records) {/* examine each mutation record: */
        /* if the record specifies an attribute mutation… */
        if (
            R.attributeName === "src" &&
            (R.target instanceof Element) && /* this check might be necessary */
            R.target.tagName.toLowerCase() === "img" &&
            R.target.getAttribute("src") !== "" /* avoid infinite loop */
        ) {
            R.target.setAttribute("src", "");
        };

        /* if the record specifies a sub-element mutation… */
        for (let N of R.addedNodes) {
            if (
                (N instanceof Element) && /* this check might be necessary */
                N.tagName.toLowerCase() === "img" &&
                N.getAttribute("src") !== "" /* avoid infinite loop */
            ) {
                N.setAttribute("src", "");
            };
        };
    };
})).observe(document, {
    /* changes wot we listen for */
    childList : true,
    subtree : true,
    attributes : true
});

/* part two: background-image styles */

let check_for_head_elem = function(_, Obs) {
    if (!document.head) {return;};
    Obs.disconnect();

    /* apply our style */
    let Style = document.createElement("style");
    document.head.appendChild(Style);
    Style.sheet.insertRule("* {background-image : none !important;}", 0);
};

let check_for_root_elem = function(_, Obs) {
    if (!document.documentElement) {return;};
    Obs.disconnect();

    /* observe until the <head> element is added */
    Obs = new MutationObserver(check_for_head_elem)
    Obs.observe(document.documentElement, {childList : true});
    check_for_head_elem(null, Obs); /* check here because it might exist already */
};

{/* observe until the <html> element is added */
    let Obs = new MutationObserver(check_for_root_elem);
    Obs.observe(document, {childList : true});
    check_for_root_elem(null, Obs); /* check here because it might exist already */
};

還有一些其他方法可以在頁面上獲取我沒有考慮過的圖像( <iframe><svg><canvas><li>項目符號點),但如有必要,您應該可以使用變異觀察器或CSS也照顧這些。

一個簡單,健壯的方法是在頁面的任何其他頁面加載之前設置CSS first-thing。

@run-at document-startGM_addStyle()執行此操作。 (在Firefox上;未在最新的Tampermonkey上測試)

這樣,圖像即使在幾分之一秒內也不會顯示,就像它們使用原始代碼或復雜,挑剔的MutationObserver方法一樣。

這個完整的腳本顯示了該過程:

// ==UserScript==
// @name     _Hide pics except for alt text
// @include  http://YOUR_SERVER.COM/YOUR_PATH/*
// @require  http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant    GM_addStyle
// @run-at   document-start
// ==/UserScript==
GM_addStyle ( "                                 \
    * {                                         \
        background-image: none !important;      \
    }                                           \
    img {                                       \
        display: none !important;               \
    }                                           \
" );

/*--- $(document).ready() is not always needed for modern Firefox, but
    use for maximum portability, when script runs at document-start.
*/
$(document).ready ( function () {
    waitForKeyElements ("img", hideImageExceptForAltText);
} );

function hideImageExceptForAltText (jNode) {
    var imgAlt      = jNode.attr("alt")     || "";
    var imgTitle    = jNode.attr("title")   || "";

    jNode.after ('<span title="' + imgTitle + '">' + imgAlt + '</span>');
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM