Change CSS of the content of an iframe, that has s

2019-07-13 03:35发布

I'm trying this code to apply new design on the Google Tasks page with the extension Tampermonkey.

When I try html{ display: none !important } then It displays nothing as the html tag is not under iframe. however, I couldn't modify under iframe[src="about:blank"] element. How should I modify to make it work?


shot 1. : Doesn't work for inside of iframe[src="about:blank"]

// ==UserScript==
// @name     test
// @match    https://mail.google.com/tasks/canvas
// @match    about:blank
// @grant    GM_addStyle
// ==/UserScript==

GM_addStyle ( `    
* {color: red !important}
` );

1条回答
孤傲高冷的网名
2楼-- · 2019-07-13 04:02

Yes, scripting for iframes with src="about:blank" can be tricky as the normal userscript mechanisms do not work the same. (Currently, @match about:blank does not work, but it would be a bad idea to use it here anyway, since it would have global side effects.)

Fortunately, on Chrome, iframes with src="about:blank" almost always have a documentElement by the time a Tampermonkey script runs, so you do not normally need to wait if you are just adding CSS.

Here is a complete working script, that styles that first iframe:

// ==UserScript==
// @name    _Style iframe with src="about:blank"
// @match   https://mail.google.com/tasks/canvas
// @grant   none
// ==/UserScript==

//-- Adjust the following selector to match your page's particulars, if needed.
var targetFrame = document.querySelector ("iframe[src='about:blank']")
if (targetFrame) {
    addStyleToFrame (
        `* {color: red !important}`
        , targetFrame
    );
}

function addStyleToFrame (cssStr, frmNode) {
    var D               = frmNode.contentDocument;
    var newNode         = D.createElement ('style');
    newNode.textContent = cssStr;

    var targ    = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
    targ.appendChild (newNode);
}



If the <iframe> tag is javascript created, or other delays hamper the above...

Use the iframeSelector parameter of waitForKeyElements to work around that.

The trick is to pick a node that always appears in the finished iframe, and pass that to waitForKeyElements.
The node should be unique.
But for the following example I used .goog-toolbar:first as a quick first attempt.

Here is that complete working script:

// ==UserScript==
// @name     _Style iframe with src="about:blank"
// @match    https://mail.google.com/tasks/canvas
// @require  https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant    GM_addStyle
// @grant    GM.getValue
// ==/UserScript==
//- The @grant directives are needed to restore the proper sandbox.

const desiredStyles = `* {color: red !important;}`;

waitForKeyElements (
    ".goog-toolbar:first",
    addCSS_Style,
    false,
    "iframe[src='about:blank']"
);

function addCSS_Style (jNode) {
    var frmBody = jNode.closest ("body");
    //-- Optionally add a check here to avoid duplicate <style> nodes.
    frmBody.append (`<style>${desiredStyles}</style>`);
}



Notes:

  1. GM_addStyle() will not work in this case, so we add styles with a frame-aware function.
  2. Google pages use: multiple, nested iframes; complex page (re)mangling; and HTML with poor "info scent". In short they are evil, ever-shifting, and can be a pain to script for. So, this simple example will work, but that's all that's in scope for this question. For more complex scenarios, open a new question and have plenty of beer money on hand.
查看更多
登录 后发表回答