1

I'm currently trying to change style elements for this Google-tasks gadget:

https://mail.google.com/tasks/ig

using a chrome content script.

In this example, I'm removing the toolbar at the bottom. Because Google is generating the HTML with javascript, and puts it in an iframe. I need to use this code:

document.getElementsByTagName('iframe')[0].contentWindow.document.getElementById(':1.ft').style.display = 'none'

When you run this code from the developer console, it hides the toolbar. But it doesn't work as content script.

I thought this is because the code is run before the page is ready. So I tried to use an event listener:

document.addEventListener("DOMContentLoaded", function () {
document.getElementsByTagName('iframe')[0].contentWindow.document.getElementById(':1.ft').style.display = 'none'
}, false);

but that didn't work either. Also tried the event listeners 'domready' and 'load'. But none of them worked.

How do I get that element?

Brock Adams
  • 90,639
  • 22
  • 233
  • 295

1 Answers1

1

In this case, you could just make sure that this style rule is applied to the appropriate iframe(s), and not worry about when it is loaded:

#:1.ft {display: none !important;}

(^_^)
But, this may not be possible for iframes with src="javascript: ....


In the more general case. If that node (or its containing iframe) is loaded by AJAX, it no-doubt appears long after 'domready' or even 'load'.
The tried-and-true solution is to poll for the element:

var waitForElementIntrvl = setInterval (checkForElement, 333);

function checkForElement () {
    var firstIframe     = document.querySelector ("iframe");
    if (firstIframe) {
        var targElement = firstIframe.contentWindow.document.getElementById (':1.ft');
        if (targElement) {
            targElement.style.display = 'none';
            clearInterval (waitForElementIntrvl);
        }
    }
}


However:

Google Chrome content-scripts still do not play nice with iframed DOM's. So, in order for that code to work, it must be injected into the target page. The final content-script code becomes:

function userscriptMain () {
    var waitForElementIntrvl = setInterval (checkForElement, 333);

    function checkForElement () {
        var firstIframe     = document.querySelector ("iframe");
        if (firstIframe) {
            var targElement = firstIframe.contentWindow.document.getElementById (':1.ft');
            if (targElement) {
                targElement.style.display = 'none';
                clearInterval (waitForElementIntrvl);
            }
        }
    }
}

addJS_Node (null, null, userscriptMain);

function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
    var D                                   = document;
    var scriptNode                          = D.createElement ('script');
    if (runOnLoad) {
        scriptNode.addEventListener ("load", runOnLoad, false);
    }
    scriptNode.type                         = "text/javascript";
    if (text)       scriptNode.textContent  = text;
    if (s_URL)      scriptNode.src          = s_URL;
    if (funcToRun)  scriptNode.textContent  = '(' + funcToRun.toString() + ')()';

    var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
    targ.appendChild (scriptNode);
}
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • Sorry about that. I forgot that mention that that code must be injected. See the updated answer. – Brock Adams Aug 27 '12 at 05:24
  • You're welcome. Glad to help. If that does it for you, please [check the check-mark next to this answer](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235). – Brock Adams Aug 27 '12 at 20:08