Search code examples
javascripthtmlgreasemonkey

Where's my `head` at?


When browsing on GameFAQS, one of my Greasemonkey scripts broke with Firefox version 56. It's a very simple one:

// ==UserScript==
// @name        MakeSignaturesBlack
// @namespace   tarelessar
// @description Makes the signatures black again
// @include     https://*.gamefaqs.com/*
// @version     1
// @grant       none
// @run-at      document-start
// ==/UserScript==
//Makes signatures black I guess

var sheet = document.createElement ('style')
sheet.innerHTML = ".signature {color: inherit !important}";
document.head.appendChild(sheet);

This script was written to change the gray signature bar on the site to black and has worked all the way up to version 54 of Firefox. After that, it stopped working on version 56.

When I troubleshot it, I found that the document.head was null. From doing a little research, I found that document.getElementsByTagName("head")[0]; should be used and tried:

// ==UserScript==
// @name        MakeSignaturesBlack
// @namespace   tarelessar
// @description Makes the signatures black again
// @include     https://*.gamefaqs.com/*
// @version     1
// @grant       none
// @run-at      document-start
// ==/UserScript==
//Makes signatures black I guess

var sheet = document.createElement ('style')
sheet.innerHTML = ".signature {color: inherit !important}";
document.head || document.getElementsByTagName("head")[0];.appendChild(sheet);

...it made no change to the signature color.

What am I doing wrong? How can I change the "head" element so that it changes the signature color?


Solution

  • In @run-at document-start mode, Greasemonkey scripts can indeed fire before the document.head is available. In such cases, fall back to documentElement.

    Code like this is best:

    let D           = document;
    let sheet       = D.createElement ('style')
    sheet.innerHTML = ".signature {color: inherit !important}";
    let targ        = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
    targ.appendChild (sheet);
    

    However, if you are just changing the appearance by injecting CSS, you would be smarter to use the Stylish extension. It's easier and performs better for this kind of thing.